/*@ MPID_Type_vector - create a vector datatype Input Parameters: + count - number of blocks in vector . blocklength - number of elements in each block . stride - distance from beginning of one block to the next (see next parameter for units) . strideinbytes - if nonzero, then stride is in bytes, otherwise stride is in terms of extent of oldtype - oldtype - type (using handle) of datatype on which vector is based Output Parameters: . newtype - handle of new vector datatype Return Value: 0 on success, MPI error code on failure. @*/ int MPID_Type_vector(int count, int blocklength, MPI_Aint stride, int strideinbytes, MPI_Datatype oldtype, MPI_Datatype *newtype) { int mpi_errno = MPI_SUCCESS; int is_builtin, old_is_contig; MPI_Aint el_sz, old_sz; MPI_Datatype el_type; MPI_Aint old_lb, old_ub, old_extent, old_true_lb, old_true_ub, eff_stride; MPID_Datatype *new_dtp; if (count == 0) return MPID_Type_zerolen(newtype); /* allocate new datatype object and handle */ new_dtp = (MPID_Datatype *) MPIU_Handle_obj_alloc(&MPID_Datatype_mem); if (!new_dtp) { /* --BEGIN ERROR HANDLING-- */ mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPID_Type_vector", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; /* --END ERROR HANDLING-- */ } /* handle is filled in by MPIU_Handle_obj_alloc() */ MPIU_Object_set_ref(new_dtp, 1); new_dtp->is_permanent = 0; new_dtp->is_committed = 0; new_dtp->attributes = NULL; new_dtp->cache_id = 0; new_dtp->name[0] = 0; new_dtp->contents = NULL; new_dtp->dataloop = NULL; new_dtp->dataloop_size = -1; new_dtp->dataloop_depth = -1; new_dtp->hetero_dloop = NULL; new_dtp->hetero_dloop_size = -1; new_dtp->hetero_dloop_depth = -1; is_builtin = (HANDLE_GET_KIND(oldtype) == HANDLE_KIND_BUILTIN); if (is_builtin) { el_sz = (MPI_Aint) MPID_Datatype_get_basic_size(oldtype); el_type = oldtype; old_lb = 0; old_true_lb = 0; old_ub = el_sz; old_true_ub = el_sz; old_sz = el_sz; old_extent = el_sz; old_is_contig = 1; new_dtp->size = (MPI_Aint) count * (MPI_Aint) blocklength * el_sz; new_dtp->has_sticky_lb = 0; new_dtp->has_sticky_ub = 0; new_dtp->alignsize = el_sz; /* ??? */ new_dtp->n_builtin_elements = count * blocklength; new_dtp->builtin_element_size = el_sz; new_dtp->basic_type = el_type; new_dtp->max_contig_blocks = count; eff_stride = (strideinbytes) ? stride : (stride * el_sz); } else /* user-defined base type (oldtype) */ { MPID_Datatype *old_dtp; MPID_Datatype_get_ptr(oldtype, old_dtp); el_sz = old_dtp->builtin_element_size; el_type = old_dtp->basic_type; old_lb = old_dtp->lb; old_true_lb = old_dtp->true_lb; old_ub = old_dtp->ub; old_true_ub = old_dtp->true_ub; old_sz = old_dtp->size; old_extent = old_dtp->extent; old_is_contig = old_dtp->is_contig; new_dtp->size = count * blocklength * old_dtp->size; new_dtp->has_sticky_lb = old_dtp->has_sticky_lb; new_dtp->has_sticky_ub = old_dtp->has_sticky_ub; new_dtp->alignsize = old_dtp->alignsize; new_dtp->n_builtin_elements = count * blocklength * old_dtp->n_builtin_elements; new_dtp->builtin_element_size = el_sz; new_dtp->basic_type = el_type; new_dtp->max_contig_blocks = old_dtp->max_contig_blocks * count * blocklength; eff_stride = (strideinbytes) ? stride : (stride * old_dtp->extent); } MPID_DATATYPE_VECTOR_LB_UB((MPI_Aint) count, eff_stride, (MPI_Aint) blocklength, old_lb, old_ub, old_extent, new_dtp->lb, new_dtp->ub); new_dtp->true_lb = new_dtp->lb + (old_true_lb - old_lb); new_dtp->true_ub = new_dtp->ub + (old_true_ub - old_ub); new_dtp->extent = new_dtp->ub - new_dtp->lb; /* new type is only contig for N types if old one was, and * size and extent of new type are equivalent, and stride is * equal to blocklength * size of old type. */ if ((MPI_Aint)(new_dtp->size) == new_dtp->extent && eff_stride == (MPI_Aint) blocklength * old_sz && old_is_contig) { new_dtp->is_contig = 1; new_dtp->max_contig_blocks = 1; } else { new_dtp->is_contig = 0; } *newtype = new_dtp->handle; MPIU_DBG_MSG_P(DATATYPE,VERBOSE,"vector type %x created.", new_dtp->handle); return mpi_errno; }
int MPID_Type_indexed(int count, const int *blocklength_array, const void *displacement_array, int dispinbytes, MPI_Datatype oldtype, MPI_Datatype *newtype) { int mpi_errno = MPI_SUCCESS; int is_builtin, old_is_contig; int i, contig_count; int el_sz, el_ct, old_ct, old_sz; MPI_Aint old_lb, old_ub, old_extent, old_true_lb, old_true_ub; MPI_Aint min_lb = 0, max_ub = 0, eff_disp; MPI_Datatype el_type; MPID_Datatype *new_dtp; if (count == 0) return MPID_Type_zerolen(newtype); /* sanity check that blocklens are all non-negative */ for (i = 0; i < count; ++i) { DLOOP_Assert(blocklength_array[i] >= 0); } /* allocate new datatype object and handle */ new_dtp = (MPID_Datatype *) MPIU_Handle_obj_alloc(&MPID_Datatype_mem); /* --BEGIN ERROR HANDLING-- */ if (!new_dtp) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPID_Type_indexed", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ /* handle is filled in by MPIU_Handle_obj_alloc() */ MPIU_Object_set_ref(new_dtp, 1); new_dtp->is_permanent = 0; new_dtp->is_committed = 0; new_dtp->attributes = NULL; new_dtp->cache_id = 0; new_dtp->name[0] = 0; new_dtp->contents = NULL; new_dtp->dataloop = NULL; new_dtp->dataloop_size = -1; new_dtp->dataloop_depth = -1; new_dtp->hetero_dloop = NULL; new_dtp->hetero_dloop_size = -1; new_dtp->hetero_dloop_depth = -1; is_builtin = (HANDLE_GET_KIND(oldtype) == HANDLE_KIND_BUILTIN); if (is_builtin) { /* builtins are handled differently than user-defined types because * they have no associated dataloop or datatype structure. */ el_sz = MPID_Datatype_get_basic_size(oldtype); old_sz = el_sz; el_ct = 1; el_type = oldtype; old_lb = 0; old_true_lb = 0; old_ub = (MPI_Aint) el_sz; old_true_ub = (MPI_Aint) el_sz; old_extent = (MPI_Aint) el_sz; old_is_contig = 1; new_dtp->has_sticky_ub = 0; new_dtp->has_sticky_lb = 0; new_dtp->alignsize = el_sz; /* ??? */ new_dtp->element_size = (MPI_Aint) el_sz; new_dtp->eltype = el_type; new_dtp->max_contig_blocks = count; } else { /* user-defined base type (oldtype) */ MPID_Datatype *old_dtp; MPID_Datatype_get_ptr(oldtype, old_dtp); /* Ensure that "element_size" fits into an int datatype. */ MPID_Ensure_Aint_fits_in_int(old_dtp->element_size); el_sz = old_dtp->element_size; old_sz = old_dtp->size; el_ct = old_dtp->n_elements; el_type = old_dtp->eltype; old_lb = old_dtp->lb; old_true_lb = old_dtp->true_lb; old_ub = old_dtp->ub; old_true_ub = old_dtp->true_ub; old_extent = old_dtp->extent; old_is_contig = old_dtp->is_contig; new_dtp->has_sticky_lb = old_dtp->has_sticky_lb; new_dtp->has_sticky_ub = old_dtp->has_sticky_ub; new_dtp->element_size = (MPI_Aint) el_sz; new_dtp->eltype = el_type; new_dtp->max_contig_blocks = 0; for(i=0; i<count; i++) new_dtp->max_contig_blocks += old_dtp->max_contig_blocks * ((MPI_Aint ) blocklength_array[i]); } /* find the first nonzero blocklength element */ i = 0; while (i < count && blocklength_array[i] == 0) i++; if (i == count) { MPIU_Handle_obj_free(&MPID_Datatype_mem, new_dtp); return MPID_Type_zerolen(newtype); } /* priming for loop */ old_ct = blocklength_array[i]; eff_disp = (dispinbytes) ? ((MPI_Aint *) displacement_array)[i] : (((MPI_Aint) ((int *) displacement_array)[i]) * old_extent); MPID_DATATYPE_BLOCK_LB_UB((MPI_Aint) blocklength_array[i], eff_disp, old_lb, old_ub, old_extent, min_lb, max_ub); /* determine min lb, max ub, and count of old types in remaining * nonzero size blocks */ for (i++; i < count; i++) { MPI_Aint tmp_lb, tmp_ub; if (blocklength_array[i] > 0) { old_ct += blocklength_array[i]; /* add more oldtypes */ eff_disp = (dispinbytes) ? ((MPI_Aint *) displacement_array)[i] : (((MPI_Aint) ((int *) displacement_array)[i]) * old_extent); /* calculate ub and lb for this block */ MPID_DATATYPE_BLOCK_LB_UB((MPI_Aint)(blocklength_array[i]), eff_disp, old_lb, old_ub, old_extent, tmp_lb, tmp_ub); if (tmp_lb < min_lb) min_lb = tmp_lb; if (tmp_ub > max_ub) max_ub = tmp_ub; } } new_dtp->size = old_ct * old_sz; new_dtp->lb = min_lb; new_dtp->ub = max_ub; new_dtp->true_lb = min_lb + (old_true_lb - old_lb); new_dtp->true_ub = max_ub + (old_true_ub - old_ub); new_dtp->extent = max_ub - min_lb; new_dtp->n_elements = old_ct * el_ct; /* new type is only contig for N types if it's all one big * block, its size and extent are the same, and the old type * was also contiguous. */ new_dtp->is_contig = 0; if(old_is_contig) { contig_count = MPID_Type_indexed_count_contig(count, blocklength_array, displacement_array, dispinbytes, old_extent); new_dtp->max_contig_blocks = contig_count; if( (contig_count == 1) && ((MPI_Aint) new_dtp->size == new_dtp->extent)) { new_dtp->is_contig = 1; } } *newtype = new_dtp->handle; return mpi_errno; }
int MPID_Type_blockindexed(int count, int blocklength, void *displacement_array, int dispinbytes, MPI_Datatype oldtype, MPI_Datatype *newtype) { int mpi_errno = MPI_SUCCESS, i; int is_builtin, contig_count, old_is_contig; MPI_Aint el_sz; MPI_Datatype el_type; MPI_Aint old_lb, old_ub, old_extent, old_true_lb, old_true_ub; MPI_Aint min_lb = 0, max_ub = 0, eff_disp; MPID_Datatype *new_dtp; if (count == 0) return MPID_Type_zerolen(newtype); /* allocate new datatype object and handle */ new_dtp = (MPID_Datatype *) MPIU_Handle_obj_alloc(&MPID_Datatype_mem); /* --BEGIN ERROR HANDLING-- */ if (!new_dtp) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPID_Type_vector", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ /* handle is filled in by MPIU_Handle_obj_alloc() */ MPIU_Object_set_ref(new_dtp, 1); new_dtp->is_permanent = 0; new_dtp->is_committed = 0; new_dtp->attributes = NULL; new_dtp->cache_id = 0; new_dtp->name[0] = 0; new_dtp->contents = NULL; new_dtp->dataloop = NULL; new_dtp->dataloop_size = -1; new_dtp->dataloop_depth = -1; new_dtp->hetero_dloop = NULL; new_dtp->hetero_dloop_size = -1; new_dtp->hetero_dloop_depth = -1; is_builtin = (HANDLE_GET_KIND(oldtype) == HANDLE_KIND_BUILTIN); if (is_builtin) { el_sz = (MPI_Aint) MPID_Datatype_get_basic_size(oldtype); el_type = oldtype; old_lb = 0; old_true_lb = 0; old_ub = el_sz; old_true_ub = el_sz; old_extent = el_sz; old_is_contig = 1; new_dtp->size = (MPI_Aint) count * (MPI_Aint) blocklength * el_sz; new_dtp->has_sticky_lb = 0; new_dtp->has_sticky_ub = 0; new_dtp->alignsize = el_sz; /* ??? */ new_dtp->n_elements = count * blocklength; new_dtp->element_size = el_sz; new_dtp->eltype = el_type; new_dtp->max_contig_blocks = count; } else { /* user-defined base type (oldtype) */ MPID_Datatype *old_dtp; MPID_Datatype_get_ptr(oldtype, old_dtp); el_sz = old_dtp->element_size; el_type = old_dtp->eltype; old_lb = old_dtp->lb; old_true_lb = old_dtp->true_lb; old_ub = old_dtp->ub; old_true_ub = old_dtp->true_ub; old_extent = old_dtp->extent; old_is_contig = old_dtp->is_contig; new_dtp->size = (MPI_Aint) count * (MPI_Aint) blocklength * (MPI_Aint) old_dtp->size; new_dtp->has_sticky_lb = old_dtp->has_sticky_lb; new_dtp->has_sticky_ub = old_dtp->has_sticky_ub; new_dtp->alignsize = old_dtp->alignsize; new_dtp->n_elements = count * blocklength * old_dtp->n_elements; new_dtp->element_size = el_sz; new_dtp->eltype = el_type; new_dtp->max_contig_blocks = old_dtp->max_contig_blocks * count * blocklength; } /* priming for loop */ eff_disp = (dispinbytes) ? ((MPI_Aint *) displacement_array)[0] : (((MPI_Aint) ((int *) displacement_array)[0]) * old_extent); MPID_DATATYPE_BLOCK_LB_UB((MPI_Aint) blocklength, eff_disp, old_lb, old_ub, old_extent, min_lb, max_ub); /* determine new min lb and max ub */ for (i=1; i < count; i++) { MPI_Aint tmp_lb, tmp_ub; eff_disp = (dispinbytes) ? ((MPI_Aint *) displacement_array)[i] : (((MPI_Aint) ((int *) displacement_array)[i]) * old_extent); MPID_DATATYPE_BLOCK_LB_UB((MPI_Aint) blocklength, eff_disp, old_lb, old_ub, old_extent, tmp_lb, tmp_ub); if (tmp_lb < min_lb) min_lb = tmp_lb; if (tmp_ub > max_ub) max_ub = tmp_ub; } new_dtp->lb = min_lb; new_dtp->ub = max_ub; new_dtp->true_lb = min_lb + (old_true_lb - old_lb); new_dtp->true_ub = max_ub + (old_true_ub - old_ub); new_dtp->extent = max_ub - min_lb; /* new type is contig for N types if it is all one big block, * its size and extent are the same, and the old type was also * contiguous. */ new_dtp->is_contig = 0; if (old_is_contig) { contig_count = MPID_Type_blockindexed_count_contig(count, blocklength, displacement_array, dispinbytes, old_extent); new_dtp->max_contig_blocks = contig_count; if( (contig_count == 1) && ((MPI_Aint) new_dtp->size == new_dtp->extent) ) { new_dtp->is_contig = 1; } } *newtype = new_dtp->handle; return mpi_errno; }
/*@ MPID_Type_struct - create a struct datatype Input Parameters: + count - number of blocks in vector . blocklength_array - number of elements in each block . displacement_array - offsets of blocks from start of type in bytes - oldtype_array - types (using handle) of datatypes on which vector is based Output Parameters: . newtype - handle of new struct datatype Return Value: MPI_SUCCESS on success, MPI errno on failure. @*/ int MPID_Type_struct(int count, const int *blocklength_array, const MPI_Aint *displacement_array, const MPI_Datatype *oldtype_array, MPI_Datatype *newtype) { int mpi_errno = MPI_SUCCESS; int i, old_are_contig = 1, definitely_not_contig = 0; int found_sticky_lb = 0, found_sticky_ub = 0, found_true_lb = 0, found_true_ub = 0, found_el_type = 0, found_lb=0, found_ub=0; MPI_Aint el_sz = 0; MPI_Aint size = 0; MPI_Datatype el_type = MPI_DATATYPE_NULL; MPI_Aint true_lb_disp = 0, true_ub_disp = 0, sticky_lb_disp = 0, sticky_ub_disp = 0, lb_disp = 0, ub_disp = 0; MPID_Datatype *new_dtp; if (count == 0) return MPID_Type_zerolen(newtype); #ifdef MPID_STRUCT_DEBUG MPIDI_Datatype_printf(oldtype_array[0], 1, displacement_array[0], blocklength_array[0], 1); for (i=1; i < count; i++) { MPIDI_Datatype_printf(oldtype_array[i], 1, displacement_array[i], blocklength_array[i], 0); } #endif /* allocate new datatype object and handle */ new_dtp = (MPID_Datatype *) MPIU_Handle_obj_alloc(&MPID_Datatype_mem); /* --BEGIN ERROR HANDLING-- */ if (!new_dtp) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPID_Type_struct", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ /* handle is filled in by MPIU_Handle_obj_alloc() */ MPIU_Object_set_ref(new_dtp, 1); new_dtp->is_permanent = 0; new_dtp->is_committed = 0; new_dtp->attributes = NULL; new_dtp->cache_id = 0; new_dtp->name[0] = 0; new_dtp->contents = NULL; new_dtp->dataloop = NULL; new_dtp->dataloop_size = -1; new_dtp->dataloop_depth = -1; new_dtp->hetero_dloop = NULL; new_dtp->hetero_dloop_size = -1; new_dtp->hetero_dloop_depth = -1; /* check for junk struct with all zero blocks */ for (i=0; i < count; i++) if (blocklength_array[i] != 0) break; if (i == count) { MPIU_Handle_obj_free(&MPID_Datatype_mem, new_dtp); return MPID_Type_zerolen(newtype); } new_dtp->max_contig_blocks = 0; for (i=0; i < count; i++) { int is_builtin = (HANDLE_GET_KIND(oldtype_array[i]) == HANDLE_KIND_BUILTIN); MPI_Aint tmp_lb, tmp_ub, tmp_true_lb, tmp_true_ub; MPI_Aint tmp_el_sz; MPI_Datatype tmp_el_type; MPID_Datatype *old_dtp = NULL; /* Interpreting typemap to not include 0 blklen things, including * MPI_LB and MPI_UB. -- Rob Ross, 10/31/2005 */ if (blocklength_array[i] == 0) continue; if (is_builtin) { tmp_el_sz = MPID_Datatype_get_basic_size(oldtype_array[i]); tmp_el_type = oldtype_array[i]; MPID_DATATYPE_BLOCK_LB_UB((MPI_Aint)(blocklength_array[i]), displacement_array[i], 0, tmp_el_sz, tmp_el_sz, tmp_lb, tmp_ub); tmp_true_lb = tmp_lb; tmp_true_ub = tmp_ub; size += tmp_el_sz * blocklength_array[i]; new_dtp->max_contig_blocks++; } else { MPID_Datatype_get_ptr(oldtype_array[i], old_dtp); /* Ensure that "builtin_element_size" fits into an int datatype. */ MPID_Ensure_Aint_fits_in_int(old_dtp->builtin_element_size); tmp_el_sz = old_dtp->builtin_element_size; tmp_el_type = old_dtp->basic_type; MPID_DATATYPE_BLOCK_LB_UB((MPI_Aint) blocklength_array[i], displacement_array[i], old_dtp->lb, old_dtp->ub, old_dtp->extent, tmp_lb, tmp_ub); tmp_true_lb = tmp_lb + (old_dtp->true_lb - old_dtp->lb); tmp_true_ub = tmp_ub + (old_dtp->true_ub - old_dtp->ub); size += old_dtp->size * blocklength_array[i]; new_dtp->max_contig_blocks += old_dtp->max_contig_blocks; } /* element size and type */ if (oldtype_array[i] != MPI_LB && oldtype_array[i] != MPI_UB) { if (found_el_type == 0) { el_sz = tmp_el_sz; el_type = tmp_el_type; found_el_type = 1; } else if (el_sz != tmp_el_sz) { el_sz = -1; el_type = MPI_DATATYPE_NULL; } else if (el_type != tmp_el_type) { /* Q: should we set el_sz = -1 even though the same? */ el_type = MPI_DATATYPE_NULL; } } /* keep lowest sticky lb */ if ((oldtype_array[i] == MPI_LB) || (!is_builtin && old_dtp->has_sticky_lb)) { if (!found_sticky_lb) { found_sticky_lb = 1; sticky_lb_disp = tmp_lb; } else if (sticky_lb_disp > tmp_lb) { sticky_lb_disp = tmp_lb; } } /* keep highest sticky ub */ if ((oldtype_array[i] == MPI_UB) || (!is_builtin && old_dtp->has_sticky_ub)) { if (!found_sticky_ub) { found_sticky_ub = 1; sticky_ub_disp = tmp_ub; } else if (sticky_ub_disp < tmp_ub) { sticky_ub_disp = tmp_ub; } } /* keep lowest lb/true_lb and highest ub/true_ub * * note: checking for contiguity at the same time, to avoid * yet another pass over the arrays */ if (oldtype_array[i] != MPI_UB && oldtype_array[i] != MPI_LB) { if (!found_true_lb) { found_true_lb = 1; true_lb_disp = tmp_true_lb; } else if (true_lb_disp > tmp_true_lb) { /* element starts before previous */ true_lb_disp = tmp_true_lb; definitely_not_contig = 1; } if (!found_lb) { found_lb = 1; lb_disp = tmp_lb; } else if (lb_disp > tmp_lb) { /* lb before previous */ lb_disp = tmp_lb; definitely_not_contig = 1; } if (!found_true_ub) { found_true_ub = 1; true_ub_disp = tmp_true_ub; } else if (true_ub_disp < tmp_true_ub) { true_ub_disp = tmp_true_ub; } else { /* element ends before previous ended */ definitely_not_contig = 1; } if (!found_ub) { found_ub = 1; ub_disp = tmp_ub; } else if (ub_disp < tmp_ub) { ub_disp = tmp_ub; } else { /* ub before previous */ definitely_not_contig = 1; } } if (!is_builtin && !old_dtp->is_contig) { old_are_contig = 0; } } new_dtp->n_builtin_elements = -1; /* TODO */ new_dtp->builtin_element_size = el_sz; new_dtp->basic_type = el_type; new_dtp->has_sticky_lb = found_sticky_lb; new_dtp->true_lb = true_lb_disp; new_dtp->lb = (found_sticky_lb) ? sticky_lb_disp : lb_disp; new_dtp->has_sticky_ub = found_sticky_ub; new_dtp->true_ub = true_ub_disp; new_dtp->ub = (found_sticky_ub) ? sticky_ub_disp : ub_disp; new_dtp->alignsize = MPID_Type_struct_alignsize(count, oldtype_array, displacement_array); new_dtp->extent = new_dtp->ub - new_dtp->lb; if ((!found_sticky_lb) && (!found_sticky_ub)) { /* account for padding */ MPI_Aint epsilon = (new_dtp->alignsize > 0) ? new_dtp->extent % ((MPI_Aint)(new_dtp->alignsize)) : 0; if (epsilon) { new_dtp->ub += ((MPI_Aint)(new_dtp->alignsize) - epsilon); new_dtp->extent = new_dtp->ub - new_dtp->lb; } } new_dtp->size = size; /* new type is contig for N types if its size and extent are the * same, and the old type was also contiguous, and we didn't see * something noncontiguous based on true ub/ub. */ if (((MPI_Aint)(new_dtp->size) == new_dtp->extent) && old_are_contig && (! definitely_not_contig)) { new_dtp->is_contig = 1; } else { new_dtp->is_contig = 0; } *newtype = new_dtp->handle; return mpi_errno; }