Blame src/mpi/datatype/type_create_pairtype.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2001 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
#include <stdlib.h>
Packit Service c5cf8c
#include <limits.h>
Packit Service c5cf8c
Packit Service c5cf8c
/* PAIRTYPE_SIZE_EXTENT - calculates size, extent, etc. for pairtype by
Packit Service c5cf8c
 * defining the appropriate C type.
Packit Service c5cf8c
 */
Packit Service c5cf8c
#define PAIRTYPE_SIZE_EXTENT(mt1_,ut1_,mt2_,ut2_, type_size_, type_extent_, \
Packit Service c5cf8c
                             el_size_, true_ub_, alignsize_)            \
Packit Service c5cf8c
    {                                                                   \
Packit Service c5cf8c
        struct { ut1_ a; ut2_ b; } foo;                                 \
Packit Service c5cf8c
        type_size_   = sizeof(foo.a) + sizeof(foo.b);                   \
Packit Service c5cf8c
        type_extent_ = (MPI_Aint) sizeof(foo);                          \
Packit Service c5cf8c
        el_size_ = (sizeof(foo.a) == sizeof(foo.b)) ? (int) sizeof(foo.a) : -1; \
Packit Service c5cf8c
        true_ub_ = (MPIR_VOID_PTR_CAST_TO_MPI_AINT ((char *) &foo.b -     \
Packit Service c5cf8c
                                                  (char *) &foo.a)) +   \
Packit Service c5cf8c
                  (MPI_Aint) sizeof(foo.b);                             \
Packit Service c5cf8c
        alignsize_ = MPL_MAX(MPIR_Datatype_get_basic_size(mt1_),        \
Packit Service c5cf8c
                             MPIR_Datatype_get_basic_size(mt2_));       \
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
/*@
Packit Service c5cf8c
  MPIR_Type_create_pairtype - create necessary data structures for certain
Packit Service c5cf8c
  pair types (all but MPI_2INT etc., which never have the size != extent
Packit Service c5cf8c
  issue).
Packit Service c5cf8c
Packit Service c5cf8c
  This function is different from the other MPIR_Type_create functions in that
Packit Service c5cf8c
  it fills in an already- allocated MPIR_Datatype.  This is important for
Packit Service c5cf8c
  allowing configure-time determination of the MPI type values (these types
Packit Service c5cf8c
  are stored in the "direct" space, for those familiar with how MPICH deals
Packit Service c5cf8c
  with type allocation).
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ type - name of pair type (e.g. MPI_FLOAT_INT)
Packit Service c5cf8c
- new_dtp - pointer to previously allocated datatype structure, which is
Packit Service c5cf8c
            filled in by this function
Packit Service c5cf8c
Packit Service c5cf8c
  Return Value:
Packit Service c5cf8c
  MPI_SUCCESS on success, MPI errno on failure.
Packit Service c5cf8c
Packit Service c5cf8c
  Note:
Packit Service c5cf8c
  Section 4.9.3 (MINLOC and MAXLOC) of the MPI-1 standard specifies that
Packit Service c5cf8c
  these types should be built as if by the following (e.g. MPI_FLOAT_INT):
Packit Service c5cf8c
Packit Service c5cf8c
    type[0] = MPI_FLOAT
Packit Service c5cf8c
    type[1] = MPI_INT
Packit Service c5cf8c
    disp[0] = 0
Packit Service c5cf8c
    disp[1] = sizeof(float) <---- questionable displacement!
Packit Service c5cf8c
    block[0] = 1
Packit Service c5cf8c
    block[1] = 1
Packit Service c5cf8c
    MPI_TYPE_STRUCT(2, block, disp, type, MPI_FLOAT_INT)
Packit Service c5cf8c
Packit Service c5cf8c
  However, this is a relatively naive approach that does not take struct
Packit Service c5cf8c
  padding into account when setting the displacement of the second element.
Packit Service c5cf8c
  Thus in our implementation we have chosen to instead use the actual
Packit Service c5cf8c
  difference in starting locations of the two types in an actual struct.
Packit Service c5cf8c
@*/
Packit Service c5cf8c
int MPIR_Type_create_pairtype(MPI_Datatype type, MPIR_Datatype * new_dtp)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int err, mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    int type_size, alignsize;
Packit Service c5cf8c
    MPI_Aint type_extent, true_ub, el_size;
Packit Service c5cf8c
Packit Service c5cf8c
    /* handle is filled in by MPIR_Handle_obj_alloc() */
Packit Service c5cf8c
    MPIR_Object_set_ref(new_dtp, 1);
Packit Service c5cf8c
    new_dtp->is_permanent = 1;
Packit Service c5cf8c
    new_dtp->is_committed = 1;  /* predefined types are pre-committed */
Packit Service c5cf8c
    new_dtp->attributes = NULL;
Packit Service c5cf8c
    new_dtp->cache_id = 0;
Packit Service c5cf8c
    new_dtp->name[0] = 0;
Packit Service c5cf8c
    new_dtp->contents = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    new_dtp->dataloop = NULL;
Packit Service c5cf8c
    new_dtp->dataloop_size = -1;
Packit Service c5cf8c
    new_dtp->dataloop_depth = -1;
Packit Service c5cf8c
Packit Service c5cf8c
    switch (type) {
Packit Service c5cf8c
        case MPI_FLOAT_INT:
Packit Service c5cf8c
            PAIRTYPE_SIZE_EXTENT(MPI_FLOAT, float, MPI_INT, int,
Packit Service c5cf8c
                                 type_size, type_extent, el_size, true_ub, alignsize);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_DOUBLE_INT:
Packit Service c5cf8c
            PAIRTYPE_SIZE_EXTENT(MPI_DOUBLE, double, MPI_INT, int,
Packit Service c5cf8c
                                 type_size, type_extent, el_size, true_ub, alignsize);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_LONG_INT:
Packit Service c5cf8c
            PAIRTYPE_SIZE_EXTENT(MPI_LONG, long, MPI_INT, int,
Packit Service c5cf8c
                                 type_size, type_extent, el_size, true_ub, alignsize);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_SHORT_INT:
Packit Service c5cf8c
            PAIRTYPE_SIZE_EXTENT(MPI_SHORT, short, MPI_INT, int,
Packit Service c5cf8c
                                 type_size, type_extent, el_size, true_ub, alignsize);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_LONG_DOUBLE_INT:
Packit Service c5cf8c
            PAIRTYPE_SIZE_EXTENT(MPI_LONG_DOUBLE, long double, MPI_INT, int,
Packit Service c5cf8c
                                 type_size, type_extent, el_size, true_ub, alignsize);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        default:
Packit Service c5cf8c
            /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
            mpi_errno = MPIR_Err_create_code(MPI_SUCCESS,
Packit Service c5cf8c
                                             MPIR_ERR_RECOVERABLE,
Packit Service c5cf8c
                                             "MPIR_Type_create_pairtype",
Packit Service c5cf8c
                                             __LINE__, MPI_ERR_OTHER, "**dtype", 0);
Packit Service c5cf8c
            return mpi_errno;
Packit Service c5cf8c
            /* --END ERROR HANDLING-- */
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    new_dtp->n_builtin_elements = 2;
Packit Service c5cf8c
    new_dtp->builtin_element_size = el_size;
Packit Service c5cf8c
    new_dtp->basic_type = type;
Packit Service c5cf8c
Packit Service c5cf8c
    new_dtp->has_sticky_lb = 0;
Packit Service c5cf8c
    new_dtp->true_lb = 0;
Packit Service c5cf8c
    new_dtp->lb = 0;
Packit Service c5cf8c
Packit Service c5cf8c
    new_dtp->has_sticky_ub = 0;
Packit Service c5cf8c
    new_dtp->true_ub = true_ub;
Packit Service c5cf8c
Packit Service c5cf8c
    new_dtp->size = type_size;
Packit Service c5cf8c
    new_dtp->ub = type_extent;  /* possible padding */
Packit Service c5cf8c
    new_dtp->extent = type_extent;
Packit Service c5cf8c
    new_dtp->alignsize = alignsize;
Packit Service c5cf8c
Packit Service c5cf8c
    /* place maximum on alignment based on padding rules */
Packit Service c5cf8c
    /* There are some really wierd rules for structure alignment;
Packit Service c5cf8c
     * these capture the ones of which we are aware. */
Packit Service c5cf8c
    switch (type) {
Packit Service c5cf8c
        case MPI_SHORT_INT:
Packit Service c5cf8c
        case MPI_LONG_INT:
Packit Service c5cf8c
#ifdef HAVE_MAX_INTEGER_ALIGNMENT
Packit Service c5cf8c
            new_dtp->alignsize = MPL_MIN(new_dtp->alignsize, HAVE_MAX_INTEGER_ALIGNMENT);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_FLOAT_INT:
Packit Service c5cf8c
#ifdef HAVE_MAX_FP_ALIGNMENT
Packit Service c5cf8c
            new_dtp->alignsize = MPL_MIN(new_dtp->alignsize, HAVE_MAX_FP_ALIGNMENT);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_DOUBLE_INT:
Packit Service c5cf8c
#ifdef HAVE_MAX_DOUBLE_FP_ALIGNMENT
Packit Service c5cf8c
            new_dtp->alignsize = MPL_MIN(new_dtp->alignsize, HAVE_MAX_DOUBLE_FP_ALIGNMENT);
Packit Service c5cf8c
#elif defined(HAVE_MAX_FP_ALIGNMENT)
Packit Service c5cf8c
            new_dtp->alignsize = MPL_MIN(new_dtp->alignsize, HAVE_MAX_FP_ALIGNMENT);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPI_LONG_DOUBLE_INT:
Packit Service c5cf8c
#ifdef HAVE_MAX_LONG_DOUBLE_FP_ALIGNMENT
Packit Service c5cf8c
            new_dtp->alignsize = MPL_MIN(new_dtp->alignsize, HAVE_MAX_LONG_DOUBLE_FP_ALIGNMENT);
Packit Service c5cf8c
#elif defined(HAVE_MAX_FP_ALIGNMENT)
Packit Service c5cf8c
            new_dtp->alignsize = MPL_MIN(new_dtp->alignsize, HAVE_MAX_FP_ALIGNMENT);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
            break;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    new_dtp->is_contig = (((MPI_Aint) type_size) == type_extent) ? 1 : 0;
Packit Service c5cf8c
    new_dtp->max_contig_blocks = (((MPI_Aint) type_size) == type_extent) ? 1 : 2;
Packit Service c5cf8c
Packit Service c5cf8c
    /* fill in dataloops -- only case where we precreate dataloops
Packit Service c5cf8c
     *
Packit Service c5cf8c
     * this is necessary because these types aren't committed by the
Packit Service c5cf8c
     * user, which is the other place where we create dataloops. so
Packit Service c5cf8c
     * if the user uses one of these w/out building some more complex
Packit Service c5cf8c
     * type and then committing it, then the dataloop will be missing.
Packit Service c5cf8c
     */
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPID_NEEDS_DLOOP_ALL_BYTES
Packit Service c5cf8c
    /* If MPID implementation needs use to reduce everything to
Packit Service c5cf8c
     * a byte stream, do that. */
Packit Service c5cf8c
    err = MPIR_Dataloop_create_pairtype(type,
Packit Service c5cf8c
                                        &(new_dtp->dataloop),
Packit Service c5cf8c
                                        &(new_dtp->dataloop_size),
Packit Service c5cf8c
                                        &(new_dtp->dataloop_depth), MPIDU_DATALOOP_ALL_BYTES);
Packit Service c5cf8c
#else
Packit Service c5cf8c
    err = MPIR_Dataloop_create_pairtype(type,
Packit Service c5cf8c
                                        &(new_dtp->dataloop),
Packit Service c5cf8c
                                        &(new_dtp->dataloop_size),
Packit Service c5cf8c
                                        &(new_dtp->dataloop_depth), MPIR_DATALOOP_DEFAULT);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPID_Type_commit_hook
Packit Service c5cf8c
    if (!err) {
Packit Service c5cf8c
        err = MPID_Type_commit_hook(new_dtp);
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* MPID_Type_commit_hook */
Packit Service c5cf8c
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
    if (err) {
Packit Service c5cf8c
        mpi_errno = MPIR_Err_create_code(MPI_SUCCESS,
Packit Service c5cf8c
                                         MPIR_ERR_RECOVERABLE,
Packit Service c5cf8c
                                         "MPIR_Dataloop_create_pairtype",
Packit Service c5cf8c
                                         __LINE__, MPI_ERR_OTHER, "**nomem", 0);
Packit Service c5cf8c
        return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}