Interface Documentation
Version: invalid
fold.hh
Go to the documentation of this file.
1 /*
2  @@@@@@@@ @@ @@@@@@ @@@@@@@@ @@
3  /@@///// /@@ @@////@@ @@////// /@@
4  /@@ /@@ @@@@@ @@ // /@@ /@@
5  /@@@@@@@ /@@ @@///@@/@@ /@@@@@@@@@/@@
6  /@@//// /@@/@@@@@@@/@@ ////////@@/@@
7  /@@ /@@/@@//// //@@ @@ /@@/@@
8  /@@ @@@//@@@@@@ //@@@@@@ @@@@@@@@ /@@
9  // /// ////// ////// //////// //
10 
11  Copyright (c) 2016, Triad National Security, LLC
12  All rights reserved.
13  */
14 #pragma once
15 
18 #if !defined(__FLECSI_PRIVATE__)
19 #error Do not include this file directly!
20 #endif
21 
22 #include "../run/backend.hh"
23 
24 #include <limits>
25 
26 /*----------------------------------------------------------------------------*
27  Reduction Interface
28  *----------------------------------------------------------------------------*/
29 
30 namespace flecsi {
31 namespace exec::fold {
32 
37 template<typename T>
38 struct min {
39 
40  using LHS = T;
41  using RHS = T;
42  static constexpr T identity{std::numeric_limits<T>::max()};
43 
44  template<bool EXCLUSIVE>
45  static void apply(LHS & lhs, RHS rhs) {
46  if constexpr(EXCLUSIVE) {
47  lhs = lhs < rhs ? lhs : rhs;
48  }
49  else {
50  int64_t * target = reinterpret_cast<int64_t *>(&lhs);
51 
52  union
53  {
54  int64_t as_int;
55  T as_T;
56  } oldval, newval;
57 
58  do {
59  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
60  newval.as_T = std::min(oldval.as_T, rhs);
61  } while(
62  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
63  } // if
64  } // apply
65 
66  template<bool EXCLUSIVE>
67  static void fold(RHS & rhs1, RHS rhs2) {
68 
69  if constexpr(EXCLUSIVE) {
70  rhs1 = std::min(rhs1, rhs2);
71  }
72  else {
73  int64_t * target = reinterpret_cast<int64_t *>(&rhs1);
74 
75  union
76  {
77  int64_t as_int;
78  T as_T;
79  } oldval, newval;
80 
81  do {
82  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
83  newval.as_T = std::min(oldval.as_T, rhs2);
84  } while(
85  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
86  } // if
87  } // fold
88 
89 }; // struct min
90 
95 template<typename T>
96 struct max {
97 
98  using LHS = T;
99  using RHS = T;
100  static constexpr T identity{std::numeric_limits<T>::min()};
101 
102  template<bool EXCLUSIVE = true>
103  static void apply(LHS & lhs, RHS rhs) {
104  if constexpr(EXCLUSIVE) {
105  lhs = lhs > rhs ? lhs : rhs;
106  }
107  else {
108  int64_t * target = reinterpret_cast<int64_t *>(&lhs);
109 
110  union
111  {
112  int64_t as_int;
113  T as_T;
114  } oldval, newval;
115 
116  do {
117  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
118  newval.as_T = std::max(oldval.as_T, rhs);
119  } while(
120  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
121  } // if
122  } // apply
123 
124  template<bool EXCLUSIVE = true>
125  static void fold(RHS & rhs1, RHS rhs2) {
126 
127  if constexpr(EXCLUSIVE) {
128  rhs1 = std::max(rhs1, rhs2);
129  }
130  else {
131  int64_t * target = reinterpret_cast<int64_t *>(&rhs1);
132 
133  union
134  {
135  int64_t as_int;
136  T as_T;
137  } oldval, newval;
138 
139  do {
140  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
141  newval.as_T = std::max(oldval.as_T, rhs2);
142  } while(
143  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
144  } // if
145  } // fold
146 
147 }; // struct max
148 
153 template<typename T>
154 struct sum {
155 
156  using LHS = T;
157  using RHS = T;
158  static constexpr T identity{};
159 
160  template<bool EXCLUSIVE = true>
161  static void apply(LHS & lhs, RHS rhs) {
162 
163  if constexpr(EXCLUSIVE) {
164  lhs += rhs;
165  }
166  else {
167  int64_t * target = reinterpret_cast<int64_t *>(&lhs);
168 
169  union
170  {
171  int64_t as_int;
172  T as_T;
173  } oldval, newval;
174 
175  do {
176  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
177  newval.as_T = oldval.as_T + rhs;
178  } while(
179  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
180  } // if constexpr
181 
182  } // apply
183 
184  template<bool EXCLUSIVE = true>
185  static void fold(RHS & rhs1, RHS rhs2) {
186 
187  if constexpr(EXCLUSIVE) {
188  rhs1 += rhs2;
189  }
190  else {
191  int64_t * target = reinterpret_cast<int64_t *>(&rhs1);
192 
193  union
194  {
195  int64_t as_int;
196  T as_T;
197  } oldval, newval;
198 
199  do {
200  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
201  newval.as_T = oldval.as_T + rhs2;
202  } while(
203  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
204  } // if constexpr
205 
206  } // fold
207 
208 }; // struct sum
209 
214 template<typename T>
215 struct product {
216 
217  using LHS = T;
218  using RHS = T;
219  static constexpr T identity{};
220 
221  template<bool EXCLUSIVE = true>
222  static void apply(LHS & lhs, RHS rhs) {
223 
224  if constexpr(EXCLUSIVE) {
225  lhs *= rhs;
226  }
227  else {
228  int64_t * target = reinterpret_cast<int64_t *>(&lhs);
229 
230  union
231  {
232  int64_t as_int;
233  T as_T;
234  } oldval, newval;
235 
236  do {
237  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
238  newval.as_T = oldval.as_T * rhs;
239  } while(
240  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
241  } // if constexpr
242 
243  } // apply
244 
245  template<bool EXCLUSIVE = true>
246  static void fold(RHS & rhs1, RHS rhs2) {
247 
248  if constexpr(EXCLUSIVE) {
249  rhs1 *= rhs2;
250  }
251  else {
252  int64_t * target = reinterpret_cast<int64_t *>(&rhs1);
253 
254  union
255  {
256  int64_t as_int;
257  T as_T;
258  } oldval, newval;
259 
260  do {
261  std::memcpy(&oldval.as_int, target, sizeof(int64_t));
262  newval.as_T = oldval.as_T * rhs2;
263  } while(
264  !__sync_bool_compare_and_swap(target, oldval.as_int, newval.as_int));
265  } // if constexpr
266 
267  } // fold
268 
269 }; // struct product
270 
271 } // namespace exec::fold
272 } // namespace flecsi
Definition: fold.hh:96
Definition: fold.hh:154
Definition: fold.hh:38
Definition: fold.hh:215
Definition: control.hh:31