1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "mpiimpl.h"
7 #include "mpir_op_util.h"
8 
9 /*
10  * In MPI-2.1, this operation is valid only for C integer, Fortran integer,
11  * Floating point, and Complex types (5.9.2 Predefined reduce operations)
12  */
13 #define MPIR_LPROD(a,b) ((a)*(b))
14 
MPIR_PROD(void * invec,void * inoutvec,int * Len,MPI_Datatype * type)15 void MPIR_PROD(void *invec, void *inoutvec, int *Len, MPI_Datatype * type)
16 {
17     int i, len = *Len;
18 
19     switch (*type) {
20 #undef MPIR_OP_TYPE_MACRO
21 #define MPIR_OP_TYPE_MACRO(mpi_type_, c_type_, type_name_) MPIR_OP_TYPE_REDUCE_CASE(mpi_type_, c_type_, MPIR_LPROD)
22             /* no semicolons by necessity */
23             MPIR_OP_TYPE_GROUP(C_INTEGER)
24                 MPIR_OP_TYPE_GROUP(FORTRAN_INTEGER)
25                 MPIR_OP_TYPE_GROUP(FLOATING_POINT)
26                 /* extra types that are not required to be supported by the MPI Standard */
27                 MPIR_OP_TYPE_GROUP(C_INTEGER_EXTRA)
28                 MPIR_OP_TYPE_GROUP(FORTRAN_INTEGER_EXTRA)
29                 MPIR_OP_TYPE_GROUP(FLOATING_POINT_EXTRA)
30 
31                 /* complex multiplication is slightly different than scalar multiplication */
32 #undef MPIR_OP_TYPE_MACRO
33 #define MPIR_OP_TYPE_MACRO(mpi_type_, c_type_, type_name_) \
34         case (mpi_type_): {                             \
35             c_type_ * restrict a = (c_type_ *)inoutvec; \
36             c_type_ * restrict b = (c_type_ *)invec;    \
37             for (i=0; i<len; i++) {                   \
38                 c_type_ c;                              \
39                 c.re = a[i].re; c.im = a[i].im;         \
40                 a[i].re = c.re*b[i].re - c.im*b[i].im;  \
41                 a[i].im = c.im*b[i].re + c.re*b[i].im;  \
42             }                                           \
43             break;                                      \
44         }
45 #undef MPIR_OP_C_COMPLEX_TYPE_MACRO
46 #define MPIR_OP_C_COMPLEX_TYPE_MACRO(mpi_type_,c_type_,type_name_) MPIR_OP_TYPE_REDUCE_CASE(mpi_type_,c_type_,MPIR_LPROD)
47                 MPIR_OP_TYPE_GROUP(COMPLEX)
48                 MPIR_OP_TYPE_GROUP(COMPLEX_EXTRA)
49                 /* put things back where we found them */
50 #undef MPIR_OP_TYPE_MACRO
51 #undef MPIR_OP_C_COMPLEX_TYPE_MACRO
52 #define MPIR_OP_C_COMPLEX_TYPE_MACRO(mpi_type_,c_type_,type_name_) MPIR_OP_TYPE_MACRO(mpi_type_,c_type_,type_name_)
53         default:
54             MPIR_Assert(0);
55             break;
56     }
57 
58     /* NOTE: the coll/allred test may report uninitialized bytes originating
59      * from the stack in this function when run under valgrind.  AFAICT,
60      * these are safe and harmless, and only occur for
61      * MPI_C_LONG_DOUBLE_COMPLEX corresponding to an 80-bit-precision value
62      * padded out to 128 bits.  The padding causes the warning when fed to
63      * writev (or similar).  Since the stack allocation is implicitly
64      * performed by the compiler, we can't force the input to be defined.
65      * Instead we mark the output defined, even though this might hide
66      * errors from uninitialized input data. [goodell@ 2010-09-30] */
67 #if defined(MPICH_DEBUG_MEMINIT) && defined(HAVE_LONG_DOUBLE__COMPLEX)
68     if (*type == MPI_C_LONG_DOUBLE_COMPLEX) {
69         MPL_VG_MAKE_MEM_DEFINED(inoutvec, (len * sizeof(long double _Complex)));
70     }
71 #endif
72 }
73 
74 
MPIR_PROD_check_dtype(MPI_Datatype type)75 int MPIR_PROD_check_dtype(MPI_Datatype type)
76 {
77     switch (type) {
78 #undef MPIR_OP_TYPE_MACRO
79 #define MPIR_OP_TYPE_MACRO(mpi_type_, c_type_, type_name_) case (mpi_type_):
80             MPIR_OP_TYPE_GROUP(C_INTEGER)
81                 MPIR_OP_TYPE_GROUP(FORTRAN_INTEGER)
82                 MPIR_OP_TYPE_GROUP(FLOATING_POINT)
83                 /* extra types that are not required to be supported by the MPI Standard */
84                 MPIR_OP_TYPE_GROUP(C_INTEGER_EXTRA)
85                 MPIR_OP_TYPE_GROUP(FORTRAN_INTEGER_EXTRA)
86                 MPIR_OP_TYPE_GROUP(FLOATING_POINT_EXTRA)
87 
88                 MPIR_OP_TYPE_GROUP(COMPLEX)
89                 MPIR_OP_TYPE_GROUP(COMPLEX_EXTRA)
90 #undef MPIR_OP_TYPE_MACRO
91                 return MPI_SUCCESS;
92             /* --BEGIN ERROR HANDLING-- */
93         default:
94             return MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, __func__, __LINE__,
95                                         MPI_ERR_OP, "**opundefined", "**opundefined %s",
96                                         "MPI_PROD");
97             /* --END ERROR HANDLING-- */
98     }
99 }
100