1 // Copyright (C) 2004 The Trustees of Indiana University.
2 // Copyright (C) 2005-2006 Douglas Gregor <doug.gregor -at- gmail.com>
4 // Use, modification and distribution is subject to the Boost Software
5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // Authors: Douglas Gregor
11 /** @file operations.hpp
13 * This header provides a mapping from function objects to @c MPI_Op
14 * constants used in MPI collective operations. It also provides
15 * several new function object types not present in the standard @c
16 * <functional> header that have direct mappings to @c MPI_Op.
18 #ifndef BOOST_MPI_IS_MPI_OP_HPP
19 #define BOOST_MPI_IS_MPI_OP_HPP
21 #include <boost/mpi/config.hpp>
22 #include <boost/mpl/bool.hpp>
23 #include <boost/mpl/if.hpp>
24 #include <boost/mpl/and.hpp>
25 #include <boost/mpi/datatype.hpp>
26 #include <boost/utility/enable_if.hpp>
29 namespace boost
{ namespace mpi
{
31 template<typename Op
, typename T
> struct is_mpi_op
;
34 * @brief Determine if a function object type is commutative.
36 * This trait determines if an operation @c Op is commutative when
37 * applied to values of type @c T. Parallel operations such as @c
38 * reduce and @c prefix_sum can be implemented more efficiently with
39 * commutative operations. To mark an operation as commutative, users
40 * should specialize @c is_commutative and derive from the class @c
43 template<typename Op
, typename T
>
44 struct is_commutative
: public mpl::false_
{ };
46 /**************************************************************************
47 * Function objects for MPI operations not in <functional> header *
48 **************************************************************************/
51 * @brief Compute the maximum of two values.
53 * This binary function object computes the maximum of the two values
54 * it is given. When used with MPI and a type @c T that has an
55 * associated, built-in MPI data type, translates to @c MPI_MAX.
58 struct maximum
: public std::binary_function
<T
, T
, T
>
60 /** @returns the maximum of x and y. */
61 const T
& operator()(const T
& x
, const T
& y
) const
68 * @brief Compute the minimum of two values.
70 * This binary function object computes the minimum of the two values
71 * it is given. When used with MPI and a type @c T that has an
72 * associated, built-in MPI data type, translates to @c MPI_MIN.
75 struct minimum
: public std::binary_function
<T
, T
, T
>
77 /** @returns the minimum of x and y. */
78 const T
& operator()(const T
& x
, const T
& y
) const
86 * @brief Compute the bitwise AND of two integral values.
88 * This binary function object computes the bitwise AND of the two
89 * values it is given. When used with MPI and a type @c T that has an
90 * associated, built-in MPI data type, translates to @c MPI_BAND.
93 struct bitwise_and
: public std::binary_function
<T
, T
, T
>
95 /** @returns @c x & y. */
96 T
operator()(const T
& x
, const T
& y
) const
103 * @brief Compute the bitwise OR of two integral values.
105 * This binary function object computes the bitwise OR of the two
106 * values it is given. When used with MPI and a type @c T that has an
107 * associated, built-in MPI data type, translates to @c MPI_BOR.
110 struct bitwise_or
: public std::binary_function
<T
, T
, T
>
112 /** @returns the @c x | y. */
113 T
operator()(const T
& x
, const T
& y
) const
120 * @brief Compute the logical exclusive OR of two integral values.
122 * This binary function object computes the logical exclusive of the
123 * two values it is given. When used with MPI and a type @c T that has
124 * an associated, built-in MPI data type, translates to @c MPI_LXOR.
127 struct logical_xor
: public std::binary_function
<T
, T
, T
>
129 /** @returns the logical exclusive OR of x and y. */
130 T
operator()(const T
& x
, const T
& y
) const
132 return (x
|| y
) && !(x
&& y
);
137 * @brief Compute the bitwise exclusive OR of two integral values.
139 * This binary function object computes the bitwise exclusive OR of
140 * the two values it is given. When used with MPI and a type @c T that
141 * has an associated, built-in MPI data type, translates to @c
145 struct bitwise_xor
: public std::binary_function
<T
, T
, T
>
147 /** @returns @c x ^ y. */
148 T
operator()(const T
& x
, const T
& y
) const
154 /**************************************************************************
156 **************************************************************************/
159 * @brief Determine if a function object has an associated @c MPI_Op.
161 * This trait determines if a function object type @c Op, when used
162 * with argument type @c T, has an associated @c MPI_Op. If so, @c
163 * is_mpi_op<Op,T> will derive from @c mpl::false_ and will
164 * contain a static member function @c op that takes no arguments but
165 * returns the associated @c MPI_Op value. For instance, @c
166 * is_mpi_op<std::plus<int>,int>::op() returns @c MPI_SUM.
168 * Users may specialize @c is_mpi_op for any other class templates
169 * that map onto operations that have @c MPI_Op equivalences, such as
170 * bitwise OR, logical and, or maximum. However, users are encouraged
171 * to use the standard function objects in the @c functional and @c
172 * boost/mpi/operations.hpp headers whenever possible. For
173 * function objects that are class templates with a single template
174 * parameter, it may be easier to specialize @c is_builtin_mpi_op.
176 template<typename Op
, typename T
>
177 struct is_mpi_op
: public mpl::false_
{ };
181 struct is_mpi_op
<maximum
<T
>, T
>
182 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
183 is_mpi_floating_point_datatype
<T
> >
185 static MPI_Op
op() { return MPI_MAX
; }
190 struct is_mpi_op
<minimum
<T
>, T
>
191 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
192 is_mpi_floating_point_datatype
<T
> >
194 static MPI_Op
op() { return MPI_MIN
; }
199 struct is_mpi_op
<std::plus
<T
>, T
>
200 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
201 is_mpi_floating_point_datatype
<T
>,
202 is_mpi_complex_datatype
<T
> >
204 static MPI_Op
op() { return MPI_SUM
; }
209 struct is_mpi_op
<std::multiplies
<T
>, T
>
210 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
211 is_mpi_floating_point_datatype
<T
>,
212 is_mpi_complex_datatype
<T
> >
214 static MPI_Op
op() { return MPI_PROD
; }
219 struct is_mpi_op
<std::logical_and
<T
>, T
>
220 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
221 is_mpi_logical_datatype
<T
> >
223 static MPI_Op
op() { return MPI_LAND
; }
228 struct is_mpi_op
<std::logical_or
<T
>, T
>
229 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
230 is_mpi_logical_datatype
<T
> >
232 static MPI_Op
op() { return MPI_LOR
; }
237 struct is_mpi_op
<logical_xor
<T
>, T
>
238 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
239 is_mpi_logical_datatype
<T
> >
241 static MPI_Op
op() { return MPI_LXOR
; }
246 struct is_mpi_op
<bitwise_and
<T
>, T
>
247 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
248 is_mpi_byte_datatype
<T
> >
250 static MPI_Op
op() { return MPI_BAND
; }
255 struct is_mpi_op
<bitwise_or
<T
>, T
>
256 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
257 is_mpi_byte_datatype
<T
> >
259 static MPI_Op
op() { return MPI_BOR
; }
264 struct is_mpi_op
<bitwise_xor
<T
>, T
>
265 : public boost::mpl::or_
<is_mpi_integer_datatype
<T
>,
266 is_mpi_byte_datatype
<T
> >
268 static MPI_Op
op() { return MPI_BXOR
; }
272 // A helper class used to create user-defined MPI_Ops
273 template<typename Op
, typename T
>
277 explicit user_op(Op
& op
)
279 BOOST_MPI_CHECK_RESULT(MPI_Op_create
,
280 (&user_op
<Op
, T
>::perform
,
281 is_commutative
<Op
, T
>::value
,
289 if (std::uncaught_exception()) {
290 // Ignore failure cases: there are obviously other problems
291 // already, and we don't want to cause program termination if
292 // MPI_Op_free fails.
293 MPI_Op_free(&mpi_op
);
295 BOOST_MPI_CHECK_RESULT(MPI_Op_free
, (&mpi_op
));
308 static void BOOST_MPI_CALLING_CONVENTION
perform(void* vinvec
, void* voutvec
, int* plen
, MPI_Datatype
*)
310 T
* invec
= static_cast<T
*>(vinvec
);
311 T
* outvec
= static_cast<T
*>(voutvec
);
312 std::transform(invec
, invec
+ *plen
, outvec
, outvec
, *op_ptr
);
316 template<typename Op
, typename T
> Op
* user_op
<Op
, T
>::op_ptr
= 0;
318 } // end namespace detail
320 } } // end namespace boost::mpi
322 #endif // BOOST_MPI_GET_MPI_OP_HPP