]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/mpi/operations.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / mpi / operations.hpp
CommitLineData
7c673cae
FG
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>
92f5a8d4
TL
26#include <boost/core/enable_if.hpp>
27#include <boost/core/uncaught_exceptions.hpp>
7c673cae
FG
28#include <functional>
29
30namespace boost { namespace mpi {
31
32template<typename Op, typename T> struct is_mpi_op;
33
34/**
35 * @brief Determine if a function object type is commutative.
36 *
37 * This trait determines if an operation @c Op is commutative when
38 * applied to values of type @c T. Parallel operations such as @c
39 * reduce and @c prefix_sum can be implemented more efficiently with
40 * commutative operations. To mark an operation as commutative, users
41 * should specialize @c is_commutative and derive from the class @c
42 * mpl::true_.
43 */
44template<typename Op, typename T>
45struct is_commutative : public mpl::false_ { };
46
47/**************************************************************************
48 * Function objects for MPI operations not in <functional> header *
49 **************************************************************************/
50
51/**
52 * @brief Compute the maximum of two values.
53 *
54 * This binary function object computes the maximum of the two values
55 * it is given. When used with MPI and a type @c T that has an
56 * associated, built-in MPI data type, translates to @c MPI_MAX.
57 */
58template<typename T>
11fdf7f2 59struct maximum
7c673cae 60{
11fdf7f2
TL
61 typedef T first_argument_type;
62 typedef T second_argument_type;
63 typedef T result_type;
7c673cae
FG
64 /** @returns the maximum of x and y. */
65 const T& operator()(const T& x, const T& y) const
66 {
67 return x < y? y : x;
68 }
69};
70
71/**
72 * @brief Compute the minimum of two values.
73 *
74 * This binary function object computes the minimum of the two values
75 * it is given. When used with MPI and a type @c T that has an
76 * associated, built-in MPI data type, translates to @c MPI_MIN.
77 */
78template<typename T>
11fdf7f2 79struct minimum
7c673cae 80{
11fdf7f2
TL
81 typedef T first_argument_type;
82 typedef T second_argument_type;
83 typedef T result_type;
7c673cae
FG
84 /** @returns the minimum of x and y. */
85 const T& operator()(const T& x, const T& y) const
86 {
87 return x < y? x : y;
88 }
89};
90
91
92/**
93 * @brief Compute the bitwise AND of two integral values.
94 *
95 * This binary function object computes the bitwise AND of the two
96 * values it is given. When used with MPI and a type @c T that has an
97 * associated, built-in MPI data type, translates to @c MPI_BAND.
98 */
99template<typename T>
11fdf7f2 100struct bitwise_and
7c673cae 101{
11fdf7f2
TL
102 typedef T first_argument_type;
103 typedef T second_argument_type;
104 typedef T result_type;
7c673cae
FG
105 /** @returns @c x & y. */
106 T operator()(const T& x, const T& y) const
107 {
108 return x & y;
109 }
110};
111
112/**
113 * @brief Compute the bitwise OR of two integral values.
114 *
115 * This binary function object computes the bitwise OR of the two
116 * values it is given. When used with MPI and a type @c T that has an
117 * associated, built-in MPI data type, translates to @c MPI_BOR.
118 */
119template<typename T>
11fdf7f2 120struct bitwise_or
7c673cae 121{
11fdf7f2
TL
122 typedef T first_argument_type;
123 typedef T second_argument_type;
124 typedef T result_type;
7c673cae
FG
125 /** @returns the @c x | y. */
126 T operator()(const T& x, const T& y) const
127 {
128 return x | y;
129 }
130};
131
132/**
133 * @brief Compute the logical exclusive OR of two integral values.
134 *
135 * This binary function object computes the logical exclusive of the
136 * two values it is given. When used with MPI and a type @c T that has
137 * an associated, built-in MPI data type, translates to @c MPI_LXOR.
138 */
139template<typename T>
11fdf7f2 140struct logical_xor
7c673cae 141{
11fdf7f2
TL
142 typedef T first_argument_type;
143 typedef T second_argument_type;
144 typedef T result_type;
7c673cae
FG
145 /** @returns the logical exclusive OR of x and y. */
146 T operator()(const T& x, const T& y) const
147 {
148 return (x || y) && !(x && y);
149 }
150};
151
152/**
153 * @brief Compute the bitwise exclusive OR of two integral values.
154 *
155 * This binary function object computes the bitwise exclusive OR of
156 * the two values it is given. When used with MPI and a type @c T that
157 * has an associated, built-in MPI data type, translates to @c
158 * MPI_BXOR.
159 */
160template<typename T>
11fdf7f2 161struct bitwise_xor
7c673cae 162{
11fdf7f2
TL
163 typedef T first_argument_type;
164 typedef T second_argument_type;
165 typedef T result_type;
7c673cae
FG
166 /** @returns @c x ^ y. */
167 T operator()(const T& x, const T& y) const
168 {
169 return x ^ y;
170 }
171};
172
173/**************************************************************************
174 * MPI_Op queries *
175 **************************************************************************/
176
177/**
178 * @brief Determine if a function object has an associated @c MPI_Op.
179 *
180 * This trait determines if a function object type @c Op, when used
181 * with argument type @c T, has an associated @c MPI_Op. If so, @c
182 * is_mpi_op<Op,T> will derive from @c mpl::false_ and will
183 * contain a static member function @c op that takes no arguments but
184 * returns the associated @c MPI_Op value. For instance, @c
185 * is_mpi_op<std::plus<int>,int>::op() returns @c MPI_SUM.
186 *
187 * Users may specialize @c is_mpi_op for any other class templates
188 * that map onto operations that have @c MPI_Op equivalences, such as
189 * bitwise OR, logical and, or maximum. However, users are encouraged
190 * to use the standard function objects in the @c functional and @c
191 * boost/mpi/operations.hpp headers whenever possible. For
192 * function objects that are class templates with a single template
193 * parameter, it may be easier to specialize @c is_builtin_mpi_op.
194 */
195template<typename Op, typename T>
196struct is_mpi_op : public mpl::false_ { };
197
198/// INTERNAL ONLY
199template<typename T>
200struct is_mpi_op<maximum<T>, T>
201 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
202 is_mpi_floating_point_datatype<T> >
203{
204 static MPI_Op op() { return MPI_MAX; }
205};
206
207/// INTERNAL ONLY
208template<typename T>
209struct is_mpi_op<minimum<T>, T>
210 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
211 is_mpi_floating_point_datatype<T> >
212{
213 static MPI_Op op() { return MPI_MIN; }
214};
215
216/// INTERNAL ONLY
217template<typename T>
218 struct is_mpi_op<std::plus<T>, T>
219 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
220 is_mpi_floating_point_datatype<T>,
221 is_mpi_complex_datatype<T> >
222{
223 static MPI_Op op() { return MPI_SUM; }
224};
225
226/// INTERNAL ONLY
227template<typename T>
228 struct is_mpi_op<std::multiplies<T>, T>
229 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
230 is_mpi_floating_point_datatype<T>,
231 is_mpi_complex_datatype<T> >
232{
233 static MPI_Op op() { return MPI_PROD; }
234};
235
236/// INTERNAL ONLY
237template<typename T>
238 struct is_mpi_op<std::logical_and<T>, T>
239 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
240 is_mpi_logical_datatype<T> >
241{
242 static MPI_Op op() { return MPI_LAND; }
243};
244
245/// INTERNAL ONLY
246template<typename T>
247 struct is_mpi_op<std::logical_or<T>, T>
248 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
249 is_mpi_logical_datatype<T> >
250{
251 static MPI_Op op() { return MPI_LOR; }
252};
253
254/// INTERNAL ONLY
255template<typename T>
256 struct is_mpi_op<logical_xor<T>, T>
257 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
258 is_mpi_logical_datatype<T> >
259{
260 static MPI_Op op() { return MPI_LXOR; }
261};
262
263/// INTERNAL ONLY
264template<typename T>
265 struct is_mpi_op<bitwise_and<T>, T>
266 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
267 is_mpi_byte_datatype<T> >
268{
269 static MPI_Op op() { return MPI_BAND; }
270};
271
272/// INTERNAL ONLY
273template<typename T>
274 struct is_mpi_op<bitwise_or<T>, T>
275 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
276 is_mpi_byte_datatype<T> >
277{
278 static MPI_Op op() { return MPI_BOR; }
279};
280
281/// INTERNAL ONLY
282template<typename T>
283 struct is_mpi_op<bitwise_xor<T>, T>
284 : public boost::mpl::or_<is_mpi_integer_datatype<T>,
285 is_mpi_byte_datatype<T> >
286{
287 static MPI_Op op() { return MPI_BXOR; }
288};
289
290namespace detail {
291 // A helper class used to create user-defined MPI_Ops
292 template<typename Op, typename T>
293 class user_op
294 {
295 public:
92f5a8d4 296 user_op()
7c673cae
FG
297 {
298 BOOST_MPI_CHECK_RESULT(MPI_Op_create,
299 (&user_op<Op, T>::perform,
300 is_commutative<Op, T>::value,
301 &mpi_op));
7c673cae
FG
302 }
303
304 ~user_op()
305 {
92f5a8d4 306 if (boost::core::uncaught_exceptions() > 0) {
7c673cae
FG
307 // Ignore failure cases: there are obviously other problems
308 // already, and we don't want to cause program termination if
309 // MPI_Op_free fails.
310 MPI_Op_free(&mpi_op);
311 } else {
312 BOOST_MPI_CHECK_RESULT(MPI_Op_free, (&mpi_op));
313 }
314 }
315
316 MPI_Op& get_mpi_op()
317 {
318 return mpi_op;
319 }
320
321 private:
322 MPI_Op mpi_op;
7c673cae
FG
323
324 static void BOOST_MPI_CALLING_CONVENTION perform(void* vinvec, void* voutvec, int* plen, MPI_Datatype*)
325 {
326 T* invec = static_cast<T*>(vinvec);
327 T* outvec = static_cast<T*>(voutvec);
92f5a8d4
TL
328 Op op;
329 std::transform(invec, invec + *plen, outvec, outvec, op);
7c673cae
FG
330 }
331 };
332
7c673cae
FG
333} // end namespace detail
334
335} } // end namespace boost::mpi
336
337#endif // BOOST_MPI_GET_MPI_OP_HPP