int MPIR_Type_create_struct_impl(int count, int array_of_blocklengths[], MPI_Aint array_of_displacements[], MPI_Datatype array_of_types[], MPI_Datatype *newtype) { int mpi_errno = MPI_SUCCESS; int i, *ints; MPI_Datatype new_handle; MPID_Datatype *new_dtp; MPIU_CHKLMEM_DECL(1); mpi_errno = MPID_Type_struct(count, array_of_blocklengths, array_of_displacements, array_of_types, &new_handle); if (mpi_errno) MPIU_ERR_POP(mpi_errno); MPIU_CHKLMEM_MALLOC_ORJUMP(ints, int *, (count + 1) * sizeof(int), mpi_errno, "content description"); ints[0] = count; for (i=0; i < count; i++) ints[i+1] = array_of_blocklengths[i]; MPID_Datatype_get_ptr(new_handle, new_dtp); mpi_errno = MPID_Datatype_set_contents(new_dtp, MPI_COMBINER_STRUCT, count+1, /* ints (cnt,blklen) */ count, /* aints (disps) */ count, /* types */ ints, array_of_displacements, array_of_types); if (mpi_errno) MPIU_ERR_POP(mpi_errno); MPIU_OBJ_PUBLISH_HANDLE(*newtype, new_handle); fn_exit: MPIU_CHKLMEM_FREEALL(); return mpi_errno; fn_fail: goto fn_exit; }
PMPI_LOCAL int MPIR_Type_cyclic(const int *array_of_gsizes, int dim, int ndims, int nprocs, int rank, int darg, int order, MPI_Aint orig_extent, MPI_Datatype type_old, MPI_Datatype *type_new, MPI_Aint *st_offset) { /* nprocs = no. of processes in dimension dim of grid rank = coordinate of this process in dimension dim */ static const char FCNAME[] = "MPIR_Type_cyclic"; int mpi_errno,blksize, i, blklens[3], st_index, end_index, local_size, rem, count; MPI_Aint stride, disps[3]; MPI_Datatype type_tmp, types[3]; if (darg == MPI_DISTRIBUTE_DFLT_DARG) blksize = 1; else blksize = darg; #ifdef HAVE_ERROR_CHECKING if (blksize <= 0) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**darraycyclic", "**darraycyclic %d", blksize); return mpi_errno; } #endif st_index = rank*blksize; end_index = array_of_gsizes[dim] - 1; if (end_index < st_index) local_size = 0; else { local_size = ((end_index - st_index + 1)/(nprocs*blksize))*blksize; rem = (end_index - st_index + 1) % (nprocs*blksize); local_size += MPIR_MIN(rem, blksize); } count = local_size/blksize; rem = local_size % blksize; stride = (MPI_Aint) nprocs * (MPI_Aint) blksize * orig_extent; if (order == MPI_ORDER_FORTRAN) for (i=0; i<dim; i++) stride *= (MPI_Aint)(array_of_gsizes[i]); else for (i=ndims-1; i>dim; i--) stride *= (MPI_Aint)(array_of_gsizes[i]); mpi_errno = MPID_Type_vector(count, blksize, stride, 1, /* stride in bytes */ type_old, type_new); /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ if (rem) { /* if the last block is of size less than blksize, include it separately using MPI_Type_struct */ types[0] = *type_new; types[1] = type_old; disps[0] = 0; disps[1] = (MPI_Aint) count * stride; blklens[0] = 1; blklens[1] = rem; mpi_errno = MPID_Type_struct(2, blklens, disps, types, &type_tmp); MPIR_Type_free_impl(type_new); *type_new = type_tmp; /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ } /* In the first iteration, we need to set the displacement in that dimension correctly. */ if (((order == MPI_ORDER_FORTRAN) && (dim == 0)) || ((order == MPI_ORDER_C) && (dim == ndims-1))) { types[0] = MPI_LB; disps[0] = 0; types[1] = *type_new; disps[1] = (MPI_Aint) rank * (MPI_Aint) blksize * orig_extent; types[2] = MPI_UB; disps[2] = orig_extent * (MPI_Aint)(array_of_gsizes[dim]); blklens[0] = blklens[1] = blklens[2] = 1; mpi_errno = MPID_Type_struct(3, blklens, disps, types, &type_tmp); MPIR_Type_free_impl(type_new); *type_new = type_tmp; /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**fail", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ *st_offset = 0; /* set it to 0 because it is taken care of in the struct above */ } else { *st_offset = (MPI_Aint) rank * (MPI_Aint) blksize; /* st_offset is in terms of no. of elements of type oldtype in * this dimension */ } if (local_size == 0) *st_offset = 0; return MPI_SUCCESS; }
/*@ MPI_Type_create_darray - Create a datatype representing a distributed array Input Parameters: + size - size of process group (positive integer) . rank - rank in process group (nonnegative integer) . ndims - number of array dimensions as well as process grid dimensions (positive integer) . array_of_gsizes - number of elements of type oldtype in each dimension of global array (array of positive integers) . array_of_distribs - distribution of array in each dimension (array of state) . array_of_dargs - distribution argument in each dimension (array of positive integers) . array_of_psizes - size of process grid in each dimension (array of positive integers) . order - array storage order flag (state) - oldtype - old datatype (handle) Output Parameters: . newtype - new datatype (handle) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_TYPE .N MPI_ERR_ARG @*/ int MPI_Type_create_darray(int size, int rank, int ndims, const int array_of_gsizes[], const int array_of_distribs[], const int array_of_dargs[], const int array_of_psizes[], int order, MPI_Datatype oldtype, MPI_Datatype *newtype) { static const char FCNAME[] = "MPI_Type_create_darray"; int mpi_errno = MPI_SUCCESS, i; MPI_Datatype new_handle; int procs, tmp_rank, tmp_size, blklens[3], *coords; MPI_Aint *st_offsets, orig_extent, disps[3]; MPI_Datatype type_old, type_new = MPI_DATATYPE_NULL, types[3]; # ifdef HAVE_ERROR_CHECKING MPI_Aint size_with_aint; MPI_Offset size_with_offset; # endif int *ints; MPID_Datatype *datatype_ptr = NULL; MPIU_CHKLMEM_DECL(3); MPID_MPI_STATE_DECL(MPID_STATE_MPI_TYPE_CREATE_DARRAY); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIU_THREAD_CS_ENTER(ALLFUNC,); MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_TYPE_CREATE_DARRAY); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_DATATYPE(oldtype, "datatype", mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPID_Datatype_get_ptr(oldtype, datatype_ptr); MPID_Datatype_get_extent_macro(oldtype, orig_extent); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Check parameters */ MPIR_ERRTEST_ARGNONPOS(size, "size", mpi_errno, MPI_ERR_ARG); /* use MPI_ERR_RANK class for PE-MPI compatibility */ MPIU_ERR_CHKANDJUMP3((rank < 0 || rank >= size), mpi_errno, MPI_ERR_RANK, "**argrange", "**argrange %s %d %d", "rank", rank, (size-1)); MPIR_ERRTEST_ARGNONPOS(ndims, "ndims", mpi_errno, MPI_ERR_DIMS); MPIR_ERRTEST_ARGNULL(array_of_gsizes, "array_of_gsizes", mpi_errno); MPIR_ERRTEST_ARGNULL(array_of_distribs, "array_of_distribs", mpi_errno); MPIR_ERRTEST_ARGNULL(array_of_dargs, "array_of_dargs", mpi_errno); MPIR_ERRTEST_ARGNULL(array_of_psizes, "array_of_psizes", mpi_errno); if (order != MPI_ORDER_C && order != MPI_ORDER_FORTRAN) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**arg", "**arg %s", "order"); goto fn_fail; } tmp_size = 1; for (i=0; mpi_errno == MPI_SUCCESS && i < ndims; i++) { MPIR_ERRTEST_ARGNONPOS(array_of_gsizes[i], "gsize", mpi_errno, MPI_ERR_ARG); MPIR_ERRTEST_ARGNONPOS(array_of_psizes[i], "psize", mpi_errno, MPI_ERR_ARG); if ((array_of_distribs[i] != MPI_DISTRIBUTE_NONE) && (array_of_distribs[i] != MPI_DISTRIBUTE_BLOCK) && (array_of_distribs[i] != MPI_DISTRIBUTE_CYCLIC)) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**darrayunknown", 0); goto fn_fail; } if ((array_of_dargs[i] != MPI_DISTRIBUTE_DFLT_DARG) && (array_of_dargs[i] <= 0)) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**arg", "**arg %s", "array_of_dargs"); goto fn_fail; } if ((array_of_distribs[i] == MPI_DISTRIBUTE_NONE) && (array_of_psizes[i] != 1)) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG, "**darraydist", "**darraydist %d %d", i, array_of_psizes[i]); goto fn_fail; } tmp_size *= array_of_psizes[i]; } MPIU_ERR_CHKANDJUMP1((tmp_size != size), mpi_errno, MPI_ERR_ARG, "**arg", "**arg %s", "array_of_psizes"); /* TODO: GET THIS CHECK IN ALSO */ /* check if MPI_Aint is large enough for size of global array. if not, complain. */ size_with_aint = orig_extent; for (i=0; i<ndims; i++) size_with_aint *= array_of_gsizes[i]; size_with_offset = orig_extent; for (i=0; i<ndims; i++) size_with_offset *= array_of_gsizes[i]; if (size_with_aint != size_with_offset) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_FATAL, FCNAME, __LINE__, MPI_ERR_ARG, "**darrayoverflow", "**darrayoverflow %L", size_with_offset); goto fn_fail; } /* Validate datatype_ptr */ MPID_Datatype_valid_ptr(datatype_ptr, mpi_errno); /* If datatype_ptr is not valid, it will be reset to null */ /* --BEGIN ERROR HANDLING-- */ if (mpi_errno) goto fn_fail; /* --END ERROR HANDLING-- */ } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ /* calculate position in Cartesian grid as MPI would (row-major ordering) */ MPIU_CHKLMEM_MALLOC_ORJUMP(coords, int *, ndims * sizeof(int), mpi_errno, "position is Cartesian grid"); procs = size; tmp_rank = rank; for (i=0; i<ndims; i++) { procs = procs/array_of_psizes[i]; coords[i] = tmp_rank/procs; tmp_rank = tmp_rank % procs; } MPIU_CHKLMEM_MALLOC_ORJUMP(st_offsets, MPI_Aint *, ndims * sizeof(MPI_Aint), mpi_errno, "st_offsets"); type_old = oldtype; if (order == MPI_ORDER_FORTRAN) { /* dimension 0 changes fastest */ for (i=0; i<ndims; i++) { switch(array_of_distribs[i]) { case MPI_DISTRIBUTE_BLOCK: mpi_errno = MPIR_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i], coords[i], array_of_dargs[i], order, orig_extent, type_old, &type_new, st_offsets+i); break; case MPI_DISTRIBUTE_CYCLIC: mpi_errno = MPIR_Type_cyclic(array_of_gsizes, i, ndims, array_of_psizes[i], coords[i], array_of_dargs[i], order, orig_extent, type_old, &type_new, st_offsets+i); break; case MPI_DISTRIBUTE_NONE: /* treat it as a block distribution on 1 process */ mpi_errno = MPIR_Type_block(array_of_gsizes, i, ndims, 1, 0, MPI_DISTRIBUTE_DFLT_DARG, order, orig_extent, type_old, &type_new, st_offsets+i); break; } if (i) { MPIR_Type_free_impl(&type_old); } type_old = type_new; /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* --END ERROR HANDLING-- */ } /* add displacement and UB */ disps[1] = st_offsets[0]; tmp_size = 1; for (i=1; i<ndims; i++) { tmp_size *= array_of_gsizes[i-1]; disps[1] += (MPI_Aint) tmp_size * st_offsets[i]; } /* rest done below for both Fortran and C order */ } else /* order == MPI_ORDER_C */ { /* dimension ndims-1 changes fastest */ for (i=ndims-1; i>=0; i--) { switch(array_of_distribs[i]) { case MPI_DISTRIBUTE_BLOCK: mpi_errno = MPIR_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i], coords[i], array_of_dargs[i], order, orig_extent, type_old, &type_new, st_offsets+i); break; case MPI_DISTRIBUTE_CYCLIC: mpi_errno = MPIR_Type_cyclic(array_of_gsizes, i, ndims, array_of_psizes[i], coords[i], array_of_dargs[i], order, orig_extent, type_old, &type_new, st_offsets+i); break; case MPI_DISTRIBUTE_NONE: /* treat it as a block distribution on 1 process */ mpi_errno = MPIR_Type_block(array_of_gsizes, i, ndims, array_of_psizes[i], coords[i], MPI_DISTRIBUTE_DFLT_DARG, order, orig_extent, type_old, &type_new, st_offsets+i); break; } if (i != ndims-1) { MPIR_Type_free_impl(&type_old); } type_old = type_new; /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* --END ERROR HANDLING-- */ } /* add displacement and UB */ disps[1] = st_offsets[ndims-1]; tmp_size = 1; for (i=ndims-2; i>=0; i--) { tmp_size *= array_of_gsizes[i+1]; disps[1] += (MPI_Aint) tmp_size * st_offsets[i]; } } disps[1] *= orig_extent; disps[2] = orig_extent; for (i=0; i<ndims; i++) disps[2] *= (MPI_Aint)(array_of_gsizes[i]); disps[0] = 0; blklens[0] = blklens[1] = blklens[2] = 1; types[0] = MPI_LB; types[1] = type_new; types[2] = MPI_UB; mpi_errno = MPID_Type_struct(3, blklens, disps, types, &new_handle); /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* --END ERROR HANDLING-- */ MPIR_Type_free_impl(&type_new); /* at this point we have the new type, and we've cleaned up any * intermediate types created in the process. we just need to save * all our contents/envelope information. */ /* Save contents */ MPIU_CHKLMEM_MALLOC_ORJUMP(ints, int *, (4 * ndims + 4) * sizeof(int), mpi_errno, "content description"); ints[0] = size; ints[1] = rank; ints[2] = ndims; for (i=0; i < ndims; i++) { ints[i + 3] = array_of_gsizes[i]; } for (i=0; i < ndims; i++) { ints[i + ndims + 3] = array_of_distribs[i]; } for (i=0; i < ndims; i++) { ints[i + 2*ndims + 3] = array_of_dargs[i]; } for (i=0; i < ndims; i++) { ints[i + 3*ndims + 3] = array_of_psizes[i]; } ints[4*ndims + 3] = order; MPID_Datatype_get_ptr(new_handle, datatype_ptr); mpi_errno = MPID_Datatype_set_contents(datatype_ptr, MPI_COMBINER_DARRAY, 4*ndims + 4, 0, 1, ints, NULL, &oldtype); /* --BEGIN ERROR HANDLING-- */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* --END ERROR HANDLING-- */ MPIU_OBJ_PUBLISH_HANDLE(*newtype, new_handle); /* ... end of body of routine ... */ fn_exit: MPIU_CHKLMEM_FREEALL(); MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_TYPE_CREATE_DARRAY); MPIU_THREAD_CS_EXIT(ALLFUNC,); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_type_create_darray", "**mpi_type_create_darray %d %d %d %p %p %p %p %d %D %p", size, rank, ndims, array_of_gsizes, array_of_distribs, array_of_dargs, array_of_psizes, order, oldtype, newtype); } # endif mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Type_struct - Creates a struct datatype Input Parameters: + count - number of blocks (integer) -- also number of entries in arrays array_of_types , array_of_displacements and array_of_blocklengths . blocklens - number of elements in each block (array) . indices - byte displacement of each block (array) - old_types - type of elements in each block (array of handles to datatype objects) Output Parameter: . newtype - new datatype (handle) Notes: If an upperbound is set explicitly by using the MPI datatype 'MPI_UB', the corresponding index must be positive. The MPI standard originally made vague statements about padding and alignment; this was intended to allow the simple definition of structures that could be sent with a count greater than one. For example, .vb struct { int a; char b; } foo; .ve may have 'sizeof(foo) > sizeof(int) + sizeof(char)'; for example, 'sizeof(foo) == 2*sizeof(int)'. The initial version of the MPI standard defined the extent of a datatype as including an `epsilon` that would have allowed an implementation to make the extent an MPI datatype for this structure equal to '2*sizeof(int)'. However, since different systems might define different paddings, there was much discussion by the MPI Forum about what was the correct value of epsilon, and one suggestion was to define epsilon as zero. This would have been the best thing to do in MPI 1.0, particularly since the 'MPI_UB' type allows the user to easily set the end of the structure. Unfortunately, this change did not make it into the final document. Currently, this routine does not add any padding, since the amount of padding needed is determined by the compiler that the user is using to build their code, not the compiler used to construct the MPI library. A later version of MPICH may provide for some natural choices of padding (e.g., multiple of the size of the largest basic member), but users are advised to never depend on this, even with vendor MPI implementations. Instead, if you define a structure datatype and wish to send or receive multiple items, you should explicitly include an 'MPI_UB' entry as the last member of the structure. For example, the following code can be used for the structure foo .vb blen[0] = 1; indices[0] = 0; oldtypes[0] = MPI_INT; blen[1] = 1; indices[1] = &foo.b - &foo; oldtypes[1] = MPI_CHAR; blen[2] = 1; indices[2] = sizeof(foo); oldtypes[2] = MPI_UB; MPI_Type_struct( 3, blen, indices, oldtypes, &newtype ); .ve .N fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_TYPE .N MPI_ERR_COUNT .N MPI_ERR_EXHAUSTED @*/ int MPI_Type_struct( int count, int blocklens[], MPI_Aint indices[], MPI_Datatype old_types[], MPI_Datatype *newtype ) { struct MPIR_DATATYPE* dteptr; MPI_Aint ub, lb, high, low, real_ub, real_lb, real_init; int high_init = 0, low_init = 0; int i, mpi_errno = MPI_SUCCESS; MPI_Aint ub_marker = 0, lb_marker = 0; /* to suppress warnings */ MPI_Aint ub_found = 0, lb_found = 0; int size, total_count; static char myname[] = "MPI_TYPE_STRUCT"; disableSignal(); /* Check for bad arguments */ if ( count < 0 ) { mpi_errno = MPIR_Err_setmsg( MPI_ERR_COUNT, MPIR_ERR_DEFAULT, myname, (char *)0, (char *)0, count ); revertSignal(); return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname ); } if (count == 0) { revertSignal(); return MPI_Type_contiguous( 0, MPI_INT, newtype ); } /* Check blocklens and old_types arrays and find number of bound */ /* markers */ total_count = 0; for (i=0; i<count; i++) { total_count += blocklens[i]; if ( blocklens[i] < 0) { mpi_errno = MPIR_Err_setmsg( MPI_ERR_ARG, MPIR_ERR_ARG_ARRAY_VAL, myname, (char *)0, (char *)0, "blocklens", i, blocklens[i] ); revertSignal(); return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno,myname); } if ( old_types[i] == MPI_DATATYPE_NULL ) { mpi_errno = MPIR_Err_setmsg( MPI_ERR_TYPE, MPIR_ERR_TYPE_ARRAY_NULL, myname, (char *)0, (char *)0, "old_types", i ); revertSignal(); return MPIR_ERROR( MPIR_COMM_WORLD, mpi_errno, myname ); } } if (total_count == 0) { revertSignal(); return MPI_Type_contiguous( 0, MPI_INT, newtype ); } /* Create and fill in the datatype */ MPIR_ALLOC(dteptr,(struct MPIR_DATATYPE *) MPIR_SBalloc( MPIR_dtes ),MPIR_COMM_WORLD, MPI_ERR_EXHAUSTED, myname ); *newtype = (MPI_Datatype) MPIR_FromPointer( dteptr ); dteptr->self = *newtype; MPIR_SET_COOKIE(dteptr,MPIR_DATATYPE_COOKIE) dteptr->dte_type = MPIR_STRUCT; dteptr->committed = 0; dteptr->basic = 0; dteptr->permanent = 0; dteptr->is_contig = 0; dteptr->ref_count = 1; dteptr->count = count; dteptr->elements = 0; dteptr->size = 0; dteptr->align = 1; dteptr->has_ub = 0; dteptr->has_lb = 0; dteptr->self = *newtype; /* Create indices and blocklens arrays and fill them */ dteptr->indices = ( MPI_Aint * ) MALLOC( count * sizeof( MPI_Aint ) ); dteptr->blocklens = ( int * ) MALLOC( count * sizeof( int ) ); dteptr->old_types = ( struct MPIR_DATATYPE ** )MALLOC(count*sizeof(struct MPIR_DATATYPE *)); if (!dteptr->indices || !dteptr->blocklens || !dteptr->old_types) { revertSignal(); return MPIR_ERROR( MPIR_COMM_WORLD, MPI_ERR_EXHAUSTED, "MPI_TYPE_STRUCT" ); } high = low = ub = lb = 0; real_ub = real_lb = 0; real_init = 0; /* If data alignment is 2, 4, or 8, then assign dteptr->align to that value. If 0, then assign dteptr->align to the maximal alignment requirement. (done below) */ if (ALIGNMENT_VALUE > 0) dteptr->align = ALIGNMENT_VALUE; for (i = 0; i < count; i++) { struct MPIR_DATATYPE *old_dtype_ptr; old_dtype_ptr = MPIR_GET_DTYPE_PTR(old_types[i]); MPIR_TEST_DTYPE(old_types[i],old_dtype_ptr,MPIR_COMM_WORLD, "MPI_TYPE_STRUCT"); dteptr->old_types[i] = MPIR_Type_dup (old_dtype_ptr); dteptr->indices[i] = indices[i]; dteptr->blocklens[i] = blocklens[i]; /* Keep track of maximal alignment requirement */ if (ALIGNMENT_VALUE == 0) { if (dteptr->align < old_dtype_ptr->align) dteptr->align = old_dtype_ptr->align; } if ( old_dtype_ptr->dte_type == MPIR_UB ) { if (ub_found) { if (indices[i] > ub_marker) ub_marker = indices[i]; } else { ub_marker = indices[i]; ub_found = 1; } } else if ( old_dtype_ptr->dte_type == MPIR_LB ) { if (lb_found) { if ( indices[i] < lb_marker ) { lb_marker = indices[i]; } } else { lb_marker = indices[i]; lb_found = 1; } } else { /* Since the datatype is NOT a UB or LB, save the real limits */ if (!real_init) { real_init = 1; real_lb = old_dtype_ptr->real_lb; real_ub = old_dtype_ptr->real_ub; } else { if (old_dtype_ptr->real_lb < real_lb) real_lb = old_dtype_ptr->real_lb; if (old_dtype_ptr->real_ub > real_ub) real_ub = old_dtype_ptr->real_ub; } /* Next, check to see if datatype has an MPI_LB or MPI_UB within it... Make sure to adjust the ub by the selected displacement and blocklens (blocklens is like Type_contiguous) */ if (old_dtype_ptr->has_ub) { MPI_Aint ub_test; ub_test = old_dtype_ptr->ub + indices[i] + (blocklens[i] - 1) * old_dtype_ptr->extent; if (ub_marker < ub_test || !ub_found) ub_marker = ub_test; ub_found = 1; } if (old_dtype_ptr->has_lb) { if (!lb_found || lb_marker > (old_dtype_ptr->lb) + indices[i] ) lb_marker = old_dtype_ptr->lb + indices[i]; lb_found = 1; } /* Get the ub/lb from the datatype (if a MPI_UB or MPI_LB was found, then these values will be ignored). We use the lb of the old type and add the indices value to it */ lb = indices[i] + old_dtype_ptr->lb; ub = lb + (blocklens[i] * old_dtype_ptr->extent) ; if (!high_init) { high = ub; high_init = 1; } else if (ub > high) high = ub; if (!low_init ) { low = lb; low_init = 1; } else if (lb < low) low = lb; if (ub > lb) { if ( high < ub ) high = ub; if ( low > lb ) low = lb; } else { if ( high < lb ) high = lb; if ( low > ub ) low = ub; } dteptr->elements += (blocklens[i] * old_dtype_ptr->elements); } /* end else */ if (i < count - 1) { size = old_dtype_ptr->size * blocklens[i]; dteptr->size += size; } else { dteptr->size += (blocklens[i] * old_dtype_ptr->size); } } /* end for loop */ /* Set the upper/lower bounds and the extent and size */ if (lb_found) { dteptr->lb = lb_marker; dteptr->has_lb = 1; } else dteptr->lb = (low_init ? low : 0); if (ub_found) { dteptr->ub = ub_marker; dteptr->has_ub = 1; } else dteptr->ub = (high_init ? high: 0); dteptr->extent = dteptr->ub - dteptr->lb ; dteptr->real_ub = real_ub; dteptr->real_lb = real_lb; /* If there is no explicit ub/lb marker, make the extent/ub fit the alignment of the largest basic item, if that structure alignment is chosen */ if (!lb_found && !ub_found) { MPI_Aint eps_offset; /* Since data is always offset by the extent, is the extent that we must adjust. */ eps_offset = dteptr->extent % dteptr->align; if (eps_offset > 0) { dteptr->ub += (dteptr->align - eps_offset); dteptr->extent = dteptr->ub - dteptr->lb; } } # if defined(MPID_HAS_TYPE_STRUCT) { mpi_errno = MPID_Type_struct(count, blocklens, indices, old_types, *newtype); } # endif revertSignal(); return (mpi_errno); }