omega_h
Reliable mesh adaptation
Omega_h_scalar.hpp
1 #ifndef OMEGA_H_SCALAR_HPP
2 #define OMEGA_H_SCALAR_HPP
3 
4 #include <Omega_h_defines.hpp>
5 #include <Omega_h_fail.hpp>
6 #include <cfloat>
7 #include <climits>
8 #include <cmath>
9 #include <utility>
10 
11 namespace Omega_h {
12 
13 /* certain operations, including Kokkos reductions and writing
14  to std::cout, don't behave as desired on std::int8_t.
15  This class is just responsible for raising std::int8_t to std::int32_t */
16 template <typename T>
17 struct Promoted {
18  typedef T type;
19 };
20 
21 template <>
22 struct Promoted<I8> {
23  typedef I32 type;
24 };
25 
26 template <typename T>
27 using promoted_t = typename Promoted<T>::type;
28 
29 template <typename T>
30 struct ArithTraits;
31 
32 template <>
33 struct ArithTraits<unsigned char> {
34  static OMEGA_H_INLINE unsigned char max() noexcept { return UCHAR_MAX; }
35  static OMEGA_H_INLINE unsigned char min() noexcept { return 0; }
36 };
37 
38 template <>
39 struct ArithTraits<signed char> {
40  static constexpr OMEGA_H_INLINE signed char max() noexcept {
41  return SCHAR_MAX;
42  }
43  static constexpr OMEGA_H_INLINE signed char min() noexcept {
44  return SCHAR_MIN;
45  }
46 };
47 
48 template <>
49 struct ArithTraits<unsigned int> {
50  static constexpr OMEGA_H_INLINE unsigned int max() noexcept {
51  return UINT_MAX;
52  }
53  static constexpr OMEGA_H_INLINE unsigned int min() noexcept { return 0; }
54 };
55 
56 template <>
57 struct ArithTraits<int> {
58  static constexpr OMEGA_H_INLINE int max() noexcept { return INT_MAX; }
59  static constexpr OMEGA_H_INLINE int min() noexcept { return INT_MIN; }
60 };
61 
62 template <>
63 struct ArithTraits<unsigned long> {
64  static constexpr OMEGA_H_INLINE unsigned long max() noexcept {
65  return ULONG_MAX;
66  }
67  static constexpr OMEGA_H_INLINE unsigned long min() noexcept { return 0; }
68 };
69 
70 template <>
71 struct ArithTraits<signed long> {
72  static constexpr OMEGA_H_INLINE signed long max() noexcept {
73  return LONG_MAX;
74  }
75  static constexpr OMEGA_H_INLINE signed long min() noexcept {
76  return LONG_MIN;
77  }
78 };
79 
80 template <>
81 struct ArithTraits<unsigned long long> {
82  static constexpr OMEGA_H_INLINE unsigned long long max() noexcept {
83  return ULLONG_MAX;
84  }
85  static constexpr OMEGA_H_INLINE unsigned long long min() noexcept {
86  return 0;
87  }
88 };
89 
90 template <>
91 struct ArithTraits<signed long long> {
92  static constexpr OMEGA_H_INLINE signed long long max() noexcept {
93  return LLONG_MAX;
94  }
95  static constexpr OMEGA_H_INLINE signed long long min() noexcept {
96  return LLONG_MIN;
97  }
98 };
99 
100 template <>
101 struct ArithTraits<double> {
102  static constexpr OMEGA_H_INLINE double max() noexcept { return DBL_MAX; }
103  static constexpr OMEGA_H_INLINE double min() noexcept { return -DBL_MAX; }
104 };
105 
106 template <typename T>
107 constexpr OMEGA_H_INLINE T max2(T a, T b) noexcept {
108  return (a < b) ? (b) : (a);
109 }
110 
111 template <typename T>
112 constexpr OMEGA_H_INLINE T min2(T a, T b) noexcept {
113  return (b < a) ? (b) : (a);
114 }
115 
116 template <typename T>
117 OMEGA_H_INLINE void swap2(T& a, T& b) noexcept {
118  T c(std::move(a));
119  a = std::move(b);
120  b = std::move(c);
121 }
122 
123 template <typename T>
124 constexpr OMEGA_H_INLINE_BIG T factorial(T x) noexcept {
125  return (x > 1) ? (x * factorial(x - 1)) : 1;
126 }
127 
128 template <typename T>
129 constexpr OMEGA_H_INLINE T average(T a, T b) noexcept {
130  return (a + b) / 2;
131 }
132 
133 template <Int p, typename T>
134 struct Raise {
135  static_assert(p >= 0, "negative power not allowed in Raise!");
136  static constexpr OMEGA_H_INLINE T eval(T x) noexcept {
137  return x * Raise<p - 1, T>::eval(x);
138  }
139 };
140 
141 template <typename T>
142 struct Raise<0, T> {
143  static constexpr OMEGA_H_INLINE T eval(T) noexcept { return 1; }
144 };
145 
146 template <Int p, typename T>
147 constexpr OMEGA_H_INLINE T raise(T x) noexcept {
148  return Raise<p, T>::eval(x);
149 }
150 
151 template <typename T>
152 constexpr OMEGA_H_INLINE T square(T x) noexcept {
153  return raise<2, T>(x);
154 }
155 
156 template <typename T>
157 OMEGA_H_INLINE T cube(T x) noexcept {
158  return raise<3, T>(x);
159 }
160 
161 OMEGA_H_INLINE Real sign(Real x) noexcept { return (x < 0.0) ? -1.0 : 1.0; }
162 
163 OMEGA_H_INLINE Real clamp(Real x, Real low, Real high) noexcept {
164  return min2(max2(x, low), high);
165 }
166 
167 template <Int dp>
168 struct Root;
169 
170 template <>
171 struct Root<0> {
172  static OMEGA_H_INLINE Real eval(Real) noexcept { return 1.0; }
173 };
174 
175 template <>
176 struct Root<1> {
177  static OMEGA_H_INLINE Real eval(Real x) noexcept { return x; }
178 };
179 
180 template <>
181 struct Root<2> {
182  static OMEGA_H_INLINE Real eval(Real x) noexcept { return std::sqrt(x); }
183 };
184 
185 template <>
186 struct Root<3> {
187  static OMEGA_H_INLINE Real eval(Real x) noexcept { return std::cbrt(x); }
188 };
189 
190 template <Int p>
191 OMEGA_H_INLINE Real root(Real x) noexcept {
192  return Root<p>::eval(x);
193 }
194 
195 /* compile-time-executable Greatest Common Denominator code */
196 constexpr OMEGA_H_INLINE Int gcd(Int a, Int b) noexcept {
197  return (b == 0) ? (a) : (gcd(b, a % b));
198 }
199 
200 /* specialization system for raising a Real to a power
201  * which is an integer fraction.
202  * these templated classes are responsible for reducing
203  * the fraction via gdc(), and returning the original value
204  * if the fraction is unity.
205  */
206 template <Int np, Int dp, Int cd = gcd(np, dp)>
207 struct Power : public Power<np / cd, dp / cd> {
208  using Power<np / cd, dp / cd>::eval;
209  static_assert(cd != 1, "reduced case should be specialized");
210 };
211 
212 template <Int np, Int dp>
213 struct Power<np, dp, 1> {
214  static OMEGA_H_INLINE Real eval(Real x) noexcept {
215  return root<dp>(raise<np>(x));
216  }
217  static_assert(np != dp, "equal case should be specialized");
218 };
219 
220 template <Int p>
221 struct Power<p, p, 1> {
222  static OMEGA_H_INLINE Real eval(Real x) noexcept { return x; }
223 };
224 
225 template <Int np, Int dp>
226 OMEGA_H_INLINE Real power(Real x) noexcept {
227  return Power<np, dp>::eval(x);
228 }
229 
230 OMEGA_H_INLINE Real power(Real x, Int np, Int dp) noexcept {
231  switch (np) {
232  case 1:
233  switch (dp) {
234  case 1:
235  return power<1, 1>(x);
236  case 2:
237  return power<1, 2>(x);
238  case 3:
239  return power<1, 3>(x);
240  }
241  return -1.0;
242  case 2:
243  switch (dp) {
244  case 1:
245  return power<2, 1>(x);
246  case 2:
247  return power<2, 2>(x);
248  case 3:
249  return power<2, 3>(x);
250  }
251  return -1.0;
252  case 3:
253  switch (dp) {
254  case 1:
255  return power<3, 1>(x);
256  case 2:
257  return power<3, 2>(x);
258  case 3:
259  return power<3, 3>(x);
260  }
261  return -1.0;
262  }
263  return -1.0;
264 }
265 
266 OMEGA_H_INLINE Real rel_diff_with_floor(
267  Real a, Real b, Real floor = EPSILON) noexcept {
268  Real am = std::abs(a);
269  Real bm = std::abs(b);
270  if (am <= floor && bm <= floor) return 0.0;
271  return std::abs(b - a) / max2(am, bm);
272 }
273 
274 OMEGA_H_INLINE bool are_close(
275  Real a, Real b, Real tol = EPSILON, Real floor = EPSILON) noexcept {
276  return rel_diff_with_floor(a, b, floor) <= tol;
277 }
278 
279 template <typename T>
280 T divide_no_remainder(T a, T b) {
281  OMEGA_H_CHECK(b != 0);
282  OMEGA_H_CHECK(a % b == 0);
283  return a / b;
284 }
285 
286 template <typename T>
287 struct plus {
288  typedef T first_argument_type;
289  typedef T second_argument_type;
290  typedef T result_type;
291  OMEGA_H_INLINE T operator()(const T& lhs, const T& rhs) const noexcept {
292  return lhs + rhs;
293  }
294 };
295 
296 template <typename T>
297 struct logical_and {
298  typedef T first_argument_type;
299  typedef T second_argument_type;
300  typedef bool result_type;
301  OMEGA_H_INLINE bool operator()(const T& lhs, const T& rhs) const noexcept {
302  return lhs && rhs;
303  }
304 };
305 
306 template <typename T>
307 struct maximum {
308  typedef T first_argument_type;
309  typedef T second_argument_type;
310  typedef T result_type;
311  OMEGA_H_INLINE T operator()(const T& lhs, const T& rhs) const noexcept {
312  return lhs < rhs ? rhs : lhs;
313  }
314 };
315 
316 template <typename T>
317 struct minimum {
318  typedef T first_argument_type;
319  typedef T second_argument_type;
320  typedef T result_type;
321  OMEGA_H_INLINE T operator()(const T& lhs, const T& rhs) const noexcept {
322  return lhs < rhs ? lhs : rhs;
323  }
324 };
325 
326 template <typename T>
327 struct identity {
328  typedef T argument_type;
329  typedef T result_type;
330  OMEGA_H_INLINE const T& operator()(const T& x) const noexcept { return x; }
331 };
332 
333 template <typename T>
334 struct multiplies {
335  typedef T first_argument_type;
336  typedef T second_argument_type;
337  typedef T result_type;
338  OMEGA_H_INLINE T operator()(const T& lhs, const T& rhs) const noexcept {
339  return lhs * rhs;
340  }
341 };
342 
343 // In the algrebra of rotations one often comes across functions that
344 // take undefined (0/0) values at some points. Close to such points
345 // these functions must be evaluated using their asymptotic
346 // expansions; otherwise the computer may produce wildly erroneous
347 // results or a floating point exception. To avoid unreachable code
348 // everywhere such functions are used, we introduce here functions to
349 // the same effect.
350 //
351 // Function form: sin(x) / x
352 // X: 0
353 // Asymptotics: 1.0 (-x^2/6)
354 // First radius: (6 * EPS)^(.5)
355 // Second radius: (120 * EPS)^(.25)
356 OMEGA_H_INLINE Real sin_x_over_x(Real x) {
357  auto const y = std::abs(x);
358  auto const e2 = std::sqrt(DBL_EPSILON);
359  auto const e4 = std::sqrt(e2);
360  if (y > e4) {
361  return std::sin(y) / y;
362  } else if (y > e2) {
363  return 1.0 - y * y / 6.0;
364  } else {
365  return 1.0;
366  }
367 }
368 
369 } // namespace Omega_h
370 
371 #endif
Definition: amr_mpi_test.cpp:6
Definition: Omega_h_scalar.hpp:30
Definition: Omega_h_scalar.hpp:207
Definition: Omega_h_scalar.hpp:17
Definition: Omega_h_scalar.hpp:134
Definition: Omega_h_scalar.hpp:168
Definition: Omega_h_scalar.hpp:327
Definition: Omega_h_scalar.hpp:297
Definition: Omega_h_scalar.hpp:307
Definition: Omega_h_scalar.hpp:317
Definition: Omega_h_scalar.hpp:334
Definition: Omega_h_scalar.hpp:287