]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/mpi/include/boost/mpi/operations.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / mpi / include / boost / mpi / operations.hpp
1 // Copyright (C) 2004 The Trustees of Indiana University.
2 // Copyright (C) 2005-2006 Douglas Gregor <doug.gregor -at- gmail.com>
3
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)
7
8 // Authors: Douglas Gregor
9 // Andrew Lumsdaine
10
11 /** @file operations.hpp
12 *
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.
17 */
18 #ifndef BOOST_MPI_IS_MPI_OP_HPP
19 #define BOOST_MPI_IS_MPI_OP_HPP
20
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>
27 #include <functional>
28
29 namespace boost { namespace mpi {
30
31 template<typename Op, typename T> struct is_mpi_op;
32
33 /**
34 * @brief Determine if a function object type is commutative.
35 *
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
41 * mpl::true_.
42 */
43 template<typename Op, typename T>
44 struct is_commutative : public mpl::false_ { };
45
46 /**************************************************************************
47 * Function objects for MPI operations not in <functional> header *
48 **************************************************************************/
49
50 /**
51 * @brief Compute the maximum of two values.
52 *
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.
56 */
57 template<typename T>
58 struct maximum : public std::binary_function<T, T, T>
59 {
60 /** @returns the maximum of x and y. */
61 const T& operator()(const T& x, const T& y) const
62 {
63 return x < y? y : x;
64 }
65 };
66
67 /**
68 * @brief Compute the minimum of two values.
69 *
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.
73 */
74 template<typename T>
75 struct minimum : public std::binary_function<T, T, T>
76 {
77 /** @returns the minimum of x and y. */
78 const T& operator()(const T& x, const T& y) const
79 {
80 return x < y? x : y;
81 }
82 };
83
84
85 /**
86 * @brief Compute the bitwise AND of two integral values.
87 *
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.
91 */
92 template<typename T>
93 struct bitwise_and : public std::binary_function<T, T, T>
94 {
95 /** @returns @c x & y. */
96 T operator()(const T& x, const T& y) const
97 {
98 return x & y;
99 }
100 };
101
102 /**
103 * @brief Compute the bitwise OR of two integral values.
104 *
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.
108 */
109 template<typename T>
110 struct bitwise_or : public std::binary_function<T, T, T>
111 {
112 /** @returns the @c x | y. */
113 T operator()(const T& x, const T& y) const
114 {
115 return x | y;
116 }
117 };
118
119 /**
120 * @brief Compute the logical exclusive OR of two integral values.
121 *
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.
125 */
126 template<typename T>
127 struct logical_xor : public std::binary_function<T, T, T>
128 {
129 /** @returns the logical exclusive OR of x and y. */
130 T operator()(const T& x, const T& y) const
131 {
132 return (x || y) && !(x && y);
133 }
134 };
135
136 /**
137 * @brief Compute the bitwise exclusive OR of two integral values.
138 *
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
142 * MPI_BXOR.
143 */
144 template<typename T>
145 struct bitwise_xor : public std::binary_function<T, T, T>
146 {
147 /** @returns @c x ^ y. */
148 T operator()(const T& x, const T& y) const
149 {
150 return x ^ y;
151 }
152 };
153
154 /**************************************************************************
155 * MPI_Op queries *
156 **************************************************************************/
157
158 /**
159 * @brief Determine if a function object has an associated @c MPI_Op.
160 *
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.
167 *
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.
175 */
176 template<typename Op, typename T>
177 struct is_mpi_op : public mpl::false_ { };
178
179 /// INTERNAL ONLY
180 template<typename T>
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> >
184 {
185 static MPI_Op op() { return MPI_MAX; }
186 };
187
188 /// INTERNAL ONLY
189 template<typename T>
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> >
193 {
194 static MPI_Op op() { return MPI_MIN; }
195 };
196
197 /// INTERNAL ONLY
198 template<typename T>
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> >
203 {
204 static MPI_Op op() { return MPI_SUM; }
205 };
206
207 /// INTERNAL ONLY
208 template<typename T>
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> >
213 {
214 static MPI_Op op() { return MPI_PROD; }
215 };
216
217 /// INTERNAL ONLY
218 template<typename T>
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> >
222 {
223 static MPI_Op op() { return MPI_LAND; }
224 };
225
226 /// INTERNAL ONLY
227 template<typename T>
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> >
231 {
232 static MPI_Op op() { return MPI_LOR; }
233 };
234
235 /// INTERNAL ONLY
236 template<typename T>
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> >
240 {
241 static MPI_Op op() { return MPI_LXOR; }
242 };
243
244 /// INTERNAL ONLY
245 template<typename T>
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> >
249 {
250 static MPI_Op op() { return MPI_BAND; }
251 };
252
253 /// INTERNAL ONLY
254 template<typename T>
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> >
258 {
259 static MPI_Op op() { return MPI_BOR; }
260 };
261
262 /// INTERNAL ONLY
263 template<typename T>
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> >
267 {
268 static MPI_Op op() { return MPI_BXOR; }
269 };
270
271 namespace detail {
272 // A helper class used to create user-defined MPI_Ops
273 template<typename Op, typename T>
274 class user_op
275 {
276 public:
277 explicit user_op(Op& op)
278 {
279 BOOST_MPI_CHECK_RESULT(MPI_Op_create,
280 (&user_op<Op, T>::perform,
281 is_commutative<Op, T>::value,
282 &mpi_op));
283
284 op_ptr = &op;
285 }
286
287 ~user_op()
288 {
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);
294 } else {
295 BOOST_MPI_CHECK_RESULT(MPI_Op_free, (&mpi_op));
296 }
297 }
298
299 MPI_Op& get_mpi_op()
300 {
301 return mpi_op;
302 }
303
304 private:
305 MPI_Op mpi_op;
306 static Op* op_ptr;
307
308 static void BOOST_MPI_CALLING_CONVENTION perform(void* vinvec, void* voutvec, int* plen, MPI_Datatype*)
309 {
310 T* invec = static_cast<T*>(vinvec);
311 T* outvec = static_cast<T*>(voutvec);
312 std::transform(invec, invec + *plen, outvec, outvec, *op_ptr);
313 }
314 };
315
316 template<typename Op, typename T> Op* user_op<Op, T>::op_ptr = 0;
317
318 } // end namespace detail
319
320 } } // end namespace boost::mpi
321
322 #endif // BOOST_MPI_GET_MPI_OP_HPP