Blame src/mpi/datatype/get_elements_x.c

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
}