1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
4 * (C) 2014 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
7 #include "mtest_datatype.h"
8 #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
11 #if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
14 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
20 /* The following two includes permit the collection of resource usage
23 #ifdef HAVE_SYS_TIME_H
26 #ifdef HAVE_SYS_RESOURCE_H
27 #include <sys/resource.h>
32 /* ------------------------------------------------------------------------ */
33 /* General datatype routines */
34 /* ------------------------------------------------------------------------ */
36 static void *MTestTypeFree(MTestDatatype * mtype)
42 if (mtype->displ_in_bytes)
43 free(mtype->displ_in_bytes);
46 if (mtype->old_datatypes)
47 free(mtype->old_datatypes);
50 mtype->displ_in_bytes = NULL;
52 mtype->old_datatypes = NULL;
57 static inline void MTestTypeReset(MTestDatatype * mtype)
60 mtype->printErrors = 0;
63 mtype->datatype = MPI_DATATYPE_NULL;
70 mtype->displ_in_bytes = NULL;
75 mtype->old_datatypes = NULL;
77 mtype->arr_sizes[0] = 0;
78 mtype->arr_sizes[1] = 0;
79 mtype->arr_subsizes[0] = 0;
80 mtype->arr_subsizes[1] = 0;
81 mtype->arr_starts[0] = 0;
82 mtype->arr_starts[1] = 0;
85 mtype->InitBuf = NULL;
86 mtype->FreeBuf = NULL;
87 mtype->CheckBuf = NULL;
90 /* ------------------------------------------------------------------------ */
91 /* Datatype routines for contiguous datatypes */
92 /* ------------------------------------------------------------------------ */
94 * Initialize buffer of basic datatype
96 static void *MTestTypeContigInit(MTestDatatype * mtype)
98 MPI_Aint extent = 0, lb = 0, size;
101 if (mtype->count > 0) {
104 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
106 MTestPrintError(merr);
109 totsize = size * mtype->count;
111 mtype->buf = (void *) malloc(totsize);
113 p = (unsigned char *) (mtype->buf);
115 char errmsg[128] = { 0 };
116 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
119 for (i = 0; i < totsize; i++) {
120 p[i] = (unsigned char) (0xff ^ (i & 0xff));
133 * Check value of received basic datatype buffer.
135 static int MTestTypeContigCheckbuf(MTestDatatype * mtype)
138 unsigned char expected;
140 MPI_Aint i, totsize, size, extent = 0, lb = 0;
142 p = (unsigned char *) mtype->buf;
144 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
146 MTestPrintError(merr);
149 totsize = size * mtype->count;
150 for (i = 0; i < totsize; i++) {
151 expected = (unsigned char) (0xff ^ (i & 0xff));
152 if (p[i] != expected) {
154 if (mtype->printErrors && err < 10) {
155 printf("Data expected = %x but got p[%zd] = %x\n", expected, i, p[i]);
165 /* ------------------------------------------------------------------------ */
166 /* Datatype routines for vector datatypes */
167 /* ------------------------------------------------------------------------ */
170 * Initialize buffer of vector datatype
172 static void *MTestTypeVectorInit(MTestDatatype * mtype)
174 MPI_Aint extent = 0, lb = 0, size, totsize, dt_offset, byte_offset;
177 if (mtype->count > 0) {
182 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
184 MTestPrintError(merr);
187 totsize = mtype->count * size;
189 mtype->buf = (void *) malloc(totsize);
191 p = (unsigned char *) (mtype->buf);
193 char errmsg[128] = { 0 };
194 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
198 /* First, set to -1 */
199 for (k = 0; k < totsize; k++)
202 /* Now, set the actual elements to the successive values.
203 * We require that the base type is a contiguous type */
206 /* For each datatype */
207 for (k = 0; k < mtype->count; k++) {
209 for (i = 0; i < mtype->nblock; i++) {
210 byte_offset = dt_offset + i * mtype->stride;
212 for (j = 0; j < mtype->blksize; j++) {
213 p[byte_offset + j] = (unsigned char) (0xff ^ (nc & 0xff));
227 * Check value of received vector datatype buffer
229 static int MTestTypeVectorCheckbuf(MTestDatatype * mtype)
232 unsigned char expected;
233 int i, err = 0, merr;
234 MPI_Aint size = 0, byte_offset, dt_offset, extent, lb;
236 p = (unsigned char *) mtype->buf;
240 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
242 MTestPrintError(merr);
247 /* For each datatype */
248 for (k = 0; k < mtype->count; k++) {
250 for (i = 0; i < mtype->nblock; i++) {
251 byte_offset = dt_offset + i * mtype->stride;
253 for (j = 0; j < mtype->blksize; j++) {
254 expected = (unsigned char) (0xff ^ (nc & 0xff));
255 if (p[byte_offset + j] != expected) {
257 if (mtype->printErrors && err < 10) {
258 printf("Data expected = %x but got p[%d,%zd] = %x\n", expected, i, j,
273 /* ------------------------------------------------------------------------ */
274 /* Datatype routines for indexed datatypes */
275 /* ------------------------------------------------------------------------ */
278 * Initialize buffer of indexed datatype
280 static void *MTestTypeIndexedInit(MTestDatatype * mtype)
282 MPI_Aint extent = 0, lb = 0, size, totsize, dt_offset, offset;
285 if (mtype->count > 0) {
290 /* Allocate buffer */
291 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
293 MTestPrintError(merr);
296 totsize = size * mtype->count;
299 mtype->buf = (void *) malloc(totsize);
301 p = (unsigned char *) (mtype->buf);
303 char errmsg[128] = { 0 };
304 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
308 /* First, set to -1 */
309 for (k = 0; k < totsize; k++)
312 /* Now, set the actual elements to the successive values.
313 * We require that the base type is a contiguous type */
316 /* For each datatype */
317 for (k = 0; k < mtype->count; k++) {
319 for (i = 0; i < mtype->nblock; i++) {
320 /* For each element in the block */
321 for (j = 0; j < mtype->index[i]; j++) {
322 offset = dt_offset + mtype->displ_in_bytes[i]
323 + j * mtype->basesize;
324 /* For each byte in the element */
325 for (b = 0; b < mtype->basesize; b++) {
326 p[offset + b] = (unsigned char) (0xff ^ (nc++ & 0xff));
344 * Check value of received indexed datatype buffer
346 static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
349 unsigned char expected;
351 MPI_Aint size = 0, offset, dt_offset, extent = 0, lb = 0;
353 p = (unsigned char *) mtype->buf;
357 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
359 MTestPrintError(merr);
364 /* For each datatype */
365 for (k = 0; k < mtype->count; k++) {
367 for (i = 0; i < mtype->nblock; i++) {
368 /* For each element in the block */
369 for (j = 0; j < mtype->index[i]; j++) {
370 offset = dt_offset + mtype->displ_in_bytes[i]
371 + j * mtype->basesize;
372 /* For each byte in the element */
373 for (b = 0; b < mtype->basesize; b++) {
374 expected = (unsigned char) (0xff ^ (nc++ & 0xff));
375 if (p[offset + b] != expected) {
377 if (mtype->printErrors && err < 10) {
378 printf("Data expected = %x but got p[%d,%d] = %x\n",
379 expected, i, j, p[offset + b]);
392 /* ------------------------------------------------------------------------ */
393 /* Datatype routines for indexed-block datatypes */
394 /* ------------------------------------------------------------------------ */
397 * Initialize buffer of indexed-block datatype
399 static void *MTestTypeIndexedBlockInit(MTestDatatype * mtype)
401 MPI_Aint extent = 0, lb = 0, size, totsize, offset, dt_offset;
404 if (mtype->count > 0) {
409 /* Allocate the send/recv buffer */
410 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
412 MTestPrintError(merr);
414 totsize = size * mtype->count;
417 mtype->buf = (void *) malloc(totsize);
419 p = (unsigned char *) (mtype->buf);
421 char errmsg[128] = { 0 };
422 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
426 /* First, set to -1 */
427 for (k = 0; k < totsize; k++)
430 /* Now, set the actual elements to the successive values.
431 * We require that the base type is a contiguous type */
434 /* For each datatype */
435 for (k = 0; k < mtype->count; k++) {
437 for (i = 0; i < mtype->nblock; i++) {
438 offset = dt_offset + mtype->displ_in_bytes[i];
439 /* For each byte in the block */
440 for (j = 0; j < mtype->blksize; j++) {
441 p[offset + j] = (unsigned char) (0xff ^ (nc++ & 0xff));
458 * Check value of received indexed-block datatype buffer
460 static int MTestTypeIndexedBlockCheckbuf(MTestDatatype * mtype)
463 unsigned char expected;
465 MPI_Aint size = 0, offset, dt_offset, lb = 0, extent = 0;
467 p = (unsigned char *) mtype->buf;
471 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
473 MTestPrintError(merr);
478 /* For each datatype */
479 for (k = 0; k < mtype->count; k++) {
481 for (i = 0; i < mtype->nblock; i++) {
482 offset = dt_offset + mtype->displ_in_bytes[i];
483 /* For each byte in the block */
484 for (j = 0; j < mtype->blksize; j++) {
485 expected = (unsigned char) (0xff ^ (nc++ & 0xff));
486 if (p[offset + j] != expected) {
488 if (mtype->printErrors && err < 10) {
489 printf("Data expected = %x but got p[%d,%zd] = %x\n",
490 expected, i, j, p[offset + j]);
502 /* ------------------------------------------------------------------------ */
503 /* Datatype routines for subarray datatypes with order Fortran */
504 /* ------------------------------------------------------------------------ */
507 * Initialize buffer of subarray datatype.
509 static void *MTestTypeSubarrayInit(MTestDatatype * mtype)
511 MPI_Aint extent = 0, lb = 0, size, totsize, offset, dt_offset, byte_offset;
514 if (mtype->count > 0) {
519 /* Allocate the send/recv buffer */
520 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
522 MTestPrintError(merr);
525 totsize = size * mtype->count;
528 mtype->buf = (void *) malloc(totsize);
530 p = (unsigned char *) (mtype->buf);
532 char errmsg[128] = { 0 };
533 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
537 /* First, set to -1 */
538 for (k = 0; k < totsize; k++)
541 /* Now, set the actual elements to the successive values.
542 * We require that the base type is a contiguous type. */
543 int ncol, sub_ncol, sub_nrow, sub_col_start, sub_row_start;
544 ncol = mtype->arr_sizes[1];
545 sub_nrow = mtype->arr_subsizes[0];
546 sub_ncol = mtype->arr_subsizes[1];
547 sub_row_start = mtype->arr_starts[0];
548 sub_col_start = mtype->arr_starts[1];
552 /* For each datatype */
553 for (k = 0; k < mtype->count; k++) {
555 for (i = 0; i < sub_nrow; i++) {
556 offset = (sub_row_start + i) * ncol + sub_col_start;
557 /* For each element in row */
558 for (j = 0; j < sub_ncol; j++) {
559 byte_offset = dt_offset + (offset + j) * mtype->basesize;
560 /* For each byte in element */
561 for (b = 0; b < mtype->basesize; b++)
562 p[byte_offset + b] = (unsigned char) (0xff ^ (nc++ & 0xff));
579 * Check value of received subarray datatype buffer
581 static int MTestTypeSubarrayCheckbuf(MTestDatatype * mtype)
584 unsigned char expected;
586 MPI_Aint size, offset, dt_offset, byte_offset, lb = 0, extent = 0;
588 p = (unsigned char *) mtype->buf;
592 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
594 MTestPrintError(merr);
598 int ncol, sub_ncol, sub_nrow, sub_col_start, sub_row_start;
599 ncol = mtype->arr_sizes[1];
600 sub_nrow = mtype->arr_subsizes[0];
601 sub_ncol = mtype->arr_subsizes[1];
602 sub_row_start = mtype->arr_starts[0];
603 sub_col_start = mtype->arr_starts[1];
607 /* For each datatype */
608 for (k = 0; k < mtype->count; k++) {
610 for (i = 0; i < sub_nrow; i++) {
611 offset = (sub_row_start + i) * ncol + sub_col_start;
612 /* For each element in row */
613 for (j = 0; j < sub_ncol; j++) {
614 byte_offset = dt_offset + (offset + j) * mtype->basesize;
615 /* For each byte in element */
616 for (b = 0; b < mtype->basesize; b++) {
617 expected = (unsigned char) (0xff ^ (nc++ & 0xff));
618 if (p[byte_offset + b] != expected) {
620 if (mtype->printErrors && err < 10) {
621 printf("Data expected = %x but got p[%d,%d,%d] = %x\n",
622 expected, i, j, b, p[byte_offset + b]);
633 printf("%s error\n", __FUNCTION__);
637 /* ------------------------------------------------------------------------ */
638 /* Datatype creators */
639 /* ------------------------------------------------------------------------ */
642 * Setup contiguous type info and handlers.
644 * A contiguous datatype is created by using following parameters (stride is unused).
645 * nblock: Number of blocks.
646 * blocklen: Number of elements in each block. The total number of elements in
647 * this datatype is set as (nblock * blocklen).
648 * lb: Lower bound of the new datatype (ignored).
649 * oldtype: Datatype of element.
651 static int MTestTypeContiguousCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride,
652 MPI_Aint lb, MPI_Datatype oldtype, const char *typename_prefix,
653 MTestDatatype * mtype)
658 MTestTypeReset(mtype);
660 merr = MPI_Type_size(oldtype, &mtype->basesize);
662 MTestPrintError(merr);
664 mtype->nblock = nblock;
665 mtype->blksize = blocklen * mtype->basesize;
667 merr = MPI_Type_contiguous(nblock * blocklen, oldtype, &mtype->datatype);
669 MTestPrintError(merr);
670 merr = MPI_Type_commit(&mtype->datatype);
672 MTestPrintError(merr);
674 memset(type_name, 0, sizeof(type_name));
675 sprintf(type_name, "%s %s (%zd count)", typename_prefix, "contiguous", nblock * blocklen);
676 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
678 MTestPrintError(merr);
680 mtype->InitBuf = MTestTypeContigInit;
681 mtype->FreeBuf = MTestTypeFree;
682 mtype->CheckBuf = MTestTypeContigCheckbuf;
687 * Setup vector type info and handlers.
689 * A vector datatype is created by using following parameters.
690 * nblock: Number of blocks.
691 * blocklen: Number of elements in each block.
692 * stride: Strided number of elements between blocks.
693 * lb: Lower bound of the new datatype (ignored).
694 * oldtype: Datatype of element.
696 static int MTestTypeVectorCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride, MPI_Aint lb,
697 MPI_Datatype oldtype, const char *typename_prefix,
698 MTestDatatype * mtype)
703 MTestTypeReset(mtype);
705 merr = MPI_Type_size(oldtype, &mtype->basesize);
707 MTestPrintError(merr);
709 /* These sizes are in bytes (see the VectorInit code) */
710 mtype->stride = stride * mtype->basesize;
711 mtype->blksize = blocklen * mtype->basesize;
712 mtype->nblock = nblock;
714 /* Vector uses stride in oldtypes */
715 merr = MPI_Type_vector(nblock, blocklen, stride, oldtype, &mtype->datatype);
717 MTestPrintError(merr);
718 merr = MPI_Type_commit(&mtype->datatype);
720 MTestPrintError(merr);
722 memset(type_name, 0, sizeof(type_name));
723 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride)", typename_prefix, "vector",
724 nblock, blocklen, stride);
725 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
727 MTestPrintError(merr);
729 mtype->InitBuf = MTestTypeVectorInit;
730 mtype->FreeBuf = MTestTypeFree;
731 mtype->CheckBuf = MTestTypeVectorCheckbuf;
736 * Setup hvector type info and handlers.
738 * A hvector datatype is created by using following parameters.
739 * nblock: Number of blocks.
740 * blocklen: Number of elements in each block.
741 * stride: Strided number of elements between blocks.
742 * lb: Lower bound of the new datatype (ignored).
743 * oldtype: Datatype of element.
745 static int MTestTypeHvectorCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride, MPI_Aint lb,
746 MPI_Datatype oldtype, const char *typename_prefix,
747 MTestDatatype * mtype)
752 MTestTypeReset(mtype);
754 merr = MPI_Type_size(oldtype, &mtype->basesize);
756 MTestPrintError(merr);
758 /* These sizes are in bytes (see the VectorInit code) */
759 mtype->stride = stride * mtype->basesize;
760 mtype->blksize = blocklen * mtype->basesize;
761 mtype->nblock = nblock;
763 /* Hvector uses stride in bytes */
764 merr = MPI_Type_create_hvector(nblock, blocklen, mtype->stride, oldtype, &mtype->datatype);
766 MTestPrintError(merr);
767 merr = MPI_Type_commit(&mtype->datatype);
769 MTestPrintError(merr);
771 memset(type_name, 0, sizeof(type_name));
772 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride)", typename_prefix, "hvector",
773 nblock, blocklen, stride);
774 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
776 MTestPrintError(merr);
778 /* User the same functions as vector, because mtype->stride is in bytes */
779 mtype->InitBuf = MTestTypeVectorInit;
780 mtype->FreeBuf = MTestTypeFree;
781 mtype->CheckBuf = MTestTypeVectorCheckbuf;
787 * Setup indexed type info and handlers.
789 * A indexed datatype is created by using following parameters.
790 * nblock: Number of blocks.
791 * blocklen: Number of elements in each block. Each block has the same length.
792 * stride: Strided number of elements between two adjacent blocks. The
793 * displacement of each block is set as (index of current block * stride).
794 * lb: Lower bound of the new datatype.
795 * oldtype: Datatype of element.
797 static int MTestTypeIndexedCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride, MPI_Aint lb,
798 MPI_Datatype oldtype, const char *typename_prefix,
799 MTestDatatype * mtype)
805 MTestTypeReset(mtype);
807 merr = MPI_Type_size(oldtype, &mtype->basesize);
809 MTestPrintError(merr);
811 mtype->displs = (int *) malloc(nblock * sizeof(int));
812 mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
813 mtype->index = (int *) malloc(nblock * sizeof(int));
814 if (!mtype->displs || !mtype->displ_in_bytes || !mtype->index) {
815 char errmsg[128] = { 0 };
816 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
820 mtype->nblock = nblock;
821 for (i = 0; i < nblock; i++) {
822 mtype->index[i] = blocklen;
823 mtype->displs[i] = lb + stride * i; /*stride between the start of two blocks */
824 mtype->displ_in_bytes[i] = (lb + stride * i) * mtype->basesize;
827 /* Indexed uses displacement in oldtypes */
828 merr = MPI_Type_indexed(nblock, mtype->index, mtype->displs, oldtype, &mtype->datatype);
830 MTestPrintError(merr);
831 merr = MPI_Type_commit(&mtype->datatype);
833 MTestPrintError(merr);
835 memset(type_name, 0, sizeof(type_name));
836 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride %zd lb)", typename_prefix,
837 "index", nblock, blocklen, stride, lb);
838 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
840 MTestPrintError(merr);
842 mtype->InitBuf = MTestTypeIndexedInit;
843 mtype->FreeBuf = MTestTypeFree;
844 mtype->CheckBuf = MTestTypeIndexedCheckbuf;
850 * Setup hindexed type info and handlers.
852 * A hindexed datatype is created by using following parameters.
853 * nblock: Number of blocks.
854 * blocklen: Number of elements in each block. Each block has the same length.
855 * stride: Strided number of elements between two adjacent blocks. The byte
856 * displacement of each block is set as (index of current block * stride * size of oldtype).
857 * lb: Lower bound of the new datatype.
858 * oldtype: Datatype of element.
860 static inline int MTestTypeHindexedCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride,
861 MPI_Aint lb, MPI_Datatype oldtype,
862 const char *typename_prefix, MTestDatatype * mtype)
868 MTestTypeReset(mtype);
870 merr = MPI_Type_size(oldtype, &mtype->basesize);
872 MTestPrintError(merr);
874 mtype->index = (int *) malloc(nblock * sizeof(int));
875 mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
876 if (!mtype->displ_in_bytes || !mtype->index) {
877 char errmsg[128] = { 0 };
878 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
882 mtype->nblock = nblock;
883 for (i = 0; i < nblock; i++) {
884 mtype->index[i] = blocklen;
885 mtype->displ_in_bytes[i] = (lb + stride * i) * mtype->basesize;
888 /* Hindexed uses displacement in bytes */
889 merr = MPI_Type_create_hindexed(nblock, mtype->index, mtype->displ_in_bytes,
890 oldtype, &mtype->datatype);
892 MTestPrintError(merr);
893 merr = MPI_Type_commit(&mtype->datatype);
895 MTestPrintError(merr);
897 memset(type_name, 0, sizeof(type_name));
898 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride %zd lb)", typename_prefix,
899 "hindex", nblock, blocklen, stride, lb);
900 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
902 MTestPrintError(merr);
904 /* Reuse indexed functions, because all of them only use displ_in_bytes */
905 mtype->InitBuf = MTestTypeIndexedInit;
906 mtype->FreeBuf = MTestTypeFree;
907 mtype->CheckBuf = MTestTypeIndexedCheckbuf;
914 * Setup indexed-block type info and handlers.
916 * A indexed-block datatype is created by using following parameters.
917 * nblock: Number of blocks.
918 * blocklen: Number of elements in each block.
919 * stride: Strided number of elements between two adjacent blocks. The
920 * displacement of each block is set as (index of current block * stride).
921 * lb: Lower bound of the new datatype.
922 * oldtype: Datatype of element.
924 static int MTestTypeIndexedBlockCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride,
925 MPI_Aint lb, MPI_Datatype oldtype,
926 const char *typename_prefix, MTestDatatype * mtype)
932 MTestTypeReset(mtype);
934 merr = MPI_Type_size(oldtype, &mtype->basesize);
936 MTestPrintError(merr);
938 mtype->displs = (int *) malloc(nblock * sizeof(int));
939 mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
940 if (!mtype->displs || !mtype->displ_in_bytes) {
941 char errmsg[128] = { 0 };
942 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
946 mtype->nblock = nblock;
947 mtype->blksize = blocklen * mtype->basesize;
948 for (i = 0; i < nblock; i++) {
949 mtype->displs[i] = lb + stride * i;
950 mtype->displ_in_bytes[i] = (lb + stride * i) * mtype->basesize;
953 /* Indexed-block uses displacement in oldtypes */
954 merr = MPI_Type_create_indexed_block(nblock, blocklen, mtype->displs,
955 oldtype, &mtype->datatype);
957 MTestPrintError(merr);
958 merr = MPI_Type_commit(&mtype->datatype);
960 MTestPrintError(merr);
962 memset(type_name, 0, sizeof(type_name));
963 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride %zd lb)", typename_prefix,
964 "index_block", nblock, blocklen, stride, lb);
965 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
967 MTestPrintError(merr);
969 mtype->InitBuf = MTestTypeIndexedBlockInit;
970 mtype->FreeBuf = MTestTypeFree;
971 mtype->CheckBuf = MTestTypeIndexedBlockCheckbuf;
977 * Setup hindexed-block type info and handlers.
979 * A hindexed-block datatype is created by using following parameters.
980 * nblock: Number of blocks.
981 * blocklen: Number of elements in each block.
982 * stride: Strided number of elements between two adjacent blocks. The byte
983 * displacement of each block is set as (index of current block * stride * size of oldtype).
984 * lb: Lower bound of the new datatype.
985 * oldtype: Datatype of element.
987 static int MTestTypeHindexedBlockCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride,
988 MPI_Aint lb, MPI_Datatype oldtype,
989 const char *typename_prefix, MTestDatatype * mtype)
995 MTestTypeReset(mtype);
997 merr = MPI_Type_size(oldtype, &mtype->basesize);
999 MTestPrintError(merr);
1001 mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
1002 if (!mtype->displ_in_bytes) {
1003 char errmsg[128] = { 0 };
1004 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
1008 mtype->nblock = nblock;
1009 mtype->blksize = blocklen * mtype->basesize;
1010 for (i = 0; i < nblock; i++) {
1011 mtype->displ_in_bytes[i] = (lb + stride * i) * mtype->basesize;
1014 /* Hindexed-block uses displacement in bytes */
1015 merr = MPI_Type_create_hindexed_block(nblock, blocklen, mtype->displ_in_bytes,
1016 oldtype, &mtype->datatype);
1018 MTestPrintError(merr);
1019 merr = MPI_Type_commit(&mtype->datatype);
1021 MTestPrintError(merr);
1023 memset(type_name, 0, sizeof(type_name));
1024 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride %zd lb)", typename_prefix,
1025 "hindex_block", nblock, blocklen, stride, lb);
1026 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
1028 MTestPrintError(merr);
1030 /* Reuse indexed-block functions, because all of them only use displ_in_bytes */
1031 mtype->InitBuf = MTestTypeIndexedBlockInit;
1032 mtype->FreeBuf = MTestTypeFree;
1033 mtype->CheckBuf = MTestTypeIndexedBlockCheckbuf;
1039 * Setup struct type info and handlers.
1041 * A struct datatype is created by using following parameters.
1042 * nblock: Number of blocks.
1043 * blocklen: Number of elements in each block. Each block has the same length.
1044 * stride: Strided number of elements between two adjacent blocks. The byte
1045 * displacement of each block is set as (index of current block * stride * size of oldtype).
1046 * lb: Lower bound of the new datatype.
1047 * oldtype: Datatype of element. Each block has the same oldtype.
1049 static int MTestTypeStructCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride, MPI_Aint lb,
1050 MPI_Datatype oldtype, const char *typename_prefix,
1051 MTestDatatype * mtype)
1054 char type_name[128];
1057 MTestTypeReset(mtype);
1059 merr = MPI_Type_size(oldtype, &mtype->basesize);
1061 MTestPrintError(merr);
1063 mtype->old_datatypes = (MPI_Datatype *) malloc(nblock * sizeof(MPI_Datatype));
1064 mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
1065 mtype->index = (int *) malloc(nblock * sizeof(int));
1066 if (!mtype->displ_in_bytes || !mtype->old_datatypes) {
1067 char errmsg[128] = { 0 };
1068 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
1072 mtype->nblock = nblock;
1073 mtype->blksize = blocklen * mtype->basesize;
1074 for (i = 0; i < nblock; i++) {
1075 mtype->displ_in_bytes[i] = (lb + stride * i) * mtype->basesize;
1076 mtype->old_datatypes[i] = oldtype;
1077 mtype->index[i] = blocklen;
1080 /* Struct uses displacement in bytes */
1081 merr = MPI_Type_create_struct(nblock, mtype->index, mtype->displ_in_bytes,
1082 mtype->old_datatypes, &mtype->datatype);
1084 MTestPrintError(merr);
1085 merr = MPI_Type_commit(&mtype->datatype);
1087 MTestPrintError(merr);
1089 memset(type_name, 0, sizeof(type_name));
1090 sprintf(type_name, "%s %s (%zd nblock %zd blocklen %zd stride %zd lb)", typename_prefix,
1091 "struct", nblock, blocklen, stride, lb);
1092 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
1094 MTestPrintError(merr);
1096 /* Reuse indexed functions, because they use the same displ_in_bytes and index */
1097 mtype->InitBuf = MTestTypeIndexedInit;
1098 mtype->FreeBuf = MTestTypeFree;
1099 mtype->CheckBuf = MTestTypeIndexedCheckbuf;
1105 * Setup order-C subarray type info and handlers.
1107 * A 2D-subarray datatype specified with order C and located in the right-bottom
1108 * of the full array is created by using input parameters.
1109 * Number of elements in the dimensions of the full array: {nblock + lb, stride}
1110 * Number of elements in the dimensions of the subarray: {nblock, blocklen}
1111 * Starting of the subarray in each dimension: {1, stride - blocklen}
1112 * order: MPI_ORDER_C
1115 static int MTestTypeSubArrayOrderCCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride,
1116 MPI_Aint lb, MPI_Datatype oldtype,
1117 const char *typename_prefix, MTestDatatype * mtype)
1120 char type_name[128];
1122 MTestTypeReset(mtype);
1124 merr = MPI_Type_size(oldtype, &mtype->basesize);
1126 MTestPrintError(merr);
1128 mtype->arr_sizes[0] = nblock + lb; /* {row, col} */
1129 mtype->arr_sizes[1] = stride;
1130 mtype->arr_subsizes[0] = nblock; /* {row, col} */
1131 mtype->arr_subsizes[1] = blocklen;
1132 mtype->arr_starts[0] = lb; /* {row, col} */
1133 mtype->arr_starts[1] = stride - blocklen;
1134 mtype->order = MPI_ORDER_C;
1136 merr = MPI_Type_create_subarray(2, mtype->arr_sizes, mtype->arr_subsizes, mtype->arr_starts,
1137 mtype->order, oldtype, &mtype->datatype);
1139 MTestPrintError(merr);
1140 merr = MPI_Type_commit(&mtype->datatype);
1142 MTestPrintError(merr);
1144 memset(type_name, 0, sizeof(type_name));
1145 sprintf(type_name, "%s %s (full{%d,%d}, sub{%d,%d},start{%d,%d})",
1146 typename_prefix, "subarray-c", mtype->arr_sizes[0], mtype->arr_sizes[1],
1147 mtype->arr_subsizes[0], mtype->arr_subsizes[1], mtype->arr_starts[0],
1148 mtype->arr_starts[1]);
1149 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
1151 MTestPrintError(merr);
1153 mtype->InitBuf = MTestTypeSubarrayInit;
1154 mtype->FreeBuf = MTestTypeFree;
1155 mtype->CheckBuf = MTestTypeSubarrayCheckbuf;
1162 * Setup order-Fortran subarray type info and handlers.
1164 * A 2D-subarray datatype specified with order Fortran and located in the right
1165 * bottom of the full array is created by using input parameters.
1166 * Number of elements in the dimensions of the full array: {stride, nblock + lb}
1167 * Number of elements in the dimensions of the subarray: {blocklen, nblock}
1168 * Starting of the subarray in each dimension: {stride - blocklen, lb}
1169 * order: MPI_ORDER_FORTRAN
1172 static int MTestTypeSubArrayOrderFortranCreate(MPI_Aint nblock, MPI_Aint blocklen, MPI_Aint stride,
1173 MPI_Aint lb, MPI_Datatype oldtype,
1174 const char *typename_prefix, MTestDatatype * mtype)
1177 char type_name[128];
1179 MTestTypeReset(mtype);
1181 merr = MPI_Type_size(oldtype, &mtype->basesize);
1183 MTestPrintError(merr);
1185 /* use the same row and col as that of order-c subarray for buffer
1186 * initialization and check because we access buffer in order-c */
1187 mtype->arr_sizes[0] = nblock + lb; /* {row, col} */
1188 mtype->arr_sizes[1] = stride;
1189 mtype->arr_subsizes[0] = nblock; /* {row, col} */
1190 mtype->arr_subsizes[1] = blocklen;
1191 mtype->arr_starts[0] = lb; /* {row, col} */
1192 mtype->arr_starts[1] = stride - blocklen;
1193 mtype->order = MPI_ORDER_FORTRAN;
1195 /* reverse row and col when create datatype so that we can get the same
1196 * packed data on the other side in order to reuse the contig check function */
1197 int arr_sizes[2] = { mtype->arr_sizes[1], mtype->arr_sizes[0] };
1198 int arr_subsizes[2] = { mtype->arr_subsizes[1], mtype->arr_subsizes[0] };
1199 int arr_starts[2] = { mtype->arr_starts[1], mtype->arr_starts[0] };
1201 merr = MPI_Type_create_subarray(2, arr_sizes, arr_subsizes, arr_starts,
1202 mtype->order, oldtype, &mtype->datatype);
1204 MTestPrintError(merr);
1205 merr = MPI_Type_commit(&mtype->datatype);
1207 MTestPrintError(merr);
1209 memset(type_name, 0, sizeof(type_name));
1210 sprintf(type_name, "%s %s (full{%d,%d}, sub{%d,%d},start{%d,%d})",
1211 typename_prefix, "subarray-f", arr_sizes[0], arr_sizes[1],
1212 arr_subsizes[0], arr_subsizes[1], arr_starts[0], arr_starts[1]);
1213 merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
1215 MTestPrintError(merr);
1217 mtype->InitBuf = MTestTypeSubarrayInit;
1218 mtype->FreeBuf = MTestTypeFree;
1219 mtype->CheckBuf = MTestTypeSubarrayCheckbuf;
1224 /* ------------------------------------------------------------------------ */
1225 /* Datatype routines exposed to test generator */
1226 /* ------------------------------------------------------------------------ */
1229 * Setup basic type info and handlers.
1231 int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
1235 MTestTypeReset(mtype);
1237 merr = MPI_Type_size(oldtype, &mtype->basesize);
1239 MTestPrintError(merr);
1241 mtype->datatype = oldtype;
1243 mtype->InitBuf = MTestTypeContigInit;
1244 mtype->FreeBuf = MTestTypeFree;
1245 mtype->CheckBuf = MTestTypeContigCheckbuf;
1251 * Setup dup type info and handlers.
1253 * A dup datatype is created by using following parameters.
1254 * oldtype: Datatype of element.
1256 int MTestTypeDupCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
1260 MTestTypeReset(mtype);
1262 merr = MPI_Type_size(oldtype, &mtype->basesize);
1264 MTestPrintError(merr);
1266 merr = MPI_Type_dup(oldtype, &mtype->datatype);
1268 MTestPrintError(merr);
1270 /* dup'ed types are already committed if the original type
1271 * was committed (MPI-2, section 8.8) */
1273 mtype->InitBuf = MTestTypeContigInit;
1274 mtype->FreeBuf = MTestTypeFree;
1275 mtype->CheckBuf = MTestTypeContigCheckbuf;
1282 * General initialization for receive buffer.
1283 * Allocate buffer and initialize for reception (e.g., set initial data to detect failure)
1284 * Both basic and derived datatype can be handled by using extent as buffer size.
1286 void *MTestTypeInitRecv(MTestDatatype * mtype)
1288 MPI_Aint size, extent = 0, lb = 0;
1291 if (mtype->count > 0) {
1293 MPI_Aint i, totsize;
1294 merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
1296 MTestPrintError(merr);
1299 totsize = size * mtype->count;
1301 mtype->buf = (void *) malloc(totsize);
1303 p = (signed char *) (mtype->buf);
1305 char errmsg[128] = { 0 };
1306 sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
1309 for (i = 0; i < totsize; i++) {
1322 void MTestTypeCreatorInit(MTestDdtCreator * creators)
1324 memset(creators, 0, sizeof(MTestDdtCreator) * MTEST_DDT_MAX);
1325 creators[MTEST_DDT_CONTIGUOUS] = MTestTypeContiguousCreate;
1326 creators[MTEST_DDT_VECTOR] = MTestTypeVectorCreate;
1327 creators[MTEST_DDT_HVECTOR] = MTestTypeHvectorCreate;
1328 creators[MTEST_DDT_INDEXED] = MTestTypeIndexedCreate;
1329 creators[MTEST_DDT_HINDEXED] = MTestTypeHindexedCreate;
1330 creators[MTEST_DDT_INDEXED_BLOCK] = MTestTypeIndexedBlockCreate;
1331 creators[MTEST_DDT_HINDEXED_BLOCK] = MTestTypeHindexedBlockCreate;
1332 creators[MTEST_DDT_STRUCT] = MTestTypeStructCreate;
1333 /* creators[MTEST_DDT_SUBARRAY_ORDER_C] = MTestTypeSubArrayOrderCCreate;*/
1334 /* creators[MTEST_DDT_SUBARRAY_ORDER_FORTRAN] = MTestTypeSubArrayOrderFortranCreate;*/
1337 void MTestTypeMinCreatorInit(MTestDdtCreator * creators)
1339 memset(creators, 0, sizeof(MTestDdtCreator) * MTEST_DDT_MAX);
1340 creators[MTEST_MIN_DDT_VECTOR] = MTestTypeVectorCreate;
1341 creators[MTEST_MIN_DDT_INDEXED] = MTestTypeIndexedCreate;