Blame src/include/mpir_op.h

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
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
Packit Service c5cf8c
#ifndef MPIR_OP_H_INCLUDED
Packit Service c5cf8c
#define MPIR_OP_H_INCLUDED
Packit Service c5cf8c
Packit Service c5cf8c
/*E
Packit Service c5cf8c
  MPIR_Op_kind - Enumerates types of MPI_Op types
Packit Service c5cf8c
Packit Service c5cf8c
  Notes:
Packit Service c5cf8c
  These are needed for implementing 'MPI_Accumulate', since only predefined
Packit Service c5cf8c
  operations are allowed for that operation.
Packit Service c5cf8c
Packit Service c5cf8c
  A gap in the enum values was made allow additional predefined operations
Packit Service c5cf8c
  to be inserted.  This might include future additions to MPI or experimental
Packit Service c5cf8c
  extensions (such as a Read-Modify-Write operation).
Packit Service c5cf8c
Packit Service c5cf8c
  Module:
Packit Service c5cf8c
  Collective-DS
Packit Service c5cf8c
  E*/
Packit Service c5cf8c
typedef enum MPIR_Op_kind {
Packit Service c5cf8c
    MPIR_OP_KIND__NULL = 0,
Packit Service c5cf8c
    MPIR_OP_KIND__MAX = 1,
Packit Service c5cf8c
    MPIR_OP_KIND__MIN = 2,
Packit Service c5cf8c
    MPIR_OP_KIND__SUM = 3,
Packit Service c5cf8c
    MPIR_OP_KIND__PROD = 4,
Packit Service c5cf8c
    MPIR_OP_KIND__LAND = 5,
Packit Service c5cf8c
    MPIR_OP_KIND__BAND = 6,
Packit Service c5cf8c
    MPIR_OP_KIND__LOR = 7,
Packit Service c5cf8c
    MPIR_OP_KIND__BOR = 8,
Packit Service c5cf8c
    MPIR_OP_KIND__LXOR = 9,
Packit Service c5cf8c
    MPIR_OP_KIND__BXOR = 10,
Packit Service c5cf8c
    MPIR_OP_KIND__MAXLOC = 11,
Packit Service c5cf8c
    MPIR_OP_KIND__MINLOC = 12,
Packit Service c5cf8c
    MPIR_OP_KIND__REPLACE = 13,
Packit Service c5cf8c
    MPIR_OP_KIND__NO_OP = 14,
Packit Service c5cf8c
    MPIR_OP_KIND__USER_NONCOMMUTE = 32,
Packit Service c5cf8c
    MPIR_OP_KIND__USER = 33
Packit Service c5cf8c
} MPIR_Op_kind;
Packit Service c5cf8c
Packit Service c5cf8c
/*S
Packit Service c5cf8c
  MPIR_User_function - Definition of a user function for MPI_Op types.
Packit Service c5cf8c
Packit Service c5cf8c
  Notes:
Packit Service c5cf8c
  This includes a 'const' to make clear which is the 'in' argument and
Packit Service c5cf8c
  which the 'inout' argument, and to indicate that the 'count' and 'datatype'
Packit Service c5cf8c
  arguments are unchanged (they are addresses in an attempt to allow
Packit Service c5cf8c
  interoperation with Fortran).  It includes 'restrict' to emphasize that
Packit Service c5cf8c
  no overlapping operations are allowed.
Packit Service c5cf8c
Packit Service c5cf8c
  We need to include a Fortran version, since those arguments will
Packit Service c5cf8c
  have type 'MPI_Fint *' instead.  We also need to add a test to the
Packit Service c5cf8c
  test suite for this case; in fact, we need tests for each of the handle
Packit Service c5cf8c
  types to ensure that the transfered handle works correctly.
Packit Service c5cf8c
Packit Service c5cf8c
  This is part of the collective module because user-defined operations
Packit Service c5cf8c
  are valid only for the collective computation routines and not for
Packit Service c5cf8c
  RMA accumulate.
Packit Service c5cf8c
Packit Service c5cf8c
  Yes, the 'restrict' is in the correct location.  C compilers that
Packit Service c5cf8c
  support 'restrict' should be able to generate code that is as good as a
Packit Service c5cf8c
  Fortran compiler would for these functions.
Packit Service c5cf8c
Packit Service c5cf8c
  We should note on the manual pages for user-defined operations that
Packit Service c5cf8c
  'restrict' should be used when available, and that a cast may be
Packit Service c5cf8c
  required when passing such a function to 'MPI_Op_create'.
Packit Service c5cf8c
Packit Service c5cf8c
  Question:
Packit Service c5cf8c
  Should each of these function types have an associated typedef?
Packit Service c5cf8c
Packit Service c5cf8c
  Should there be a C++ function here?
Packit Service c5cf8c
Packit Service c5cf8c
  Module:
Packit Service c5cf8c
  Collective-DS
Packit Service c5cf8c
  S*/
