[mpich-commits] [mpich] MPICH primary repository branch, master, updated. v3.1.3-135-ge3c310e

Service Account noreply at mpich.org
Wed Nov 5 11:15:52 CST 2014


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "MPICH primary repository".

The branch, master has been updated
       via  e3c310e88ba4d08717609b6256c59ab335fbaf36 (commit)
       via  7b1e86b49a818c61ac387aa104ae30c855cccade (commit)
       via  95355c96677df7794358f1a54abd53202f597b67 (commit)
       via  042324069d11f25a62604fe4316db6b1a05c46ca (commit)
       via  1c9e18f55b0d8b9f19aea650cdb305c8516781f5 (commit)
       via  68832c84f84e6871331b5861cb8b44fc88e0e7ba (commit)
       via  b8173c7f5cb549a33de27dc268e5bedc4a0015cc (commit)
       via  2f896172913cc63d7c03e832e10c0e62710ae5dc (commit)
      from  1e3af7ca6308c76b7fc13b406668ea327c1feaa8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.mpich.org/mpich.git/commitdiff/e3c310e88ba4d08717609b6256c59ab335fbaf36

commit e3c310e88ba4d08717609b6256c59ab335fbaf36
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Wed Oct 29 15:34:32 2014 -0500

    Increase timelimit to 10mins for bcast2 and bcast3.
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/coll/testlist b/test/mpi/coll/testlist
index c4028f6..2e68ed7 100644
--- a/test/mpi/coll/testlist
+++ b/test/mpi/coll/testlist
@@ -35,8 +35,8 @@ bcasttest 10
 bcast2 4
 # More that 8 processes are required to get bcast to switch to the long
 # msg algorithm (see coll definitions in mpiimpl.h)
-bcast2 10 timeLimit=420
-bcast3 10 timeLimit=420
+bcast2 10 timeLimit=600
+bcast3 10 timeLimit=600
 bcastzerotype 1
 bcastzerotype 4
 bcastzerotype 5

http://git.mpich.org/mpich.git/commitdiff/7b1e86b49a818c61ac387aa104ae30c855cccade

