Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Reduce the size of partial shared malloc tests.
[simgrid.git] / teshsuite / smpi / mpich3-test / datatype / contents.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2001 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 #include "mpi.h"
7 #include "mpitestconf.h"
8 #ifdef HAVE_UNISTD_H
9 #include <unistd.h>
10 #endif
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 static int verbose = 0;
15
16 /* tests */
17 int builtin_float_test(void);
18 int vector_of_vectors_test(void);
19 int optimizable_vector_of_basics_test(void);
20 int indexed_of_basics_test(void);
21 int indexed_of_vectors_test(void);
22 int struct_of_basics_test(void);
23
24 /* helper functions */
25 char *combiner_to_string(int combiner);
26 int parse_args(int argc, char **argv);
27
28 int main(int argc, char **argv)
29 {
30     int err, errs = 0;
31
32     MPI_Init(&argc, &argv);     /* MPI-1.2 doesn't allow for MPI_Init(0,0) */
33     parse_args(argc, argv);
34
35     /* To improve reporting of problems about operations, we
36      * change the error handler to errors return */
37     MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
38
39     /* perform some tests */
40     err = builtin_float_test();
41     errs += err;
42     if (err) {
43         fprintf(stderr, "Found %d errors in builtin float test.\n", err);
44     }
45
46     err = vector_of_vectors_test();
47     errs += err;
48     if (err) {
49         fprintf(stderr, "Found %d errors in vector of vectors test.\n", err);
50     }
51
52     err = optimizable_vector_of_basics_test();
53     errs += err;
54     if (err) {
55         fprintf(stderr, "Found %d errors in vector of basics test.\n", err);
56     }
57
58     err = indexed_of_basics_test();
59     errs += err;
60     if (err) {
61         fprintf(stderr, "Found %d errors in indexed of basics test.\n", err);
62     }
63
64     err = indexed_of_vectors_test();
65     errs += err;
66     if (err) {
67         fprintf(stderr, "Found %d errors in indexed of vectors test.\n", err);
68     }
69
70 #ifdef HAVE_MPI_TYPE_CREATE_STRUCT
71     err = struct_of_basics_test();
72     errs += err;
73 #endif
74
75     /* print message and exit */
76     if (errs) {
77         fprintf(stderr, "Found %d errors\n", errs);
78     }
79     else {
80         printf(" No Errors\n");
81     }
82     MPI_Finalize();
83     return 0;
84 }
85
86 /* builtin_float_test()
87  *
88  * Tests functionality of get_envelope() and get_contents() on a MPI_FLOAT.
89  *
90  * Returns the number of errors encountered.
91  */
92 int builtin_float_test(void)
93 {
94     int nints, nadds, ntypes, combiner;
95
96     int err, errs = 0;
97
98     err = MPI_Type_get_envelope(MPI_FLOAT, &nints, &nadds, &ntypes, &combiner);
99
100     if (combiner != MPI_COMBINER_NAMED)
101         errs++;
102     if (verbose && combiner != MPI_COMBINER_NAMED)
103         fprintf(stderr, "combiner = %s; should be named\n", combiner_to_string(combiner));
104
105     /* Note: it is erroneous to call MPI_Type_get_contents() on a basic. */
106     return errs;
107 }
108
109 /* vector_of_vectors_test()
110  *
111  * Builds a vector of a vector of ints.  Assuming an int array of size 9
112  * integers, and treating the array as a 3x3 2D array, this will grab the
113  * corners.
114  *
115  * Returns the number of errors encountered.
116  */
117 int vector_of_vectors_test(void)
118 {
119     MPI_Datatype inner_vector, inner_vector_copy;
120     MPI_Datatype outer_vector;
121
122     int nints, nadds, ntypes, combiner, *ints;
123     MPI_Aint *adds = NULL;
124     MPI_Datatype *types;
125
126     int err, errs = 0;
127
128     /* set up type */
129     err = MPI_Type_vector(2, 1, 2, MPI_INT, &inner_vector);
130     if (err != MPI_SUCCESS) {
131         if (verbose)
132             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
133         return errs + 1;
134     }
135
136     err = MPI_Type_vector(2, 1, 2, inner_vector, &outer_vector);
137     if (err != MPI_SUCCESS) {
138         if (verbose)
139             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
140         return errs + 1;
141     }
142
143     /* decode outer vector (get envelope, then contents) */
144     err = MPI_Type_get_envelope(outer_vector, &nints, &nadds, &ntypes, &combiner);
145     if (err != MPI_SUCCESS) {
146         if (verbose)
147             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
148         return errs + 1;
149     }
150
151     if (nints != 3)
152         errs++;
153     if (nadds != 0)
154         errs++;
155     if (ntypes != 1)
156         errs++;
157     if (combiner != MPI_COMBINER_VECTOR)
158         errs++;
159
160     if (verbose) {
161         if (nints != 3)
162             fprintf(stderr, "outer vector nints = %d; should be 3\n", nints);
163         if (nadds != 0)
164             fprintf(stderr, "outer vector nadds = %d; should be 0\n", nadds);
165         if (ntypes != 1)
166             fprintf(stderr, "outer vector ntypes = %d; should be 1\n", ntypes);
167         if (combiner != MPI_COMBINER_VECTOR)
168             fprintf(stderr, "outer vector combiner = %s; should be vector\n",
169                     combiner_to_string(combiner));
170     }
171     if (errs) {
172         if (verbose)
173             fprintf(stderr, "aborting after %d errors\n", errs);
174         return errs;
175     }
176
177     ints = malloc(nints * sizeof(*ints));
178     if (nadds)
179         adds = malloc(nadds * sizeof(*adds));
180     types = malloc(ntypes * sizeof(*types));
181
182     /* get contents of outer vector */
183     err = MPI_Type_get_contents(outer_vector, nints, nadds, ntypes, ints, adds, types);
184
185     if (ints[0] != 2)
186         errs++;
187     if (ints[1] != 1)
188         errs++;
189     if (ints[2] != 2)
190         errs++;
191
192     if (verbose) {
193         if (ints[0] != 2)
194             fprintf(stderr, "outer vector count = %d; should be 2\n", ints[0]);
195         if (ints[1] != 1)
196             fprintf(stderr, "outer vector blocklength = %d; should be 1\n", ints[1]);
197         if (ints[2] != 2)
198             fprintf(stderr, "outer vector stride = %d; should be 2\n", ints[2]);
199     }
200     if (errs) {
201         if (verbose)
202             fprintf(stderr, "aborting after %d errors\n", errs);
203         return errs;
204     }
205
206     inner_vector_copy = types[0];
207     free(ints);
208     if (nadds)
209         free(adds);
210     free(types);
211
212     /* decode inner vector */
213     err = MPI_Type_get_envelope(inner_vector_copy, &nints, &nadds, &ntypes, &combiner);
214     if (err != MPI_SUCCESS) {
215         if (verbose)
216             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
217         return errs + 1;
218     }
219
220     if (nints != 3)
221         errs++;
222     if (nadds != 0)
223         errs++;
224     if (ntypes != 1)
225         errs++;
226     if (combiner != MPI_COMBINER_VECTOR)
227         errs++;
228
229     if (verbose) {
230         if (nints != 3)
231             fprintf(stderr, "inner vector nints = %d; should be 3\n", nints);
232         if (nadds != 0)
233             fprintf(stderr, "inner vector nadds = %d; should be 0\n", nadds);
234         if (ntypes != 1)
235             fprintf(stderr, "inner vector ntypes = %d; should be 1\n", ntypes);
236         if (combiner != MPI_COMBINER_VECTOR)
237             fprintf(stderr, "inner vector combiner = %s; should be vector\n",
238                     combiner_to_string(combiner));
239     }
240     if (errs) {
241         if (verbose)
242             fprintf(stderr, "aborting after %d errors\n", errs);
243         return errs;
244     }
245
246     ints = malloc(nints * sizeof(*ints));
247     if (nadds)
248         adds = malloc(nadds * sizeof(*adds));
249     types = malloc(ntypes * sizeof(*types));
250
251     err = MPI_Type_get_contents(inner_vector_copy, nints, nadds, ntypes, ints, adds, types);
252
253     if (ints[0] != 2)
254         errs++;
255     if (ints[1] != 1)
256         errs++;
257     if (ints[2] != 2)
258         errs++;
259
260     if (verbose) {
261         if (ints[0] != 2)
262             fprintf(stderr, "inner vector count = %d; should be 2\n", ints[0]);
263         if (ints[1] != 1)
264             fprintf(stderr, "inner vector blocklength = %d; should be 1\n", ints[1]);
265         if (ints[2] != 2)
266             fprintf(stderr, "inner vector stride = %d; should be 2\n", ints[2]);
267     }
268     if (errs) {
269         if (verbose)
270             fprintf(stderr, "aborting after %d errors\n", errs);
271         return errs;
272     }
273
274     free(ints);
275     if (nadds)
276         free(adds);
277     free(types);
278
279     MPI_Type_free(&inner_vector_copy);
280     MPI_Type_free(&inner_vector);
281     MPI_Type_free(&outer_vector);
282
283     return 0;
284 }
285
286 /* optimizable_vector_of_basics_test()
287  *
288  * Builds a vector of ints.  Count is 10, blocksize is 2, stride is 2, so this
289  * is equivalent to a contig of 20.  But remember...we should get back our
290  * suboptimal values under MPI-2.
291  *
292  * Returns the number of errors encountered.
293  */
294 int optimizable_vector_of_basics_test(void)
295 {
296     MPI_Datatype parent_type;
297
298     int nints, nadds, ntypes, combiner, *ints;
299     MPI_Aint *adds = NULL;
300     MPI_Datatype *types;
301
302     int err, errs = 0;
303
304     /* set up type */
305     err = MPI_Type_vector(10, 2, 2, MPI_INT, &parent_type);
306
307     /* decode */
308     err = MPI_Type_get_envelope(parent_type, &nints, &nadds, &ntypes, &combiner);
309
310     if (nints != 3)
311         errs++;
312     if (nadds != 0)
313         errs++;
314     if (ntypes != 1)
315         errs++;
316     if (combiner != MPI_COMBINER_VECTOR)
317         errs++;
318
319     if (verbose) {
320         if (nints != 3)
321             fprintf(stderr, "nints = %d; should be 3\n", nints);
322         if (nadds != 0)
323             fprintf(stderr, "nadds = %d; should be 0\n", nadds);
324         if (ntypes != 1)
325             fprintf(stderr, "ntypes = %d; should be 1\n", ntypes);
326         if (combiner != MPI_COMBINER_VECTOR)
327             fprintf(stderr, "combiner = %s; should be vector\n", combiner_to_string(combiner));
328     }
329
330     ints = malloc(nints * sizeof(*ints));
331     if (nadds)
332         adds = malloc(nadds * sizeof(*adds));
333     types = malloc(ntypes * sizeof(*types));
334
335     err = MPI_Type_get_contents(parent_type, nints, nadds, ntypes, ints, adds, types);
336
337     if (ints[0] != 10)
338         errs++;
339     if (ints[1] != 2)
340         errs++;
341     if (ints[2] != 2)
342         errs++;
343     if (types[0] != MPI_INT)
344         errs++;
345
346     if (verbose) {
347         if (ints[0] != 10)
348             fprintf(stderr, "count = %d; should be 10\n", ints[0]);
349         if (ints[1] != 2)
350             fprintf(stderr, "blocklength = %d; should be 2\n", ints[1]);
351         if (ints[2] != 2)
352             fprintf(stderr, "stride = %d; should be 2\n", ints[2]);
353         if (types[0] != MPI_INT)
354             fprintf(stderr, "type is not MPI_INT\n");
355     }
356
357     free(ints);
358     if (nadds)
359         free(adds);
360     free(types);
361
362     MPI_Type_free(&parent_type);
363
364     return errs;
365 }
366
367
368 /* indexed_of_basics_test(void)
369  *
370  * Simple indexed type.
371  *
372  * Returns number of errors encountered.
373  */
374 int indexed_of_basics_test(void)
375 {
376     MPI_Datatype parent_type;
377     int s_count = 3, s_blocklengths[3] = { 3, 2, 1 };
378     int s_displacements[3] = { 10, 20, 30 };
379
380     int nints, nadds, ntypes, combiner, *ints;
381     MPI_Aint *adds = NULL;
382     MPI_Datatype *types;
383
384     int err, errs = 0;
385
386     /* set up type */
387     err = MPI_Type_indexed(s_count, s_blocklengths, s_displacements, MPI_INT, &parent_type);
388
389     /* decode */
390     err = MPI_Type_get_envelope(parent_type, &nints, &nadds, &ntypes, &combiner);
391
392     if (nints != 7)
393         errs++;
394     if (nadds != 0)
395         errs++;
396     if (ntypes != 1)
397         errs++;
398     if (combiner != MPI_COMBINER_INDEXED)
399         errs++;
400
401     if (verbose) {
402         if (nints != 7)
403             fprintf(stderr, "nints = %d; should be 7\n", nints);
404         if (nadds != 0)
405             fprintf(stderr, "nadds = %d; should be 0\n", nadds);
406         if (ntypes != 1)
407             fprintf(stderr, "ntypes = %d; should be 1\n", ntypes);
408         if (combiner != MPI_COMBINER_INDEXED)
409             fprintf(stderr, "combiner = %s; should be indexed\n", combiner_to_string(combiner));
410     }
411
412     ints = malloc(nints * sizeof(*ints));
413     if (nadds)
414         adds = malloc(nadds * sizeof(*adds));
415     types = malloc(ntypes * sizeof(*types));
416
417     err = MPI_Type_get_contents(parent_type, nints, nadds, ntypes, ints, adds, types);
418
419     if (ints[0] != s_count)
420         errs++;
421     if (ints[1] != s_blocklengths[0])
422         errs++;
423     if (ints[2] != s_blocklengths[1])
424         errs++;
425     if (ints[3] != s_blocklengths[2])
426         errs++;
427     if (ints[4] != s_displacements[0])
428         errs++;
429     if (ints[5] != s_displacements[1])
430         errs++;
431     if (ints[6] != s_displacements[2])
432         errs++;
433     if (types[0] != MPI_INT)
434         errs++;
435
436     if (verbose) {
437         if (ints[0] != s_count)
438             fprintf(stderr, "count = %d; should be %d\n", ints[0], s_count);
439         if (ints[1] != s_blocklengths[0])
440             fprintf(stderr, "blocklength[0] = %d; should be %d\n", ints[1], s_blocklengths[0]);
441         if (ints[2] != s_blocklengths[1])
442             fprintf(stderr, "blocklength[1] = %d; should be %d\n", ints[2], s_blocklengths[1]);
443         if (ints[3] != s_blocklengths[2])
444             fprintf(stderr, "blocklength[2] = %d; should be %d\n", ints[3], s_blocklengths[2]);
445         if (ints[4] != s_displacements[0])
446             fprintf(stderr, "displacement[0] = %d; should be %d\n", ints[4], s_displacements[0]);
447         if (ints[5] != s_displacements[1])
448             fprintf(stderr, "displacement[1] = %d; should be %d\n", ints[5], s_displacements[1]);
449         if (ints[6] != s_displacements[2])
450             fprintf(stderr, "displacement[2] = %d; should be %d\n", ints[6], s_displacements[2]);
451         if (types[0] != MPI_INT)
452             fprintf(stderr, "type[0] does not match\n");
453     }
454
455     free(ints);
456     if (nadds)
457         free(adds);
458     free(types);
459
460     MPI_Type_free(&parent_type);
461     return errs;
462 }
463
464 /* indexed_of_vectors_test()
465  *
466  * Builds an indexed type of vectors of ints.
467  *
468  * Returns the number of errors encountered.
469  */
470 int indexed_of_vectors_test(void)
471 {
472     MPI_Datatype inner_vector, inner_vector_copy;
473     MPI_Datatype outer_indexed;
474
475     int i_count = 3, i_blocklengths[3] = { 3, 2, 1 };
476     int i_displacements[3] = { 10, 20, 30 };
477
478     int nints, nadds, ntypes, combiner, *ints;
479     MPI_Aint *adds = NULL;
480     MPI_Datatype *types;
481
482     int err, errs = 0;
483
484     /* set up type */
485     err = MPI_Type_vector(2, 1, 2, MPI_INT, &inner_vector);
486     if (err != MPI_SUCCESS) {
487         if (verbose)
488             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
489         return errs + 1;
490     }
491
492     err = MPI_Type_indexed(i_count, i_blocklengths, i_displacements, inner_vector, &outer_indexed);
493     if (err != MPI_SUCCESS) {
494         if (verbose)
495             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
496         return errs + 1;
497     }
498
499     /* decode outer vector (get envelope, then contents) */
500     err = MPI_Type_get_envelope(outer_indexed, &nints, &nadds, &ntypes, &combiner);
501     if (err != MPI_SUCCESS) {
502         if (verbose)
503             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
504         return errs + 1;
505     }
506
507     if (nints != 7)
508         errs++;
509     if (nadds != 0)
510         errs++;
511     if (ntypes != 1)
512         errs++;
513     if (combiner != MPI_COMBINER_INDEXED)
514         errs++;
515
516     if (verbose) {
517         if (nints != 7)
518             fprintf(stderr, "nints = %d; should be 7\n", nints);
519         if (nadds != 0)
520             fprintf(stderr, "nadds = %d; should be 0\n", nadds);
521         if (ntypes != 1)
522             fprintf(stderr, "ntypes = %d; should be 1\n", ntypes);
523         if (combiner != MPI_COMBINER_INDEXED)
524             fprintf(stderr, "combiner = %s; should be indexed\n", combiner_to_string(combiner));
525     }
526
527     if (errs) {
528         if (verbose)
529             fprintf(stderr, "aborting after %d errors\n", errs);
530         return errs;
531     }
532
533     ints = malloc(nints * sizeof(*ints));
534     if (nadds)
535         adds = malloc(nadds * sizeof(*adds));
536     types = malloc(ntypes * sizeof(*types));
537
538     /* get contents of outer vector */
539     err = MPI_Type_get_contents(outer_indexed, nints, nadds, ntypes, ints, adds, types);
540
541     if (ints[0] != i_count)
542         errs++;
543     if (ints[1] != i_blocklengths[0])
544         errs++;
545     if (ints[2] != i_blocklengths[1])
546         errs++;
547     if (ints[3] != i_blocklengths[2])
548         errs++;
549     if (ints[4] != i_displacements[0])
550         errs++;
551     if (ints[5] != i_displacements[1])
552         errs++;
553     if (ints[6] != i_displacements[2])
554         errs++;
555
556     if (verbose) {
557         if (ints[0] != i_count)
558             fprintf(stderr, "count = %d; should be %d\n", ints[0], i_count);
559         if (ints[1] != i_blocklengths[0])
560             fprintf(stderr, "blocklength[0] = %d; should be %d\n", ints[1], i_blocklengths[0]);
561         if (ints[2] != i_blocklengths[1])
562             fprintf(stderr, "blocklength[1] = %d; should be %d\n", ints[2], i_blocklengths[1]);
563         if (ints[3] != i_blocklengths[2])
564             fprintf(stderr, "blocklength[2] = %d; should be %d\n", ints[3], i_blocklengths[2]);
565         if (ints[4] != i_displacements[0])
566             fprintf(stderr, "displacement[0] = %d; should be %d\n", ints[4], i_displacements[0]);
567         if (ints[5] != i_displacements[1])
568             fprintf(stderr, "displacement[1] = %d; should be %d\n", ints[5], i_displacements[1]);
569         if (ints[6] != i_displacements[2])
570             fprintf(stderr, "displacement[2] = %d; should be %d\n", ints[6], i_displacements[2]);
571     }
572
573     if (errs) {
574         if (verbose)
575             fprintf(stderr, "aborting after %d errors\n", errs);
576         return errs;
577     }
578
579     inner_vector_copy = types[0];
580     free(ints);
581     if (nadds)
582         free(adds);
583     free(types);
584
585     /* decode inner vector */
586     err = MPI_Type_get_envelope(inner_vector_copy, &nints, &nadds, &ntypes, &combiner);
587     if (err != MPI_SUCCESS) {
588         if (verbose)
589             fprintf(stderr, "error in MPI call; aborting after %d errors\n", errs + 1);
590         return errs + 1;
591     }
592
593     if (nints != 3)
594         errs++;
595     if (nadds != 0)
596         errs++;
597     if (ntypes != 1)
598         errs++;
599     if (combiner != MPI_COMBINER_VECTOR)
600         errs++;
601
602     if (verbose) {
603         if (nints != 3)
604             fprintf(stderr, "inner vector nints = %d; should be 3\n", nints);
605         if (nadds != 0)
606             fprintf(stderr, "inner vector nadds = %d; should be 0\n", nadds);
607         if (ntypes != 1)
608             fprintf(stderr, "inner vector ntypes = %d; should be 1\n", ntypes);
609         if (combiner != MPI_COMBINER_VECTOR)
610             fprintf(stderr, "inner vector combiner = %s; should be vector\n",
611                     combiner_to_string(combiner));
612     }
613     if (errs) {
614         if (verbose)
615             fprintf(stderr, "aborting after %d errors\n", errs);
616         return errs;
617     }
618
619     ints = malloc(nints * sizeof(*ints));
620     if (nadds)
621         adds = malloc(nadds * sizeof(*adds));
622     types = malloc(ntypes * sizeof(*types));
623
624     err = MPI_Type_get_contents(inner_vector_copy, nints, nadds, ntypes, ints, adds, types);
625
626     if (ints[0] != 2)
627         errs++;
628     if (ints[1] != 1)
629         errs++;
630     if (ints[2] != 2)
631         errs++;
632
633     if (verbose) {
634         if (ints[0] != 2)
635             fprintf(stderr, "inner vector count = %d; should be 2\n", ints[0]);
636         if (ints[1] != 1)
637             fprintf(stderr, "inner vector blocklength = %d; should be 1\n", ints[1]);
638         if (ints[2] != 2)
639             fprintf(stderr, "inner vector stride = %d; should be 2\n", ints[2]);
640     }
641     if (errs) {
642         if (verbose)
643             fprintf(stderr, "aborting after %d errors\n", errs);
644         return errs;
645     }
646
647     free(ints);
648     if (nadds)
649         free(adds);
650     free(types);
651
652     MPI_Type_free(&inner_vector_copy);
653     MPI_Type_free(&inner_vector);
654     MPI_Type_free(&outer_indexed);
655
656     return 0;
657 }
658
659
660 #ifdef HAVE_MPI_TYPE_CREATE_STRUCT
661 /* struct_of_basics_test(void)
662  *
663  * There's nothing simple about structs :).  Although this is an easy one.
664  *
665  * Returns number of errors encountered.
666  *
667  * NOT TESTED.
668  */
669 int struct_of_basics_test(void)
670 {
671     MPI_Datatype parent_type;
672     int s_count = 3, s_blocklengths[3] = { 3, 2, 1 };
673     MPI_Aint s_displacements[3] = { 10, 20, 30 };
674     MPI_Datatype s_types[3] = { MPI_CHAR, MPI_INT, MPI_FLOAT };
675
676     int nints, nadds, ntypes, combiner, *ints;
677     MPI_Aint *adds = NULL;
678     MPI_Datatype *types;
679
680     int err, errs = 0;
681
682     /* set up type */
683     err = MPI_Type_create_struct(s_count, s_blocklengths, s_displacements, s_types, &parent_type);
684
685     /* decode */
686     err = MPI_Type_get_envelope(parent_type, &nints, &nadds, &ntypes, &combiner);
687
688     if (nints != 4)
689         errs++;
690     if (nadds != 3)
691         errs++;
692     if (ntypes != 3)
693         errs++;
694     if (combiner != MPI_COMBINER_STRUCT)
695         errs++;
696
697     if (verbose) {
698         if (nints != 4)
699             fprintf(stderr, "nints = %d; should be 3\n", nints);
700         if (nadds != 3)
701             fprintf(stderr, "nadds = %d; should be 0\n", nadds);
702         if (ntypes != 3)
703             fprintf(stderr, "ntypes = %d; should be 3\n", ntypes);
704         if (combiner != MPI_COMBINER_STRUCT)
705             fprintf(stderr, "combiner = %s; should be struct\n", combiner_to_string(combiner));
706     }
707
708     ints = malloc(nints * sizeof(*ints));
709     adds = malloc(nadds * sizeof(*adds));
710     types = malloc(ntypes * sizeof(*types));
711
712     err = MPI_Type_get_contents(parent_type, nints, nadds, ntypes, ints, adds, types);
713
714     if (ints[0] != s_count)
715         errs++;
716     if (ints[1] != s_blocklengths[0])
717         errs++;
718     if (ints[2] != s_blocklengths[1])
719         errs++;
720     if (ints[3] != s_blocklengths[2])
721         errs++;
722     if (adds[0] != s_displacements[0])
723         errs++;
724     if (adds[1] != s_displacements[1])
725         errs++;
726     if (adds[2] != s_displacements[2])
727         errs++;
728     if (types[0] != s_types[0])
729         errs++;
730     if (types[1] != s_types[1])
731         errs++;
732     if (types[2] != s_types[2])
733         errs++;
734
735     if (verbose) {
736         if (ints[0] != s_count)
737             fprintf(stderr, "count = %d; should be %d\n", ints[0], s_count);
738         if (ints[1] != s_blocklengths[0])
739             fprintf(stderr, "blocklength[0] = %d; should be %d\n", ints[1], s_blocklengths[0]);
740         if (ints[2] != s_blocklengths[1])
741             fprintf(stderr, "blocklength[1] = %d; should be %d\n", ints[2], s_blocklengths[1]);
742         if (ints[3] != s_blocklengths[2])
743             fprintf(stderr, "blocklength[2] = %d; should be %d\n", ints[3], s_blocklengths[2]);
744         if (adds[0] != s_displacements[0])
745             fprintf(stderr, "displacement[0] = %d; should be %d\n", adds[0], s_displacements[0]);
746         if (adds[1] != s_displacements[1])
747             fprintf(stderr, "displacement[1] = %d; should be %d\n", adds[1], s_displacements[1]);
748         if (adds[2] != s_displacements[2])
749             fprintf(stderr, "displacement[2] = %d; should be %d\n", adds[2], s_displacements[2]);
750         if (types[0] != s_types[0])
751             fprintf(stderr, "type[0] does not match\n");
752         if (types[1] != s_types[1])
753             fprintf(stderr, "type[1] does not match\n");
754         if (types[2] != s_types[2])
755             fprintf(stderr, "type[2] does not match\n");
756     }
757
758     free(ints);
759     free(adds);
760     free(types);
761
762     MPI_Type_free(&parent_type);
763
764     return errs;
765 }
766 #endif
767
768 /* combiner_to_string(combiner)
769  *
770  * Converts a numeric combiner into a pointer to a string used for printing.
771  */
772 char *combiner_to_string(int combiner)
773 {
774     static char c_named[] = "named";
775     static char c_contig[] = "contig";
776     static char c_vector[] = "vector";
777     static char c_hvector[] = "hvector";
778     static char c_indexed[] = "indexed";
779     static char c_hindexed[] = "hindexed";
780     static char c_struct[] = "struct";
781 #ifdef HAVE_MPI2_COMBINERS
782     static char c_dup[] = "dup";
783     static char c_hvector_integer[] = "hvector_integer";
784     static char c_hindexed_integer[] = "hindexed_integer";
785     static char c_indexed_block[] = "indexed_block";
786     static char c_struct_integer[] = "struct_integer";
787     static char c_subarray[] = "subarray";
788     static char c_darray[] = "darray";
789     static char c_f90_real[] = "f90_real";
790     static char c_f90_complex[] = "f90_complex";
791     static char c_f90_integer[] = "f90_integer";
792     static char c_resized[] = "resized";
793 #endif
794
795     if (combiner == MPI_COMBINER_NAMED)
796         return c_named;
797     if (combiner == MPI_COMBINER_CONTIGUOUS)
798         return c_contig;
799     if (combiner == MPI_COMBINER_VECTOR)
800         return c_vector;
801     if (combiner == MPI_COMBINER_HVECTOR)
802         return c_hvector;
803     if (combiner == MPI_COMBINER_INDEXED)
804         return c_indexed;
805     if (combiner == MPI_COMBINER_HINDEXED)
806         return c_hindexed;
807     if (combiner == MPI_COMBINER_STRUCT)
808         return c_struct;
809 #ifdef HAVE_MPI2_COMBINERS
810     if (combiner == MPI_COMBINER_DUP)
811         return c_dup;
812     if (combiner == MPI_COMBINER_HVECTOR_INTEGER)
813         return c_hvector_integer;
814     if (combiner == MPI_COMBINER_HINDEXED_INTEGER)
815         return c_hindexed_integer;
816     if (combiner == MPI_COMBINER_INDEXED_BLOCK)
817         return c_indexed_block;
818     if (combiner == MPI_COMBINER_STRUCT_INTEGER)
819         return c_struct_integer;
820     if (combiner == MPI_COMBINER_SUBARRAY)
821         return c_subarray;
822     if (combiner == MPI_COMBINER_DARRAY)
823         return c_darray;
824     if (combiner == MPI_COMBINER_F90_REAL)
825         return c_f90_real;
826     if (combiner == MPI_COMBINER_F90_COMPLEX)
827         return c_f90_complex;
828     if (combiner == MPI_COMBINER_F90_INTEGER)
829         return c_f90_integer;
830     if (combiner == MPI_COMBINER_RESIZED)
831         return c_resized;
832 #endif
833
834     return NULL;
835 }
836
837 int parse_args(int argc, char **argv)
838 {
839 #ifdef HAVE_GET_OPT
840     int ret;
841
842     while ((ret = getopt(argc, argv, "v")) >= 0) {
843         switch (ret) {
844         case 'v':
845             verbose = 1;
846             break;
847         }
848     }
849 #else
850 #endif
851     return 0;
852 }