Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
simplify
[simgrid.git] / teshsuite / smpi / mpich3-test / util / mtest_datatype_gen_manual.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 SMPI_VARINIT_GLOBAL_AND_SET(dbgflag2, int, 0);         /* Flag used for debugging */
32 SMPI_VARINIT_GLOBAL_AND_SET(wrank2, int, -1);  /* World rank */
33 SMPI_VARINIT_GLOBAL_AND_SET(verbose2,int, 0);         /* Message level (0 is none) */
34
35 /*
36  * Utility routines for writing MPI datatype communication tests.
37  *
38  * Both basic and derived datatype are included.
39  * For basic datatypes, every type has a test case that both the send and
40  * receive buffer use the same datatype and count.
41  *
42  *  For derived datatypes:
43  *    All the test cases are defined in this file, and the datatype definitions
44  *    are in file mtest_datatype.c. Each test case will be automatically called
45  *    by every datatype.
46  *
47  *  Test case generation:
48  *    Every datatype tests derived datatype send buffer and
49  *    derived datatype receive buffer separately. Each test contains various sub
50  *    tests for different structures (i.e., different value of count or block
51  *    length). The following four structures are defined:
52  *      L count & S block length & S stride
53  *      S count & L block length & S stride
54  *      L count & S block length & L stride
55  *      S count & L block length & L stride
56  *      S count & L block length & S stride & S lower-bound
57  *      contiguous (stride = block length)
58  *      contiguous (stride = block length) & S lower-bound
59  *
60  *  How to add a new structure for each datatype:
61  *    1. Add structure definition in function MTestDdtStructDefine.
62  *    2. Increase MTEST_DDT_NUM_SUBTESTS
63  *
64  *  Datatype definition:
65  *    Every type is initialized by the creation function stored in
66  *    mtestDdtCreators variable, all of their create/init/check functions are
67  *    defined in file mtest_datatype.c.
68  *
69  *  How to add a new derived datatype:
70  *    1. Add the new datatype in enum MTEST_DERIVED_DT.
71  *    2. Add its create/init/check functions in file mtest_datatype.c
72  *    3. Add its creator function to mtestDdtCreators variable
73  *
74  *  Following three test levels of datatype are defined.
75  *    1. Basic
76  *      All basic datatypes
77  *    2. Minimum
78  *      All basic datatypes | Vector | Indexed
79  *    3. Full
80  *      All basic datatypes | Vector | Hvector | Indexed | Hindexed |
81  *      Indexed-block | Hindexed-block | Subarray with order-C | Subarray with order-Fortran
82  *
83  *  There are two ways to specify the test level of datatype. The second way has
84  *  higher priority (means the value specified by the first way will be overwritten
85  *  by that in the second way).
86  *  1. Specify global test level by setting the MPITEST_DATATYPE_TEST_LEVEL
87  *     environment variable before execution (basic,min,full|full by default).
88  *  2. Initialize a special level for a datatype loop by calling the corresponding
89  *     initialization function before that loop, otherwise the default value specified
90  *     in the first way is used.
91  *    Basic     : MTestInitBasicDatatypes
92  *    Minimum   : MTestInitMinDatatypes
93  *    Full      : MTestInitFullDatatypes
94  */
95
96 SMPI_VARINIT_GLOBAL_AND_SET(datatype_index,int,0);
97
98 /* ------------------------------------------------------------------------ */
99 /* Routine and internal parameters to define the range of datatype tests */
100 /* ------------------------------------------------------------------------ */
101
102 #define MTEST_DDT_NUM_SUBTESTS 7        /* 7 kinds of derived datatype structure */
103 SMPI_VARINIT_GLOBAL_AND_SET( mtestDdtCreators, MTestDdtCreator*,NULL);
104
105 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_BDT_START_IDX, int, -1);
106 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_BDT_NUM_TESTS, int, 0);
107 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_BDT_RANGE, int, 0);
108
109 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_DDT_NUM_TYPES, int, 0);
110 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_SEND_DDT_START_IDX, int, 0);
111 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_SEND_DDT_NUM_TESTS, int, 0);
112 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_SEND_DDT_RANGE, int, 0);
113
114 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_RECV_DDT_START_IDX, int, 0);
115 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_RECV_DDT_NUM_TESTS, int, 0);
116 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_RECV_DDT_RANGE, int, 0);
117
118 enum {
119     MTEST_DATATYPE_TEST_LEVEL_FULL,
120     MTEST_DATATYPE_TEST_LEVEL_MIN,
121     MTEST_DATATYPE_TEST_LEVEL_BASIC
122 };
123
124 /* current datatype test level */
125 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_DATATYPE_TEST_LEVEL,int, MTEST_DATATYPE_TEST_LEVEL_FULL);
126 /* default datatype test level specified by environment variable */
127 SMPI_VARINIT_GLOBAL_AND_SET(MTEST_DATATYPE_TEST_LEVEL_ENV, int, -1);
128 /* default datatype initialization function */
129 static void (*MTestInitDefaultTestFunc) (void) = NULL;
130
131 static void MTestInitDatatypeGen(int basic_dt_num, int derived_dt_num)
132 {
133     SMPI_VARGET_GLOBAL(MTEST_BDT_START_IDX) = 0;
134     SMPI_VARGET_GLOBAL(MTEST_BDT_NUM_TESTS) = basic_dt_num;
135     SMPI_VARGET_GLOBAL(MTEST_BDT_RANGE) = SMPI_VARGET_GLOBAL(MTEST_BDT_START_IDX) + SMPI_VARGET_GLOBAL(MTEST_BDT_NUM_TESTS);
136     SMPI_VARGET_GLOBAL(MTEST_DDT_NUM_TYPES) = derived_dt_num;
137     SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_START_IDX) = SMPI_VARGET_GLOBAL(MTEST_BDT_NUM_TESTS);
138     SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_NUM_TESTS) = SMPI_VARGET_GLOBAL(MTEST_DDT_NUM_TYPES) * MTEST_DDT_NUM_SUBTESTS;
139     SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_RANGE) = SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_START_IDX) + SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_NUM_TESTS);
140     SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_START_IDX) = SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_START_IDX) + SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_NUM_TESTS);
141     SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_NUM_TESTS) = SMPI_VARGET_GLOBAL(MTEST_DDT_NUM_TYPES) * MTEST_DDT_NUM_SUBTESTS;
142     SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_RANGE) = SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_START_IDX) + SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_NUM_TESTS);
143 }
144
145 static int MTestIsDatatypeGenInited()
146 {
147     return (SMPI_VARGET_GLOBAL(MTEST_BDT_START_IDX) < 0) ? 0 : 1;
148 }
149
150 static void MTestPrintDatatypeGen()
151 {
152     MTestPrintfMsg(1, "MTest datatype test level : %s. %d basic datatype tests, "
153                    "%d derived datatype tests will be generated\n",
154                    (SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL) == MTEST_DATATYPE_TEST_LEVEL_FULL) ? "FULL" : "MIN",
155                    SMPI_VARGET_GLOBAL(MTEST_BDT_NUM_TESTS), SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_NUM_TESTS) + SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_NUM_TESTS));
156 }
157
158 static void MTestResetDatatypeGen()
159 {
160     SMPI_VARGET_GLOBAL(MTEST_BDT_START_IDX) = -1;
161 }
162
163 void MTestInitFullDatatypes(void)
164 {
165     if(SMPI_VARGET_GLOBAL(mtestDdtCreators)==NULL)
166       SMPI_VARGET_GLOBAL(mtestDdtCreators)= (MTestDdtCreator*)malloc(sizeof(MTestDdtCreator)*MTEST_DDT_MAX);
167     /* Do not allow to change datatype test level during loop.
168      * Otherwise indexes will be wrong.
169      * Test must explicitly call reset or wait for current datatype loop being
170      * done before changing to another test level. */
171     if (!MTestIsDatatypeGenInited()) {
172         SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL) = MTEST_DATATYPE_TEST_LEVEL_FULL;
173         MTestTypeCreatorInit((MTestDdtCreator *) SMPI_VARGET_GLOBAL(mtestDdtCreators));
174         MTestInitDatatypeGen(MTEST_BDT_MAX, MTEST_DDT_MAX);
175     }
176     else {
177         printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
178     }
179 }
180
181 void MTestInitMinDatatypes(void)
182 {
183     if(SMPI_VARGET_GLOBAL(mtestDdtCreators)==NULL)
184       SMPI_VARGET_GLOBAL(mtestDdtCreators)= (MTestDdtCreator*)malloc(sizeof(MTestDdtCreator)*MTEST_DDT_MAX);
185     /* Do not allow to change datatype test level during loop.
186      * Otherwise indexes will be wrong.
187      * Test must explicitly call reset or wait for current datatype loop being
188      * done before changing to another test level. */
189     if (!MTestIsDatatypeGenInited()) {
190         SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL) = MTEST_DATATYPE_TEST_LEVEL_MIN;
191         MTestTypeMinCreatorInit((MTestDdtCreator *) SMPI_VARGET_GLOBAL(mtestDdtCreators));
192         MTestInitDatatypeGen(MTEST_BDT_MAX, MTEST_MIN_DDT_MAX);
193     }
194     else {
195         printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
196     }
197 }
198
199 void MTestInitBasicDatatypes(void)
200 {
201     if(SMPI_VARGET_GLOBAL(mtestDdtCreators)==NULL)
202       SMPI_VARGET_GLOBAL(mtestDdtCreators)= (MTestDdtCreator*)malloc(sizeof(MTestDdtCreator)*MTEST_DDT_MAX);
203     /* Do not allow to change datatype test level during loop.
204      * Otherwise indexes will be wrong.
205      * Test must explicitly call reset or wait for current datatype loop being
206      * done before changing to another test level. */
207     if (!MTestIsDatatypeGenInited()) {
208         SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL) = MTEST_DATATYPE_TEST_LEVEL_BASIC;
209         MTestInitDatatypeGen(MTEST_BDT_MAX, 0);
210     }
211     else {
212         printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
213     }
214 }
215
216 static inline void MTestInitDatatypeEnv()
217 {
218     char *envval = 0;
219
220     /* Read global test level specified by user environment variable.
221      * Only initialize once at the first time that test calls datatype routine. */
222     if (SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL_ENV) > -1)
223         return;
224
225     /* default full */
226     SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL_ENV) = MTEST_DATATYPE_TEST_LEVEL_FULL;
227     MTestInitDefaultTestFunc = MTestInitFullDatatypes;
228
229     envval = getenv("MPITEST_DATATYPE_TEST_LEVEL");
230     if (envval && strlen(envval)) {
231         if (!strncmp(envval, "min", strlen("min"))) {
232             SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL_ENV) = MTEST_DATATYPE_TEST_LEVEL_MIN;
233             MTestInitDefaultTestFunc = MTestInitMinDatatypes;
234         }
235         else if (!strncmp(envval, "basic", strlen("basic"))) {
236             SMPI_VARGET_GLOBAL(MTEST_DATATYPE_TEST_LEVEL_ENV) = MTEST_DATATYPE_TEST_LEVEL_BASIC;
237             MTestInitDefaultTestFunc = MTestInitBasicDatatypes;
238         }
239         else if (strncmp(envval, "full", strlen("full"))) {
240             fprintf(stderr, "Unknown MPITEST_DATATYPE_TEST_LEVEL %s\n", envval);
241         }
242     }
243 }
244
245 /* -------------------------------------------------------------------------------*/
246 /* Routine to define various sets of blocklen/count/stride for derived datatypes. */
247 /* ------------------------------------------------------------------------------ */
248
249 static inline int MTestDdtStructDefine(int ddt_index, MPI_Aint tot_count, MPI_Aint * count,
250                                        MPI_Aint * blen, MPI_Aint * stride,
251                                        MPI_Aint * align_tot_count, MPI_Aint * lb)
252 {
253     int merr = 0;
254     int ddt_c_st;
255     MPI_Aint _short = 0, _align_tot_count = 0, _count = 0, _blen = 0, _stride = 0;
256     MPI_Aint _lb = 0;
257
258     ddt_c_st = ddt_index % MTEST_DDT_NUM_SUBTESTS;
259
260     /* Get short value according to user specified tot_count.
261      * It is used as count for large-block-length structure, or block length
262      * for large-count structure. */
263     if (tot_count < 2) {
264         _short = 1;
265     }
266     else if (tot_count < 64) {
267         _short = 2;
268     }
269     else {
270         _short = 64;
271     }
272     _align_tot_count = (tot_count + _short - 1) & ~(_short - 1);
273
274     switch (ddt_c_st) {
275     case 0:
276         /* Large block length. */
277         _count = _short;
278         _blen = _align_tot_count / _short;
279         _stride = _blen * 2;
280         break;
281     case 1:
282         /* Large count */
283         _count = _align_tot_count / _short;
284         _blen = _short;
285         _stride = _blen * 2;
286         break;
287     case 2:
288         /* Large block length and large stride */
289         _count = _short;
290         _blen = _align_tot_count / _short;
291         _stride = _blen * 10;
292         break;
293     case 3:
294         /* Large count and large stride */
295         _count = _align_tot_count / _short;
296         _blen = _short;
297         _stride = _blen * 10;
298         break;
299     case 4:
300         /* Large block length with lb */
301         _count = _short;
302         _blen = _align_tot_count / _short;
303         _stride = _blen * 2;
304         _lb = _short / 2;       /* make sure lb < blen */
305         break;
306     case 5:
307         /* Contig ddt (stride = block length) without lb */
308         _count = _align_tot_count / _short;
309         _blen = _short;
310         _stride = _blen;
311         break;
312     case 6:
313         /* Contig ddt (stride = block length) with lb */
314         _count = _short;
315         _blen = _align_tot_count / _short;
316         _stride = _blen;
317         _lb = _short / 2;       /* make sure lb < blen */
318         break;
319     default:
320         /* Undefined index */
321         merr = 1;
322         break;
323     }
324
325     *align_tot_count = _align_tot_count;
326     *count = _count;
327     *blen = _blen;
328     *stride = _stride;
329     *lb = _lb;
330
331     return merr;
332 }
333
334 /* ------------------------------------------------------------------------ */
335 /* Routine to generate basic datatypes                                       */
336 /* ------------------------------------------------------------------------ */
337
338 static inline int MTestGetBasicDatatypes(MTestDatatype * sendtype,
339                                          MTestDatatype * recvtype, MPI_Aint tot_count)
340 {
341     int merr = 0;
342     int bdt_index = SMPI_VARGET_GLOBAL(datatype_index) - SMPI_VARGET_GLOBAL(MTEST_BDT_START_IDX);
343     if (bdt_index >= MTEST_BDT_MAX) {
344       printf("Wrong index:  global %d, bst %d in %s\n", SMPI_VARGET_GLOBAL(datatype_index), bdt_index, __func__);
345       merr++;
346       return merr;
347     }
348
349     switch (bdt_index) {
350     case MTEST_BDT_INT:
351         merr = MTestTypeBasicCreate(MPI_INT, sendtype);
352         merr = MTestTypeBasicCreate(MPI_INT, recvtype);
353         break;
354     case MTEST_BDT_DOUBLE:
355         merr = MTestTypeBasicCreate(MPI_DOUBLE, sendtype);
356         merr = MTestTypeBasicCreate(MPI_DOUBLE, recvtype);
357         break;
358     case MTEST_BDT_FLOAT_INT:
359         merr = MTestTypeBasicCreate(MPI_FLOAT_INT, sendtype);
360         merr = MTestTypeBasicCreate(MPI_FLOAT_INT, recvtype);
361         break;
362     case MTEST_BDT_SHORT:
363         merr = MTestTypeBasicCreate(MPI_SHORT, sendtype);
364         merr = MTestTypeBasicCreate(MPI_SHORT, recvtype);
365         break;
366     case MTEST_BDT_LONG:
367         merr = MTestTypeBasicCreate(MPI_LONG, sendtype);
368         merr = MTestTypeBasicCreate(MPI_LONG, recvtype);
369         break;
370     case MTEST_BDT_CHAR:
371         merr = MTestTypeBasicCreate(MPI_CHAR, sendtype);
372         merr = MTestTypeBasicCreate(MPI_CHAR, recvtype);
373         break;
374     case MTEST_BDT_UINT64_T:
375         merr = MTestTypeBasicCreate(MPI_UINT64_T, sendtype);
376         merr = MTestTypeBasicCreate(MPI_UINT64_T, recvtype);
377         break;
378     case MTEST_BDT_FLOAT:
379         merr = MTestTypeBasicCreate(MPI_FLOAT, sendtype);
380         merr = MTestTypeBasicCreate(MPI_FLOAT, recvtype);
381         break;
382     case MTEST_BDT_BYTE:
383         merr = MTestTypeBasicCreate(MPI_BYTE, sendtype);
384         merr = MTestTypeBasicCreate(MPI_BYTE, recvtype);
385         break;
386     }
387     sendtype->count = tot_count;
388     recvtype->count = tot_count;
389
390     return merr;
391 }
392
393 /* ------------------------------------------------------------------------ */
394 /* Routine to generate send/receive derived datatypes                     */
395 /* ------------------------------------------------------------------------ */
396
397 static inline int MTestGetSendDerivedDatatypes(MTestDatatype * sendtype,
398                                                MTestDatatype * recvtype, MPI_Aint tot_count)
399 {
400     int merr = 0;
401     int ddt_datatype_index, ddt_c_dt;
402     MPI_Aint blen, stride, count, align_tot_count, lb;
403     MPI_Datatype old_type = MPI_DOUBLE;
404
405     /* Check index */
406     ddt_datatype_index = SMPI_VARGET_GLOBAL(datatype_index) - SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_START_IDX);
407     ddt_c_dt = ddt_datatype_index / MTEST_DDT_NUM_SUBTESTS;
408     if (ddt_c_dt >= MTEST_DDT_MAX || !SMPI_VARGET_GLOBAL(mtestDdtCreators)[ddt_c_dt]) {
409       printf("Wrong index:  global %d, send %d send-ddt %d, or undefined creator in %s\n",
410              SMPI_VARGET_GLOBAL(datatype_index), ddt_datatype_index, ddt_c_dt, __func__);
411       merr++;
412       return merr;
413     }
414
415     /* Set datatype structure */
416     merr = MTestDdtStructDefine(ddt_datatype_index, tot_count, &count, &blen,
417                                 &stride, &align_tot_count, &lb);
418     if (merr) {
419       printf("Wrong index:  global %d, send %d send-ddt %d, or undefined ddt structure in %s\n",
420              SMPI_VARGET_GLOBAL(datatype_index), ddt_datatype_index, ddt_c_dt, __func__);
421       merr++;
422       return merr;
423     }
424
425     /* Create send datatype */
426     merr = SMPI_VARGET_GLOBAL(mtestDdtCreators)[ddt_c_dt] (count, blen, stride, lb, old_type, "send", sendtype);
427     if (merr)
428         return merr;
429
430     sendtype->count = 1;
431
432     /* Create receive datatype */
433     merr = MTestTypeBasicCreate(old_type, recvtype);
434     if (merr)
435         return merr;
436
437     recvtype->count = sendtype->count * align_tot_count;
438
439     return merr;
440 }
441
442 static inline int MTestGetRecvDerivedDatatypes(MTestDatatype * sendtype,
443                                                MTestDatatype * recvtype, MPI_Aint tot_count)
444 {
445     int merr = 0;
446     int ddt_datatype_index, ddt_c_dt;
447     MPI_Aint blen, stride, count, align_tot_count, lb;
448     MPI_Datatype old_type = MPI_DOUBLE;
449
450     /* Check index */
451     ddt_datatype_index = SMPI_VARGET_GLOBAL(datatype_index) - SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_START_IDX);
452     ddt_c_dt = ddt_datatype_index / MTEST_DDT_NUM_SUBTESTS;
453     if (ddt_c_dt >= MTEST_DDT_MAX || !SMPI_VARGET_GLOBAL(mtestDdtCreators)[ddt_c_dt]) {
454       printf("Wrong index:  global %d, recv %d recv-ddt %d, or undefined creator in %s\n",
455              SMPI_VARGET_GLOBAL(datatype_index), ddt_datatype_index, ddt_c_dt, __func__);
456       merr++;
457       return merr;
458     }
459
460     /* Set datatype structure */
461     merr = MTestDdtStructDefine(ddt_datatype_index, tot_count, &count, &blen,
462                                 &stride, &align_tot_count, &lb);
463     if (merr) {
464       printf("Wrong index:  global %d, recv %d recv-ddt %d, or undefined ddt structure in %s\n",
465              SMPI_VARGET_GLOBAL(datatype_index), ddt_datatype_index, ddt_c_dt, __func__);
466       return merr;
467     }
468
469     /* Create receive datatype */
470     merr = SMPI_VARGET_GLOBAL(mtestDdtCreators)[ddt_c_dt] (count, blen, stride, lb, old_type, "recv", recvtype);
471     if (merr)
472         return merr;
473
474     recvtype->count = 1;
475
476     /* Create send datatype */
477     merr = MTestTypeBasicCreate(old_type, sendtype);
478     if (merr)
479         return merr;
480
481     sendtype->count = recvtype->count * align_tot_count;
482
483     return merr;
484 }
485
486 /* ------------------------------------------------------------------------ */
487 /* Exposed routine to external tests                                         */
488 /* ------------------------------------------------------------------------ */
489 int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, MPI_Aint tot_count)
490 {
491     int merr = 0;
492
493     MTestGetDbgInfo(&SMPI_VARGET_GLOBAL(dbgflag2), &SMPI_VARGET_GLOBAL(verbose2));
494     MTestInitDatatypeEnv();
495     MPI_Comm_rank(MPI_COMM_WORLD, &SMPI_VARGET_GLOBAL(wrank2));
496
497     /* Initialize the default test level if test does not specify. */
498     if (!MTestIsDatatypeGenInited()) {
499         MTestInitDefaultTestFunc();
500     }
501
502     if (SMPI_VARGET_GLOBAL(datatype_index) == 0) {
503         MTestPrintDatatypeGen();
504     }
505
506     /* Start generating tests */
507     if (SMPI_VARGET_GLOBAL(datatype_index) < SMPI_VARGET_GLOBAL(MTEST_BDT_RANGE)) {
508         merr = MTestGetBasicDatatypes(sendtype, recvtype, tot_count);
509
510     }
511     else if (SMPI_VARGET_GLOBAL(datatype_index) < SMPI_VARGET_GLOBAL(MTEST_SEND_DDT_RANGE)) {
512         merr = MTestGetSendDerivedDatatypes(sendtype, recvtype, tot_count);
513
514     }
515     else if (SMPI_VARGET_GLOBAL(datatype_index) < SMPI_VARGET_GLOBAL(MTEST_RECV_DDT_RANGE)) {
516         merr = MTestGetRecvDerivedDatatypes(sendtype, recvtype, tot_count);
517
518     }
519     else {
520         /* out of range */
521         SMPI_VARGET_GLOBAL(datatype_index) = -1;
522         MTestResetDatatypeGen();
523     }
524
525     /* stop if error reported */
526     if (merr) {
527         SMPI_VARGET_GLOBAL(datatype_index) = -1;
528     }
529
530     if (SMPI_VARGET_GLOBAL(datatype_index) > 0) {
531         /* general initialization for receive buffer. */
532         recvtype->InitBuf = MTestTypeInitRecv;
533     }
534
535     SMPI_VARGET_GLOBAL(datatype_index)++;
536
537     if (SMPI_VARGET_GLOBAL(verbose2) >= 2 && SMPI_VARGET_GLOBAL(datatype_index) > 0) {
538         MPI_Count ssize, rsize;
539         MPI_Aint slb, rlb, sextent, rextent;
540         const char *sendtype_nm = MTestGetDatatypeName(sendtype);
541         const char *recvtype_nm = MTestGetDatatypeName(recvtype);
542         MPI_Type_size_x(sendtype->datatype, &ssize);
543         MPI_Type_size_x(recvtype->datatype, &rsize);
544
545         MPI_Type_get_extent(sendtype->datatype, &slb, &sextent);
546         MPI_Type_get_extent(recvtype->datatype, &rlb, &rextent);
547
548         MTestPrintfMsg(2, "Get datatypes: send = %s(size %d ext %ld lb %ld count %d basesize %d), "
549                        "recv = %s(size %d ext %ld lb %ld count %d basesize %d), tot_count=%d\n",
550                        sendtype_nm, ssize, sextent, slb, sendtype->count, sendtype->basesize,
551                        recvtype_nm, rsize, rextent, rlb, recvtype->count, recvtype->basesize,
552                        tot_count);
553         fflush(stdout);
554     }
555
556     return SMPI_VARGET_GLOBAL(datatype_index);
557 }
558
559 /* Reset the datatype index (start from the initial data type.
560    Note: This routine is rarely needed; MTestGetDatatypes automatically
561    starts over after the last available datatype is used.
562 */
563 void MTestResetDatatypes(void)
564 {
565     SMPI_VARGET_GLOBAL(datatype_index) = 0;
566     MTestResetDatatypeGen();
567 }
568
569 /* Return the index of the current datatype.  This is rarely needed and
570    is provided mostly to enable debugging of the MTest package itself */
571 int MTestGetDatatypeIndex(void)
572 {
573     return SMPI_VARGET_GLOBAL(datatype_index);
574 }
575
576 /* Free the storage associated with a datatype */
577 void MTestFreeDatatype(MTestDatatype * mtype)
578 {
579     int merr;
580     /* Invoke a datatype-specific free function to handle
581      * both the datatype and the send/receive buffers */
582     if (mtype->FreeBuf) {
583         (mtype->FreeBuf) (mtype);
584     }
585     /* Free the datatype itself if it was created */
586     if (!mtype->isBasic) {
587         merr = MPI_Type_free(&mtype->datatype);
588         if (merr)
589             MTestPrintError(merr);
590     }
591 }
592
593 /* Check that a message was received correctly.  Returns the number of
594    errors detected.  Status may be NULL or MPI_STATUS_IGNORE */
595 int MTestCheckRecv(MPI_Status * status, MTestDatatype * recvtype)
596 {
597     int count;
598     int errs = 0, merr;
599
600     if (status && status != MPI_STATUS_IGNORE) {
601         merr = MPI_Get_count(status, recvtype->datatype, &count);
602         if (merr)
603             MTestPrintError(merr);
604
605         /* Check count against expected count */
606         if (count != recvtype->count) {
607             errs++;
608         }
609     }
610
611     /* Check received data */
612     if (!errs && recvtype->CheckBuf(recvtype)) {
613         errs++;
614     }
615     return errs;
616 }
617
618     SMPI_VARINIT_GLOBAL_AND_SET(name , char*,NULL);
619     SMPI_VARINIT_GLOBAL_AND_SET(sp,int,0);
620
621 /* This next routine uses a circular buffer of static name arrays just to
622    simplify the use of the routine */
623 const char *MTestGetDatatypeName(MTestDatatype * dtype)
624 {
625     if(SMPI_VARGET_GLOBAL(name)==NULL) SMPI_VARGET_GLOBAL(name)=(char*)malloc(4*MPI_MAX_OBJECT_NAME*sizeof(char));
626     int rlen, merr;
627
628     if (SMPI_VARGET_GLOBAL(sp) >= 4)
629         SMPI_VARGET_GLOBAL(sp) = 0;
630     merr = MPI_Type_get_name(dtype->datatype, &SMPI_VARGET_GLOBAL(name)[SMPI_VARGET_GLOBAL(sp)*MPI_MAX_OBJECT_NAME], &rlen);
631     if (merr)
632         MTestPrintError(merr);
633     return (const char *) &SMPI_VARGET_GLOBAL(name)[(SMPI_VARGET_GLOBAL(sp)++) *MPI_MAX_OBJECT_NAME];
634 }