Packit Service c5cf8c
typedef union MPIR_User_function {
Packit Service c5cf8c
    void (*c_function) (const void *, void *, const int *, const MPI_Datatype *);
Packit Service c5cf8c
    void (*f77_function) (const void *, void *, const MPI_Fint *, const MPI_Fint *);
Packit Service c5cf8c
} MPIR_User_function;
Packit Service c5cf8c
/* FIXME: Should there be "restrict" in the definitions above, e.g.,
Packit Service c5cf8c
   (*c_function)(const void restrict * , void restrict *, ...)? */
Packit Service c5cf8c
Packit Service c5cf8c
/*S
Packit Service c5cf8c
  MPIR_Op - MPI_Op structure
Packit Service c5cf8c
Packit Service c5cf8c
  Notes:
Packit Service c5cf8c
  All of the predefined functions are commutative.  Only user functions may
Packit Service c5cf8c
  be noncummutative, so there are two separate op types for commutative and
Packit Service c5cf8c
  non-commutative user-defined operations.
Packit Service c5cf8c
Packit Service c5cf8c
  Operations do not require reference counts because there are no nonblocking
Packit Service c5cf8c
  operations that accept user-defined operations.  Thus, there is no way that
Packit Service c5cf8c
  a valid program can free an 'MPI_Op' while it is in use.
Packit Service c5cf8c
Packit Service c5cf8c
  Module:
Packit Service c5cf8c
  Collective-DS
Packit Service c5cf8c
  S*/
Packit Service c5cf8c
typedef struct MPIR_Op {
Packit Service c5cf8c
    MPIR_OBJECT_HEADER;         /* adds handle and ref_count fields */
Packit Service c5cf8c
    MPIR_Op_kind kind;
Packit Service c5cf8c
    MPIR_Lang_t language;
Packit Service c5cf8c
    MPIR_User_function function;
Packit Service c5cf8c
#ifdef MPID_DEV_OP_DECL
Packit Service c5cf8c
     MPID_DEV_OP_DECL
Packit Service c5cf8c
#endif
Packit Service c5cf8c
} MPIR_Op;
Packit Service c5cf8c
#define MPIR_OP_N_BUILTIN 15
Packit Service c5cf8c
extern MPIR_Op MPIR_Op_builtin[MPIR_OP_N_BUILTIN];
Packit Service c5cf8c
extern MPIR_Op MPIR_Op_direct[];
Packit Service c5cf8c
extern MPIR_Object_alloc_t MPIR_Op_mem;
Packit Service c5cf8c
Packit Service c5cf8c
#define MPIR_Op_ptr_add_ref(op_p_) \
Packit Service c5cf8c
    do { MPIR_Object_add_ref(op_p_); } while (0)
Packit Service c5cf8c
#define MPIR_Op_ptr_release_ref(op_p_, inuse_) \
Packit Service c5cf8c
    do { MPIR_Object_release_ref(op_p_, inuse_); } while (0)
