Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_Algorithm.H
Go to the documentation of this file.
1#ifndef AMREX_ALGORITHM_H_
2#define AMREX_ALGORITHM_H_
3#include <AMReX_Config.H>
4
10#include <AMReX_GpuQualifiers.H>
11#include <AMReX_Extension.H>
12#include <AMReX_Dim3.H>
13#include <AMReX_BLassert.H>
14#include <AMReX_Math.H>
15
16#include <algorithm>
17#include <concepts>
18#include <limits>
19#include <type_traits>
20#include <cstdint>
21#include <climits>
22
23namespace amrex
24{
29 template <class T>
31 AMREX_FORCE_INLINE constexpr const T& min (const T& a, const T& b) noexcept
32 {
33 return std::min(a,b);
34 }
35
40 template <class T, class ... Ts>
42 AMREX_FORCE_INLINE constexpr const T& min (const T& a, const T& b, const Ts& ... c) noexcept
43 {
44 return min(min(a,b),c...);
45 }
46
51 template <class T>
53 AMREX_FORCE_INLINE constexpr const T& max (const T& a, const T& b) noexcept
54 {
55 return std::max(a,b);
56 }
57
62 template <class T, class ... Ts>
64 AMREX_FORCE_INLINE constexpr const T& max (const T& a, const T& b, const Ts& ... c) noexcept
65 {
66 return max(max(a,b),c...);
67 }
68
71 template <class T>
73 T elemwiseMin (T const& a, T const& b) noexcept {
74 return T{amrex::min(a.x,b.x),amrex::min(a.y,b.y),amrex::min(a.z,b.z)};
75 }
76
79 template <class T, class ... Ts>
81 T elemwiseMin (const T& a, const T& b, const Ts& ... c) noexcept
82 {
83 return elemwiseMin(elemwiseMin(a,b),c...);
84 }
85
88 template <class T>
90 T elemwiseMax (T const& a, T const& b) noexcept {
91 return T{amrex::max(a.x,b.x),amrex::max(a.y,b.y),amrex::max(a.z,b.z)};
92 }
93
96 template <class T, class ... Ts>
98 T elemwiseMax (const T& a, const T& b, const Ts& ... c) noexcept
99 {
100 return elemwiseMax(elemwiseMax(a,b),c...);
101 }
102
106 template<typename T>
108 void Swap (T& t1, T& t2) noexcept
109 {
110 T temp = std::move(t1);
111 t1 = std::move(t2);
112 t2 = std::move(temp);
113 }
114
120 template <typename T>
122 constexpr const T& Clamp (const T& v, const T& lo, const T& hi)
123 {
124 if (v < lo) {
125 return lo; // NOLINT(bugprone-return-const-ref-from-parameter)
126 } else if (hi < v) {
127 return hi; // NOLINT(bugprone-return-const-ref-from-parameter)
128 } else {
129 return v; // NOLINT(bugprone-return-const-ref-from-parameter)
130 }
131 }
132
136 template <std::floating_point T>
138 bool
139 almostEqual (T x, T y, int ulp = 2)
140 {
141 // Reference: https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
142 // The machine epsilon has to be scaled to the magnitude of the values used
143 // and multiplied by the desired precision in ULPs (units in the last place)
144 return std::abs(x-y) <= std::numeric_limits<T>::epsilon() * std::abs(x+y) * ulp
145 // unless the result is subnormal
146 || std::abs(x-y) < std::numeric_limits<T>::min();
147 }
148
167 template <std::floating_point T, class F>
169 T bisect (T lo, T hi, F f, T tol=1e-12, int max_iter=100)
170 {
172 "Error - calling bisect but lo and hi don't describe a reasonable interval.");
173
174 T flo = f(lo);
175 T fhi = f(hi);
176
177 if (flo == T(0)) { return lo; }
178 if (fhi == T(0)) { return hi; }
179
180 AMREX_ASSERT_WITH_MESSAGE(flo * fhi <= T(0),
181 "Error - calling bisect but lo and hi don't bracket a root.");
182
183 T mi = (lo + hi) / T(2);
184 T fmi = T(0);
185 int n = 1;
186 while (n <= max_iter)
187 {
188 if (hi - lo < tol || almostEqual(lo,hi)) { break; }
189 mi = (lo + hi) / T(2);
190 fmi = f(mi);
191 if (fmi == T(0)) { break; }
192 fmi*flo < T(0) ? hi = mi : lo = mi;
193 flo = f(lo);
194 fhi = f(hi);
195 ++n;
196 }
197
198 AMREX_ASSERT_WITH_MESSAGE(n <= max_iter,
199 "Error - maximum number of iterations reached in bisect.");
200
201 return mi;
202 }
203
226 template <typename T, std::integral I>
228 I bisect (T const* d, I lo, I hi, T const& v)
229 {
230 while (hi - lo > 1) {
231 I mid = lo + (hi - lo) / 2;
232 if (v < d[mid]) {
233 hi = mid;
234 } else {
235 lo = mid;
236 }
237 };
238 return lo;
239 }
240
256 template<typename ItType, typename ValType>
258 ItType upper_bound (ItType first, ItType last, const ValType& val)
259 {
261 std::ptrdiff_t count = last-first;
262 while(count>0){
263 auto it = first;
264 const auto step = count/2;
265 it += step;
266 if (!(val < *it)){
267 first = ++it;
268 count -= step + 1;
269 }
270 else{
271 count = step;
272 }
273 }
274 return first;
275 ))
277 return std::upper_bound(first, last, val);
278 ))
279 }
280
296 template<typename ItType, typename ValType>
298 ItType lower_bound (ItType first, ItType last, const ValType& val)
299 {
301 std::ptrdiff_t count = last-first;
302 while(count>0)
303 {
304 auto it = first;
305 const auto step = count/2;
306 it += step;
307 if (*it < val){
308 first = ++it;
309 count -= step + 1;
310 }
311 else{
312 count = step;
313 }
314 }
315
316 return first;
317 ))
319 return std::lower_bound(first, last, val);
320 ))
321 }
322
341 template<typename ItType, std::floating_point ValType>
342 requires (std::floating_point<typename std::iterator_traits<ItType>::value_type>)
344 void linspace (ItType first, const ItType& last, const ValType& start, const ValType& stop)
345 {
346 const std::ptrdiff_t count = last-first;
347 if (count >= 2){
348 const auto delta = (stop - start)/(count - 1);
349 for (std::ptrdiff_t i = 0; i < count-1; ++i){
350 *(first++) = start + i*delta;
351 }
352 *first = stop;
353 }
354 }
355
375 template<typename ItType, std::floating_point ValType>
376 requires (std::floating_point<typename std::iterator_traits<ItType>::value_type>)
378 void logspace (ItType first, const ItType& last,
379 const ValType& start, const ValType& stop, const ValType& base)
380 {
381 const std::ptrdiff_t count = last-first;
382 if (count >= 2){
383 const auto delta = (stop - start)/(count - 1);
384 for (std::ptrdiff_t i = 0; i < count-1; ++i){
385 *(first++) = std::pow(base, start + i*delta);
386 }
387 *first = std::pow(base, stop);
388 }
389 }
390}
391
392#endif
Assertion macros used across AMReX for runtime consistency checks.
#define AMREX_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:37
Simple structs for 3-component integer and real-valued tuples.
Compiler- and backend-specific extension macros (e.g., restrict, SIMD, inline).
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:124
#define AMREX_IF_ON_DEVICE(CODE)
Definition AMReX_GpuQualifiers.H:56
#define AMREX_IF_ON_HOST(CODE)
Definition AMReX_GpuQualifiers.H:58
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
__host__ __device__ ItType upper_bound(ItType first, ItType last, const ValType &val)
Return an iterator to the first element greater than a given value.
Definition AMReX_Algorithm.H:258
__host__ __device__ void logspace(ItType first, const ItType &last, const ValType &start, const ValType &stop, const ValType &base)
Fill a range with logarithmically spaced values over a closed interval.
Definition AMReX_Algorithm.H:378
__host__ __device__ void Swap(T &t1, T &t2) noexcept
Definition AMReX_Algorithm.H:108
__host__ __device__ T bisect(T lo, T hi, F f, T tol=1e-12, int max_iter=100)
Find a root of a scalar function on a bracketing interval using bisection.
Definition AMReX_Algorithm.H:169
__host__ __device__ constexpr T elemwiseMax(T const &a, T const &b) noexcept
Definition AMReX_Algorithm.H:90
__host__ __device__ constexpr const T & Clamp(const T &v, const T &lo, const T &hi)
Definition AMReX_Algorithm.H:122
__host__ __device__ constexpr const T & min(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:31
__host__ __device__ ItType lower_bound(ItType first, ItType last, const ValType &val)
Return an iterator to the first element not less than a given value.
Definition AMReX_Algorithm.H:298
__host__ __device__ void linspace(ItType first, const ItType &last, const ValType &start, const ValType &stop)
Fill a range with linearly spaced values over a closed interval.
Definition AMReX_Algorithm.H:344
__host__ __device__ constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:53
__host__ __device__ bool almostEqual(T x, T y, int ulp=2)
Definition AMReX_Algorithm.H:139
__host__ __device__ constexpr T elemwiseMin(T const &a, T const &b) noexcept
Definition AMReX_Algorithm.H:73
Definition AMReX_Amr.cpp:50