int MPIR_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; MPI_Aint contig_count; MPI_Aint 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; MPIR_Datatype *new_dtp; if (count == 0) return MPII_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 = (MPIR_Datatype *) MPIR_Handle_obj_alloc(&MPIR_Datatype_mem); /* --BEGIN ERROR HANDLING-- */ if (!new_dtp) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPIR_Type_indexed", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ /* handle is filled in by MPIR_Handle_obj_alloc() */ MPIR_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; 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 = MPIR_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; MPIR_Assign_trunc(new_dtp->alignsize, el_sz, MPI_Aint); new_dtp->builtin_element_size = el_sz; new_dtp->basic_type = el_type; new_dtp->max_contig_blocks = count; } else { /* user-defined base type (oldtype) */ MPIR_Datatype *old_dtp; MPIR_Datatype_get_ptr(oldtype, old_dtp); /* Ensure that "builtin_element_size" fits into an int datatype. */ MPIR_Ensure_Aint_fits_in_int(old_dtp->builtin_element_size); el_sz = old_dtp->builtin_element_size; old_sz = old_dtp->size; el_ct = old_dtp->n_builtin_elements; 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_extent = old_dtp->extent; MPIR_Datatype_is_contig(oldtype, &old_is_contig); new_dtp->has_sticky_lb = old_dtp->has_sticky_lb; new_dtp->has_sticky_ub = old_dtp->has_sticky_ub; new_dtp->builtin_element_size = (MPI_Aint) el_sz; new_dtp->basic_type = 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) { MPIR_Handle_obj_free(&MPIR_Datatype_mem, new_dtp); return MPII_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); MPII_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 */ MPII_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_builtin_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) { MPI_Aint *blklens = MPL_malloc(count * sizeof(MPI_Aint), MPL_MEM_DATATYPE); MPIR_Assert(blklens != NULL); for (i = 0; i < count; i++) blklens[i] = blocklength_array[i]; contig_count = MPIR_Type_indexed_count_contig(count, blklens, 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; } MPL_free(blklens); } *newtype = new_dtp->handle; return mpi_errno; }
/*@ MPIR_Type_contiguous - create a contiguous datatype Input Parameters: + count - number of elements in the contiguous block - oldtype - type (using handle) of datatype on which vector is based Output Parameters: . newtype - handle of new contiguous datatype Return Value: MPI_SUCCESS on success, MPI error code on failure. @*/ int MPIR_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype *newtype) { int mpi_errno = MPI_SUCCESS; int is_builtin; MPI_Aint el_sz; MPI_Datatype el_type; MPIR_Datatype *new_dtp; if (count == 0) return MPII_Type_zerolen(newtype); /* allocate new datatype object and handle */ new_dtp = (MPIR_Datatype *) MPIR_Handle_obj_alloc(&MPIR_Datatype_mem); /* --BEGIN ERROR HANDLING-- */ if (!new_dtp) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPIR_Type_contiguous", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ /* handle is filled in by MPIR_Handle_obj_alloc() */ MPIR_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 = MPIR_Datatype_get_basic_size(oldtype); el_type = oldtype; new_dtp->size = count * el_sz; new_dtp->has_sticky_ub = 0; new_dtp->has_sticky_lb = 0; new_dtp->true_lb = 0; new_dtp->lb = 0; new_dtp->true_ub = count * el_sz; new_dtp->ub = new_dtp->true_ub; new_dtp->extent = new_dtp->ub - new_dtp->lb; new_dtp->alignsize = el_sz; new_dtp->n_builtin_elements = count; new_dtp->builtin_element_size = el_sz; new_dtp->basic_type = el_type; new_dtp->is_contig = 1; new_dtp->max_contig_blocks = 1; } else { /* user-defined base type (oldtype) */ MPIR_Datatype *old_dtp; MPIR_Datatype_get_ptr(oldtype, old_dtp); el_sz = old_dtp->builtin_element_size; el_type = old_dtp->basic_type; new_dtp->size = count * old_dtp->size; new_dtp->has_sticky_ub = old_dtp->has_sticky_ub; new_dtp->has_sticky_lb = old_dtp->has_sticky_lb; MPII_DATATYPE_CONTIG_LB_UB((MPI_Aint) count, old_dtp->lb, old_dtp->ub, old_dtp->extent, new_dtp->lb, new_dtp->ub); /* easiest to calc true lb/ub relative to lb/ub; doesn't matter * if there are sticky lb/ubs or not when doing this. */ new_dtp->true_lb = new_dtp->lb + (old_dtp->true_lb - old_dtp->lb); new_dtp->true_ub = new_dtp->ub + (old_dtp->true_ub - old_dtp->ub); new_dtp->extent = new_dtp->ub - new_dtp->lb; new_dtp->alignsize = old_dtp->alignsize; new_dtp->n_builtin_elements = count * old_dtp->n_builtin_elements; new_dtp->builtin_element_size = old_dtp->builtin_element_size; new_dtp->basic_type = el_type; MPIR_Datatype_is_contig(oldtype, &new_dtp->is_contig); if(new_dtp->is_contig) new_dtp->max_contig_blocks = 1; else new_dtp->max_contig_blocks = count * old_dtp->max_contig_blocks; } *newtype = new_dtp->handle; MPL_DBG_MSG_P(MPIR_DBG_DATATYPE,VERBOSE,"contig type %x created.", new_dtp->handle); return mpi_errno; }
/*@ MPIR_Type_blockindexed - create a block indexed datatype Input Parameters: + count - number of blocks in type . blocklength - number of elements in each block . displacement_array - offsets of blocks from start of type (see next parameter for units) . dispinbytes - if nonzero, then displacements are in bytes, otherwise they in terms of extent of oldtype - oldtype - type (using handle) of datatype on which new type is based Output Parameters: . newtype - handle of new block indexed datatype Return Value: MPI_SUCCESS on success, MPI error on failure. @*/ int MPIR_Type_blockindexed(int count, int blocklength, const void *displacement_array, int dispinbytes, MPI_Datatype oldtype, MPI_Datatype * newtype) { int mpi_errno = MPI_SUCCESS, i; int is_builtin, old_is_contig; MPI_Aint contig_count; 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; MPIR_Datatype *new_dtp; if (count == 0) return MPII_Type_zerolen(newtype); /* allocate new datatype object and handle */ new_dtp = (MPIR_Datatype *) MPIR_Handle_obj_alloc(&MPIR_Datatype_mem); /* --BEGIN ERROR HANDLING-- */ if (!new_dtp) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPIR_Type_vector", __LINE__, MPI_ERR_OTHER, "**nomem", 0); return mpi_errno; } /* --END ERROR HANDLING-- */ /* handle is filled in by MPIR_Handle_obj_alloc() */ MPIR_Object_set_ref(new_dtp, 1); new_dtp->is_committed = 0; new_dtp->attributes = NULL; new_dtp->name[0] = 0; new_dtp->contents = NULL; new_dtp->dataloop = NULL; new_dtp->dataloop_size = -1; is_builtin = (HANDLE_GET_KIND(oldtype) == HANDLE_KIND_BUILTIN); if (is_builtin) { el_sz = (MPI_Aint) MPIR_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_builtin_elements = count * blocklength; new_dtp->builtin_element_size = el_sz; new_dtp->basic_type = el_type; new_dtp->max_contig_blocks = count; } else { /* user-defined base type (oldtype) */ MPIR_Datatype *old_dtp; MPIR_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_extent = old_dtp->extent; MPIR_Datatype_is_contig(oldtype, &old_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_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; } /* priming for loop */ eff_disp = (dispinbytes) ? ((MPI_Aint *) displacement_array)[0] : (((MPI_Aint) ((int *) displacement_array)[0]) * old_extent); MPII_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); MPII_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 = MPII_Datatype_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; }