Packit Service c5cf8c
Packit Service c5cf8c
/* release and free-if-not-in-use helper */
Packit Service c5cf8c
#define MPIR_Op_ptr_release(op_p_)                       \
Packit Service c5cf8c
    do {                                                 \
Packit Service c5cf8c
        int in_use_;                                     \
Packit Service c5cf8c
        MPIR_Op_ptr_release_ref((op_p_), &in_use_);      \
Packit Service c5cf8c
        if (!in_use_) {                                  \
Packit Service c5cf8c
            MPIR_Handle_obj_free(&MPIR_Op_mem, (op_p_)); \
Packit Service c5cf8c
        }                                                \
Packit Service c5cf8c
    } while (0)
Packit Service c5cf8c
Packit Service c5cf8c
void MPIR_MAXF(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_MINF(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_SUM(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_PROD(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_LAND(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_BAND(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_LOR(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_BOR(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_LXOR(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_BXOR(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_MAXLOC(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_MINLOC(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_REPLACE(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void MPIR_NO_OP(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
Packit Service c5cf8c
int MPIR_MAXF_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_MINF_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_SUM_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_PROD_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_LAND_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_BAND_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_LOR_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_BOR_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_LXOR_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_BXOR_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_MAXLOC_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_MINLOC_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_REPLACE_check_dtype(MPI_Datatype);
Packit Service c5cf8c
int MPIR_NO_OP_check_dtype(MPI_Datatype);
Packit Service c5cf8c
Packit Service c5cf8c
#define MPIR_Op_add_ref_if_not_builtin(op)               \
Packit Service c5cf8c
    do {                                                 \
Packit Service c5cf8c
        if (HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN) {\
Packit Service c5cf8c
            MPIR_Op *op_ptr = NULL;                      \
Packit Service c5cf8c
            MPIR_Op_get_ptr(op, op_ptr);                 \
Packit Service c5cf8c
            MPIR_Assert(op_ptr != NULL);                 \
Packit Service c5cf8c
            MPIR_Op_ptr_add_ref(op_ptr);                 \
Packit Service c5cf8c
        }                                                \
Packit Service c5cf8c
    } while (0)                                          \
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#define MPIR_Op_release_if_not_builtin(op)               \
Packit Service c5cf8c
    do {                                                 \
Packit Service c5cf8c
        if (HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN) {\
Packit Service c5cf8c
            MPIR_Op *op_ptr = NULL;                      \
Packit Service c5cf8c
            MPIR_Op_get_ptr(op, op_ptr);                 \
Packit Service c5cf8c
            MPIR_Assert(op_ptr != NULL);                 \
Packit Service c5cf8c
            MPIR_Op_ptr_release(op_ptr);                 \
Packit Service c5cf8c
        }                                                \
Packit Service c5cf8c
    } while (0)                                          \
Packit Service c5cf8c
Packit Service c5cf8c
#define MPIR_PREDEF_OP_COUNT 14
Packit Service c5cf8c
extern MPI_User_function *MPIR_Op_table[];
Packit Service c5cf8c
Packit Service c5cf8c
typedef int (MPIR_Op_check_dtype_fn) (MPI_Datatype);
Packit Service c5cf8c
extern MPIR_Op_check_dtype_fn *MPIR_Op_check_dtype_table[];
Packit Service c5cf8c
Packit Service c5cf8c
#define MPIR_OP_HDL_TO_FN(op) MPIR_Op_table[((op)&0xf)]
Packit Service c5cf8c
#define MPIR_OP_HDL_TO_DTYPE_FN(op) MPIR_Op_check_dtype_table[((op)&0xf)]
Packit Service c5cf8c
Packit Service c5cf8c
int MPIR_Op_commutative(MPIR_Op * op_ptr, int *commute);
Packit Service c5cf8c
Packit Service c5cf8c
int MPIR_Op_is_commutative(MPI_Op);
Packit Service c5cf8c
Packit Service c5cf8c
int MPIR_Op_create_impl(MPI_User_function * user_fn, int commute, MPI_Op * op);
Packit Service c5cf8c
void MPIR_Op_free_impl(MPI_Op * op);
Packit Service c5cf8c
#endif /* MPIR_OP_H_INCLUDED */