commit 7b1e86b49a818c61ac387aa104ae30c855cccade
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Mon Nov 3 15:41:15 2014 -0600

    Add min version of mtest datatype generator.
    
    Some mpi tests such as bcast2 and bcast3 take 20mins to run all the
    datatypes on tcp. Therefore, we also define a minimum version of the
    datatype generator which only generates vector and indexed tests so that
    such heavy tests can use the min version to shorten time.
    
    We enable the full version by default, tests can turn to min version by
    calling the corresponding init func before datatype loop.
    
    In coll/bcast2, coll/bcast3 and pt2pt/pingpong tests, we change to min
    version from the second datatype loop.
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/coll/bcast2.c b/test/mpi/coll/bcast2.c
index 2ff6d86..2acfda3 100644
--- a/test/mpi/coll/bcast2.c
+++ b/test/mpi/coll/bcast2.c
@@ -38,6 +38,14 @@ int main( int argc, char *argv[] )
 	MPI_Errhandler_set( comm, MPI_ERRORS_RETURN );
 
     MTEST_DATATYPE_FOR_EACH_COUNT(count) {
+
+        /* Only run full datatype tests in comm world to shorten test time. */
+        if (comm == MPI_COMM_WORLD) {
+            MTestInitFullDatatypes();
+        } else {
+            MTestInitMinDatatypes();
+        }
+
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		for (root=0; root<size; root++) {
 		    if (rank == root) {
diff --git a/test/mpi/coll/bcast3.c b/test/mpi/coll/bcast3.c
index 3457208..c78d769 100644
--- a/test/mpi/coll/bcast3.c
+++ b/test/mpi/coll/bcast3.c
@@ -34,6 +34,14 @@ int main( int argc, char *argv[] )
 	
 	count = 1;
 	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
+
+        /* Only run full datatype tests in comm world to shorten test time. */
+        if (comm == MPI_COMM_WORLD) {
+            MTestInitFullDatatypes();
+        } else {
+            MTestInitMinDatatypes();
+        }
+
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		for (root=0; root<size; root++) {
 		    if (rank == root) {
diff --git a/test/mpi/include/mpitest.h b/test/mpi/include/mpitest.h
index cdbbe79..0b46ef7 100644
--- a/test/mpi/include/mpitest.h
+++ b/test/mpi/include/mpitest.h
@@ -63,6 +63,14 @@ typedef struct _MTestDatatype {
 #define MTEST_DATATYPE_FOR_EACH_COUNT(count) \
         for (count = 1; count <= 262144; count *= 8)
 
+/* Setup the full version of datatype tests.
+ * It generate tests for all basic datatypes and all derived datatypes except darray. */
+void MTestInitFullDatatypes();
+
+/* Setup the minimum version of datatype tests.
+ * It generate tests for all basic datatypes, vector and indexed. */
+void MTestInitMinDatatypes();
+
 int MTestCheckRecv( MPI_Status *, MTestDatatype * );
 int MTestGetDatatypes( MTestDatatype *, MTestDatatype *, int );
 void MTestResetDatatypes( void );
diff --git a/test/mpi/pt2pt/pingping.c b/test/mpi/pt2pt/pingping.c
index 95f6e39..c725216 100644
--- a/test/mpi/pt2pt/pingping.c
+++ b/test/mpi/pt2pt/pingping.c
@@ -41,6 +41,14 @@ int main( int argc, char *argv[] )
 	MPI_Comm_set_errhandler( comm, MPI_ERRORS_RETURN );
 
 	for (count = 1; count < MAX_COUNT; count = count * 2) {
+
+        /* Only run full datatype tests in comm world to shorten test time. */
+        if (comm == MPI_COMM_WORLD) {
+            MTestInitFullDatatypes();
+        } else {
+            MTestInitMinDatatypes();
+        }
+
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		int nbytes;
 		MPI_Type_size( sendtype.datatype, &nbytes );
diff --git a/test/mpi/util/mtest_datatype.c b/test/mpi/util/mtest_datatype.c
index 412faa7..39a5f1e 100644
--- a/test/mpi/util/mtest_datatype.c
+++ b/test/mpi/util/mtest_datatype.c
@@ -1281,3 +1281,10 @@ void MTestTypeCreatorInit(MTestDdtCreator * creators)
     creators[MTEST_DDT_SUBARRAY_ORDER_C] = MTestTypeSubArrayOrderCCreate;
     creators[MTEST_DDT_SUBARRAY_ORDER_FORTRAN] = MTestTypeSubArrayOrderFortranCreate;
 }
+
+void MTestTypeMinCreatorInit(MTestDdtCreator * creators)
+{
+    memset(creators, 0, sizeof(MTestDdtCreator) * MTEST_DDT_MAX);
+    creators[MTEST_MIN_DDT_VECTOR] = MTestTypeVectorCreate;
+    creators[MTEST_MIN_DDT_INDEXED] = MTestTypeIndexedCreate;
+}
diff --git a/test/mpi/util/mtest_datatype.h b/test/mpi/util/mtest_datatype.h
index f4c6828..c33a8e4 100644
--- a/test/mpi/util/mtest_datatype.h
+++ b/test/mpi/util/mtest_datatype.h
@@ -44,9 +44,16 @@ enum MTEST_DERIVED_DT {
     MTEST_DDT_MAX
 };
 
+enum MTEST_MIN_DERIVED_DT {
+    MTEST_MIN_DDT_VECTOR,
+    MTEST_MIN_DDT_INDEXED,
+    MTEST_MIN_DDT_MAX
+};
+
 typedef int (*MTestDdtCreator) (int, int, int, MPI_Datatype, const char *, MTestDatatype *);
 
 extern void MTestTypeCreatorInit(MTestDdtCreator * creators);
+extern void MTestTypeMinCreatorInit(MTestDdtCreator * creators);
 extern void *MTestTypeInitRecv(MTestDatatype * mtype);
 
 extern int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype);
diff --git a/test/mpi/util/mtest_datatype_gen.c b/test/mpi/util/mtest_datatype_gen.c
index 60c53ef..2cd1d2c 100644
--- a/test/mpi/util/mtest_datatype_gen.c
+++ b/test/mpi/util/mtest_datatype_gen.c
@@ -61,35 +61,117 @@ static int verbose = 0;         /* Message level (0 is none) */
  *  Datatype definition:
  *    Every type is initialized by the creation function stored in
  *    mtestDdtCreators variable, all of their create/init/check functions are
- *    defined in file mtest_datatype.c. Following derived datatypes are defined:
- *    Contiguous | Vector | HVector | Indexed | Hindexed | Indexed-block |
- *    Hindexed-block | Struct | Subarray with order-C | Subarray with order-Fortran
+ *    defined in file mtest_datatype.c.
  *
  *  How to add a new derived datatype:
  *    1. Add the new datatype in enum MTEST_DERIVED_DT.
  *    2. Add its create/init/check functions in file mtest_datatype.c
  *    3. Add its creator function to mtestDdtCreators variable
+ *
+ *  Following two datatype generators are defined.
+ *    1. Full datatypes generator:
+ *      All basic datatypes | Vector | Hvector | Indexed | Hindexed |
+ *      Indexed-block | Hindexed-block | Subarray with order-C | Subarray with order-Fortran
+ *    2. Minimum datatypes generator:
+ *      All basic datatypes | Vector | Indexed
+ *
+ *  MPI test can initialize either generator by calling the corresponding init
+ *  function before datatype loop, The full generator is set by default.
+ *    Full generator : MTestInitFullDatatypes
+ *    Minimum generator : MTestInitMinDatatypes
  */
 
 static int datatype_index = 0;
 
+/* ------------------------------------------------------------------------ */
+/* Routine and internal parameters to define the range of datatype tests */
+/* ------------------------------------------------------------------------ */
+#define MTEST_DDT_NUM_SUBTESTS 4        /* 4 kinds of derived datatype structure */
+static MTestDdtCreator mtestDdtCreators[MTEST_DDT_MAX];
 
-#define MTEST_BDT_START_IDX 0
-#define MTEST_BDT_NUM_TESTS (MTEST_BDT_MAX)
-#define MTEST_BDT_RANGE (MTEST_BDT_START_IDX + MTEST_BDT_NUM_TESTS)
+static int MTEST_BDT_START_IDX = -1;
+static int MTEST_BDT_NUM_TESTS = 0;
+static int MTEST_BDT_RANGE = 0;
 
-#define MTEST_DDT_NUM_SUBTESTS 4        /* 4 kinds of derived datatype structure */
-#define MTEST_DDT_NUM_TYPES (MTEST_DDT_MAX)
+static int MTEST_DDT_NUM_TYPES = 0;
+static int MTEST_SEND_DDT_START_IDX = 0;
+static int MTEST_SEND_DDT_NUM_TESTS = 0;
+static int MTEST_SEND_DDT_RANGE = 0;
 
-#define MTEST_SEND_DDT_START_IDX (MTEST_BDT_NUM_TESTS)
-#define MTEST_SEND_DDT_NUM_TESTS (MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS)
-#define MTEST_SEND_DDT_RANGE (MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS)
+static int MTEST_RECV_DDT_START_IDX = 0;
+static int MTEST_RECV_DDT_NUM_TESTS = 0;
+static int MTEST_RECV_DDT_RANGE = 0;
 
-#define MTEST_RECV_DDT_START_IDX (MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS)
-#define MTEST_RECV_DDT_NUM_TESTS (MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS)
-#define MTEST_RECV_DDT_RANGE (MTEST_RECV_DDT_START_IDX + MTEST_RECV_DDT_NUM_TESTS)
+enum {
+    MTEST_DATATYPE_VERSION_FULL,
+    MTEST_DATATYPE_VERSION_MIN
+};
 
-static MTestDdtCreator mtestDdtCreators[MTEST_DDT_MAX];
+static int MTEST_DATATYPE_VERSION = MTEST_DATATYPE_VERSION_FULL;
+
+static void MTestInitDatatypeGen(int basic_dt_num, int derived_dt_num)
+{
+    MTEST_BDT_START_IDX = 0;
+    MTEST_BDT_NUM_TESTS = basic_dt_num;
+    MTEST_BDT_RANGE = MTEST_BDT_START_IDX + MTEST_BDT_NUM_TESTS;
+    MTEST_DDT_NUM_TYPES = derived_dt_num;
+    MTEST_SEND_DDT_START_IDX = MTEST_BDT_NUM_TESTS;
+    MTEST_SEND_DDT_NUM_TESTS = MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS;
+    MTEST_SEND_DDT_RANGE = MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS;
+    MTEST_RECV_DDT_START_IDX = MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS;
+    MTEST_RECV_DDT_NUM_TESTS = MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS;
+    MTEST_RECV_DDT_RANGE = MTEST_RECV_DDT_START_IDX + MTEST_RECV_DDT_NUM_TESTS;
+}
+
+static int MTestIsDatatypeGenInited()
+{
+    return (MTEST_BDT_START_IDX < 0) ? 0 : 1;
+}
+
+static void MTestPrintDatatypeGen()
+{
+    MTestPrintfMsg(1, "MTest datatype version : %s. %d basic datatype tests, "
+                   "%d derived datatype tests will be generated\n",
+                   (MTEST_DATATYPE_VERSION == MTEST_DATATYPE_VERSION_FULL) ? "FULL" : "MIN",
+                   MTEST_BDT_NUM_TESTS, MTEST_SEND_DDT_NUM_TESTS + MTEST_RECV_DDT_NUM_TESTS);
+}
+
+static void MTestResetDatatypeGen()
+{
+    MTEST_BDT_START_IDX = -1;
+}
+
+void MTestInitFullDatatypes()
+{
+    /* Do not allow to change datatype version during loop.
+     * Otherwise indexes will be wrong.
+     * Test must explicitly call reset or wait for current datatype loop being
+     * done before changing to another datatype version. */
+    if (!MTestIsDatatypeGenInited()) {
+        MTEST_DATATYPE_VERSION = MTEST_DATATYPE_VERSION_FULL;
+        MTestTypeCreatorInit((MTestDdtCreator *) mtestDdtCreators);
+        MTestInitDatatypeGen(MTEST_BDT_MAX, MTEST_DDT_MAX);
+    }
+    else {
+        printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
+    }
+}
+
+void MTestInitMinDatatypes()
+{
+    /* Do not allow to change datatype version during loop.
+     * Otherwise indexes will be wrong.
+     * Test must explicitly call reset or wait for current datatype loop being
+     * done before changing to another datatype version. */
+    if (!MTestIsDatatypeGenInited()) {
+        MTEST_DATATYPE_VERSION = MTEST_DATATYPE_VERSION_MIN;
+        MTestTypeMinCreatorInit((MTestDdtCreator *) mtestDdtCreators);
+        MTestInitDatatypeGen(MTEST_BDT_MAX, MTEST_MIN_DDT_MAX);
+    }
+    else {
+        printf("Warning: trying to reinitialize mtest datatype during " "datatype iteration!");
+    }
+}
 
 
 /* -------------------------------------------------------------------------------*/
@@ -325,8 +407,16 @@ int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, int to
     MTestGetDbgInfo(&dbgflag, &verbose);
     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
 
-    MTestTypeCreatorInit((MTestDdtCreator *) mtestDdtCreators);
+    /* Initialize the full version if test does not specify. */
+    if (!MTestIsDatatypeGenInited()) {
+        MTestInitFullDatatypes();
+    }
+
+    if (datatype_index == 0) {
+        MTestPrintDatatypeGen();
+    }
 
+    /* Start generating tests */
     if (datatype_index < MTEST_BDT_RANGE) {
         merr = MTestGetBasicDatatypes(sendtype, recvtype, tot_count);
 
@@ -342,6 +432,7 @@ int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, int to
     else {
         /* out of range */
         datatype_index = -1;
+        MTestResetDatatypeGen();
     }
 
     /* stop if error reported */
@@ -356,17 +447,18 @@ int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, int to
 
     datatype_index++;
 
-    if ((verbose || dbgflag) && datatype_index > 0) {
+    if (verbose >= 2 && datatype_index > 0) {
         int ssize, rsize;
         const char *sendtype_nm = MTestGetDatatypeName(sendtype);
         const char *recvtype_nm = MTestGetDatatypeName(recvtype);
         MPI_Type_size(sendtype->datatype, &ssize);
         MPI_Type_size(recvtype->datatype, &rsize);
-        printf("Get datatypes: send = %s(size %d count %d basesize %d), "
-               "recv = %s(size %d count %d basesize %d), tot_count=%d\n",
-               sendtype_nm, ssize, sendtype->count, sendtype->basesize,
-               recvtype_nm, rsize, recvtype->count, recvtype->basesize,
-               tot_count);
+
+        MTestPrintfMsg(2, "Get datatypes: send = %s(size %d count %d basesize %d), "
+                       "recv = %s(size %d count %d basesize %d), tot_count=%d\n",
+                       sendtype_nm, ssize, sendtype->count, sendtype->basesize,
+                       recvtype_nm, rsize, recvtype->count, recvtype->basesize,
+                       tot_count);
         fflush(stdout);
     }
 
@@ -380,6 +472,7 @@ int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, int to
 void MTestResetDatatypes(void)
 {
     datatype_index = 0;
+    MTestResetDatatypeGen();
 }
 
 /* Return the index of the current datatype.  This is rarely needed and

http://git.mpich.org/mpich.git/commitdiff/95355c96677df7794358f1a54abd53202f597b67

commit 95355c96677df7794358f1a54abd53202f597b67
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Fri Oct 24 13:22:37 2014 -0500

    Change count of mtest datatype in bcast3 mpi test.
    
    0 count is not allowed in subarray. Please revert this change if it has
    special reason to set count-1 in the datatype while loop.
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/coll/bcast3.c b/test/mpi/coll/bcast3.c
index daf8c1c..3457208 100644
--- a/test/mpi/coll/bcast3.c
+++ b/test/mpi/coll/bcast3.c
@@ -34,7 +34,7 @@ int main( int argc, char *argv[] )
 	
 	count = 1;
 	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
-	    while (MTestGetDatatypes( &sendtype, &recvtype, count-1 )) {
+	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		for (root=0; root<size; root++) {
 		    if (rank == root) {
 			sendtype.InitBuf( &sendtype );

http://git.mpich.org/mpich.git/commitdiff/042324069d11f25a62604fe4316db6b1a05c46ca

commit 042324069d11f25a62604fe4316db6b1a05c46ca
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Fri Oct 24 12:35:56 2014 -0500

    Use unified loop of mtest datatype in mpi tests.
    
    Each mpi test originally called the mtest datatype by using a hardcoded
    count loop. Now we predefine a count loop and let the mpi tests call
    this predefined loop instead of hardcoding. This change allows the mtest
    routine to manage the size of generated datatypes in every mpi
    test (i.e., to ensure that every mpi test reaches the large message
    algorithms).
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/coll/bcast2.c b/test/mpi/coll/bcast2.c
index b2c2f79..2ff6d86 100644
--- a/test/mpi/coll/bcast2.c
+++ b/test/mpi/coll/bcast2.c
@@ -37,9 +37,7 @@ int main( int argc, char *argv[] )
 	   change the error handler to errors return */
 	MPI_Errhandler_set( comm, MPI_ERRORS_RETURN );
 
-	/* The max value of count must be very large to ensure that we 
-	   reach the long message algorithms */
-	for (count = 1; count < 280000; count = count * 4) {
+    MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		for (root=0; root<size; root++) {
 		    if (rank == root) {
diff --git a/test/mpi/coll/bcast3.c b/test/mpi/coll/bcast3.c
index 84250b2..daf8c1c 100644
--- a/test/mpi/coll/bcast3.c
+++ b/test/mpi/coll/bcast3.c
@@ -33,9 +33,7 @@ int main( int argc, char *argv[] )
 	MPI_Comm_size( comm, &size );
 	
 	count = 1;
-	/* This must be very large to ensure that we reach the long message
-	   algorithms */
-	for (count = 4; count < 66000; count = count * 4) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count-1 )) {
 		for (root=0; root<size; root++) {
 		    if (rank == root) {
diff --git a/test/mpi/include/mpitest.h b/test/mpi/include/mpitest.h
index f31c1bc..cdbbe79 100644
--- a/test/mpi/include/mpitest.h
+++ b/test/mpi/include/mpitest.h
@@ -57,6 +57,12 @@ typedef struct _MTestDatatype {
     int   (*CheckBuf)( struct _MTestDatatype * );
 } MTestDatatype;
 
+/* The max value of count must be very large to ensure that we
+ *  reach the long message algorithms. (The maximal count or block length
+ *  can be generated by 256K count is 4K or 32Kbytes respectively) */
+#define MTEST_DATATYPE_FOR_EACH_COUNT(count) \
+        for (count = 1; count <= 262144; count *= 8)
+
 int MTestCheckRecv( MPI_Status *, MTestDatatype * );
 int MTestGetDatatypes( MTestDatatype *, MTestDatatype *, int );
 void MTestResetDatatypes( void );
diff --git a/test/mpi/pt2pt/sendrecv1.c b/test/mpi/pt2pt/sendrecv1.c
index 13f1dd2..57059eb 100644
--- a/test/mpi/pt2pt/sendrecv1.c
+++ b/test/mpi/pt2pt/sendrecv1.c
@@ -39,7 +39,7 @@ int main( int argc, char *argv[] )
 	   change the error handler to errors return */
 	MPI_Comm_set_errhandler( comm, MPI_ERRORS_RETURN );
 
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		/* Make sure that everyone has a recv buffer */
 		recvtype.InitBuf( &recvtype );
diff --git a/test/mpi/pt2pt/sendself.c b/test/mpi/pt2pt/sendself.c
index 5286272..6b1e261 100644
--- a/test/mpi/pt2pt/sendself.c
+++ b/test/mpi/pt2pt/sendself.c
@@ -31,7 +31,7 @@ int main( int argc, char *argv[] )
        change the error handler to errors return */
     MPI_Comm_set_errhandler( comm, MPI_ERRORS_RETURN );
     
-    for (count = 1; count < 65000; count = count * 2) {
+    MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 	    
 	    sendtype.InitBuf( &sendtype );
diff --git a/test/mpi/rma/accfence1.c b/test/mpi/rma/accfence1.c
index 91d9f43..0ede7ab 100644
--- a/test/mpi/rma/accfence1.c
+++ b/test/mpi/rma/accfence1.c
@@ -36,7 +36,7 @@ int main( int argc, char *argv[] )
 	source = 0;
 	dest   = size - 1;
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		/* Make sure that everyone has a recv buffer */
 		recvtype.InitBuf( &recvtype );
diff --git a/test/mpi/rma/accpscw1.c b/test/mpi/rma/accpscw1.c
index 4b4976e..893a577 100644
--- a/test/mpi/rma/accpscw1.c
+++ b/test/mpi/rma/accpscw1.c
@@ -37,7 +37,7 @@ int main( int argc, char *argv[] )
 	source = 0;
 	dest   = size - 1;
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		/* Make sure that everyone has a recv buffer */
 		recvtype.InitBuf( &recvtype );
diff --git a/test/mpi/rma/epochtest.c b/test/mpi/rma/epochtest.c
index 7a3222a..4504454 100644
--- a/test/mpi/rma/epochtest.c
+++ b/test/mpi/rma/epochtest.c
@@ -57,7 +57,7 @@ int main( int argc, char **argv )
 	source = 0;
 	dest   = size - 1;
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 
 		MTestPrintfMsg( 1, 
diff --git a/test/mpi/rma/getfence1.c b/test/mpi/rma/getfence1.c
index 2aaba82..869b143 100644
--- a/test/mpi/rma/getfence1.c
+++ b/test/mpi/rma/getfence1.c
@@ -36,7 +36,7 @@ int main( int argc, char *argv[] )
 	source = 0;
 	dest   = size - 1;
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		/* Make sure that everyone has a recv buffer */
 		recvtype.InitBuf( &recvtype );
diff --git a/test/mpi/rma/putfence1.c b/test/mpi/rma/putfence1.c
index 1020063..5c6bee4 100644
--- a/test/mpi/rma/putfence1.c
+++ b/test/mpi/rma/putfence1.c
@@ -36,7 +36,7 @@ int main( int argc, char *argv[] )
 	source = 0;
 	dest   = size - 1;
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 
 		MTestPrintfMsg( 1, 
diff --git a/test/mpi/rma/putpscw1.c b/test/mpi/rma/putpscw1.c
index ff18f4c..fb05df5 100644
--- a/test/mpi/rma/putpscw1.c
+++ b/test/mpi/rma/putpscw1.c
@@ -37,7 +37,7 @@ int main( int argc, char *argv[] )
 	source = 0;
 	dest   = size - 1;
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		/* Make sure that everyone has a recv buffer */
 		recvtype.InitBuf( &recvtype );
diff --git a/test/mpi/template.c b/test/mpi/template.c
index 323586e..801fc5e 100644
--- a/test/mpi/template.c
+++ b/test/mpi/template.c
@@ -38,7 +38,7 @@ int main( int argc, char *argv[] )
 	   change the error handler to errors return */
 	MPI_Comm_set_errhandler( comm, MPI_ERRORS_RETURN );
 	
-	for (count = 1; count < 65000; count = count * 2) {
+	MTEST_DATATYPE_FOR_EACH_COUNT(count) {
 	    while (MTestGetDatatypes( &sendtype, &recvtype, count )) {
 		if (rank == source) {
 		    sendtype.InitBuf( &sendtype );

http://git.mpich.org/mpich.git/commitdiff/1c9e18f55b0d8b9f19aea650cdb305c8516781f5

commit 1c9e18f55b0d8b9f19aea650cdb305c8516781f5
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Tue Nov 4 14:31:29 2014 -0600

    Add new datatypes in mtest_datatype.
    
    Add hvector, hindexed, indexed_block, hindexed_block, struct,
    subarray with order-c and subarray with order-fortran datatypes.
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/include/mpitest.h b/test/mpi/include/mpitest.h
index 86a6a54..f31c1bc 100644
--- a/test/mpi/include/mpitest.h
+++ b/test/mpi/include/mpitest.h
@@ -44,11 +44,14 @@ typedef struct _MTestDatatype {
 			       (used by the CheckBuf routines) */
     /* The following is optional data that is used by some of
        the derived datatypes */
-    int  stride, nblock, blksize, *index;
-    /* stride, nelm, and blksize are in bytes */
-    int *displs, *displ_in_bytes, basesize;
-    /* displacements are in multiples of base type; basesize is the
-       size of that type*/
+    int  nblock, *index;
+    /* stride, and blksize are in bytes */
+    MPI_Aint stride, blksize, *displ_in_bytes;
+    int *displs, basesize;
+    MPI_Datatype *old_datatypes;
+    /* used in subarray */
+    int arr_sizes[2], arr_subsizes[2], arr_starts[2], order;
+
     void *(*InitBuf)( struct _MTestDatatype * );
     void *(*FreeBuf)( struct _MTestDatatype * );
     int   (*CheckBuf)( struct _MTestDatatype * );
diff --git a/test/mpi/util/mtest_datatype.c b/test/mpi/util/mtest_datatype.c
index c07aedd..412faa7 100644
--- a/test/mpi/util/mtest_datatype.c
+++ b/test/mpi/util/mtest_datatype.c
@@ -43,10 +43,13 @@ static void *MTestTypeFree(MTestDatatype * mtype)
         free(mtype->displ_in_bytes);
     if (mtype->index)
         free(mtype->index);
+    if (mtype->old_datatypes)
+        free(mtype->old_datatypes);
     mtype->buf = 0;
     mtype->displs = 0;
     mtype->displ_in_bytes = 0;
     mtype->index = 0;
+    mtype->old_datatypes = 0;
 
     return 0;
 }
@@ -63,6 +66,7 @@ static inline void MTestTypeReset(MTestDatatype * mtype)
     mtype->index = 0;
     mtype->displs = 0;
     mtype->displ_in_bytes = 0;
+    mtype->old_datatypes = 0;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -248,12 +252,12 @@ static int MTestTypeVectorCheckbuf(MTestDatatype * mtype)
  */
 static void *MTestTypeIndexedInit(MTestDatatype * mtype)
 {
-    MPI_Aint size = 0, totsize;
+    MPI_Aint size = 0, totsize, dt_offset, offset;
     int merr;
 
     if (mtype->count > 0) {
         unsigned char *p;
-        int i, j, k, b, nc, offset, dt_offset;
+        int i, j, k, b, nc;
 
         /* Allocate buffer */
         merr = MPI_Type_extent(mtype->datatype, &size);
@@ -314,11 +318,11 @@ static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
     unsigned char *p;
     unsigned char expected;
     int err = 0, merr;
-    MPI_Aint size = 0;
+    MPI_Aint size = 0, offset, dt_offset;
 
     p = (unsigned char *) mtype->buf;
     if (p) {
-        int i, j, k, b, nc, offset, dt_offset;
+        int i, j, k, b, nc;
         merr = MPI_Type_extent(mtype->datatype, &size);
         if (merr)
             MTestPrintError(merr);
@@ -353,6 +357,240 @@ static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
     return err;
 }
 
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for indexed-block datatypes                            */
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Initialize buffer of indexed-block datatype
+ */
+static void *MTestTypeIndexedBlockInit(MTestDatatype * mtype)
+{
+    MPI_Aint size = 0, totsize, offset, dt_offset;
+    int merr;
+
+    if (mtype->count > 0) {
+        unsigned char *p;
+        int i, k, j, nc;
+
+        /* Allocate the send/recv buffer */
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = size * mtype->count;
+
+        if (!mtype->buf) {
+            mtype->buf = (void *) malloc(totsize);
+        }
+        p = (unsigned char *) (mtype->buf);
+        if (!p) {
+            char errmsg[128] = { 0 };
+            sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+            MTestError(errmsg);
+        }
+
+        /* First, set to -1 */
+        for (i = 0; i < totsize; i++)
+            p[i] = 0xff;
+
+        /* Now, set the actual elements to the successive values.
+         * We require that the base type is a contiguous type */
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each block */
+            for (i = 0; i < mtype->nblock; i++) {
+                offset = dt_offset + mtype->displ_in_bytes[i];
+                /* For each byte in the block */
+                for (j = 0; j < mtype->blksize; j++) {
+                    p[offset + j] = (unsigned char) (0xff ^ (nc++ & 0xff));
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    else {
+        /* count == 0 */
+        if (mtype->buf) {
+            free(mtype->buf);
+        }
+        mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/*
+ * Check value of received indexed-block datatype buffer
+ */
+static int MTestTypeIndexedBlockCheckbuf(MTestDatatype * mtype)
+{
+    unsigned char *p;
+    unsigned char expected;
+    int err = 0, merr;
+    MPI_Aint size = 0, offset, dt_offset;
+
+    p = (unsigned char *) mtype->buf;
+    if (p) {
+        int i, j, k, nc;
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each block */
+            for (i = 0; i < mtype->nblock; i++) {
+                offset = dt_offset + mtype->displ_in_bytes[i];
+                /* For each byte in the block */
+                for (j = 0; j < mtype->blksize; j++) {
+                    expected = (unsigned char) (0xff ^ (nc++ & 0xff));
+                    if (p[offset + j] != expected) {
+                        err++;
+                        if (mtype->printErrors && err < 10) {
+                            printf("Data expected = %x but got p[%d,%d] = %x\n",
+                                   expected, i, j, p[offset + j]);
+                            fflush(stdout);
+                        }
+                    }
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    return err;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for subarray datatypes with order Fortran              */
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Initialize buffer of subarray datatype.
+ */
+static void *MTestTypeSubarrayInit(MTestDatatype * mtype)
+{
+    MPI_Aint size = 0, totsize, offset, dt_offset, byte_offset;
+    int merr;
+
+    if (mtype->count > 0) {
+        unsigned char *p;
+        int i, k, j, b, nc;
+
+        /* Allocate the send/recv buffer */
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = size * mtype->count;
+
+        if (!mtype->buf) {
+            mtype->buf = (void *) malloc(totsize);
+        }
+        p = (unsigned char *) (mtype->buf);
+        if (!p) {
+            char errmsg[128] = { 0 };
+            sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+            MTestError(errmsg);
+        }
+
+        /* First, set to -1 */
+        for (i = 0; i < totsize; i++)
+            p[i] = 0xff;
+
+        /* Now, set the actual elements to the successive values.
+         * We require that the base type is a contiguous type. */
+        int ncol, sub_ncol, sub_nrow, sub_col_start, sub_row_start;
+        ncol = mtype->arr_sizes[1];
+        sub_nrow = mtype->arr_subsizes[0];
+        sub_ncol = mtype->arr_subsizes[1];
+        sub_row_start = mtype->arr_starts[0];
+        sub_col_start = mtype->arr_starts[1];
+
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each row */
+            for (i = 0; i < sub_nrow; i++) {
+                offset = (sub_row_start + i) * ncol + sub_col_start;
+                /* For each element in row */
+                for (j = 0; j < sub_ncol; j++) {
+                    byte_offset = dt_offset + (offset + j) * mtype->basesize;
+                    /* For each byte in element */
+                    for (b = 0; b < mtype->basesize; b++)
+                        p[byte_offset + b] = (unsigned char) (0xff ^ (nc++ & 0xff));
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    else {
+        /* count == 0 */
+        if (mtype->buf) {
+            free(mtype->buf);
+        }
+        mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/*
+ * Check value of received subarray datatype buffer
+ */
+static int MTestTypeSubarrayCheckbuf(MTestDatatype * mtype)
+{
+    unsigned char *p;
+    unsigned char expected;
+    int err = 0, merr;
+    MPI_Aint size, offset, dt_offset, byte_offset;
+
+    p = (unsigned char *) mtype->buf;
+    if (p) {
+        int j, k, i, b, nc;
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+
+        int ncol, sub_ncol, sub_nrow, sub_col_start, sub_row_start;
+        ncol = mtype->arr_sizes[1];
+        sub_nrow = mtype->arr_subsizes[0];
+        sub_ncol = mtype->arr_subsizes[1];
+        sub_row_start = mtype->arr_starts[0];
+        sub_col_start = mtype->arr_starts[1];
+
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each row */
+            for (i = 0; i < sub_nrow; i++) {
+                offset = (sub_row_start + i) * ncol + sub_col_start;
+                /* For each element in row */
+                for (j = 0; j < sub_ncol; j++) {
+                    byte_offset = dt_offset + (offset + j) * mtype->basesize;
+                    /* For each byte in element */
+                    for (b = 0; b < mtype->basesize; b++) {
+                        expected = (unsigned char) (0xff ^ (nc++ & 0xff));
+                        if (p[byte_offset + b] != expected) {
+                            err++;
+                            if (mtype->printErrors && err < 10) {
+                                printf("Data expected = %x but got p[%d,%d,%d] = %x\n",
+                                       expected, i, j, b, p[byte_offset + b]);
+                                fflush(stdout);
+                            }
+                        }
+                    }
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    if (err)
+        printf("%s error\n", __FUNCTION__);
+    return err;
+}
 
 /* ------------------------------------------------------------------------ */
 /* Datatype creators                                                      */
@@ -451,6 +689,56 @@ static int MTestTypeVectorCreate(int nblock, int blocklen, int stride,
 }
 
 /*
+ * Setup hvector type info and handlers.
+ *
+ * A hvector datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block.
+ * stride:   Strided number of elements between blocks.
+ * oldtype:  Datatype of element.
+ */
+static int MTestTypeHvectorCreate(int nblock, int blocklen, int stride,
+                                  MPI_Datatype oldtype, const char *typename_prefix,
+                                  MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* These sizes are in bytes (see the VectorInit code) */
+    mtype->stride = stride * mtype->basesize;
+    mtype->blksize = blocklen * mtype->basesize;
+    mtype->nblock = nblock;
+
+    /* Hvector uses stride in bytes */
+    merr = MPI_Type_create_hvector(nblock, blocklen, mtype->stride, oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "hvector",
+            nblock, blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* User the same functions as vector, because mtype->stride is in bytes */
+    mtype->InitBuf = MTestTypeVectorInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeVectorCheckbuf;
+
+    return merr;
+}
+
+/*
  * Setup indexed type info and handlers.
  *
  * A indexed datatype is created by using following parameters.
@@ -475,7 +763,7 @@ static int MTestTypeIndexedCreate(int nblock, int blocklen, int stride,
         MTestPrintError(merr);
 
     mtype->displs = (int *) malloc(nblock * sizeof(int));
-    mtype->displ_in_bytes = (int *) malloc(nblock * sizeof(int));
+    mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
     mtype->index = (int *) malloc(nblock * sizeof(int));
     if (!mtype->displs || !mtype->displ_in_bytes || !mtype->index) {
         char errmsg[128] = { 0 };
@@ -513,6 +801,381 @@ static int MTestTypeIndexedCreate(int nblock, int blocklen, int stride,
 }
 
 /*
+ * Setup hindexed type info and handlers.
+ *
+ * A hindexed datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block. Each block has the same length.
+ * stride:   Strided number of elements between two adjacent blocks. The byte
+ *           displacement of each block is set as (index of current block * stride * size of oldtype).
+ * oldtype:  Datatype of element.
+ */
+static inline int MTestTypeHindexedCreate(int nblock, int blocklen, int stride,
+                                          MPI_Datatype oldtype, const char *typename_prefix,
+                                          MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+    int i;
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->index = (int *) malloc(nblock * sizeof(int));
+    mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
+    if (!mtype->displ_in_bytes || !mtype->index) {
+        char errmsg[128] = { 0 };
+        sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+        MTestError(errmsg);
+    }
+
+    mtype->nblock = nblock;
+    for (i = 0; i < nblock; i++) {
+        mtype->index[i] = blocklen;
+        mtype->displ_in_bytes[i] = stride * i * mtype->basesize;
+    }
+
+    /* Hindexed uses displacement in bytes */
+    merr = MPI_Type_create_hindexed(nblock, mtype->index, mtype->displ_in_bytes,
+                                    oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "hindex", nblock,
+            blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* Reuse indexed functions, because all of them only use displ_in_bytes */
+    mtype->InitBuf = MTestTypeIndexedInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeIndexedCheckbuf;
+
+    return merr;
+}
+
+
+/*
+ * Setup indexed-block type info and handlers.
+ *
+ * A indexed-block datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block.
+ * stride:   Strided number of elements between two adjacent blocks. The
+ *           displacement of each block is set as (index of current block * stride).
+ * oldtype:  Datatype of element.
+ */
+static int MTestTypeIndexedBlockCreate(int nblock, int blocklen, int stride,
+                                       MPI_Datatype oldtype, const char *typename_prefix,
+                                       MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+    int i;
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->displs = (int *) malloc(nblock * sizeof(int));
+    mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
+    if (!mtype->displs || !mtype->displ_in_bytes) {
+        char errmsg[128] = { 0 };
+        sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+        MTestError(errmsg);
+    }
+
+    mtype->nblock = nblock;
+    mtype->blksize = blocklen * mtype->basesize;
+    for (i = 0; i < nblock; i++) {
+        mtype->displs[i] = stride * i;
+        mtype->displ_in_bytes[i] = stride * i * mtype->basesize;
+    }
+
+    /* Indexed-block uses displacement in oldtypes */
+    merr = MPI_Type_create_indexed_block(nblock, blocklen, mtype->displs,
+                                         oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "index_block",
+            nblock, blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->InitBuf = MTestTypeIndexedBlockInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeIndexedBlockCheckbuf;
+
+    return merr;
+}
+
+/*
+ * Setup hindexed-block type info and handlers.
+ *
+ * A hindexed-block datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block.
+ * stride:   Strided number of elements between two adjacent blocks. The byte
+ *           displacement of each block is set as (index of current block * stride * size of oldtype).
+ * oldtype:  Datatype of element.
+ */
+static int MTestTypeHindexedBlockCreate(int nblock, int blocklen, int stride,
+                                        MPI_Datatype oldtype, const char *typename_prefix,
+                                        MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+    int i;
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
+    if (!mtype->displ_in_bytes) {
+        char errmsg[128] = { 0 };
+        sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+        MTestError(errmsg);
+    }
+
+    mtype->nblock = nblock;
+    mtype->blksize = blocklen * mtype->basesize;
+    for (i = 0; i < nblock; i++) {
+        mtype->displ_in_bytes[i] = stride * i * mtype->basesize;
+    }
+
+    /* Hindexed-block uses displacement in bytes */
+    merr = MPI_Type_create_hindexed_block(nblock, blocklen, mtype->displ_in_bytes,
+                                          oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "hindex_block",
+            nblock, blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* Reuse indexed-block functions, because all of them only use displ_in_bytes */
+    mtype->InitBuf = MTestTypeIndexedBlockInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeIndexedBlockCheckbuf;
+
+    return merr;
+}
+
+/*
+ * Setup struct type info and handlers.
+ *
+ * A struct datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block. Each block has the same length.
+ * stride:   Strided number of elements between two adjacent blocks. The byte
+ *           displacement of each block is set as (index of current block * stride * size of oldtype).
+ * oldtype:  Datatype of element. Each block has the same oldtype.
+ */
+static int MTestTypeStructCreate(int nblock, int blocklen, int stride,
+                                 MPI_Datatype oldtype, const char *typename_prefix,
+                                 MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+    int i;
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->old_datatypes = (MPI_Datatype *) malloc(nblock * sizeof(MPI_Datatype));
+    mtype->displ_in_bytes = (MPI_Aint *) malloc(nblock * sizeof(MPI_Aint));
+    mtype->index = (int *) malloc(nblock * sizeof(int));
+    if (!mtype->displ_in_bytes || !mtype->old_datatypes) {
+        char errmsg[128] = { 0 };
+        sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+        MTestError(errmsg);
+    }
+
+    mtype->nblock = nblock;
+    mtype->blksize = blocklen * mtype->basesize;
+    for (i = 0; i < nblock; i++) {
+        mtype->displ_in_bytes[i] = stride * i * mtype->basesize;
+        mtype->old_datatypes[i] = oldtype;
+        mtype->index[i] = blocklen;
+    }
+
+    /* Struct uses displacement in bytes */
+    merr = MPI_Type_create_struct(nblock, mtype->index, mtype->displ_in_bytes,
+                                  mtype->old_datatypes, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "struct",
+            nblock, blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* Reuse indexed functions, because they use the same displ_in_bytes and index */
+    mtype->InitBuf = MTestTypeIndexedInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeIndexedCheckbuf;
+
+    return merr;
+}
+
+/*
+ * Setup order-C subarray type info and handlers.
+ *
+ * A 2D-subarray datatype specified with order C and located in the left-middle
+ * of the full array is created by using input parameters.
+ * Number of elements in the dimensions of the full array: {nblock + 2, stride}
+ * Number of elements in the dimensions of the subarray: {nblock, blocklen}
+ * Starting of the subarray in each dimension: {1, stride - blocklen}
+ * order: MPI_ORDER_C
+ * oldtype: oldtype
+ */
+static int MTestTypeSubArrayOrderCCreate(int nblock, int blocklen, int stride,
+                                         MPI_Datatype oldtype, const char *typename_prefix,
+                                         MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->arr_sizes[0] = nblock + 2;   /* {row, col} */
+    mtype->arr_sizes[1] = stride;
+    mtype->arr_subsizes[0] = nblock;    /* {row, col} */
+    mtype->arr_subsizes[1] = blocklen;
+    mtype->arr_starts[0] = 1;   /* {row, col} */
+    mtype->arr_starts[1] = stride - blocklen;
+    mtype->order = MPI_ORDER_C;
+
+    merr = MPI_Type_create_subarray(2, mtype->arr_sizes, mtype->arr_subsizes, mtype->arr_starts,
+                                    mtype->order, oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (full{%d,%d}, sub{%d,%d},start{%d,%d})",
+            typename_prefix, "subarray-c", mtype->arr_sizes[0], mtype->arr_sizes[1],
+            mtype->arr_subsizes[0], mtype->arr_subsizes[1], mtype->arr_starts[0],
+            mtype->arr_starts[1]);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->InitBuf = MTestTypeSubarrayInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeSubarrayCheckbuf;
+
+    return merr;
+}
+
+
+/*
+ * Setup order-Fortran subarray type info and handlers.
+ *
+ * A 2D-subarray datatype specified with order Fortran and located in the middle
+ * bottom of the full array is created by using input parameters.
+ * Number of elements in the dimensions of the full array: {stride, nblock + 2}
+ * Number of elements in the dimensions of the subarray: {blocklen, nblock}
+ * Starting of the subarray in each dimension: {stride - blocklen, 1}
+ * order: MPI_ORDER_FORTRAN
+ * oldtype: oldtype
+ */
+static int MTestTypeSubArrayOrderFortranCreate(int nblock, int blocklen, int stride,
+                                               MPI_Datatype oldtype, const char *typename_prefix,
+                                               MTestDatatype * mtype)
+{
+    int merr;
+    char type_name[128];
+
+    MTestTypeReset(mtype);
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* use the same row and col as that of order-c subarray for buffer
+     * initialization and check because we access buffer in order-c */
+    mtype->arr_sizes[0] = nblock + 2;   /* {row, col} */
+    mtype->arr_sizes[1] = stride;
+    mtype->arr_subsizes[0] = nblock;    /* {row, col} */
+    mtype->arr_subsizes[1] = blocklen;
+    mtype->arr_starts[0] = 1;   /* {row, col} */
+    mtype->arr_starts[1] = stride - blocklen;
+    mtype->order = MPI_ORDER_FORTRAN;
+
+    /* reverse row and col when create datatype so that we can get the same
+     * packed data on the other side in order to reuse the contig check function */
+    int arr_sizes[2] = { mtype->arr_sizes[1], mtype->arr_sizes[0] };
+    int arr_subsizes[2] = { mtype->arr_subsizes[1], mtype->arr_subsizes[0] };
+    int arr_starts[2] = { mtype->arr_starts[1], mtype->arr_starts[0] };
+
+    merr = MPI_Type_create_subarray(2, arr_sizes, arr_subsizes, arr_starts,
+                                    mtype->order, oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (full{%d,%d}, sub{%d,%d},start{%d,%d})",
+            typename_prefix, "subarray-f", arr_sizes[0], arr_sizes[1],
+            arr_subsizes[0], arr_subsizes[1], arr_starts[0], arr_starts[1]);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->InitBuf = MTestTypeSubarrayInit;
+    mtype->FreeBuf = MTestTypeFree;
+    mtype->CheckBuf = MTestTypeSubarrayCheckbuf;
+
+    return merr;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines exposed to test generator                             */
+/* ------------------------------------------------------------------------ */
+
+/*
  * Setup basic type info and handlers.
  */
 int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
@@ -609,5 +1272,12 @@ void MTestTypeCreatorInit(MTestDdtCreator * creators)
     memset(creators, 0, sizeof(MTestDdtCreator) * MTEST_DDT_MAX);
     creators[MTEST_DDT_CONTIGUOUS] = MTestTypeContiguousCreate;
     creators[MTEST_DDT_VECTOR] = MTestTypeVectorCreate;
+    creators[MTEST_DDT_HVECTOR] = MTestTypeHvectorCreate;
     creators[MTEST_DDT_INDEXED] = MTestTypeIndexedCreate;
+    creators[MTEST_DDT_HINDEXED] = MTestTypeHindexedCreate;
+    creators[MTEST_DDT_INDEXED_BLOCK] = MTestTypeIndexedBlockCreate;
+    creators[MTEST_DDT_HINDEXED_BLOCK] = MTestTypeHindexedBlockCreate;
+    creators[MTEST_DDT_STRUCT] = MTestTypeStructCreate;
+    creators[MTEST_DDT_SUBARRAY_ORDER_C] = MTestTypeSubArrayOrderCCreate;
+    creators[MTEST_DDT_SUBARRAY_ORDER_FORTRAN] = MTestTypeSubArrayOrderFortranCreate;
 }
diff --git a/test/mpi/util/mtest_datatype.h b/test/mpi/util/mtest_datatype.h
index 48fa96d..f4c6828 100644
--- a/test/mpi/util/mtest_datatype.h
+++ b/test/mpi/util/mtest_datatype.h
@@ -33,7 +33,14 @@ enum MTEST_BASIC_DT {
 enum MTEST_DERIVED_DT {
     MTEST_DDT_CONTIGUOUS,
     MTEST_DDT_VECTOR,
+    MTEST_DDT_HVECTOR,
     MTEST_DDT_INDEXED,
+    MTEST_DDT_HINDEXED,
+    MTEST_DDT_INDEXED_BLOCK,
+    MTEST_DDT_HINDEXED_BLOCK,
+    MTEST_DDT_STRUCT,
+    MTEST_DDT_SUBARRAY_ORDER_C,
+    MTEST_DDT_SUBARRAY_ORDER_FORTRAN,
     MTEST_DDT_MAX
 };
 
diff --git a/test/mpi/util/mtest_datatype_gen.c b/test/mpi/util/mtest_datatype_gen.c
index a19247b..60c53ef 100644
--- a/test/mpi/util/mtest_datatype_gen.c
+++ b/test/mpi/util/mtest_datatype_gen.c
@@ -62,7 +62,8 @@ static int verbose = 0;         /* Message level (0 is none) */
  *    Every type is initialized by the creation function stored in
  *    mtestDdtCreators variable, all of their create/init/check functions are
  *    defined in file mtest_datatype.c. Following derived datatypes are defined:
- *    Contiguous | Vector | Indexed
+ *    Contiguous | Vector | HVector | Indexed | Hindexed | Indexed-block |
+ *    Hindexed-block | Struct | Subarray with order-C | Subarray with order-Fortran
  *
  *  How to add a new derived datatype:
  *    1. Add the new datatype in enum MTEST_DERIVED_DT.

http://git.mpich.org/mpich.git/commitdiff/68832c84f84e6871331b5861cb8b44fc88e0e7ba

commit 68832c84f84e6871331b5861cb8b44fc88e0e7ba
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Tue Nov 4 14:30:38 2014 -0600

    Move datatype reset to mtest_datatype.c
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/util/mtest_datatype.c b/test/mpi/util/mtest_datatype.c
index 596e979..c07aedd 100644
--- a/test/mpi/util/mtest_datatype.c
+++ b/test/mpi/util/mtest_datatype.c
@@ -51,6 +51,19 @@ static void *MTestTypeFree(MTestDatatype * mtype)
     return 0;
 }
 
+static inline void MTestTypeReset(MTestDatatype * mtype)
+{
+    mtype->InitBuf = 0;
+    mtype->FreeBuf = 0;
+    mtype->CheckBuf = 0;
+    mtype->datatype = 0;
+    mtype->isBasic = 0;
+    mtype->printErrors = 0;
+    mtype->buf = 0;
+    mtype->index = 0;
+    mtype->displs = 0;
+    mtype->displ_in_bytes = 0;
+}
 
 /* ------------------------------------------------------------------------ */
 /* Datatype routines for contiguous datatypes                               */
@@ -361,6 +374,8 @@ static int MTestTypeContiguousCreate(int nblock, int blocklen, int stride,
     int merr = 0;
     char type_name[128];
 
+    MTestTypeReset(mtype);
+
     merr = MPI_Type_size(oldtype, &mtype->basesize);
     if (merr)
         MTestPrintError(merr);
@@ -403,6 +418,8 @@ static int MTestTypeVectorCreate(int nblock, int blocklen, int stride,
     int merr = 0;
     char type_name[128];
 
+    MTestTypeReset(mtype);
+
     merr = MPI_Type_size(oldtype, &mtype->basesize);
     if (merr)
         MTestPrintError(merr);
@@ -451,6 +468,8 @@ static int MTestTypeIndexedCreate(int nblock, int blocklen, int stride,
     char type_name[128];
     int i;
 
+    MTestTypeReset(mtype);
+
     merr = MPI_Type_size(oldtype, &mtype->basesize);
     if (merr)
         MTestPrintError(merr);
@@ -500,6 +519,8 @@ int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
 {
     int merr = 0;
 
+    MTestTypeReset(mtype);
+
     merr = MPI_Type_size(oldtype, &mtype->basesize);
     if (merr)
         MTestPrintError(merr);
@@ -523,6 +544,8 @@ int MTestTypeDupCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
 {
     int merr = 0;
 
+    MTestTypeReset(mtype);
+
     merr = MPI_Type_size(oldtype, &mtype->basesize);
     if (merr)
         MTestPrintError(merr);
diff --git a/test/mpi/util/mtest_datatype_gen.c b/test/mpi/util/mtest_datatype_gen.c
index 79fb1f9..a19247b 100644
--- a/test/mpi/util/mtest_datatype_gen.c
+++ b/test/mpi/util/mtest_datatype_gen.c
@@ -314,18 +314,6 @@ static inline int MTestGetRecvDerivedDatatypes(MTestDatatype * sendtype,
     return merr;
 }
 
-static inline void MTestResetDatatype(MTestDatatype * mtype)
-{
-    mtype->InitBuf = 0;
-    mtype->FreeBuf = 0;
-    mtype->CheckBuf = 0;
-    mtype->datatype = 0;
-    mtype->isBasic = 0;
-    mtype->printErrors = 0;
-    mtype->buf = 0;
-}
-
-
 /* ------------------------------------------------------------------------ */
 /* Exposed routine to external tests                                         */
 /* ------------------------------------------------------------------------ */
@@ -336,9 +324,6 @@ int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, int to
     MTestGetDbgInfo(&dbgflag, &verbose);
     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
 
-    MTestResetDatatype(sendtype);
-    MTestResetDatatype(recvtype);
-
     MTestTypeCreatorInit((MTestDdtCreator *) mtestDdtCreators);
 
     if (datatype_index < MTEST_BDT_RANGE) {

http://git.mpich.org/mpich.git/commitdiff/b8173c7f5cb549a33de27dc268e5bedc4a0015cc

commit b8173c7f5cb549a33de27dc268e5bedc4a0015cc
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Mon Nov 3 14:53:47 2014 -0600

    Use general free func for all datatype.
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/util/mtest_datatype.c b/test/mpi/util/mtest_datatype.c
index b2cf308..596e979 100644
--- a/test/mpi/util/mtest_datatype.c
+++ b/test/mpi/util/mtest_datatype.c
@@ -28,6 +28,30 @@
 #endif
 #include <errno.h>
 
+
+/* ------------------------------------------------------------------------ */
+/* General datatype routines                        */
+/* ------------------------------------------------------------------------ */
+
+static void *MTestTypeFree(MTestDatatype * mtype)
+{
+    if (mtype->buf)
+        free(mtype->buf);
+    if (mtype->displs)
+        free(mtype->displs);
+    if (mtype->displ_in_bytes)
+        free(mtype->displ_in_bytes);
+    if (mtype->index)
+        free(mtype->index);
+    mtype->buf = 0;
+    mtype->displs = 0;
+    mtype->displ_in_bytes = 0;
+    mtype->index = 0;
+
+    return 0;
+}
+
+
 /* ------------------------------------------------------------------------ */
 /* Datatype routines for contiguous datatypes                               */
 /* ------------------------------------------------------------------------ */
@@ -69,18 +93,6 @@ static void *MTestTypeContigInit(MTestDatatype * mtype)
 }
 
 /*
- * Free buffer of basic datatype
- */
-static void *MTestTypeContigFree(MTestDatatype * mtype)
-{
-    if (mtype->buf) {
-        free(mtype->buf);
-        mtype->buf = 0;
-    }
-    return 0;
-}
-
-/*
  * Check value of received basic datatype buffer.
  */
 static int MTestTypeContigCheckbuf(MTestDatatype * mtype)
@@ -170,18 +182,6 @@ static void *MTestTypeVectorInit(MTestDatatype * mtype)
 }
 
 /*
- * Free buffer of vector datatype
- */
-static void *MTestTypeVectorFree(MTestDatatype * mtype)
-{
-    if (mtype->buf) {
-        free(mtype->buf);
-        mtype->buf = 0;
-    }
-    return 0;
-}
-
-/*
  * Check value of received vector datatype buffer
  */
 static int MTestTypeVectorCheckbuf(MTestDatatype * mtype)
@@ -294,24 +294,6 @@ static void *MTestTypeIndexedInit(MTestDatatype * mtype)
 }
 
 /*
- * Free buffer of indexed datatype
- */
-static void *MTestTypeIndexedFree(MTestDatatype * mtype)
-{
-    if (mtype->buf) {
-        free(mtype->buf);
-        free(mtype->displs);
-        free(mtype->displ_in_bytes);
-        free(mtype->index);
-        mtype->buf = 0;
-        mtype->displs = 0;
-        mtype->displ_in_bytes = 0;
-        mtype->index = 0;
-    }
-    return 0;
-}
-
-/*
  * Check value of received indexed datatype buffer
  */
 static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
@@ -360,7 +342,7 @@ static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
 
 
 /* ------------------------------------------------------------------------ */
-/* Datatype generators                                                      */
+/* Datatype creators                                                      */
 /* ------------------------------------------------------------------------ */
 
 /*
@@ -400,7 +382,7 @@ static int MTestTypeContiguousCreate(int nblock, int blocklen, int stride,
         MTestPrintError(merr);
 
     mtype->InitBuf = MTestTypeContigInit;
-    mtype->FreeBuf = MTestTypeContigFree;
+    mtype->FreeBuf = MTestTypeFree;
     mtype->CheckBuf = MTestTypeContigCheckbuf;
     return merr;
 }
@@ -446,7 +428,7 @@ static int MTestTypeVectorCreate(int nblock, int blocklen, int stride,
         MTestPrintError(merr);
 
     mtype->InitBuf = MTestTypeVectorInit;
-    mtype->FreeBuf = MTestTypeVectorFree;
+    mtype->FreeBuf = MTestTypeFree;
     mtype->CheckBuf = MTestTypeVectorCheckbuf;
     return merr;
 }
@@ -505,7 +487,7 @@ static int MTestTypeIndexedCreate(int nblock, int blocklen, int stride,
         MTestPrintError(merr);
 
     mtype->InitBuf = MTestTypeIndexedInit;
-    mtype->FreeBuf = MTestTypeIndexedFree;
+    mtype->FreeBuf = MTestTypeFree;
     mtype->CheckBuf = MTestTypeIndexedCheckbuf;
 
     return merr;
@@ -525,7 +507,7 @@ int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
     mtype->datatype = oldtype;
     mtype->isBasic = 1;
     mtype->InitBuf = MTestTypeContigInit;
-    mtype->FreeBuf = MTestTypeContigFree;
+    mtype->FreeBuf = MTestTypeFree;
     mtype->CheckBuf = MTestTypeContigCheckbuf;
 
     return merr;
@@ -553,7 +535,7 @@ int MTestTypeDupCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
      * was committed (MPI-2, section 8.8) */
 
     mtype->InitBuf = MTestTypeContigInit;
-    mtype->FreeBuf = MTestTypeContigFree;
+    mtype->FreeBuf = MTestTypeFree;
     mtype->CheckBuf = MTestTypeContigCheckbuf;
 
     return merr;

http://git.mpich.org/mpich.git/commitdiff/2f896172913cc63d7c03e832e10c0e62710ae5dc

commit 2f896172913cc63d7c03e832e10c0e62710ae5dc
Author: Min Si <msi at il.is.s.u-tokyo.ac.jp>
Date:   Tue Oct 21 12:48:44 2014 -0500

    Separate and rewrite mtest datatype.
    
    This patch separates mtest datatype from file mtest.c and then rewrites
    the whole structure for applying various test patterns and datatypes.
    
    We separate mtest datatype funcs and test generators.
    1. In mtest_datatype_gen.c, we generate test cases for both basic and
    derived datatype.
    2. In mtest_datatype.c, we define the MTestDatatype creator,
    init/free/check functions for each derived datatype in order to reuse in
    multiple test cases generated by 1.
    
    About test case definition:
    1. For every basic datatype, we only define one test case using
    the same type for both send and receive buffers.
    2. For every derived datatype, we test ddt send buffer and receive
    buffer separately, each with contig buffer on the other side. We define
    following four different ddt structures for each test:
    	a.large block length
    	b.large count
    	c.large block length and large stride
    	d.large count and large stride
    
    Signed-off-by: Wesley Bland <wbland at anl.gov>

diff --git a/test/mpi/Makefile.mtest b/test/mpi/Makefile.mtest
index f051b0f..67a9983 100644
--- a/test/mpi/Makefile.mtest
+++ b/test/mpi/Makefile.mtest
@@ -17,6 +17,8 @@
 # AM_CPPFLAGS are used for C++ code as well
 AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
 LDADD = $(top_builddir)/util/mtest.o
+LDADD += $(top_builddir)/util/mtest_datatype.o
+LDADD += $(top_builddir)/util/mtest_datatype_gen.o
 
 ## FIXME "DEPADD" is a simplemake concept, which we can handle on a per-target
 ## prog_DEPENDENCIES variable, but it would be better to figure out the right
@@ -26,6 +28,12 @@ LDADD = $(top_builddir)/util/mtest.o
 $(top_builddir)/util/mtest.$(OBJEXT): $(top_srcdir)/util/mtest.c
 	(cd $(top_builddir)/util && $(MAKE) mtest.$(OBJEXT))
 
+$(top_builddir)/util/mtest_datatype.$(OBJEXT): $(top_srcdir)/util/mtest_datatype.c
+	(cd $(top_builddir)/util && $(MAKE) mtest_datatype.$(OBJEXT))
+
+$(top_builddir)/util/mtest_datatype_gen.$(OBJEXT): $(top_srcdir)/util/mtest_datatype_gen.c
+	(cd $(top_builddir)/util && $(MAKE) mtest_datatype_gen.$(OBJEXT))
+
 testing:
 	$(top_builddir)/runtests -srcdir=$(srcdir) -tests=testlist \
 		-mpiexec=${MPIEXEC} -xmlfile=summary.xml \
diff --git a/test/mpi/include/mpitest.h b/test/mpi/include/mpitest.h
index 292033a..86a6a54 100644
--- a/test/mpi/include/mpitest.h
+++ b/test/mpi/include/mpitest.h
@@ -25,6 +25,7 @@ int MTestReturnValue( int );
  * Utilities
  */
 void MTestSleep( int );
+void MTestGetDbgInfo(int *dbgflag, int *verbose);
 
 /*
  * This structure contains the information used to test datatypes
@@ -43,9 +44,9 @@ typedef struct _MTestDatatype {
 			       (used by the CheckBuf routines) */
     /* The following is optional data that is used by some of
        the derived datatypes */
-    int  stride, nelm, blksize, *index;
+    int  stride, nblock, blksize, *index;
     /* stride, nelm, and blksize are in bytes */
-    int *displs, basesize;
+    int *displs, *displ_in_bytes, basesize;
     /* displacements are in multiples of base type; basesize is the
        size of that type*/
     void *(*InitBuf)( struct _MTestDatatype * );
diff --git a/test/mpi/util/mtest.c b/test/mpi/util/mtest.c
index 43a1590..ea309c0 100644
--- a/test/mpi/util/mtest.c
+++ b/test/mpi/util/mtest.c
@@ -256,712 +256,12 @@ void MTestSleep( int sec )
 }
 #endif
 
-/*
- * Datatypes
- *
- * Eventually, this could read a description of a file.  For now, we hard 
- * code the choices.
- *
- * Each kind of datatype has the following functions:
- *    MTestTypeXXXInit     - Initialize a send buffer for that type
- *    MTestTypeXXXInitRecv - Initialize a receive buffer for that type
- *    MTestTypeXXXFree     - Free any buffers associate with that type
- *    MTestTypeXXXCheckbuf - Check that the buffer contains the expected data
- * These routines work with (nearly) any datatype that is of type XXX, 
- * allowing the test codes to create a variety of contiguous, vector, and
- * indexed types, then test them by calling these routines.
- *
- * Available types (for the XXX) are
- *    Contig   - Simple contiguous buffers
- *    Vector   - Simple strided "vector" type
- *    Indexed  - Indexed datatype.  Only for a count of 1 instance of the 
- *               datatype
- */
-static int datatype_index = 0;
-
-/* ------------------------------------------------------------------------ */
-/* Datatype routines for contiguous datatypes                               */
-/* ------------------------------------------------------------------------ */
-/* 
- * Setup contiguous buffers of n copies of a datatype.
- */
-static void *MTestTypeContigInit( MTestDatatype *mtype )
-{
-    MPI_Aint size;
-    int merr;
-
-    if (mtype->count > 0) {
-	signed char *p;
-	int  i, totsize;
-	merr = MPI_Type_extent( mtype->datatype, &size );
-	if (merr) MTestPrintError( merr );
-	totsize = size * mtype->count;
-	if (!mtype->buf) {
-	    mtype->buf = (void *) malloc( totsize );
-	}
-	p = (signed char *)(mtype->buf);
-	if (!p) {
-	    /* Error - out of memory */
-	    MTestError( "Out of memory in type buffer init" );
-	}
-	for (i=0; i<totsize; i++) {
-	    p[i] = 0xff ^ (i & 0xff);
-	}
-    }
-    else {
-	if (mtype->buf) {
-	    free( mtype->buf );
-	}
-	mtype->buf = 0;
-    }
-    return mtype->buf;
-}
-
-/* 
- * Setup contiguous buffers of n copies of a datatype.  Initialize for
- * reception (e.g., set initial data to detect failure)
- */
-static void *MTestTypeContigInitRecv( MTestDatatype *mtype )
-{
-    MPI_Aint size;
-    int      merr;
-
-    if (mtype->count > 0) {
-	signed char *p;
-	int  i, totsize;
-	merr = MPI_Type_extent( mtype->datatype, &size );
-	if (merr) MTestPrintError( merr );
-	totsize = size * mtype->count;
-	if (!mtype->buf) {
-	    mtype->buf = (void *) malloc( totsize );
-	}
-	p = (signed char *)(mtype->buf);
-	if (!p) {
-	    /* Error - out of memory */
-	    MTestError( "Out of memory in type buffer init" );
-	}
-	for (i=0; i<totsize; i++) {
-	    p[i] = 0xff;
-	}
-    }
-    else {
-	if (mtype->buf) {
-	    free( mtype->buf );
-	}
-	mtype->buf = 0;
-    }
-    return mtype->buf;
-}
-static void *MTestTypeContigFree( MTestDatatype *mtype )
-{
-    if (mtype->buf) {
-	free( mtype->buf );
-	mtype->buf = 0;
-    }
-    return 0;
-}
-static int MTestTypeContigCheckbuf( MTestDatatype *mtype )
-{
-    unsigned char *p;
-    unsigned char expected;
-    int  i, totsize, err = 0, merr;
-    MPI_Aint size;
-
-    p = (unsigned char *)mtype->buf;
-    if (p) {
-	merr = MPI_Type_extent( mtype->datatype, &size );
-	if (merr) MTestPrintError( merr );
-	totsize = size * mtype->count;
-	for (i=0; i<totsize; i++) {
-	    expected = (0xff ^ (i & 0xff));
-	    if (p[i] != expected) {
-		err++;
-		if (mtype->printErrors && err < 10) {
-		    printf( "Data expected = %x but got p[%d] = %x\n",
-			    expected, i, p[i] );
-		    fflush( stdout );
-		}
-	    }
-	}
-    }
-    return err;
-}
-
-/* ------------------------------------------------------------------------ */
-/* Datatype routines for vector datatypes                                   */
-/* ------------------------------------------------------------------------ */
-
-static void *MTestTypeVectorInit( MTestDatatype *mtype )
-{
-    MPI_Aint size;
-    int      merr;
-
-    if (mtype->count > 0) {
-	unsigned char *p;
-	int  i, j, k, nc, totsize;
-
-	merr = MPI_Type_extent( mtype->datatype, &size );
-	if (merr) MTestPrintError( merr );
-	totsize	   = mtype->count * size;
-	if (!mtype->buf) {
-	    mtype->buf = (void *) malloc( totsize );
-	}
-	p	   = (unsigned char *)(mtype->buf);
-	if (!p) {
-	    /* Error - out of memory */
-	    MTestError( "Out of memory in type buffer init" );
-	}
-
-	/* First, set to -1 */
-	for (i=0; i<totsize; i++) p[i] = 0xff;
-
-	/* Now, set the actual elements to the successive values.
-	   To do this, we need to run 3 loops */
-	nc = 0;
-	/* count is usually one for a vector type */
-	for (k=0; k<mtype->count; k++) {
-	    /* For each element (block) */
-	    for (i=0; i<mtype->nelm; i++) {
-		/* For each value */
-		for (j=0; j<mtype->blksize; j++) {
-		    p[j] = (0xff ^ (nc & 0xff));
-		    nc++;
-		}
-		p += mtype->stride;
-	    }
-	}
-    }
-    else {
-	mtype->buf = 0;
-    }
-    return mtype->buf;
+/* Other mtest subfiles read debug setting using this function. */
+void MTestGetDbgInfo(int *_dbgflag, int *_verbose) {
+    *_dbgflag = dbgflag;
+    *_verbose = verbose;
 }
 
-static void *MTestTypeVectorFree( MTestDatatype *mtype )
-{
-    if (mtype->buf) {
-	free( mtype->buf );
-	mtype->buf = 0;
-    }
-    return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-/* Datatype routines for indexed block datatypes                            */
-/* ------------------------------------------------------------------------ */
-
-/* 
- * Setup a buffer for one copy of an indexed datatype. 
- */
-static void *MTestTypeIndexedInit( MTestDatatype *mtype )
-{
-    MPI_Aint totsize;
-    int      merr;
-    
-    if (mtype->count > 1) {
-	MTestError( "This datatype is supported only for a single count" );
-    }
-    if (mtype->count == 1) {
-	signed char *p;
-	int  i, k, offset, j;
-
-	/* Allocate the send/recv buffer */
-	merr = MPI_Type_extent( mtype->datatype, &totsize );
-	if (merr) MTestPrintError( merr );
-	if (!mtype->buf) {
-	    mtype->buf = (void *) malloc( totsize );
-	}
-	p = (signed char *)(mtype->buf);
-	if (!p) {
-	    MTestError( "Out of memory in type buffer init\n" );
-	}
-	/* Initialize the elements */
-	/* First, set to -1 */
-	for (i=0; i<totsize; i++) p[i] = 0xff;
-
-	/* Now, set the actual elements to the successive values.
-	   We require that the base type is a contiguous type */
-	k = 0;
-	for (i=0; i<mtype->nelm; i++) {
-	    int b;
-	    /* Compute the offset: */
-	    offset = mtype->displs[i] * mtype->basesize;
-	    /* For each element in the block */
-	    for (b=0; b<mtype->index[i]; b++) {
-		for (j=0; j<mtype->basesize; j++) {
-		    p[offset+j] = 0xff ^ (k++ & 0xff);
-		}
-		offset += mtype->basesize;
-	    }
-	}
-    }
-    else {
-	/* count == 0 */
-	if (mtype->buf) {
-	    free( mtype->buf );
-	}
-	mtype->buf = 0;
-    }
-    return mtype->buf;
-}
-
-/* 
- * Setup indexed buffers for 1 copy of a datatype.  Initialize for
- * reception (e.g., set initial data to detect failure)
- */
-static void *MTestTypeIndexedInitRecv( MTestDatatype *mtype )
-{
-    MPI_Aint totsize;
-    int      merr;
-
-    if (mtype->count > 1) {
-	MTestError( "This datatype is supported only for a single count" );
-    }
-    if (mtype->count == 1) {
-	signed char *p;
-	int  i;
-	merr = MPI_Type_extent( mtype->datatype, &totsize );
-	if (merr) MTestPrintError( merr );
-	if (!mtype->buf) {
-	    mtype->buf = (void *) malloc( totsize );
-	}
-	p = (signed char *)(mtype->buf);
-	if (!p) {
-	    /* Error - out of memory */
-	    MTestError( "Out of memory in type buffer init\n" );
-	}
-	for (i=0; i<totsize; i++) {
-	    p[i] = 0xff;
-	}
-    }
-    else {
-	/* count == 0 */
-	if (mtype->buf) {
-	    free( mtype->buf );
-	}
-	mtype->buf = 0;
-    }
-    return mtype->buf;
-}
-
-static void *MTestTypeIndexedFree( MTestDatatype *mtype )
-{
-    if (mtype->buf) {
-	free( mtype->buf );
-	free( mtype->displs );
-	free( mtype->index );
-	mtype->buf    = 0;
-	mtype->displs = 0;
-	mtype->index  = 0;
-    }
-    return 0;
-}
-
-static int MTestTypeIndexedCheckbuf( MTestDatatype *mtype )
-{
-    unsigned char *p;
-    unsigned char expected;
-    int  i, err = 0, merr;
-    MPI_Aint totsize;
-
-    p = (unsigned char *)mtype->buf;
-    if (p) {
-	int j, k, offset;
-	merr = MPI_Type_extent( mtype->datatype, &totsize );
-	if (merr) MTestPrintError( merr );
-	
-	k = 0;
-	for (i=0; i<mtype->nelm; i++) {
-	    int b;
-	    /* Compute the offset: */
-	    offset = mtype->displs[i] * mtype->basesize;
-	    for (b=0; b<mtype->index[i]; b++) {
-		for (j=0; j<mtype->basesize; j++) {
-		    expected = (0xff ^ (k & 0xff));
-		    if (p[offset+j] != expected) {
-			err++;
-			if (mtype->printErrors && err < 10) {
-			    printf( "Data expected = %x but got p[%d,%d] = %x\n",
-				    expected, i,j, p[offset+j] );
-			    fflush( stdout );
-			}
-		    }
-		    k++;
-		}
-		offset += mtype->basesize;
-	    }
-	}
-    }
-    return err;
-}
-
-
-/* ------------------------------------------------------------------------ */
-/* Routines to select a datatype and associated buffer create/fill/check    */
-/* routines                                                                 */
-/* ------------------------------------------------------------------------ */
-
-/* 
-   Create a range of datatypes with a given count elements.
-   This uses a selection of types, rather than an exhaustive collection.
-   It allocates both send and receive types so that they can have the same
-   type signature (collection of basic types) but different type maps (layouts
-   in memory) 
- */
-int MTestGetDatatypes( MTestDatatype *sendtype, MTestDatatype *recvtype,
-		       int count )
-{
-    int merr;
-    int i;
-
-    sendtype->InitBuf	  = 0;
-    sendtype->FreeBuf	  = 0;
-    sendtype->CheckBuf	  = 0;
-    sendtype->datatype	  = 0;
-    sendtype->isBasic	  = 0;
-    sendtype->printErrors = 0;
-    recvtype->InitBuf	  = 0;
-    recvtype->FreeBuf	  = 0;
-
-    recvtype->CheckBuf	  = 0;
-    recvtype->datatype	  = 0;
-    recvtype->isBasic	  = 0;
-    recvtype->printErrors = 0;
-
-    sendtype->buf	  = 0;
-    recvtype->buf	  = 0;
-
-    /* Set the defaults for the message lengths */
-    sendtype->count	  = count;
-    recvtype->count	  = count;
-    /* Use datatype_index to choose a datatype to use.  If at the end of the
-       list, return 0 */
-    switch (datatype_index) {
-    case 0:
-	sendtype->datatype = MPI_INT;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_INT;
-	recvtype->isBasic  = 1;
-	break;
-    case 1:
-	sendtype->datatype = MPI_DOUBLE;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_DOUBLE;
-	recvtype->isBasic  = 1;
-	break;
-    case 2:
-	sendtype->datatype = MPI_FLOAT_INT;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_FLOAT_INT;
-	recvtype->isBasic  = 1;
-	break;
-    case 3:
-	merr = MPI_Type_dup( MPI_INT, &sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_set_name( sendtype->datatype,
-                                  (char*)"dup of MPI_INT" );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_dup( MPI_INT, &recvtype->datatype );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_set_name( recvtype->datatype,
-                                  (char*)"dup of MPI_INT" );
-	if (merr) MTestPrintError( merr );
-	/* dup'ed types are already committed if the original type 
-	   was committed (MPI-2, section 8.8) */
-	break;
-    case 4:
-	/* vector send type and contiguous receive type */
-	/* These sizes are in bytes (see the VectorInit code) */
- 	sendtype->stride   = 3 * sizeof(int);
-	sendtype->blksize  = sizeof(int);
-	sendtype->nelm     = recvtype->count;
-
-	merr = MPI_Type_vector( recvtype->count, 1, 3, MPI_INT, 
-				&sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-        merr = MPI_Type_commit( &sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_set_name( sendtype->datatype,
-                                  (char*)"int-vector" );
-	if (merr) MTestPrintError( merr );
-	sendtype->count    = 1;
- 	recvtype->datatype = MPI_INT;
-	recvtype->isBasic  = 1;
-	sendtype->InitBuf  = MTestTypeVectorInit;
-	recvtype->InitBuf  = MTestTypeContigInitRecv;
-	sendtype->FreeBuf  = MTestTypeVectorFree;
-	recvtype->FreeBuf  = MTestTypeContigFree;
-	sendtype->CheckBuf = 0;
-	recvtype->CheckBuf = MTestTypeContigCheckbuf;
-	break;
-
-    case 5:
-	/* Indexed send using many small blocks and contig receive */
-	sendtype->blksize  = sizeof(int);
-	sendtype->nelm     = recvtype->count;
-	sendtype->basesize = sizeof(int);
-	sendtype->displs   = (int *)malloc( sendtype->nelm * sizeof(int) );
-	sendtype->index    = (int *)malloc( sendtype->nelm * sizeof(int) );
-	if (!sendtype->displs || !sendtype->index) {
-	    MTestError( "Out of memory in type init\n" );
-	}
-	/* Make the sizes larger (4 ints) to help push the total
-	   size to over 256k in some cases, as the MPICH code as of
-	   10/1/06 used large internal buffers for packing non-contiguous
-	   messages */
-	for (i=0; i<sendtype->nelm; i++) {
-	    sendtype->index[i]   = 4;
-	    sendtype->displs[i]  = 5*i;
-	}
-	merr = MPI_Type_indexed( sendtype->nelm,
-				 sendtype->index, sendtype->displs, 
-				 MPI_INT, &sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-        merr = MPI_Type_commit( &sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_set_name( sendtype->datatype,
-                                  (char*)"int-indexed(4-int)" );
-	if (merr) MTestPrintError( merr );
-	sendtype->count    = 1;
-	sendtype->InitBuf  = MTestTypeIndexedInit;
-	sendtype->FreeBuf  = MTestTypeIndexedFree;
-	sendtype->CheckBuf = 0;
-
- 	recvtype->datatype = MPI_INT;
-	recvtype->isBasic  = 1;
-	recvtype->count    = count * 4;
-	recvtype->InitBuf  = MTestTypeContigInitRecv;
-	recvtype->FreeBuf  = MTestTypeContigFree;
-	recvtype->CheckBuf = MTestTypeContigCheckbuf;
-	break;
-
-    case 6:
-	/* Indexed send using 2 large blocks and contig receive */
-	sendtype->blksize  = sizeof(int);
-	sendtype->nelm     = 2;
-	sendtype->basesize = sizeof(int);
-	sendtype->displs   = (int *)malloc( sendtype->nelm * sizeof(int) );
-	sendtype->index    = (int *)malloc( sendtype->nelm * sizeof(int) );
-	if (!sendtype->displs || !sendtype->index) {
-	    MTestError( "Out of memory in type init\n" );
-	}
-	/* index -> block size */
-	sendtype->index[0]   = (recvtype->count + 1) / 2;
-	sendtype->displs[0]  = 0;
-	sendtype->index[1]   = recvtype->count - sendtype->index[0];
-	sendtype->displs[1]  = sendtype->index[0] + 1; 
-	/* There is a deliberate gap here */
-
-	merr = MPI_Type_indexed( sendtype->nelm,
-				 sendtype->index, sendtype->displs, 
-				 MPI_INT, &sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-        merr = MPI_Type_commit( &sendtype->datatype );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_set_name( sendtype->datatype,
-                                  (char*)"int-indexed(2 blocks)" );
-	if (merr) MTestPrintError( merr );
-	sendtype->count    = 1;
-	sendtype->InitBuf  = MTestTypeIndexedInit;
-	sendtype->FreeBuf  = MTestTypeIndexedFree;
-	sendtype->CheckBuf = 0;
-
- 	recvtype->datatype = MPI_INT;
-	recvtype->isBasic  = 1;
-	recvtype->count    = sendtype->index[0] + sendtype->index[1];
-	recvtype->InitBuf  = MTestTypeContigInitRecv;
-	recvtype->FreeBuf  = MTestTypeContigFree;
-	recvtype->CheckBuf = MTestTypeContigCheckbuf;
-	break;
-
-    case 7:
-	/* Indexed receive using many small blocks and contig send */
-	recvtype->blksize  = sizeof(int);
-	recvtype->nelm     = recvtype->count;
-	recvtype->basesize = sizeof(int);
-	recvtype->displs   = (int *)malloc( recvtype->nelm * sizeof(int) );
-	recvtype->index    = (int *)malloc( recvtype->nelm * sizeof(int) );
-	if (!recvtype->displs || !recvtype->index) {
-	    MTestError( "Out of memory in type recv init\n" );
-	}
-	/* Make the sizes larger (4 ints) to help push the total
-	   size to over 256k in some cases, as the MPICH code as of
-	   10/1/06 used large internal buffers for packing non-contiguous
-	   messages */
-	/* Note that there are gaps in the indexed type */
-	for (i=0; i<recvtype->nelm; i++) {
-	    recvtype->index[i]   = 4;
-	    recvtype->displs[i]  = 5*i;
-	}
-	merr = MPI_Type_indexed( recvtype->nelm,
-				 recvtype->index, recvtype->displs, 
-				 MPI_INT, &recvtype->datatype );
-	if (merr) MTestPrintError( merr );
-        merr = MPI_Type_commit( &recvtype->datatype );
-	if (merr) MTestPrintError( merr );
-	merr = MPI_Type_set_name( recvtype->datatype,
-                                  (char*)"recv-int-indexed(4-int)" );
-	if (merr) MTestPrintError( merr );
-	recvtype->count    = 1;
-	recvtype->InitBuf  = MTestTypeIndexedInitRecv;
-	recvtype->FreeBuf  = MTestTypeIndexedFree;
-	recvtype->CheckBuf = MTestTypeIndexedCheckbuf;
-
- 	sendtype->datatype = MPI_INT;
-	sendtype->isBasic  = 1;
-	sendtype->count    = count * 4;
-	sendtype->InitBuf  = MTestTypeContigInit;
-	sendtype->FreeBuf  = MTestTypeContigFree;
-	sendtype->CheckBuf = 0;
-	break;
-
-	/* Less commonly used but still simple types */
-    case 8:
-	sendtype->datatype = MPI_SHORT;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_SHORT;
-	recvtype->isBasic  = 1;
-	break;
-    case 9:
-	sendtype->datatype = MPI_LONG;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_LONG;
-	recvtype->isBasic  = 1;
-	break;
-    case 10:
-	sendtype->datatype = MPI_CHAR;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_CHAR;
-	recvtype->isBasic  = 1;
-	break;
-    case 11:
-	sendtype->datatype = MPI_UINT64_T;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_UINT64_T;
-	recvtype->isBasic  = 1;
-	break;
-    case 12:
-	sendtype->datatype = MPI_FLOAT;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_FLOAT;
-	recvtype->isBasic  = 1;
-	break;
-
-#ifndef USE_STRICT_MPI
-	/* MPI_BYTE may only be used with MPI_BYTE in strict MPI */
-    case 13:
-	sendtype->datatype = MPI_INT;
-	sendtype->isBasic  = 1;
-	recvtype->datatype = MPI_BYTE;
-	recvtype->isBasic  = 1;
-	recvtype->count    *= sizeof(int);
-	break;
-#endif
-    default:
-	datatype_index = -1;
-    }
-
-    if (!sendtype->InitBuf) {
-	sendtype->InitBuf  = MTestTypeContigInit;
-	recvtype->InitBuf  = MTestTypeContigInitRecv;
-	sendtype->FreeBuf  = MTestTypeContigFree;
-	recvtype->FreeBuf  = MTestTypeContigFree;
-	sendtype->CheckBuf = MTestTypeContigCheckbuf;
-	recvtype->CheckBuf = MTestTypeContigCheckbuf;
-    }
-    datatype_index++;
-
-    if (dbgflag && datatype_index > 0) {
-	int typesize;
-	fprintf( stderr, "%d: sendtype is %s\n", wrank, MTestGetDatatypeName( sendtype ) );
-	merr = MPI_Type_size( sendtype->datatype, &typesize );
-	if (merr) MTestPrintError( merr );
-	fprintf( stderr, "%d: sendtype size = %d\n", wrank, typesize );
-	fprintf( stderr, "%d: recvtype is %s\n", wrank, MTestGetDatatypeName( recvtype ) );
-	merr = MPI_Type_size( recvtype->datatype, &typesize );
-	if (merr) MTestPrintError( merr );
-	fprintf( stderr, "%d: recvtype size = %d\n", wrank, typesize );
-	fflush( stderr );
-	
-    }
-    else if (verbose && datatype_index > 0) {
-	printf( "Get new datatypes: send = %s, recv = %s\n", 
-		MTestGetDatatypeName( sendtype ), 
-		MTestGetDatatypeName( recvtype ) );
-	fflush( stdout );
-    }
-
-    return datatype_index;
-}
-
-/* Reset the datatype index (start from the initial data type.
-   Note: This routine is rarely needed; MTestGetDatatypes automatically
-   starts over after the last available datatype is used.
-*/
-void MTestResetDatatypes( void )
-{
-    datatype_index = 0;
-}
-/* Return the index of the current datatype.  This is rarely needed and
-   is provided mostly to enable debugging of the MTest package itself */
-int MTestGetDatatypeIndex( void )
-{
-    return datatype_index;
-}
-
-/* Free the storage associated with a datatype */
-void MTestFreeDatatype( MTestDatatype *mtype )
-{
-    int merr;
-    /* Invoke a datatype-specific free function to handle
-       both the datatype and the send/receive buffers */
-    if (mtype->FreeBuf) {
-	(mtype->FreeBuf)( mtype );
-    }
-    /* Free the datatype itself if it was created */
-    if (!mtype->isBasic) {
-	merr = MPI_Type_free( &mtype->datatype );
-	if (merr) MTestPrintError( merr );
-    }
-}
-
-/* Check that a message was received correctly.  Returns the number of
-   errors detected.  Status may be NULL or MPI_STATUS_IGNORE */
-int MTestCheckRecv( MPI_Status *status, MTestDatatype *recvtype )
-{
-    int count;
-    int errs = 0, merr;
-
-    if (status && status != MPI_STATUS_IGNORE) {
-	merr = MPI_Get_count( status, recvtype->datatype, &count );
-	if (merr) MTestPrintError( merr );
-	
-	/* Check count against expected count */
-	if (count != recvtype->count) {
-	    errs ++;
-	}
-    }
-
-    /* Check received data */
-    if (!errs && recvtype->CheckBuf( recvtype )) {
-	errs++;
-    }
-    return errs;
-}
-
-/* This next routine uses a circular buffer of static name arrays just to
-   simplify the use of the routine */
-const char *MTestGetDatatypeName( MTestDatatype *dtype )
-{
-    static char name[4][MPI_MAX_OBJECT_NAME];
-    static int sp=0;
-    int rlen, merr;
-
-    if (sp >= 4) sp = 0;
-    merr = MPI_Type_get_name( dtype->datatype, name[sp], &rlen );
-    if (merr) MTestPrintError( merr );
-    return (const char *)name[sp++];
-}
 /* ----------------------------------------------------------------------- */
 
 /* 
diff --git a/test/mpi/util/mtest_datatype.c b/test/mpi/util/mtest_datatype.c
new file mode 100644
index 0000000..b2cf308
--- /dev/null
+++ b/test/mpi/util/mtest_datatype.c
@@ -0,0 +1,608 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2014 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mtest_datatype.h"
+#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
+#include <stdio.h>
+#endif
+#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
+#include <stdlib.h>
+#endif
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+/* The following two includes permit the collection of resource usage
+   data in the tests
+ */
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <errno.h>
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for contiguous datatypes                               */
+/* ------------------------------------------------------------------------ */
+/*
+ * Initialize buffer of basic datatype
+ */
+static void *MTestTypeContigInit(MTestDatatype * mtype)
+{
+    MPI_Aint size;
+    int merr;
+
+    if (mtype->count > 0) {
+        unsigned char *p;
+        int i, totsize;
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = size * mtype->count;
+        if (!mtype->buf) {
+            mtype->buf = (void *) malloc(totsize);
+        }
+        p = (unsigned char *) (mtype->buf);
+        if (!p) {
+            char errmsg[128] = { 0 };
+            sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+            MTestError(errmsg);
+        }
+        for (i = 0; i < totsize; i++) {
+            p[i] = (unsigned char) (0xff ^ (i & 0xff));
+        }
+    }
+    else {
+        if (mtype->buf) {
+            free(mtype->buf);
+        }
+        mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/*
+ * Free buffer of basic datatype
+ */
+static void *MTestTypeContigFree(MTestDatatype * mtype)
+{
+    if (mtype->buf) {
+        free(mtype->buf);
+        mtype->buf = 0;
+    }
+    return 0;
+}
+
+/*
+ * Check value of received basic datatype buffer.
+ */
+static int MTestTypeContigCheckbuf(MTestDatatype * mtype)
+{
+    unsigned char *p;
+    unsigned char expected;
+    int i, totsize, err = 0, merr;
+    MPI_Aint size;
+
+    p = (unsigned char *) mtype->buf;
+    if (p) {
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = size * mtype->count;
+        for (i = 0; i < totsize; i++) {
+            expected = (unsigned char) (0xff ^ (i & 0xff));
+            if (p[i] != expected) {
+                err++;
+                if (mtype->printErrors && err < 10) {
+                    printf("Data expected = %x but got p[%d] = %x\n", expected, i, p[i]);
+                    fflush(stdout);
+                }
+            }
+        }
+    }
+    return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for vector datatypes                                   */
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Initialize buffer of vector datatype
+ */
+static void *MTestTypeVectorInit(MTestDatatype * mtype)
+{
+    MPI_Aint size, totsize, dt_offset, byte_offset;
+    int merr;
+
+    if (mtype->count > 0) {
+        unsigned char *p;
+        int i, j, k, nc;
+
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = mtype->count * size;
+        if (!mtype->buf) {
+            mtype->buf = (void *) malloc(totsize);
+        }
+        p = (unsigned char *) (mtype->buf);
+        if (!p) {
+            char errmsg[128] = { 0 };
+            sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+            MTestError(errmsg);
+        }
+
+        /* First, set to -1 */
+        for (i = 0; i < totsize; i++)
+            p[i] = 0xff;
+
+        /* Now, set the actual elements to the successive values.
+         * We require that the base type is a contiguous type */
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each block */
+            for (i = 0; i < mtype->nblock; i++) {
+                byte_offset = dt_offset + i * mtype->stride;
+                /* For each byte */
+                for (j = 0; j < mtype->blksize; j++) {
+                    p[byte_offset + j] = (unsigned char) (0xff ^ (nc & 0xff));
+                    nc++;
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    else {
+        mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/*
+ * Free buffer of vector datatype
+ */
+static void *MTestTypeVectorFree(MTestDatatype * mtype)
+{
+    if (mtype->buf) {
+        free(mtype->buf);
+        mtype->buf = 0;
+    }
+    return 0;
+}
+
+/*
+ * Check value of received vector datatype buffer
+ */
+static int MTestTypeVectorCheckbuf(MTestDatatype * mtype)
+{
+    unsigned char *p;
+    unsigned char expected;
+    int i, err = 0, merr;
+    MPI_Aint size = 0, byte_offset, dt_offset;
+
+    p = (unsigned char *) mtype->buf;
+    if (p) {
+        int j, k, nc;
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each block */
+            for (i = 0; i < mtype->nblock; i++) {
+                byte_offset = dt_offset + i * mtype->stride;
+                /* For each byte */
+                for (j = 0; j < mtype->blksize; j++) {
+                    expected = (unsigned char) (0xff ^ (nc & 0xff));
+                    if (p[byte_offset + j] != expected) {
+                        err++;
+                        if (mtype->printErrors && err < 10) {
+                            printf("Data expected = %x but got p[%d,%d] = %x\n", expected, i, j,
+                                   p[byte_offset + j]);
+                            fflush(stdout);
+                        }
+                    }
+                    nc++;
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Datatype routines for indexed datatypes                            */
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Initialize buffer of indexed datatype
+ */
+static void *MTestTypeIndexedInit(MTestDatatype * mtype)
+{
+    MPI_Aint size = 0, totsize;
+    int merr;
+
+    if (mtype->count > 0) {
+        unsigned char *p;
+        int i, j, k, b, nc, offset, dt_offset;
+
+        /* Allocate buffer */
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = size * mtype->count;
+
+        if (!mtype->buf) {
+            mtype->buf = (void *) malloc(totsize);
+        }
+        p = (unsigned char *) (mtype->buf);
+        if (!p) {
+            char errmsg[128] = { 0 };
+            sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+            MTestError(errmsg);
+        }
+
+        /* First, set to -1 */
+        for (i = 0; i < totsize; i++)
+            p[i] = 0xff;
+
+        /* Now, set the actual elements to the successive values.
+         * We require that the base type is a contiguous type */
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each block */
+            for (i = 0; i < mtype->nblock; i++) {
+                /* For each element in the block */
+                for (j = 0; j < mtype->index[i]; j++) {
+                    offset = dt_offset + mtype->displ_in_bytes[i]
+                        + j * mtype->basesize;
+                    /* For each byte in the element */
+                    for (b = 0; b < mtype->basesize; b++) {
+                        p[offset + b] = (unsigned char) (0xff ^ (nc++ & 0xff));
+                    }
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    else {
+        /* count == 0 */
+        if (mtype->buf) {
+            free(mtype->buf);
+        }
+        mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+/*
+ * Free buffer of indexed datatype
+ */
+static void *MTestTypeIndexedFree(MTestDatatype * mtype)
+{
+    if (mtype->buf) {
+        free(mtype->buf);
+        free(mtype->displs);
+        free(mtype->displ_in_bytes);
+        free(mtype->index);
+        mtype->buf = 0;
+        mtype->displs = 0;
+        mtype->displ_in_bytes = 0;
+        mtype->index = 0;
+    }
+    return 0;
+}
+
+/*
+ * Check value of received indexed datatype buffer
+ */
+static int MTestTypeIndexedCheckbuf(MTestDatatype * mtype)
+{
+    unsigned char *p;
+    unsigned char expected;
+    int err = 0, merr;
+    MPI_Aint size = 0;
+
+    p = (unsigned char *) mtype->buf;
+    if (p) {
+        int i, j, k, b, nc, offset, dt_offset;
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+
+        nc = 0;
+        dt_offset = 0;
+        /* For each datatype */
+        for (k = 0; k < mtype->count; k++) {
+            /* For each block */
+            for (i = 0; i < mtype->nblock; i++) {
+                /* For each element in the block */
+                for (j = 0; j < mtype->index[i]; j++) {
+                    offset = dt_offset + mtype->displ_in_bytes[i]
+                        + j * mtype->basesize;
+                    /* For each byte in the element */
+                    for (b = 0; b < mtype->basesize; b++) {
+                        expected = (unsigned char) (0xff ^ (nc++ & 0xff));
+                        if (p[offset + b] != expected) {
+                            err++;
+                            if (mtype->printErrors && err < 10) {
+                                printf("Data expected = %x but got p[%d,%d] = %x\n",
+                                       expected, i, j, p[offset + b]);
+                                fflush(stdout);
+                            }
+                        }
+                    }
+                }
+            }
+            dt_offset += size;
+        }
+    }
+    return err;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Datatype generators                                                      */
+/* ------------------------------------------------------------------------ */
+
+/*
+ * Setup contiguous type info and handlers.
+ *
+ * A contiguous datatype is created by using following parameters (stride is unused).
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block. The total number of elements in
+ *           this datatype is set as (nblock * blocklen).
+ * oldtype:  Datatype of element.
+ */
+static int MTestTypeContiguousCreate(int nblock, int blocklen, int stride,
+                                     MPI_Datatype oldtype, const char *typename_prefix,
+                                     MTestDatatype * mtype)
+{
+    int merr = 0;
+    char type_name[128];
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->nblock = nblock;
+    mtype->blksize = blocklen * mtype->basesize;
+
+    merr = MPI_Type_contiguous(nblock * blocklen, oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d count)", typename_prefix, "contiguous", nblock * blocklen);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->InitBuf = MTestTypeContigInit;
+    mtype->FreeBuf = MTestTypeContigFree;
+    mtype->CheckBuf = MTestTypeContigCheckbuf;
+    return merr;
+}
+
+/*
+ * Setup vector type info and handlers.
+ *
+ * A vector datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block.
+ * stride:   Strided number of elements between blocks.
+ * oldtype:  Datatype of element.
+ */
+static int MTestTypeVectorCreate(int nblock, int blocklen, int stride,
+                                 MPI_Datatype oldtype, const char *typename_prefix,
+                                 MTestDatatype * mtype)
+{
+    int merr = 0;
+    char type_name[128];
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* These sizes are in bytes (see the VectorInit code) */
+    mtype->stride = stride * mtype->basesize;
+    mtype->blksize = blocklen * mtype->basesize;
+    mtype->nblock = nblock;
+
+    /* Vector uses stride in oldtypes */
+    merr = MPI_Type_vector(nblock, blocklen, stride, oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "vector", nblock,
+            blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->InitBuf = MTestTypeVectorInit;
+    mtype->FreeBuf = MTestTypeVectorFree;
+    mtype->CheckBuf = MTestTypeVectorCheckbuf;
+    return merr;
+}
+
+/*
+ * Setup indexed type info and handlers.
+ *
+ * A indexed datatype is created by using following parameters.
+ * nblock:   Number of blocks.
+ * blocklen: Number of elements in each block. Each block has the same length.
+ * stride:   Strided number of elements between two adjacent blocks. The
+ *           displacement of each block is set as (index of current block * stride).
+ * oldtype:  Datatype of element.
+ */
+static int MTestTypeIndexedCreate(int nblock, int blocklen, int stride,
+                                  MPI_Datatype oldtype, const char *typename_prefix,
+                                  MTestDatatype * mtype)
+{
+    int merr = 0;
+    char type_name[128];
+    int i;
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->displs = (int *) malloc(nblock * sizeof(int));
+    mtype->displ_in_bytes = (int *) malloc(nblock * sizeof(int));
+    mtype->index = (int *) malloc(nblock * sizeof(int));
+    if (!mtype->displs || !mtype->displ_in_bytes || !mtype->index) {
+        char errmsg[128] = { 0 };
+        sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+        MTestError(errmsg);
+    }
+
+    mtype->nblock = nblock;
+    for (i = 0; i < nblock; i++) {
+        mtype->index[i] = blocklen;
+        mtype->displs[i] = stride * i;  /*stride between the start of two blocks */
+        mtype->displ_in_bytes[i] = stride * i * mtype->basesize;
+    }
+
+    /* Indexed uses displacement in oldtypes */
+    merr = MPI_Type_indexed(nblock, mtype->index, mtype->displs, oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+    merr = MPI_Type_commit(&mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    memset(type_name, 0, sizeof(type_name));
+    sprintf(type_name, "%s %s (%d nblock %d blocklen %d stride)", typename_prefix, "index", nblock,
+            blocklen, stride);
+    merr = MPI_Type_set_name(mtype->datatype, (char *) type_name);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->InitBuf = MTestTypeIndexedInit;
+    mtype->FreeBuf = MTestTypeIndexedFree;
+    mtype->CheckBuf = MTestTypeIndexedCheckbuf;
+
+    return merr;
+}
+
+/*
+ * Setup basic type info and handlers.
+ */
+int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
+{
+    int merr = 0;
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    mtype->datatype = oldtype;
+    mtype->isBasic = 1;
+    mtype->InitBuf = MTestTypeContigInit;
+    mtype->FreeBuf = MTestTypeContigFree;
+    mtype->CheckBuf = MTestTypeContigCheckbuf;
+
+    return merr;
+}
+
+/*
+ * Setup dup type info and handlers.
+ *
+ * A dup datatype is created by using following parameters.
+ * oldtype:  Datatype of element.
+ */
+int MTestTypeDupCreate(MPI_Datatype oldtype, MTestDatatype * mtype)
+{
+    int merr = 0;
+
+    merr = MPI_Type_size(oldtype, &mtype->basesize);
+    if (merr)
+        MTestPrintError(merr);
+
+    merr = MPI_Type_dup(oldtype, &mtype->datatype);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* dup'ed types are already committed if the original type
+     * was committed (MPI-2, section 8.8) */
+
+    mtype->InitBuf = MTestTypeContigInit;
+    mtype->FreeBuf = MTestTypeContigFree;
+    mtype->CheckBuf = MTestTypeContigCheckbuf;
+
+    return merr;
+}
+
+
+/*
+ * General initialization for receive buffer.
+ * Allocate buffer and initialize for reception (e.g., set initial data to detect failure)
+ * Both basic and derived datatype can be handled by using extent as buffer size.
+ */
+void *MTestTypeInitRecv(MTestDatatype * mtype)
+{
+    MPI_Aint size;
+    int merr;
+
+    if (mtype->count > 0) {
+        signed char *p;
+        int i, totsize;
+        merr = MPI_Type_extent(mtype->datatype, &size);
+        if (merr)
+            MTestPrintError(merr);
+        totsize = size * mtype->count;
+        if (!mtype->buf) {
+            mtype->buf = (void *) malloc(totsize);
+        }
+        p = (signed char *) (mtype->buf);
+        if (!p) {
+            char errmsg[128] = { 0 };
+            sprintf(errmsg, "Out of memory in %s", __FUNCTION__);
+            MTestError(errmsg);
+        }
+        for (i = 0; i < totsize; i++) {
+            p[i] = 0xff;
+        }
+    }
+    else {
+        if (mtype->buf) {
+            free(mtype->buf);
+        }
+        mtype->buf = 0;
+    }
+    return mtype->buf;
+}
+
+void MTestTypeCreatorInit(MTestDdtCreator * creators)
+{
+    memset(creators, 0, sizeof(MTestDdtCreator) * MTEST_DDT_MAX);
+    creators[MTEST_DDT_CONTIGUOUS] = MTestTypeContiguousCreate;
+    creators[MTEST_DDT_VECTOR] = MTestTypeVectorCreate;
+    creators[MTEST_DDT_INDEXED] = MTestTypeIndexedCreate;
+}
diff --git a/test/mpi/util/mtest_datatype.h b/test/mpi/util/mtest_datatype.h
new file mode 100644
index 0000000..48fa96d
--- /dev/null
+++ b/test/mpi/util/mtest_datatype.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2014 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+
+#ifndef MTEST_DATATYPE_H_
+#define MTEST_DATATYPE_H_
+
+#include "mpi.h"
+#include "mpitestconf.h"
+#include "mpitest.h"
+
+/* Provide backward portability to MPI 1 */
+#ifndef MPI_VERSION
+#define MPI_VERSION 1
+#endif
+
+enum MTEST_BASIC_DT {
+    MTEST_BDT_INT,
+    MTEST_BDT_DOUBLE,
+    MTEST_BDT_FLOAT_INT,
+    MTEST_BDT_SHORT,
+    MTEST_BDT_LONG,
+    MTEST_BDT_CHAR,
+    MTEST_BDT_UINT64_T,
+    MTEST_BDT_FLOAT,
+    MTEST_BDT_BYTE,
+    MTEST_BDT_MAX
+};
+
+enum MTEST_DERIVED_DT {
+    MTEST_DDT_CONTIGUOUS,
+    MTEST_DDT_VECTOR,
+    MTEST_DDT_INDEXED,
+    MTEST_DDT_MAX
+};
+
+typedef int (*MTestDdtCreator) (int, int, int, MPI_Datatype, const char *, MTestDatatype *);
+
+extern void MTestTypeCreatorInit(MTestDdtCreator * creators);
+extern void *MTestTypeInitRecv(MTestDatatype * mtype);
+
+extern int MTestTypeBasicCreate(MPI_Datatype oldtype, MTestDatatype * mtype);
+extern int MTestTypeDupCreate(MPI_Datatype oldtype, MTestDatatype * mtype);
+
+#endif /* MTEST_DATATYPE_H_ */
diff --git a/test/mpi/util/mtest_datatype_gen.c b/test/mpi/util/mtest_datatype_gen.c
new file mode 100644
index 0000000..79fb1f9
--- /dev/null
+++ b/test/mpi/util/mtest_datatype_gen.c
@@ -0,0 +1,462 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2014 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mtest_datatype.h"
+#if defined(HAVE_STDIO_H) || defined(STDC_HEADERS)
+#include <stdio.h>
+#endif
+#if defined(HAVE_STDLIB_H) || defined(STDC_HEADERS)
+#include <stdlib.h>
+#endif
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+/* The following two includes permit the collection of resource usage
+   data in the tests
+ */
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <errno.h>
+
+static int dbgflag = 0;         /* Flag used for debugging */
+static int wrank = -1;          /* World rank */
+static int verbose = 0;         /* Message level (0 is none) */
+
+/*
+ * Utility routines for writing MPI datatype communication tests.
+ *
+ * Both basic and derived datatype are included.
+ * For basic datatypes, every type has a test case that both the send and
+ * receive buffer use the same datatype and count.
+ *
+ *  For derived datatypes:
+ *    All the test cases are defined in this file, and the datatype definitions
+ *    are in file mtest_datatype.c. Each test case will be automatically called
+ *    by every datatype.
+ *
+ *  Test case generation:
+ *    Every datatype tests derived datatype send buffer and
+ *    derived datatype receive buffer separately. Each test contains various sub
+ *    tests for different structures (i.e., different value of count or block
+ *    length). The following four structures are defined:
+ *      L count & S block length & S stride
+ *      S count & L block length & S stride
+ *      L count & S block length & L stride
+ *      S count & L block length & L stride
+ *
+ *  How to add a new structure for each datatype:
+ *    1. Add structure definition in function MTestDdtStructDefine.
+ *    2. Increase MTEST_DDT_NUM_SUBTESTS
+ *
+ *  Datatype definition:
+ *    Every type is initialized by the creation function stored in
+ *    mtestDdtCreators variable, all of their create/init/check functions are
+ *    defined in file mtest_datatype.c. Following derived datatypes are defined:
+ *    Contiguous | Vector | Indexed
+ *
+ *  How to add a new derived datatype:
+ *    1. Add the new datatype in enum MTEST_DERIVED_DT.
+ *    2. Add its create/init/check functions in file mtest_datatype.c
+ *    3. Add its creator function to mtestDdtCreators variable
+ */
+
+static int datatype_index = 0;
+
+
+#define MTEST_BDT_START_IDX 0
+#define MTEST_BDT_NUM_TESTS (MTEST_BDT_MAX)
+#define MTEST_BDT_RANGE (MTEST_BDT_START_IDX + MTEST_BDT_NUM_TESTS)
+
+#define MTEST_DDT_NUM_SUBTESTS 4        /* 4 kinds of derived datatype structure */
+#define MTEST_DDT_NUM_TYPES (MTEST_DDT_MAX)
+
+#define MTEST_SEND_DDT_START_IDX (MTEST_BDT_NUM_TESTS)
+#define MTEST_SEND_DDT_NUM_TESTS (MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS)
+#define MTEST_SEND_DDT_RANGE (MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS)
+
+#define MTEST_RECV_DDT_START_IDX (MTEST_SEND_DDT_START_IDX + MTEST_SEND_DDT_NUM_TESTS)
+#define MTEST_RECV_DDT_NUM_TESTS (MTEST_DDT_NUM_TYPES * MTEST_DDT_NUM_SUBTESTS)
+#define MTEST_RECV_DDT_RANGE (MTEST_RECV_DDT_START_IDX + MTEST_RECV_DDT_NUM_TESTS)
+
+static MTestDdtCreator mtestDdtCreators[MTEST_DDT_MAX];
+
+
+/* -------------------------------------------------------------------------------*/
+/* Routine to define various sets of blocklen/count/stride for derived datatypes. */
+/* ------------------------------------------------------------------------------ */
+
+static inline int MTestDdtStructDefine(int ddt_index, int tot_count, int *count,
+                                       int *blen, int *stride, int *align_tot_count)
+{
+    int merr = 0;
+    int ddt_c_st;
+    int _short = 0, _align_tot_count = 0, _count = 0, _blen = 0, _stride = 0;
+    ddt_c_st = ddt_index % MTEST_DDT_NUM_SUBTESTS;
+
+    /* Get short value according to user specified tot_count.
+     * It is used as count for large-block-length structure, or block length
+     * for large-count structure. */
+    if (tot_count < 2) {
+        _short = 1;
+    }
+    else if (tot_count < 64) {
+        _short = 2;
+    }
+    else {
+        _short = 64;
+    }
+    _align_tot_count = (tot_count + _short - 1) & ~(_short - 1);
+
+    switch (ddt_c_st) {
+    case 0:
+        /* Large block length. */
+        _count = _short;
+        _blen = _align_tot_count / _short;
+        _stride = _blen * 2;
+        break;
+    case 1:
+        /* Large count */
+        _count = _align_tot_count / _short;
+        _blen = _short;
+        _stride = _blen * 2;
+        break;
+    case 2:
+        /* Large block length and large stride */
+        _count = _short;
+        _blen = _align_tot_count / _short;
+        _stride = _blen * 10;
+        break;
+    case 3:
+        /* Large count and large stride */
+        _count = _align_tot_count / _short;
+        _blen = _short;
+        _stride = _blen * 10;
+        break;
+    default:
+        /* Undefined index */
+        merr = 1;
+        break;
+    }
+
+    *align_tot_count = _align_tot_count;
+    *count = _count;
+    *blen = _blen;
+    *stride = _stride;
+
+    return merr;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Routine to generate basic datatypes                                       */
+/* ------------------------------------------------------------------------ */
+
+static inline int MTestGetBasicDatatypes(MTestDatatype * sendtype,
+                                         MTestDatatype * recvtype, int tot_count)
+{
+    int merr = 0;
+    int bdt_index = datatype_index - MTEST_BDT_START_IDX;
+    if (bdt_index >= MTEST_BDT_MAX) {
+        printf("Wrong index:  global %d, bst %d in %s\n", datatype_index, bdt_index, __FUNCTION__);
+        merr++;
+        return merr;
+    }
+
+    switch (bdt_index) {
+    case MTEST_BDT_INT:
+        merr = MTestTypeBasicCreate(MPI_INT, sendtype);
+        merr = MTestTypeBasicCreate(MPI_INT, recvtype);
+        break;
+    case MTEST_BDT_DOUBLE:
+        merr = MTestTypeBasicCreate(MPI_DOUBLE, sendtype);
+        merr = MTestTypeBasicCreate(MPI_DOUBLE, recvtype);
+        break;
+    case MTEST_BDT_FLOAT_INT:
+        merr = MTestTypeBasicCreate(MPI_FLOAT_INT, sendtype);
+        merr = MTestTypeBasicCreate(MPI_FLOAT_INT, recvtype);
+        break;
+    case MTEST_BDT_SHORT:
+        merr = MTestTypeBasicCreate(MPI_SHORT, sendtype);
+        merr = MTestTypeBasicCreate(MPI_SHORT, recvtype);
+        break;
+    case MTEST_BDT_LONG:
+        merr = MTestTypeBasicCreate(MPI_LONG, sendtype);
+        merr = MTestTypeBasicCreate(MPI_LONG, recvtype);
+        break;
+    case MTEST_BDT_CHAR:
+        merr = MTestTypeBasicCreate(MPI_CHAR, sendtype);
+        merr = MTestTypeBasicCreate(MPI_CHAR, recvtype);
+        break;
+    case MTEST_BDT_UINT64_T:
+        merr = MTestTypeBasicCreate(MPI_UINT64_T, sendtype);
+        merr = MTestTypeBasicCreate(MPI_UINT64_T, recvtype);
+        break;
+    case MTEST_BDT_FLOAT:
+        merr = MTestTypeBasicCreate(MPI_FLOAT, sendtype);
+        merr = MTestTypeBasicCreate(MPI_FLOAT, recvtype);
+        break;
+    case MTEST_BDT_BYTE:
+        merr = MTestTypeBasicCreate(MPI_BYTE, sendtype);
+        merr = MTestTypeBasicCreate(MPI_BYTE, recvtype);
+        break;
+    }
+    sendtype->count = tot_count;
+    recvtype->count = tot_count;
+
+    return merr;
+}
+
+/* ------------------------------------------------------------------------ */
+/* Routine to generate send/receive derived datatypes                     */
+/* ------------------------------------------------------------------------ */
+
+static inline int MTestGetSendDerivedDatatypes(MTestDatatype * sendtype,
+                                               MTestDatatype * recvtype, int tot_count)
+{
+    int merr = 0;
+    int ddt_datatype_index, ddt_c_dt;
+    int blen, stride, count, align_tot_count, tsize = 1;
+    MPI_Datatype old_type = MPI_DOUBLE;
+
+    /* Check index */
+    ddt_datatype_index = datatype_index - MTEST_SEND_DDT_START_IDX;
+    ddt_c_dt = ddt_datatype_index / MTEST_DDT_NUM_SUBTESTS;
+    if (ddt_c_dt >= MTEST_DDT_MAX || !mtestDdtCreators[ddt_c_dt]) {
+        printf("Wrong index:  global %d, send %d send-ddt %d, or undefined creator in %s\n",
+               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
+        merr++;
+        return merr;
+    }
+
+    /* Set datatype structure */
+    merr = MTestDdtStructDefine(ddt_datatype_index, tot_count, &count, &blen,
+                                &stride, &align_tot_count);
+    if (merr) {
+        printf("Wrong index:  global %d, send %d send-ddt %d, or undefined ddt structure in %s\n",
+               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
+        merr++;
+        return merr;
+    }
+
+    /* Create send datatype */
+    merr = mtestDdtCreators[ddt_c_dt] (count, blen, stride, old_type, "send", sendtype);
+    if (merr)
+        return merr;
+
+    sendtype->count = 1;
+    merr = MPI_Type_size(sendtype->datatype, &tsize);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* Create receive datatype */
+    merr = MTestTypeBasicCreate(MPI_CHAR, recvtype);
+    if (merr)
+        return merr;
+
+    recvtype->count = sendtype->count * tsize;
+
+    return merr;
+}
+
+static inline int MTestGetRecvDerivedDatatypes(MTestDatatype * sendtype,
+                                               MTestDatatype * recvtype, int tot_count)
+{
+    int merr = 0;
+    int ddt_datatype_index, ddt_c_dt;
+    int blen, stride, count, align_tot_count, tsize;
+    MPI_Datatype old_type = MPI_DOUBLE;
+
+    /* Check index */
+    ddt_datatype_index = datatype_index - MTEST_RECV_DDT_START_IDX;
+    ddt_c_dt = ddt_datatype_index / MTEST_DDT_NUM_SUBTESTS;
+    if (ddt_c_dt >= MTEST_DDT_MAX || !mtestDdtCreators[ddt_c_dt]) {
+        printf("Wrong index:  global %d, recv %d recv-ddt %d, or undefined creator in %s\n",
+               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
+        merr++;
+        return merr;
+    }
+
+    /* Set datatype structure */
+    merr = MTestDdtStructDefine(ddt_datatype_index, tot_count, &count, &blen,
+                                &stride, &align_tot_count);
+    if (merr) {
+        printf("Wrong index:  global %d, recv %d recv-ddt %d, or undefined ddt structure in %s\n",
+               datatype_index, ddt_datatype_index, ddt_c_dt, __FUNCTION__);
+        return merr;
+    }
+
+    /* Create receive datatype */
+    merr = mtestDdtCreators[ddt_c_dt] (count, blen, stride, old_type, "recv", recvtype);
+    if (merr)
+        return merr;
+
+    recvtype->count = 1;
+    merr = MPI_Type_size(recvtype->datatype, &tsize);
+    if (merr)
+        MTestPrintError(merr);
+
+    /* Create send datatype */
+    merr = MTestTypeBasicCreate(MPI_CHAR, sendtype);
+    if (merr)
+        return merr;
+
+    sendtype->count = recvtype->count * tsize;
+
+    return merr;
+}
+
+static inline void MTestResetDatatype(MTestDatatype * mtype)
+{
+    mtype->InitBuf = 0;
+    mtype->FreeBuf = 0;
+    mtype->CheckBuf = 0;
+    mtype->datatype = 0;
+    mtype->isBasic = 0;
+    mtype->printErrors = 0;
+    mtype->buf = 0;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Exposed routine to external tests                                         */
+/* ------------------------------------------------------------------------ */
+int MTestGetDatatypes(MTestDatatype * sendtype, MTestDatatype * recvtype, int tot_count)
+{
+    int merr = 0;
+
+    MTestGetDbgInfo(&dbgflag, &verbose);
+    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
+
+    MTestResetDatatype(sendtype);
+    MTestResetDatatype(recvtype);
+
+    MTestTypeCreatorInit((MTestDdtCreator *) mtestDdtCreators);
+
+    if (datatype_index < MTEST_BDT_RANGE) {
+        merr = MTestGetBasicDatatypes(sendtype, recvtype, tot_count);
+
+    }
+    else if (datatype_index < MTEST_SEND_DDT_RANGE) {
+        merr = MTestGetSendDerivedDatatypes(sendtype, recvtype, tot_count);
+
+    }
+    else if (datatype_index < MTEST_RECV_DDT_RANGE) {
+        merr = MTestGetRecvDerivedDatatypes(sendtype, recvtype, tot_count);
+
+    }
+    else {
+        /* out of range */
+        datatype_index = -1;
+    }
+
+    /* stop if error reported */
+    if (merr) {
+        datatype_index = -1;
+    }
+
+    if (datatype_index > 0) {
+        /* general initialization for receive buffer. */
+        recvtype->InitBuf = MTestTypeInitRecv;
+    }
+
+    datatype_index++;
+
+    if ((verbose || dbgflag) && datatype_index > 0) {
+        int ssize, rsize;
+        const char *sendtype_nm = MTestGetDatatypeName(sendtype);
+        const char *recvtype_nm = MTestGetDatatypeName(recvtype);
+        MPI_Type_size(sendtype->datatype, &ssize);
+        MPI_Type_size(recvtype->datatype, &rsize);
+        printf("Get datatypes: send = %s(size %d count %d basesize %d), "
+               "recv = %s(size %d count %d basesize %d), tot_count=%d\n",
+               sendtype_nm, ssize, sendtype->count, sendtype->basesize,
+               recvtype_nm, rsize, recvtype->count, recvtype->basesize,
+               tot_count);
+        fflush(stdout);
+    }
+
+    return datatype_index;
+}
+
+/* Reset the datatype index (start from the initial data type.
+   Note: This routine is rarely needed; MTestGetDatatypes automatically
+   starts over after the last available datatype is used.
+*/
+void MTestResetDatatypes(void)
+{
+    datatype_index = 0;
+}
+
+/* Return the index of the current datatype.  This is rarely needed and
+   is provided mostly to enable debugging of the MTest package itself */
+int MTestGetDatatypeIndex(void)
+{
+    return datatype_index;
+}
+
+/* Free the storage associated with a datatype */
+void MTestFreeDatatype(MTestDatatype * mtype)
+{
+    int merr;
+    /* Invoke a datatype-specific free function to handle
+     * both the datatype and the send/receive buffers */
+    if (mtype->FreeBuf) {
+        (mtype->FreeBuf) (mtype);
+    }
+    /* Free the datatype itself if it was created */
+    if (!mtype->isBasic) {
+        merr = MPI_Type_free(&mtype->datatype);
+        if (merr)
+            MTestPrintError(merr);
+    }
+}
+
+/* Check that a message was received correctly.  Returns the number of
+   errors detected.  Status may be NULL or MPI_STATUS_IGNORE */
+int MTestCheckRecv(MPI_Status * status, MTestDatatype * recvtype)
+{
+    int count;
+    int errs = 0, merr;
+
+    if (status && status != MPI_STATUS_IGNORE) {
+        merr = MPI_Get_count(status, recvtype->datatype, &count);
+        if (merr)
+            MTestPrintError(merr);
+
+        /* Check count against expected count */
+        if (count != recvtype->count) {
+            errs++;
+        }
+    }
+
+    /* Check received data */
+    if (!errs && recvtype->CheckBuf(recvtype)) {
+        errs++;
+    }
+    return errs;
+}
+
+/* This next routine uses a circular buffer of static name arrays just to
+   simplify the use of the routine */
+const char *MTestGetDatatypeName(MTestDatatype * dtype)
+{
+    static char name[4][MPI_MAX_OBJECT_NAME];
+    static int sp = 0;
+    int rlen, merr;
+
+    if (sp >= 4)
+        sp = 0;
+    merr = MPI_Type_get_name(dtype->datatype, name[sp], &rlen);
+    if (merr)
+        MTestPrintError(merr);
+    return (const char *) name[sp++];
+}

-----------------------------------------------------------------------

Summary of changes:
 test/mpi/Makefile.mtest            |    8 +
 test/mpi/coll/bcast2.c             |   12 +-
 test/mpi/coll/bcast3.c             |   14 +-
 test/mpi/coll/testlist             |    4 +-
 test/mpi/include/mpitest.h         |   26 +-
 test/mpi/pt2pt/pingping.c          |    8 +
 test/mpi/pt2pt/sendrecv1.c         |    2 +-
 test/mpi/pt2pt/sendself.c          |    2 +-
 test/mpi/rma/accfence1.c           |    2 +-
 test/mpi/rma/accpscw1.c            |    2 +-
 test/mpi/rma/epochtest.c           |    2 +-
 test/mpi/rma/getfence1.c           |    2 +-
 test/mpi/rma/putfence1.c           |    2 +-
 test/mpi/rma/putpscw1.c            |    2 +-
 test/mpi/template.c                |    2 +-
 test/mpi/util/mtest.c              |  708 +--------------------
 test/mpi/util/mtest_datatype.c     | 1290 ++++++++++++++++++++++++++++++++++++
 test/mpi/util/mtest_datatype.h     |   62 ++
 test/mpi/util/mtest_datatype_gen.c |  541 +++++++++++++++
 19 files changed, 1965 insertions(+), 726 deletions(-)
 create mode 100644 test/mpi/util/mtest_datatype.c
 create mode 100644 test/mpi/util/mtest_datatype.h
 create mode 100644 test/mpi/util/mtest_datatype_gen.c


hooks/post-receive
-- 
MPICH primary repository


More information about the commits mailing list