|
Packit Service |
c5cf8c |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit Service |
c5cf8c |
/*
|
|
Packit Service |
c5cf8c |
* (C) 2011 by Argonne National Laboratory.
|
|
Packit Service |
c5cf8c |
* See COPYRIGHT in top-level directory.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* -- Begin Profiling Symbol Block for routine MPI_Get_elements_x */
|
|
Packit Service |
c5cf8c |
#if defined(HAVE_PRAGMA_WEAK)
|
|
Packit Service |
c5cf8c |
#pragma weak MPI_Get_elements_x = PMPI_Get_elements_x
|
|
Packit Service |
c5cf8c |
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
|
|
Packit Service |
c5cf8c |
#pragma _HP_SECONDARY_DEF PMPI_Get_elements_x MPI_Get_elements_x
|
|
Packit Service |
c5cf8c |
#elif defined(HAVE_PRAGMA_CRI_DUP)
|
|
Packit Service |
c5cf8c |
#pragma _CRI duplicate MPI_Get_elements_x as PMPI_Get_elements_x
|
|
Packit Service |
c5cf8c |
#elif defined(HAVE_WEAK_ATTRIBUTE)
|
|
Packit Service |
c5cf8c |
int MPI_Get_elements_x(const MPI_Status * status, MPI_Datatype datatype, MPI_Count * count)
|
|
Packit Service |
c5cf8c |
__attribute__ ((weak, alias("PMPI_Get_elements_x")));
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
/* -- End Profiling Symbol Block */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Internal helper routines. If you want to get the number of elements from
|
|
Packit Service |
c5cf8c |
* within the MPI library, call MPIR_Get_elements_x_impl instead. */
|
|
Packit Service |
c5cf8c |
PMPI_LOCAL MPI_Count MPIR_Type_get_basic_type_elements(MPI_Count * bytes_p,
|
|
Packit Service |
c5cf8c |
MPI_Count count, MPI_Datatype datatype);
|
|
Packit Service |
c5cf8c |
PMPI_LOCAL MPI_Count MPIR_Type_get_elements(MPI_Count * bytes_p,
|
|
Packit Service |
c5cf8c |
MPI_Count count, MPI_Datatype datatype);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
|
|
Packit Service |
c5cf8c |
the MPI routines */
|
|
Packit Service |
c5cf8c |
#ifndef MPICH_MPI_FROM_PMPI
|
|
Packit Service |
c5cf8c |
#undef MPI_Get_elements_x
|
|
Packit Service |
c5cf8c |
#define MPI_Get_elements_x PMPI_Get_elements_x
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* any non-MPI functions go here, especially non-static ones */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* MPIR_Type_get_basic_type_elements()
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Arguments:
|
|
Packit Service |
c5cf8c |
* - bytes_p - input/output byte count
|
|
Packit Service |
c5cf8c |
* - count - maximum number of this type to subtract from the bytes; a count
|
|
Packit Service |
c5cf8c |
* of -1 indicates use as many as we like
|
|
Packit Service |
c5cf8c |
* - datatype - input datatype
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Returns number of elements available given the two constraints of number of
|
|
Packit Service |
c5cf8c |
* bytes and count of types. Also reduces the byte count by the amount taken
|
|
Packit Service |
c5cf8c |
* up by the types.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Assumptions:
|
|
Packit Service |
c5cf8c |
* - the type passed to this function must be a basic *or* a pairtype
|
|
Packit Service |
c5cf8c |
* (which aren't basic types)
|
|
Packit Service |
c5cf8c |
* - the count is not zero (otherwise we can't tell between a "no more
|
|
Packit Service |
c5cf8c |
* complete types" case and a "zero count" case)
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* As per section 4.9.3 of the MPI 1.1 specification, the two-part reduction
|
|
Packit Service |
c5cf8c |
* types are to be treated as structs of the constituent types. So we have to
|
|
Packit Service |
c5cf8c |
* do something special to handle them correctly in here.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* As per section 3.12.5 get_count and get_elements report the same value for
|
|
Packit Service |
c5cf8c |
* basic datatypes; I'm currently interpreting this to *not* include these
|
|
Packit Service |
c5cf8c |
* reduction types, as they are considered structs.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
PMPI_LOCAL MPI_Count MPIR_Type_get_basic_type_elements(MPI_Count * bytes_p,
|
|
Packit Service |
c5cf8c |
MPI_Count count, MPI_Datatype datatype)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPI_Count elements, usable_bytes, used_bytes, type1_sz, type2_sz;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (count == 0)
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* determine the maximum number of bytes we should take from the
|
|
Packit Service |
c5cf8c |
* byte count.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (count < 0) {
|
|
Packit Service |
c5cf8c |
usable_bytes = *bytes_p;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
usable_bytes = MPL_MIN(*bytes_p, count * MPIR_Datatype_get_basic_size(datatype));
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
switch (datatype) {
|
|
Packit Service |
c5cf8c |
/* we don't get valid fortran datatype handles in all cases... */
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_FORTRAN_BINDING
|
|
Packit Service |
c5cf8c |
case MPI_2REAL:
|
|
Packit Service |
c5cf8c |
type1_sz = type2_sz = MPIR_Datatype_get_basic_size(MPI_REAL);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_2DOUBLE_PRECISION:
|
|
Packit Service |
c5cf8c |
type1_sz = type2_sz = MPIR_Datatype_get_basic_size(MPI_DOUBLE_PRECISION);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_2INTEGER:
|
|
Packit Service |
c5cf8c |
type1_sz = type2_sz = MPIR_Datatype_get_basic_size(MPI_INTEGER);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
case MPI_2INT:
|
|
Packit Service |
c5cf8c |
type1_sz = type2_sz = MPIR_Datatype_get_basic_size(MPI_INT);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_FLOAT_INT:
|
|
Packit Service |
c5cf8c |
type1_sz = MPIR_Datatype_get_basic_size(MPI_FLOAT);
|
|
Packit Service |
c5cf8c |
type2_sz = MPIR_Datatype_get_basic_size(MPI_INT);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_DOUBLE_INT:
|
|
Packit Service |
c5cf8c |
type1_sz = MPIR_Datatype_get_basic_size(MPI_DOUBLE);
|
|
Packit Service |
c5cf8c |
type2_sz = MPIR_Datatype_get_basic_size(MPI_INT);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_LONG_INT:
|
|
Packit Service |
c5cf8c |
type1_sz = MPIR_Datatype_get_basic_size(MPI_LONG);
|
|
Packit Service |
c5cf8c |
type2_sz = MPIR_Datatype_get_basic_size(MPI_INT);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_SHORT_INT:
|
|
Packit Service |
c5cf8c |
type1_sz = MPIR_Datatype_get_basic_size(MPI_SHORT);
|
|
Packit Service |
c5cf8c |
type2_sz = MPIR_Datatype_get_basic_size(MPI_INT);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_LONG_DOUBLE_INT:
|
|
Packit Service |
c5cf8c |
type1_sz = MPIR_Datatype_get_basic_size(MPI_LONG_DOUBLE);
|
|
Packit Service |
c5cf8c |
type2_sz = MPIR_Datatype_get_basic_size(MPI_INT);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
/* all other types. this is more complicated than
|
|
Packit Service |
c5cf8c |
* necessary for handling these types, but it puts us in the
|
|
Packit Service |
c5cf8c |
* same code path for all the basics, so we stick with it.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
type1_sz = type2_sz = MPIR_Datatype_get_basic_size(datatype);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* determine the number of elements in the region */
|
|
Packit Service |
c5cf8c |
elements = 2 * (usable_bytes / (type1_sz + type2_sz));
|
|
Packit Service |
c5cf8c |
if (usable_bytes % (type1_sz + type2_sz) >= type1_sz)
|
|
Packit Service |
c5cf8c |
elements++;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* determine how many bytes we used up with those elements */
|
|
Packit Service |
c5cf8c |
used_bytes = ((elements / 2) * (type1_sz + type2_sz));
|
|
Packit Service |
c5cf8c |
if (elements % 2 == 1)
|
|
Packit Service |
c5cf8c |
used_bytes += type1_sz;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*bytes_p -= used_bytes;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return elements;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* MPIR_Type_get_elements
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Arguments:
|
|
Packit Service |
c5cf8c |
* - bytes_p - input/output byte count
|
|
Packit Service |
c5cf8c |
* - count - maximum number of this type to subtract from the bytes; a count
|
|
Packit Service |
c5cf8c |
* of <0 indicates use as many as we like
|
|
Packit Service |
c5cf8c |
* - datatype - input datatype
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Returns number of elements available given the two constraints of number of
|
|
Packit Service |
c5cf8c |
* bytes and count of types. Also reduces the byte count by the amount taken
|
|
Packit Service |
c5cf8c |
* up by the types.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* This is called from MPI_Get_elements() when it sees a type with multiple
|
|
Packit Service |
c5cf8c |
* element types (datatype_ptr->element_sz = -1). This function calls itself too.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
PMPI_LOCAL MPI_Count MPIR_Type_get_elements(MPI_Count * bytes_p,
|
|
Packit Service |
c5cf8c |
MPI_Count count, MPI_Datatype datatype)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_Datatype *datatype_ptr = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_ptr(datatype, datatype_ptr); /* invalid if builtin */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* if we have gotten down to a type with only one element type,
|
|
Packit Service |
c5cf8c |
* call MPIR_Type_get_basic_type_elements() and return.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN ||
|
|
Packit Service |
c5cf8c |
datatype == MPI_FLOAT_INT ||
|
|
Packit Service |
c5cf8c |
datatype == MPI_DOUBLE_INT ||
|
|
Packit Service |
c5cf8c |
datatype == MPI_LONG_INT || datatype == MPI_SHORT_INT || datatype == MPI_LONG_DOUBLE_INT) {
|
|
Packit Service |
c5cf8c |
return MPIR_Type_get_basic_type_elements(bytes_p, count, datatype);
|
|
Packit Service |
c5cf8c |
} else if (datatype_ptr->builtin_element_size >= 0) {
|
|
Packit Service |
c5cf8c |
MPI_Datatype basic_type = MPI_DATATYPE_NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_basic_type(datatype_ptr->basic_type, basic_type);
|
|
Packit Service |
c5cf8c |
return MPIR_Type_get_basic_type_elements(bytes_p,
|
|
Packit Service |
c5cf8c |
count * datatype_ptr->n_builtin_elements,
|
|
Packit Service |
c5cf8c |
basic_type);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* we have bytes left and still don't have a single element size; must
|
|
Packit Service |
c5cf8c |
* recurse.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int i, j, *ints;
|
|
Packit Service |
c5cf8c |
MPI_Count typecount = 0, nr_elements = 0, last_nr_elements;
|
|
Packit Service |
c5cf8c |
MPI_Aint *aints;
|
|
Packit Service |
c5cf8c |
MPI_Datatype *types;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Establish locations of arrays */
|
|
Packit Service |
c5cf8c |
MPIR_Type_access_contents(datatype_ptr->handle, &ints, &aints, &types);
|
|
Packit Service |
c5cf8c |
if (!ints || !aints || !types)
|
|
Packit Service |
c5cf8c |
return MPI_ERR_TYPE;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
switch (datatype_ptr->contents->combiner) {
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_NAMED:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_DUP:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_RESIZED:
|
|
Packit Service |
c5cf8c |
return MPIR_Type_get_elements(bytes_p, count, *types);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_CONTIGUOUS:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_VECTOR:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_HVECTOR_INTEGER:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_HVECTOR:
|
|
Packit Service |
c5cf8c |
/* count is first in ints array */
|
|
Packit Service |
c5cf8c |
return MPIR_Type_get_elements(bytes_p, count * (*ints), *types);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_INDEXED_BLOCK:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_HINDEXED_BLOCK:
|
|
Packit Service |
c5cf8c |
/* count is first in ints array, blocklength is second */
|
|
Packit Service |
c5cf8c |
return MPIR_Type_get_elements(bytes_p, count * ints[0] * ints[1], *types);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_INDEXED:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_HINDEXED_INTEGER:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_HINDEXED:
|
|
Packit Service |
c5cf8c |
for (i = 0; i < (*ints); i++) {
|
|
Packit Service |
c5cf8c |
/* add up the blocklengths to get a max. # of the next type */
|
|
Packit Service |
c5cf8c |
typecount += ints[i + 1];
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return MPIR_Type_get_elements(bytes_p, count * typecount, *types);
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_STRUCT_INTEGER:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_STRUCT:
|
|
Packit Service |
c5cf8c |
/* In this case we can't simply multiply the count of the next
|
|
Packit Service |
c5cf8c |
* type by the count of the current type, because we need to
|
|
Packit Service |
c5cf8c |
* cycle through the types just as the struct would. thus the
|
|
Packit Service |
c5cf8c |
* nested loops.
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* We need to keep going until we get less elements than expected
|
|
Packit Service |
c5cf8c |
* or we run out of bytes.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
last_nr_elements = 1; /* seed value */
|
|
Packit Service |
c5cf8c |
for (j = 0; (count < 0 || j < count) && *bytes_p > 0 && last_nr_elements > 0; j++) {
|
|
Packit Service |
c5cf8c |
/* recurse on each type; bytes are reduced in calls */
|
|
Packit Service |
c5cf8c |
for (i = 0; i < (*ints); i++) {
|
|
Packit Service |
c5cf8c |
/* skip zero-count elements of the struct */
|
|
Packit Service |
c5cf8c |
if (ints[i + 1] == 0)
|
|
Packit Service |
c5cf8c |
continue;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
last_nr_elements = MPIR_Type_get_elements(bytes_p, ints[i + 1], types[i]);
|
|
Packit Service |
c5cf8c |
nr_elements += last_nr_elements;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(last_nr_elements >= 0);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (last_nr_elements < ints[i + 1])
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
return nr_elements;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_SUBARRAY:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_DARRAY:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_F90_REAL:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_F90_COMPLEX:
|
|
Packit Service |
c5cf8c |
case MPI_COMBINER_F90_INTEGER:
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
MPIR_Assert(0);
|
|
Packit Service |
c5cf8c |
return -1;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPIR_Get_elements_x_impl
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
/* MPIR_Get_elements_x_impl
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Arguments:
|
|
Packit Service |
c5cf8c |
* - byte_count - input/output byte count
|
|
Packit Service |
c5cf8c |
* - datatype - input datatype
|
|
Packit Service |
c5cf8c |
* - elements - Number of basic elements this byte_count would contain
|
|
Packit Service |
c5cf8c |
*
|
|
Packit Service |
c5cf8c |
* Returns number of elements available given the two constraints of number of
|
|
Packit Service |
c5cf8c |
* bytes and count of types. Also reduces the byte count by the amount taken
|
|
Packit Service |
c5cf8c |
* up by the types.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int MPIR_Get_elements_x_impl(MPI_Count * byte_count, MPI_Datatype datatype, MPI_Count * elements)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPIR_Datatype *datatype_ptr = NULL;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_ptr(datatype, datatype_ptr);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* three cases:
|
|
Packit Service |
c5cf8c |
* - nice, simple, single element type
|
|
Packit Service |
c5cf8c |
* - derived type with a zero size
|
|
Packit Service |
c5cf8c |
* - type with multiple element types (nastiest)
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (HANDLE_GET_KIND(datatype) == HANDLE_KIND_BUILTIN ||
|
|
Packit Service |
c5cf8c |
(datatype_ptr->builtin_element_size != -1 && datatype_ptr->size > 0)) {
|
|
Packit Service |
c5cf8c |
/* QUESTION: WHAT IF SOMEONE GAVE US AN MPI_UB OR MPI_LB???
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* in both cases we do not limit the number of types that might
|
|
Packit Service |
c5cf8c |
* be in bytes
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
|
|
Packit Service |
c5cf8c |
MPI_Datatype basic_type = MPI_DATATYPE_NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_basic_type(datatype_ptr->basic_type, basic_type);
|
|
Packit Service |
c5cf8c |
*elements = MPIR_Type_get_basic_type_elements(byte_count, -1, basic_type);
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* Behaves just like MPI_Get_Count in the predefined case */
|
|
Packit Service |
c5cf8c |
MPI_Count size;
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_size_macro(datatype, size);
|
|
Packit Service |
c5cf8c |
if ((*byte_count % size) != 0)
|
|
Packit Service |
c5cf8c |
*elements = MPI_UNDEFINED;
|
|
Packit Service |
c5cf8c |
else
|
|
Packit Service |
c5cf8c |
*elements = MPIR_Type_get_basic_type_elements(byte_count, -1, datatype);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPIR_Assert(*byte_count >= 0);
|
|
Packit Service |
c5cf8c |
} else if (datatype_ptr->size == 0) {
|
|
Packit Service |
c5cf8c |
if (*byte_count > 0) {
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* datatype size of zero and count > 0 should never happen. */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
(*elements) = MPI_UNDEFINED;
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
/* This is ambiguous. However, discussions on MPI Forum
|
|
Packit Service |
c5cf8c |
* reached a consensus that this is the correct return
|
|
Packit Service |
c5cf8c |
* value
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
(*elements) = 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
} else { /* derived type with weird element type or weird size */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Assert(datatype_ptr->builtin_element_size == -1);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
*elements = MPIR_Type_get_elements(byte_count, -1, datatype);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#endif /* MPICH_MPI_FROM_PMPI */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#undef FUNCNAME
|
|
Packit Service |
c5cf8c |
#define FUNCNAME MPI_Get_elements_x
|
|
Packit Service |
c5cf8c |
#undef FCNAME
|
|
Packit Service |
c5cf8c |
#define FCNAME MPL_QUOTE(FUNCNAME)
|
|
Packit Service |
c5cf8c |
/* N.B. "count" is the name mandated by the MPI-3 standard, but it should
|
|
Packit Service |
c5cf8c |
* probably be called "elements" instead and is handled that way in the _impl
|
|
Packit Service |
c5cf8c |
* routine [goodell@ 2012-11-05 */
|
|
Packit Service |
c5cf8c |
/*@
|
|
Packit Service |
c5cf8c |
MPI_Get_elements_x - Returns the number of basic elements
|
|
Packit Service |
c5cf8c |
in a datatype
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
Input Parameters:
|
|
Packit Service |
c5cf8c |
+ status - return status of receive operation (Status)
|
|
Packit Service |
c5cf8c |
- datatype - datatype used by receive operation (handle)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
Output Parameters:
|
|
Packit Service |
c5cf8c |
. count - number of received basic elements (integer)
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
.N ThreadSafe
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
.N Fortran
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
.N Errors
|
|
Packit Service |
c5cf8c |
@*/
|
|
Packit Service |
c5cf8c |
int MPI_Get_elements_x(const MPI_Status * status, MPI_Datatype datatype, MPI_Count * count)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
int mpi_errno = MPI_SUCCESS;
|
|
Packit Service |
c5cf8c |
MPI_Count byte_count;
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GET_ELEMENTS_X);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GET_ELEMENTS_X);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Validate parameters, especially handles needing to be converted */
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPID_BEGIN_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* TODO more checks may be appropriate */
|
|
Packit Service |
c5cf8c |
if (mpi_errno != MPI_SUCCESS)
|
|
Packit Service |
c5cf8c |
goto fn_fail;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_END_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif /* HAVE_ERROR_CHECKING */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Convert MPI object handles to object pointers */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Validate parameters and objects (post conversion) */
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPID_BEGIN_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
|
|
Packit Service |
c5cf8c |
MPIR_Datatype *datatype_ptr = NULL;
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_get_ptr(datatype, datatype_ptr);
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno);
|
|
Packit Service |
c5cf8c |
MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* TODO more checks may be appropriate (counts, in_place, buffer aliasing, etc) */
|
|
Packit Service |
c5cf8c |
if (mpi_errno != MPI_SUCCESS)
|
|
Packit Service |
c5cf8c |
goto fn_fail;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
MPID_END_ERROR_CHECKS;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif /* HAVE_ERROR_CHECKING */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ... body of routine ... */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
byte_count = MPIR_STATUS_GET_COUNT(*status);
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Get_elements_x_impl(&byte_count, datatype, count);
|
|
Packit Service |
c5cf8c |
if (mpi_errno)
|
|
Packit Service |
c5cf8c |
MPIR_ERR_POP(mpi_errno);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* ... end of body of routine ... */
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_exit:
|
|
Packit Service |
c5cf8c |
MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GET_ELEMENTS_X);
|
|
Packit Service |
c5cf8c |
MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
|
|
Packit Service |
c5cf8c |
return mpi_errno;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
fn_fail:
|
|
Packit Service |
c5cf8c |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
mpi_errno =
|
|
Packit Service |
c5cf8c |
MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
|
|
Packit Service |
c5cf8c |
"**mpi_get_elements_x", "**mpi_get_elements_x %p %D %p", status,
|
|
Packit Service |
c5cf8c |
datatype, count);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno);
|
|
Packit Service |
c5cf8c |
goto fn_exit;
|
|
Packit Service |
c5cf8c |
/* --END ERROR HANDLING-- */
|
|
Packit Service |
c5cf8c |
}
|