Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use standard __func__ instead of __FUNCTION__.
[simgrid.git] / teshsuite / smpi / mpich3-test / util / mtest_datatype.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2014 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 #include "mtest_datatype.h"
8 #if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
9 #include <stdio.h>
10 #endif
11 #if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
12 #include <stdlib.h>
13 #endif
14 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
15 #include <string.h>
16 #endif
17 #ifdef HAVE_STDARG_H
18 #include <stdarg.h>
19 #endif
20 /* The following two includes permit the collection of resource usage
21    data in the tests
22  */
23 #ifdef HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif
26 #ifdef HAVE_SYS_RESOURCE_H
27 #include <sys/resource.h>
28 #endif
29 #include <errno.h>
30
31
32 /* ------------------------------------------------------------------------ */
33 /* General datatype routines                        */
34 /* ------------------------------------------------------------------------ */
35
36 static void *MTestTypeFree(MTestDatatype * mtype)
37 {
38     if (mtype->buf)
39         free(mtype->buf);
40     if (mtype->displs)
41         free(mtype->displs);
42     if (mtype->displ_in_bytes)
43         free(mtype->displ_in_bytes);
44     if (mtype->index)
45         free(mtype->index);
46     if (mtype->old_datatypes)
47         free(mtype->old_datatypes);
48     mtype->buf = NULL;
49     mtype->displs = NULL;
50     mtype->displ_in_bytes = NULL;
51     mtype->index = NULL;
52     mtype->old_datatypes = NULL;
53
54     return 0;
55 }
56
57 static inline void MTestTypeReset(MTestDatatype * mtype)
58 {
59     mtype->isBasic = 0;
60     mtype->printErrors = 0;
61     mtype->buf = NULL;
62
63     mtype->datatype = MPI_DATATYPE_NULL;
64     mtype->count = 0;
65     mtype->nblock = 0;
66     mtype->index = NULL;
67
68     mtype->stride = 0;
69     mtype->blksize = 0;
70     mtype->displ_in_bytes = NULL;
71
72     mtype->displs = NULL;
73     mtype->basesize = 0;
74
75     mtype->old_datatypes = NULL;
76
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;
83     mtype->order = 0;
84
85     mtype->InitBuf = NULL;
86     mtype->FreeBuf = NULL;
87     mtype->CheckBuf = NULL;
88 }
89
90 /* ------------------------------------------------------------------------ */
91 /* Datatype routines for contiguous datatypes                               */
92 /* ------------------------------------------------------------------------ */
93 /*
94  * Initialize buffer of basic datatype
95  */
96 static void *MTestTypeContigInit(MTestDatatype * mtype)
97 {
98     MPI_Aint extent = 0, lb = 0, size;
99     int merr;
100
101     if (mtype->count > 0) {
102         unsigned char *p;
103         MPI_Aint i, totsize;
104         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
105         if (merr)
106             MTestPrintError(merr);
107
108         size = extent + lb;
109         totsize = size * mtype->count;
110         if (!mtype->buf) {
111             mtype->buf = (void *) malloc(totsize);
112         }
113         p = (unsigned char *) (mtype->buf);
114         if (!p) {
115             char errmsg[128] = { 0 };
116             sprintf(errmsg, "Out of memory in %s", __func__);
117             MTestError(errmsg);
118         }
119         for (i = 0; i < totsize; i++) {
120             p[i] = (unsigned char) (0xff ^ (i & 0xff));
121         }
122     }
123     else {
124         if (mtype->buf) {
125             free(mtype->buf);
126         }
127         mtype->buf = 0;
128     }
129     return mtype->buf;
130 }
131
132 /*
133  * Check value of received basic datatype buffer.
134  */
135 static int MTestTypeContigCheckbuf(MTestDatatype * mtype)
136 {
137     unsigned char *p;
138     unsigned char expected;
139     int err = 0, merr;
140     MPI_Aint i, totsize, size, extent = 0, lb = 0;
141
142     p = (unsigned char *) mtype->buf;
143     if (p) {
144         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
145         if (merr)
146             MTestPrintError(merr);
147
148         size = lb + extent;
149         totsize = size * mtype->count;
150         for (i = 0; i < totsize; i++) {
151             expected = (unsigned char) (0xff ^ (i & 0xff));
152             if (p[i] != expected) {
153                 err++;
154                 if (mtype->printErrors && err < 10) {
155                     printf("Data expected = %x but got p[%zd] = %x\n", expected, i, p[i]);
156                     fflush(stdout);
157                 }
158             }
159         }
160     }
161     return err;
162 }
163
164
165 /* ------------------------------------------------------------------------ */
166 /* Datatype routines for vector datatypes                                   */
167 /* ------------------------------------------------------------------------ */
168
169 /*
170  * Initialize buffer of vector datatype
171  */
172 static void *MTestTypeVectorInit(MTestDatatype * mtype)
173 {
174     MPI_Aint extent = 0, lb = 0, size, totsize, dt_offset, byte_offset;
175     int merr;
176
177     if (mtype->count > 0) {
178         unsigned char *p;
179         MPI_Aint k, j;
180         int i, nc;
181
182         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
183         if (merr)
184             MTestPrintError(merr);
185
186         size = extent + lb;
187         totsize = mtype->count * size;
188         if (!mtype->buf) {
189             mtype->buf = (void *) malloc(totsize);
190         }
191         p = (unsigned char *) (mtype->buf);
192         if (!p) {
193             char errmsg[128] = { 0 };
194             sprintf(errmsg, "Out of memory in %s", __func__);
195             MTestError(errmsg);
196         }
197
198         /* First, set to -1 */
199         for (k = 0; k < totsize; k++)
200             p[k] = 0xff;
201
202         /* Now, set the actual elements to the successive values.
203          * We require that the base type is a contiguous type */
204         nc = 0;
205         dt_offset = 0;
206         /* For each datatype */
207         for (k = 0; k < mtype->count; k++) {
208             /* For each block */
209             for (i = 0; i < mtype->nblock; i++) {
210                 byte_offset = dt_offset + i * mtype->stride;
211                 /* For each byte */
212                 for (j = 0; j < mtype->blksize; j++) {
213                     p[byte_offset + j] = (unsigned char) (0xff ^ (nc & 0xff));
214                     nc++;
215                 }
216             }
217             dt_offset += size;
218         }
219     }
220     else {
221         mtype->buf = 0;
222     }
223     return mtype->buf;
224 }
225
226 /*
227  * Check value of received vector datatype buffer
228  */
229 static int MTestTypeVectorCheckbuf(MTestDatatype * mtype)
230 {
231     unsigned char *p;
232     unsigned char expected;
233     int i, err = 0, merr;
234     MPI_Aint size = 0, byte_offset, dt_offset, extent, lb;
235
236     p = (unsigned char *) mtype->buf;
237     if (p) {
238         MPI_Aint k, j;
239         int nc;
240         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
241         if (merr)
242             MTestPrintError(merr);
243
244         size = extent + lb;
245         nc = 0;
246         dt_offset = 0;
247         /* For each datatype */
248         for (k = 0; k < mtype->count; k++) {
249             /* For each block */
250             for (i = 0; i < mtype->nblock; i++) {
251                 byte_offset = dt_offset + i * mtype->stride;
252                 /* For each byte */
253                 for (j = 0; j < mtype->blksize; j++) {
254                     expected = (unsigned char) (0xff ^ (nc & 0xff));
255                     if (p[byte_offset + j] != expected) {
256                         err++;
257                         if (mtype->printErrors && err < 10) {
258                             printf("Data expected = %x but got p[%d,%zd] = %x\n", expected, i, j,
259                                    p[byte_offset + j]);
260                             fflush(stdout);
261                         }
262                     }
263                     nc++;
264                 }
265             }
266             dt_offset += size;
267         }
268     }
269     return err;
270 }
271
272
273 /* ------------------------------------------------------------------------ */
274 /* Datatype routines for indexed datatypes                            */
275 /* ------------------------------------------------------------------------ */
276
277 /*
278  * Initialize buffer of indexed datatype
279  */
280 static void *MTestTypeIndexedInit(MTestDatatype * mtype)
281 {
282     MPI_Aint extent = 0, lb = 0, size, totsize, dt_offset, offset;
283     int merr;
284
285     if (mtype->count > 0) {
286         unsigned char *p;
287         MPI_Aint k, b;
288         int i, j, nc;
289
290         /* Allocate buffer */
291         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
292         if (merr)
293             MTestPrintError(merr);
294
295         size = extent + lb;
296         totsize = size * mtype->count;
297
298         if (!mtype->buf) {
299             mtype->buf = (void *) malloc(totsize);
300         }
301         p = (unsigned char *) (mtype->buf);
302         if (!p) {
303             char errmsg[128] = { 0 };
304             sprintf(errmsg, "Out of memory in %s", __func__);
305             MTestError(errmsg);
306         }
307
308         /* First, set to -1 */
309         for (k = 0; k < totsize; k++)
310             p[k] = 0xff;
311
312         /* Now, set the actual elements to the successive values.
313          * We require that the base type is a contiguous type */
314         nc = 0;
315         dt_offset = 0;
316         /* For each datatype */
317         for (k = 0; k < mtype->count; k++) {
318             /* For each block */
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));
327                     }
328                 }
329             }
330             dt_offset += size;
331         }
332     }
333     else {
334         /* count == 0 */
335         if (mtype->buf) {
336             free(mtype->buf);
337         }
338         mtype->buf = 0;
339     }
340     return mtype->buf;
341 }
342
343 /*
344  * Check value of received indexed datatype buffer
345  */
346 static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
347 {
348     unsigned char *p;
349     unsigned char expected;
350     int err = 0, merr;
351     MPI_Aint size = 0, offset, dt_offset, extent = 0, lb = 0;
352
353     p = (unsigned char *) mtype->buf;
354     if (p) {
355         MPI_Aint k, b;
356         int i, j, nc;
357         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
358         if (merr)
359             MTestPrintError(merr);
360
361         size = lb + extent;
362         nc = 0;
363         dt_offset = 0;
364         /* For each datatype */
365         for (k = 0; k < mtype->count; k++) {
366             /* For each block */
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) {
376                             err++;
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]);
380                                 fflush(stdout);
381                             }
382                         }
383                     }
384                 }
385             }
386             dt_offset += size;
387         }
388     }
389     return err;
390 }
391
392 /* ------------------------------------------------------------------------ */
393 /* Datatype routines for indexed-block datatypes                            */
394 /* ------------------------------------------------------------------------ */
395
396 /*
397  * Initialize buffer of indexed-block datatype
398  */
399 static void *MTestTypeIndexedBlockInit(MTestDatatype * mtype)
400 {
401     MPI_Aint extent = 0, lb = 0, size, totsize, offset, dt_offset;
402     int merr;
403
404     if (mtype->count > 0) {
405         unsigned char *p;
406         MPI_Aint k, j;
407         int i, nc;
408
409         /* Allocate the send/recv buffer */
410         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
411         if (merr)
412             MTestPrintError(merr);
413         size = extent + lb;
414         totsize = size * mtype->count;
415
416         if (!mtype->buf) {
417             mtype->buf = (void *) malloc(totsize);
418         }
419         p = (unsigned char *) (mtype->buf);
420         if (!p) {
421             char errmsg[128] = { 0 };
422             sprintf(errmsg, "Out of memory in %s", __func__);
423             MTestError(errmsg);
424         }
425
426         /* First, set to -1 */
427         for (k = 0; k < totsize; k++)
428             p[k] = 0xff;
429
430         /* Now, set the actual elements to the successive values.
431          * We require that the base type is a contiguous type */
432         nc = 0;
433         dt_offset = 0;
434         /* For each datatype */
435         for (k = 0; k < mtype->count; k++) {
436             /* For each block */
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));
442                 }
443             }
444             dt_offset += size;
445         }
446     }
447     else {
448         /* count == 0 */
449         if (mtype->buf) {
450             free(mtype->buf);
451         }
452         mtype->buf = 0;
453     }
454     return mtype->buf;
455 }
456
457 /*
458  * Check value of received indexed-block datatype buffer
459  */
460 static int MTestTypeIndexedBlockCheckbuf(MTestDatatype * mtype)
461 {
462     unsigned char *p;
463     unsigned char expected;
464     int err = 0, merr;
465     MPI_Aint size = 0, offset, dt_offset, lb = 0, extent = 0;
466
467     p = (unsigned char *) mtype->buf;
468     if (p) {
469         MPI_Aint j, k;
470         int i, nc;
471         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
472         if (merr)
473             MTestPrintError(merr);
474
475         size = lb + extent;
476         nc = 0;
477         dt_offset = 0;
478         /* For each datatype */
479         for (k = 0; k < mtype->count; k++) {
480             /* For each block */
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) {
487                         err++;
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]);
491                             fflush(stdout);
492                         }
493                     }
494                 }
495             }
496             dt_offset += size;
497         }
498     }
499     return err;
500 }
501
502 /* ------------------------------------------------------------------------ */
503 /* Datatype routines for subarray datatypes with order Fortran              */
504 /* ------------------------------------------------------------------------ */
505
506 /*
507  * Initialize buffer of subarray datatype.
508  */
509 static void *MTestTypeSubarrayInit(MTestDatatype * mtype)
510 {
511     MPI_Aint extent = 0, lb = 0, size, totsize, offset, dt_offset, byte_offset;
512     int merr;
513
514     if (mtype->count > 0) {
515         unsigned char *p;
516         MPI_Aint k;
517         int j, b, i, nc;
518
519         /* Allocate the send/recv buffer */
520         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
521         if (merr)
522             MTestPrintError(merr);
523
524         size = extent + lb;
525         totsize = size * mtype->count;
526
527         if (!mtype->buf) {
528             mtype->buf = (void *) malloc(totsize);
529         }
530         p = (unsigned char *) (mtype->buf);
531         if (!p) {
532             char errmsg[128] = { 0 };
533             sprintf(errmsg, "Out of memory in %s", __func__);
534             MTestError(errmsg);
535         }
536
537         /* First, set to -1 */
538         for (k = 0; k < totsize; k++)
539             p[k] = 0xff;
540
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];
549
550         nc = 0;
551         dt_offset = 0;
552         /* For each datatype */
553         for (k = 0; k < mtype->count; k++) {
554             /* For each row */
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));
563                 }
564             }
565             dt_offset += size;
566         }
567     }
568     else {
569         /* count == 0 */
570         if (mtype->buf) {
571             free(mtype->buf);
572         }
573         mtype->buf = 0;
574     }
575     return mtype->buf;
576 }
577
578 /*
579  * Check value of received subarray datatype buffer
580  */
581 static int MTestTypeSubarrayCheckbuf(MTestDatatype * mtype)
582 {
583     unsigned char *p;
584     unsigned char expected;
585     int err = 0, merr;
586     MPI_Aint size, offset, dt_offset, byte_offset, lb = 0, extent = 0;
587
588     p = (unsigned char *) mtype->buf;
589     if (p) {
590         MPI_Aint k;
591         int j, b, i, nc;
592         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
593         if (merr)
594             MTestPrintError(merr);
595
596         size = lb + extent;
597
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];
604
605         nc = 0;
606         dt_offset = 0;
607         /* For each datatype */
608         for (k = 0; k < mtype->count; k++) {
609             /* For each row */
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) {
619                             err++;
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]);
623                                 fflush(stdout);
624                             }
625                         }
626                     }
627                 }
628             }
629             dt_offset += size;
630         }
631     }
632     if (err)
633       printf("%s error\n", __func__);
634     return err;
635 }
636
637 /* ------------------------------------------------------------------------ */
638 /* Datatype creators                                                        */
639 /* ------------------------------------------------------------------------ */
640
641 /*
642  * Setup contiguous type info and handlers.
643  *
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.
650  */
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)
654 {
655     int merr = 0;
656     char type_name[128];
657
658     MTestTypeReset(mtype);
659
660     merr = MPI_Type_size(oldtype, &mtype->basesize);
661     if (merr)
662         MTestPrintError(merr);
663
664     mtype->nblock = nblock;
665     mtype->blksize = blocklen * mtype->basesize;
666
667     merr = MPI_Type_contiguous(nblock * blocklen, oldtype, &mtype->datatype);
668     if (merr)
669         MTestPrintError(merr);
670     merr = MPI_Type_commit(&mtype->datatype);
671     if (merr)
672         MTestPrintError(merr);
673
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);
677     if (merr)
678         MTestPrintError(merr);
679
680     mtype->InitBuf = MTestTypeContigInit;
681     mtype->FreeBuf = MTestTypeFree;
682     mtype->CheckBuf = MTestTypeContigCheckbuf;
683     return merr;
684 }
685
686 /*
687  * Setup vector type info and handlers.
688  *
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.
695  */
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)
699 {
700     int merr = 0;
701     char type_name[128];
702
703     MTestTypeReset(mtype);
704
705     merr = MPI_Type_size(oldtype, &mtype->basesize);
706     if (merr)
707         MTestPrintError(merr);
708
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;
713
714     /* Vector uses stride in oldtypes */
715     merr = MPI_Type_vector(nblock, blocklen, stride, oldtype, &mtype->datatype);
716     if (merr)
717         MTestPrintError(merr);
718     merr = MPI_Type_commit(&mtype->datatype);
719     if (merr)
720         MTestPrintError(merr);
721
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);
726     if (merr)
727         MTestPrintError(merr);
728
729     mtype->InitBuf = MTestTypeVectorInit;
730     mtype->FreeBuf = MTestTypeFree;
731     mtype->CheckBuf = MTestTypeVectorCheckbuf;
732     return merr;
733 }
734
735 /*
736  * Setup hvector type info and handlers.
737  *
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.
744  */
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)
748 {
749     int merr;
750     char type_name[128];
751
752     MTestTypeReset(mtype);
753
754     merr = MPI_Type_size(oldtype, &mtype->basesize);
755     if (merr)
756         MTestPrintError(merr);
757
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;
762
763     /* Hvector uses stride in bytes */
764     merr = MPI_Type_create_hvector(nblock, blocklen, mtype->stride, oldtype, &mtype->datatype);
765     if (merr)
766         MTestPrintError(merr);
767     merr = MPI_Type_commit(&mtype->datatype);
768     if (merr)
769         MTestPrintError(merr);
770
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);
775     if (merr)
776         MTestPrintError(merr);
777
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;
782
783     return merr;
784 }
785
786 /*
787  * Setup indexed type info and handlers.
788  *
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.
796  */
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)
800 {
801     int merr = 0;
802     char type_name[128];
803     int i;
804
805     MTestTypeReset(mtype);
806
807     merr = MPI_Type_size(oldtype, &mtype->basesize);
808     if (merr)
809         MTestPrintError(merr);
810
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", __func__);
817         MTestError(errmsg);
818     }
819
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;
825     }
826
827     /* Indexed uses displacement in oldtypes */
828     merr = MPI_Type_indexed(nblock, mtype->index, mtype->displs, oldtype, &mtype->datatype);
829     if (merr)
830         MTestPrintError(merr);
831     merr = MPI_Type_commit(&mtype->datatype);
832     if (merr)
833         MTestPrintError(merr);
834
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);
839     if (merr)
840         MTestPrintError(merr);
841
842     mtype->InitBuf = MTestTypeIndexedInit;
843     mtype->FreeBuf = MTestTypeFree;
844     mtype->CheckBuf = MTestTypeIndexedCheckbuf;
845
846     return merr;
847 }
848
849 /*
850  * Setup hindexed type info and handlers.
851  *
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.
859  */
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)
863 {
864     int merr;
865     char type_name[128];
866     int i;
867
868     MTestTypeReset(mtype);
869
870     merr = MPI_Type_size(oldtype, &mtype->basesize);
871     if (merr)
872         MTestPrintError(merr);
873
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", __func__);
879         MTestError(errmsg);
880     }
881
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;
886     }
887
888     /* Hindexed uses displacement in bytes */
889     merr = MPI_Type_create_hindexed(nblock, mtype->index, mtype->displ_in_bytes,
890                                     oldtype, &mtype->datatype);
891     if (merr)
892         MTestPrintError(merr);
893     merr = MPI_Type_commit(&mtype->datatype);
894     if (merr)
895         MTestPrintError(merr);
896
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);
901     if (merr)
902         MTestPrintError(merr);
903
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;
908
909     return merr;
910 }
911
912
913 /*
914  * Setup indexed-block type info and handlers.
915  *
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.
923  */
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)
927 {
928     int merr;
929     char type_name[128];
930     int i;
931
932     MTestTypeReset(mtype);
933
934     merr = MPI_Type_size(oldtype, &mtype->basesize);
935     if (merr)
936         MTestPrintError(merr);
937
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", __func__);
943         MTestError(errmsg);
944     }
945
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;
951     }
952
953     /* Indexed-block uses displacement in oldtypes */
954     merr = MPI_Type_create_indexed_block(nblock, blocklen, mtype->displs,
955                                          oldtype, &mtype->datatype);
956     if (merr)
957         MTestPrintError(merr);
958     merr = MPI_Type_commit(&mtype->datatype);
959     if (merr)
960         MTestPrintError(merr);
961
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);
966     if (merr)
967         MTestPrintError(merr);
968
969     mtype->InitBuf = MTestTypeIndexedBlockInit;
970     mtype->FreeBuf = MTestTypeFree;
971     mtype->CheckBuf = MTestTypeIndexedBlockCheckbuf;
972
973     return merr;
974 }
975
976 /*
977  * Setup hindexed-block type info and handlers.
978  *
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.
986  */
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)
990 {
991     int merr;
992     char type_name[128];
993     int i;
994
995     MTestTypeReset(mtype);
996
997     merr = MPI_Type_size(oldtype, &mtype->basesize);
998     if (merr)
999         MTestPrintError(merr);
1000
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", __func__);
1005         MTestError(errmsg);
1006     }
1007
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;
1012     }
1013
1014     /* Hindexed-block uses displacement in bytes */
1015     merr = MPI_Type_create_hindexed_block(nblock, blocklen, mtype->displ_in_bytes,
1016                                           oldtype, &mtype->datatype);
1017     if (merr)
1018         MTestPrintError(merr);
1019     merr = MPI_Type_commit(&mtype->datatype);
1020     if (merr)
1021         MTestPrintError(merr);
1022
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);
1027     if (merr)
1028         MTestPrintError(merr);
1029
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;
1034
1035     return merr;
1036 }
1037
1038 /*
1039  * Setup struct type info and handlers.
1040  *
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.
1048  */
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)
1052 {
1053     int merr;
1054     char type_name[128];
1055     int i;
1056
1057     MTestTypeReset(mtype);
1058
1059     merr = MPI_Type_size(oldtype, &mtype->basesize);
1060     if (merr)
1061         MTestPrintError(merr);
1062
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", __func__);
1069         MTestError(errmsg);
1070     }
1071
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;
1078     }
1079
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);
1083     if (merr)
1084         MTestPrintError(merr);
1085     merr = MPI_Type_commit(&mtype->datatype);
1086     if (merr)
1087         MTestPrintError(merr);
1088
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);
1093     if (merr)
1094         MTestPrintError(merr);
1095
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;
1100
1101     return merr;
1102 }
1103
1104 /*
1105  * Setup order-C subarray type info and handlers.
1106  *
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
1113  * oldtype: oldtype
1114  */
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)
1118 {
1119     int merr;
1120     char type_name[128];
1121
1122     MTestTypeReset(mtype);
1123
1124     merr = MPI_Type_size(oldtype, &mtype->basesize);
1125     if (merr)
1126         MTestPrintError(merr);
1127
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;
1135
1136     merr = MPI_Type_create_subarray(2, mtype->arr_sizes, mtype->arr_subsizes, mtype->arr_starts,
1137                                     mtype->order, oldtype, &mtype->datatype);
1138     if (merr)
1139         MTestPrintError(merr);
1140     merr = MPI_Type_commit(&mtype->datatype);
1141     if (merr)
1142         MTestPrintError(merr);
1143
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);
1150     if (merr)
1151         MTestPrintError(merr);
1152
1153     mtype->InitBuf = MTestTypeSubarrayInit;
1154     mtype->FreeBuf = MTestTypeFree;
1155     mtype->CheckBuf = MTestTypeSubarrayCheckbuf;
1156
1157     return merr;
1158 }
1159
1160
1161 /*
1162  * Setup order-Fortran subarray type info and handlers.
1163  *
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
1170  * oldtype: oldtype
1171  */
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)
1175 {
1176     int merr;
1177     char type_name[128];
1178
1179     MTestTypeReset(mtype);
1180
1181     merr = MPI_Type_size(oldtype, &mtype->basesize);
1182     if (merr)
1183         MTestPrintError(merr);
1184
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;
1194
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] };
1200
1201     merr = MPI_Type_create_subarray(2, arr_sizes, arr_subsizes, arr_starts,
1202                                     mtype->order, oldtype, &mtype->datatype);
1203     if (merr)
1204         MTestPrintError(merr);
1205     merr = MPI_Type_commit(&mtype->datatype);
1206     if (merr)
1207         MTestPrintError(merr);
1208
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);
1214     if (merr)
1215         MTestPrintError(merr);
1216
1217     mtype->InitBuf = MTestTypeSubarrayInit;
1218     mtype->FreeBuf = MTestTypeFree;
1219     mtype->CheckBuf = MTestTypeSubarrayCheckbuf;
1220
1221     return merr;
1222 }
1223
1224 /* ------------------------------------------------------------------------ */
1225 /* Datatype routines exposed to test generator                             */
1226 /* ------------------------------------------------------------------------ */
1227
1228 /*
1229  * Setup basic type info and handlers.
1230  */
1231 int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
1232 {
1233     int merr = 0;
1234
1235     MTestTypeReset(mtype);
1236
1237     merr = MPI_Type_size(oldtype, &mtype->basesize);
1238     if (merr)
1239         MTestPrintError(merr);
1240
1241     mtype->datatype = oldtype;
1242     mtype->isBasic = 1;
1243     mtype->InitBuf = MTestTypeContigInit;
1244     mtype->FreeBuf = MTestTypeFree;
1245     mtype->CheckBuf = MTestTypeContigCheckbuf;
1246
1247     return merr;
1248 }
1249
1250 /*
1251  * Setup dup type info and handlers.
1252  *
1253  * A dup datatype is created by using following parameters.
1254  * oldtype:  Datatype of element.
1255  */
1256 int MTestTypeDupCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
1257 {
1258     int merr = 0;
1259
1260     MTestTypeReset(mtype);
1261
1262     merr = MPI_Type_size(oldtype, &mtype->basesize);
1263     if (merr)
1264         MTestPrintError(merr);
1265
1266     merr = MPI_Type_dup(oldtype, &mtype->datatype);
1267     if (merr)
1268         MTestPrintError(merr);
1269
1270     /* dup'ed types are already committed if the original type
1271      * was committed (MPI-2, section 8.8) */
1272
1273     mtype->InitBuf = MTestTypeContigInit;
1274     mtype->FreeBuf = MTestTypeFree;
1275     mtype->CheckBuf = MTestTypeContigCheckbuf;
1276
1277     return merr;
1278 }
1279
1280
1281 /*
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.
1285  */
1286 void *MTestTypeInitRecv(MTestDatatype * mtype)
1287 {
1288     MPI_Aint size, extent = 0, lb = 0;
1289     int merr;
1290
1291     if (mtype->count > 0) {
1292         signed char *p;
1293         MPI_Aint i, totsize;
1294         merr = MPI_Type_get_extent(mtype->datatype, &lb, &extent);
1295         if (merr)
1296             MTestPrintError(merr);
1297
1298         size = extent + lb;
1299         totsize = size * mtype->count;
1300         if (!mtype->buf) {
1301             mtype->buf = (void *) malloc(totsize);
1302         }
1303         p = (signed char *) (mtype->buf);
1304         if (!p) {
1305             char errmsg[128] = { 0 };
1306             sprintf(errmsg, "Out of memory in %s", __func__);
1307             MTestError(errmsg);
1308         }
1309         for (i = 0; i < totsize; i++) {
1310             p[i] = 0xff;
1311         }
1312     }
1313     else {
1314         if (mtype->buf) {
1315             free(mtype->buf);
1316         }
1317         mtype->buf = 0;
1318     }
1319     return mtype->buf;
1320 }
1321
1322 void MTestTypeCreatorInit(MTestDdtCreator * creators)
1323 {
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;*/
1335 }
1336
1337 void MTestTypeMinCreatorInit(MTestDdtCreator * creators)
1338 {
1339     memset(creators, 0, sizeof(MTestDdtCreator) * MTEST_DDT_MAX);
1340     creators[MTEST_MIN_DDT_VECTOR] = MTestTypeVectorCreate;
1341     creators[MTEST_MIN_DDT_INDEXED] = MTestTypeIndexedCreate;
1342 }