Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_Math.H
Go to the documentation of this file.
1#ifndef AMREX_MATH_H_
2#define AMREX_MATH_H_
3#include <AMReX_Config.H>
4
6#include <AMReX_Extension.H>
7#include <AMReX_INT.H>
8#include <AMReX_SIMD.H>
9#include <AMReX_REAL.H>
10#include <bit>
11#include <concepts>
12#include <cmath>
13#include <cstdint>
14#include <cstdlib>
15#include <limits>
16#include <numbers>
17#include <type_traits>
18#include <utility>
19
20#ifdef AMREX_USE_SYCL
21# include <sycl/sycl.hpp>
22#endif
23
24namespace amrex { // NOLINT(modernize-concat-nested-namespaces)
26inline namespace disabled {
27 // If it is inside namespace amrex, or amrex namespace is imported with using namespace amrex or
28 // amrex::disabled, unqualified abs functions are disabled with a compile time error such as,
29 // call of overload abs(int&) is ambiguous, or a link time error such as, undefined reference to
30 // `amrex::disabled::abs(double)'. To fix it, one can use `std::abs` or `amrex::Math::abs`.
31 // We have amrex::Math::abs, because std::abs did not work with HIP and SYCL in the past.
32 AMREX_GPU_HOST_DEVICE double abs (double);
33 AMREX_GPU_HOST_DEVICE float abs (float);
34 AMREX_GPU_HOST_DEVICE long double abs (long double);
35 AMREX_GPU_HOST_DEVICE int abs (int);
36 AMREX_GPU_HOST_DEVICE long abs (long);
37 AMREX_GPU_HOST_DEVICE long long abs (long long);
38}
40}
41
42namespace amrex::Math {
43
44// Since Intel's SYCL compiler now supports the following std functions on device,
45// one no longer needs to use amrex::Math::abs, etc. They are kept here for
46// backward compatibility.
47
48using std::abs;
49using std::ceil;
50using std::copysign;
51using std::floor;
52using std::round;
53
54// Under fast math (e.g., -ffast-math, -ffinite-math-only, /fp:fast, and Intel's
55// SYCL compiler by default), std::isnan etc. may always evaluate to false. The
56// functions below work in all modes. In fast-math modes, they test the bit
57// pattern, hidden from the optimizer so that it cannot fold the test away.
58
60// Clang: no macro tells if -fno-honor-nans or -fno-honor-infinities is on.
61// _WIN32: std::isnan is host only for nvcc with MSVC.
62#if (defined(__FINITE_MATH_ONLY__) && (__FINITE_MATH_ONLY__ == 1)) \
63 || defined(__FAST_MATH__) || defined(_M_FP_FAST) || defined(_WIN32) \
64 || defined(__clang__)
65# define AMREX_MATH_ISNAN_BITS 1
66#endif
67
68namespace detail {
72 template <typename U>
74 U fp_opaque (U v) noexcept
75 {
76#if defined(AMREX_MATH_ISNAN_BITS) && (defined(__GNUC__) || defined(__clang__))
77# if defined(__HIP_DEVICE_COMPILE__)
78 __asm__("" : "+v"(v));
79# else
80 AMREX_IF_ON_HOST((__asm__("" : "+r"(v));))
81# endif
82#endif
83 return v;
84 }
85
86 template <typename T>
87 using fp_uint_t = std::conditional_t<sizeof(T) == 8, std::uint64_t, std::uint32_t>;
88
90 template <typename T>
92 constexpr fp_uint_t<T> fp_exp_mask () noexcept
93 {
94 return (sizeof(T) == 8) ? fp_uint_t<T>(0x7ff0'0000'0000'0000ULL)
95 : fp_uint_t<T>(0x7f80'0000U);
96 }
97
99 template <bool opaque = true, typename T>
101 fp_uint_t<T> fp_abs_bits (T x) noexcept
102 {
103 using U = fp_uint_t<T>;
104 auto bits = std::bit_cast<U>(x);
105 if constexpr (opaque) { bits = fp_opaque(bits); }
106 return bits & (~U(0) >> 1);
107 }
108
109 template <typename T>
110 concept FloatOrDouble = std::same_as<T,float> || std::same_as<T,double>;
111}
113
115template <typename T>
117bool isnan (T x) noexcept
118{
119#if defined(AMREX_USE_SYCL)
120 return sycl::isnan(x);
121#else
122#if defined(AMREX_MATH_ISNAN_BITS)
123 if constexpr (detail::FloatOrDouble<T>) {
124 return detail::fp_abs_bits(x) > detail::fp_exp_mask<T>();
125 } else
126#endif
127 {
128 return std::isnan(x);
129 }
130#endif
131}
132
134template <typename T>
136bool isinf (T x) noexcept
137{
138#if defined(AMREX_USE_SYCL)
139 return sycl::isinf(x);
140#else
141#if defined(AMREX_MATH_ISNAN_BITS)
142 if constexpr (detail::FloatOrDouble<T>) {
143 return detail::fp_abs_bits(x) == detail::fp_exp_mask<T>();
144 } else
145#endif
146 {
147 return std::isinf(x);
148 }
149#endif
150}
151
153template <typename T>
155bool isfinite (T x) noexcept
156{
157#if defined(AMREX_USE_SYCL)
158 return sycl::isfinite(x);
159#else
160#if defined(AMREX_MATH_ISNAN_BITS)
161 if constexpr (detail::FloatOrDouble<T>) {
162 return detail::fp_abs_bits(x) < detail::fp_exp_mask<T>();
163 } else
164#endif
165 {
166 return std::isfinite(x);
167 }
168#endif
169}
170
172namespace detail {
176 template <typename T>
177 struct AbsNanToInf
178 {
179 T inf = make_inf();
180
182 T operator() (T x) const noexcept
183 {
184 if constexpr (FloatOrDouble<T>) {
185 auto const a = fp_abs_bits<false>(x);
186 return (a < fp_exp_mask<T>()) ? std::bit_cast<T>(a) : inf;
187 } else if constexpr (std::is_floating_point_v<T>) {
188 return amrex::Math::isnan(x) ? inf : std::abs(x);
189 } else {
190 return std::abs(x);
191 }
192 }
193
194 private:
196 static T make_inf () noexcept
197 {
198 if constexpr (FloatOrDouble<T>) {
199 return std::bit_cast<T>(fp_opaque(fp_exp_mask<T>()));
200 } else if constexpr (std::is_floating_point_v<T>) {
201 return std::numeric_limits<T>::infinity();
202 } else {
203 return T(0);
204 }
205 }
206 };
207}
209
210template <std::floating_point T>
211constexpr T pi ()
212{
213 return std::numbers::pi_v<T>;
214}
215
218double cospi (double x)
219{
220#if defined(AMREX_USE_SYCL)
221 return sycl::cospi(x);
222#else
223 AMREX_IF_ON_DEVICE(( return ::cospi(x); ))
224 AMREX_IF_ON_HOST(( return std::cos(pi<double>()*x); ))
225#endif
226}
227
230float cospi (float x)
231{
232#if defined(AMREX_USE_SYCL)
233 return sycl::cospi(x);
234#else
235 AMREX_IF_ON_DEVICE(( return ::cospif(x); ))
236 AMREX_IF_ON_HOST(( return std::cos(pi<float>()*x); ))
237#endif
238}
239
242double sinpi (double x)
243{
244#if defined(AMREX_USE_SYCL)
245 return sycl::sinpi(x);
246#else
247 AMREX_IF_ON_DEVICE(( return ::sinpi(x); ))
248 AMREX_IF_ON_HOST(( return std::sin(pi<double>()*x); ))
249#endif
250}
251
254float sinpi (float x)
255{
256#if defined(AMREX_USE_SYCL)
257 return sycl::sinpi(x);
258#else
259 AMREX_IF_ON_DEVICE(( return ::sinpif(x); ))
260 AMREX_IF_ON_HOST(( return std::sin(pi<float>()*x); ))
261#endif
262}
263
265namespace detail {
266 AMREX_FORCE_INLINE void sincos (double x, double* sinx, double* cosx) {
267#if defined(_GNU_SOURCE) && !defined(__APPLE__)
268 ::sincos(x, sinx, cosx);
269#else
270 *sinx = std::sin(x);
271 *cosx = std::cos(x);
272#endif
273 }
274
275 AMREX_FORCE_INLINE void sincosf (float x, float* sinx, float* cosx) {
276#if defined(_GNU_SOURCE) && !defined(__APPLE__)
277 ::sincosf(x, sinx, cosx);
278#else
279 *sinx = std::sin(x);
280 *cosx = std::cos(x);
281#endif
282 }
283}
285
286#ifdef AMREX_USE_SIMD
288template<typename T_Real>
289requires (amrex::simd::stdx::is_simd_v<T_Real>)
291std::pair<T_Real,T_Real> sincos (T_Real x)
292{
293 using namespace amrex::simd::stdx;
294 std::pair<T_Real,T_Real> r;
295 r.first = sin(x);
296 r.second = cos(x);
297 return r;
298}
299#endif
300
303std::pair<double,double> sincos (double x)
304{
305 std::pair<double,double> r;
306#if defined(AMREX_USE_SYCL)
307 r.first = sycl::sincos(x, sycl::private_ptr<double>(&r.second));
308#else
309 AMREX_IF_ON_DEVICE(( ::sincos(x, &r.first, &r.second); ))
310 AMREX_IF_ON_HOST(( detail::sincos(x, &r.first, &r.second); ))
311#endif
312 return r;
313}
314
317std::pair<float,float> sincos (float x)
318{
319 std::pair<float,float> r;
320#if defined(AMREX_USE_SYCL)
321 r.first = sycl::sincos(x, sycl::private_ptr<float>(&r.second));
322#else
323 AMREX_IF_ON_DEVICE(( ::sincosf(x, &r.first, &r.second); ))
324 AMREX_IF_ON_HOST(( detail::sincosf(x, &r.first, &r.second); ))
325#endif
326 return r;
327}
328
329#ifdef AMREX_USE_SIMD
331template<typename T_Real>
332requires (amrex::simd::stdx::is_simd_v<T_Real>)
334std::pair<T_Real,T_Real> sincospi (T_Real x)
335{
336 using namespace amrex::simd::stdx;
337 T_Real const px = pi<typename T_Real::value_type>() * x;
338 std::pair<T_Real,T_Real> r;
339 r.first = sin(px);
340 r.second = cos(px);
341 return r;
342}
343#endif
344
347std::pair<double,double> sincospi (double x)
348{
349 std::pair<double,double> r;
350#if defined(AMREX_USE_SYCL)
351 r = sincos(pi<double>()*x);
352#else
353 AMREX_IF_ON_DEVICE(( ::sincospi(x, &r.first, &r.second); ))
354 AMREX_IF_ON_HOST(( r = sincos(pi<double>()*x); ))
355#endif
356 return r;
357}
358
361std::pair<float,float> sincospi (float x)
362{
363 std::pair<float,float> r;
364#if defined(AMREX_USE_SYCL)
365 r = sincos(pi<float>()*x);
366#else
367 AMREX_IF_ON_DEVICE(( ::sincospif(x, &r.first, &r.second); ))
368 AMREX_IF_ON_HOST(( r = sincos(pi<float>()*x); ))
369#endif
370 return r;
371}
372
374template <int Power, typename T>
375requires (!std::integral<T> || Power >= 0)
377constexpr T powi (T x) noexcept
378{
379 if constexpr (Power < 0) {
380 return T(1)/powi<-Power>(x);
381 } else if constexpr (Power == 0) {
382 //note: 0^0 is implementation-defined, but most compilers return 1
383 return T(1);
384 } else if constexpr (Power == 1) {
385 return x;
386 } else if constexpr (Power == 2) {
387 return x*x;
388 } else if constexpr (Power%2 == 0) {
389 return powi<2>(powi<Power/2>(x));
390 } else {
391 return x*powi<Power-1>(x);
392 }
393}
394
395} // namespace amrex::Math
396
397#if defined(AMREX_USE_CUDA)
398// Forward-declare libdevice integer-exponent intrinsics. They are part of
399// NVIDIA's libdevice and linked at PTX time but are not declared in standard
400// CUDA cmath headers outside __CUDACC_RTC__ / _LIBCPP_VERSION blocks.
401// See https://docs.nvidia.com/cuda/libdevice-users-guide/__nv_powif.html
402extern "C" __device__ float __nv_powif (float, int);
403extern "C" __device__ double __nv_powi (double, int);
404#endif
405
406namespace amrex::Math {
407
418float powi (float x, int n) noexcept
419{
420#if defined(AMREX_USE_SYCL)
421 return sycl::pown(x, n);
422#elif defined(AMREX_USE_HIP)
423 AMREX_IF_ON_DEVICE(( return ::powif(x, n); ))
424 AMREX_IF_ON_HOST(( return std::pow(x, static_cast<float>(n)); ))
425#elif defined(AMREX_USE_CUDA)
426 AMREX_IF_ON_DEVICE(( return __nv_powif(x, n); ))
427 AMREX_IF_ON_HOST(( return std::pow(x, static_cast<float>(n)); ))
428#else
429 return std::pow(x, static_cast<float>(n));
430#endif
431}
432
434double powi (double x, int n) noexcept
435{
436#if defined(AMREX_USE_SYCL)
437 return sycl::pown(x, n);
438#elif defined(AMREX_USE_HIP)
439 AMREX_IF_ON_DEVICE(( return ::powi(x, n); ))
440 AMREX_IF_ON_HOST(( return std::pow(x, n); ))
441#elif defined(AMREX_USE_CUDA)
442 AMREX_IF_ON_DEVICE(( return __nv_powi(x, n); ))
443 AMREX_IF_ON_HOST(( return std::pow(x, n); ))
444#else
445 return std::pow(x, n);
446#endif
447}
448
449#if defined(AMREX_INT128_SUPPORTED)
451std::uint64_t umulhi (std::uint64_t a, std::uint64_t b)
452{
453#if defined(AMREX_USE_SYCL)
454 return sycl::mul_hi(a,b);
455#else
456 AMREX_IF_ON_DEVICE(( return __umul64hi(a, b); ))
458 auto tmp = amrex::UInt128_t(a) * amrex::UInt128_t(b);
459 return std::uint64_t(tmp >> 64);
460 ))
461#endif
462}
463#endif
464
465template <typename T>
468{
469 if (std::abs(k) == T(1)) {
470 return std::numeric_limits<T>::infinity();
471 }
472 // Computing K based on DLMF
473 // https://dlmf.nist.gov/19.8
474 T tol = std::numeric_limits<T>::epsilon();
475
476 T a0 = T(1);
477 T g0 = std::sqrt((T(1)+k)*(T(1)-k));
478 T a = a0;
479 T g = g0;
480
481 // Find Arithmetic Geometric mean
482 while(std::abs(a0 - g0) > tol) {
483 a = T(0.5)*(a0 + g0);
484 g = std::sqrt(a0 * g0);
485
486 a0 = a;
487 g0 = g;
488 }
489
490 return T(0.5)*pi<T>()/a;
491}
492
493template <typename T>
496{
497 if (std::abs(k) == T(1)) {
498 return T(1);
499 }
500 // Computing E based on DLMF
501 // https://dlmf.nist.gov/19.8
502 T Kcomp = amrex::Math::comp_ellint_1<T>(k);
503 T tol = std::numeric_limits<T>::epsilon();
504
505 // Step Zero
506 T a0 = T(1);
507 T g0 = std::sqrt((T(1)+k)*(T(1)-k));
508 T cn = std::sqrt(a0*a0 - g0*g0);
509
510 // Step 1
511 int n = 1;
512 T a = T(0.5) * (a0 + g0);
513 T g = std::sqrt(a0*g0);
514 cn = T(0.25)*cn*cn/a;
515
516 T sum_val = a*a;
517 a0 = a;
518 g0 = g;
519
520 while(std::abs(cn*cn) > tol) {
521 // Compute coefficients for this iteration
522 a = T(0.5) * (a0 + g0);
523 g = std::sqrt(a0*g0);
524 cn = T(0.25)*cn*cn/a;
525
526 n++;
527 sum_val -= amrex::Math::powi(T(2), n-1)*cn*cn;
528
529 // Save a and g for next iteration
530 a0 = a;
531 g0 = g;
532 }
533
534 return Kcomp*sum_val;
535}
536
539double rsqrt (double x)
540{
541 double r;
542#if defined(AMREX_USE_SYCL)
543 AMREX_IF_ON_DEVICE(( r = sycl::rsqrt(x); ))
544#else
545 AMREX_IF_ON_DEVICE(( r = ::rsqrt(x); ))
546#endif
547 AMREX_IF_ON_HOST(( r = 1. / std::sqrt(x); ))
548 return r;
549}
550
553float rsqrt (float x)
554{
555 float r;
556#if defined(AMREX_USE_SYCL)
557 AMREX_IF_ON_DEVICE(( r = sycl::rsqrt(x); ))
558#else
559 AMREX_IF_ON_DEVICE(( r = ::rsqrtf(x); ))
560#endif
561 AMREX_IF_ON_HOST(( r = 1.F / std::sqrt(x); ))
562 return r;
563}
564
567double exp10 (double x)
568{
569 double r;
570#if defined(AMREX_USE_SYCL)
571 AMREX_IF_ON_DEVICE(( r = sycl::exp10(x); ))
572#else
573 AMREX_IF_ON_DEVICE(( r = ::exp10(x); ))
574#endif
575 AMREX_IF_ON_HOST(( r = std::pow(10.0, x); ))
576 return r;
577}
578
581float exp10 (float x)
582{
583 float r;
584#if defined(AMREX_USE_SYCL)
585 AMREX_IF_ON_DEVICE(( r = sycl::exp10(x); ))
586#else
587 AMREX_IF_ON_DEVICE(( r = ::exp10f(x); ))
588#endif
589 AMREX_IF_ON_HOST(( r = std::pow(10.0F, x); ))
590 return r;
591}
592
593/***************************************************************************************************
594 * Copyright (c) 2017 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
595 * SPDX-License-Identifier: BSD-3-Clause
596 *
597 * Redistribution and use in source and binary forms, with or without
598 * modification, are permitted provided that the following conditions are met:
599 *
600 * 1. Redistributions of source code must retain the above copyright notice, this
601 * list of conditions and the following disclaimer.
602 *
603 * 2. Redistributions in binary form must reproduce the above copyright notice,
604 * this list of conditions and the following disclaimer in the documentation
605 * and/or other materials provided with the distribution.
606 *
607 * 3. Neither the name of the copyright holder nor the names of its
608 * contributors may be used to endorse or promote products derived from
609 * this software without specific prior written permission.
610 *
611 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
612 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
613 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
614 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
615 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
616 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
617 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
618 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
619 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
620 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
621 *
622 **************************************************************************************************/
623
625
641{
642 std::uint64_t divisor = 0;
643
644#ifdef AMREX_INT128_SUPPORTED
645 std::uint64_t multiplier = 1U;
646 unsigned int shift_right = 0;
647 unsigned int round_up = 0;
648
649 //
650 // Static methods
651 //
652
654 static std::uint32_t integer_log2 (std::uint64_t x)
655 {
656 std::uint32_t n = 0;
657 while (x >>= 1) {
658 ++n;
659 }
660 return n;
661 }
662
666 FastDivmodU64 (std::uint64_t divisor_)
667 : divisor(divisor_)
668 {
669 if (divisor) {
670 shift_right = integer_log2(divisor);
671
672 if ((divisor & (divisor - 1)) == 0) {
673 multiplier = 0;
674 }
675 else {
676 std::uint64_t power_of_two = (std::uint64_t(1) << shift_right);
677 auto n = amrex::UInt128_t(power_of_two) << 64;
678 std::uint64_t multiplier_lo = n / divisor;
679 n += power_of_two;
680 multiplier = n / divisor;
681 round_up = (multiplier_lo == multiplier ? 1 : 0);
682 }
683 }
684 }
685
686#else
687
688 FastDivmodU64 (std::uint64_t divisor_) : divisor(divisor_) {}
689
690#endif
691
693 FastDivmodU64 () = default;
694
696 [[nodiscard]] AMREX_GPU_HOST_DEVICE
697 std::uint64_t divide (std::uint64_t dividend) const
698 {
699#if defined(AMREX_INT128_SUPPORTED)
700 auto x = dividend;
701 if (multiplier) {
702 x = amrex::Math::umulhi(dividend + round_up, multiplier);
703 }
704 return (x >> shift_right);
705#else
706 return dividend / divisor;
707#endif
708 }
709
711 [[nodiscard]] AMREX_GPU_HOST_DEVICE
712 std::uint64_t modulus (std::uint64_t quotient, std::uint64_t dividend) const
713 {
714 return dividend - quotient * divisor;
715 }
716
718 [[nodiscard]] AMREX_GPU_HOST_DEVICE
719 std::uint64_t divmod (std::uint64_t &remainder, std::uint64_t dividend) const
720 {
721 auto quotient = divide(dividend);
722 remainder = modulus(quotient, dividend);
723 return quotient;
724 }
725
729 void operator() (std::uint64_t &quotient, std::uint64_t &remainder, std::uint64_t dividend) const
730 {
731 quotient = divmod(remainder, dividend);
732 }
733};
734
735}
736
737namespace amrex {
738 using Math::isnan;
739 using Math::isinf;
740 using Math::isfinite;
741}
742
743#endif
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
__device__ double __nv_powi(double, int)
__device__ float __nv_powif(float, int)
Definition AMReX_Math.H:42
constexpr T pi()
Definition AMReX_Math.H:211
constexpr T powi(T x) noexcept
Return pow(x, Power), where Power is an integer known at compile time.
Definition AMReX_Math.H:377
__host__ __device__ bool isinf(T x) noexcept
Return true if x is +/-infinity. Works under fast math.
Definition AMReX_Math.H:136
__host__ __device__ double sinpi(double x)
Return sin(x*pi) given x.
Definition AMReX_Math.H:242
__host__ __device__ std::pair< double, double > sincospi(double x)
Return sin(pi*x) and cos(pi*x) given x.
Definition AMReX_Math.H:347
__host__ __device__ double cospi(double x)
Return cos(x*pi) given x.
Definition AMReX_Math.H:218
__host__ __device__ bool isnan(T x) noexcept
Return true if x is NaN. Works under fast math.
Definition AMReX_Math.H:117
__host__ __device__ double exp10(double x)
Return 10**x.
Definition AMReX_Math.H:567
__host__ __device__ T comp_ellint_1(T k)
Definition AMReX_Math.H:467
__host__ __device__ std::pair< double, double > sincos(double x)
Return sine and cosine of given number.
Definition AMReX_Math.H:303
__host__ __device__ T comp_ellint_2(T k)
Definition AMReX_Math.H:495
__host__ __device__ double rsqrt(double x)
Return inverse square root of x.
Definition AMReX_Math.H:539
__host__ __device__ bool isfinite(T x) noexcept
Return true if x is neither NaN nor infinity. Works under fast math.
Definition AMReX_Math.H:155
Definition AMReX_SIMD.H:25
Definition AMReX_Amr.cpp:50
__host__ __device__ T abs(const GpuComplex< T > &a_z) noexcept
Return the absolute value of a complex number.
Definition AMReX_GpuComplex.H:361
Definition AMReX_Math.H:641
__host__ __device__ std::uint64_t divide(std::uint64_t dividend) const
Returns the quotient of floor(dividend / divisor)
Definition AMReX_Math.H:697
__host__ __device__ std::uint64_t divmod(std::uint64_t &remainder, std::uint64_t dividend) const
Returns the quotient of floor(dividend / divisor) and computes the remainder.
Definition AMReX_Math.H:719
__host__ __device__ void operator()(std::uint64_t &quotient, std::uint64_t &remainder, std::uint64_t dividend) const
Definition AMReX_Math.H:729
__host__ __device__ std::uint64_t modulus(std::uint64_t quotient, std::uint64_t dividend) const
Computes the remainder given a computed quotient and dividend.
Definition AMReX_Math.H:712
std::uint64_t divisor
Definition AMReX_Math.H:642
FastDivmodU64(std::uint64_t divisor_)
Definition AMReX_Math.H:688
FastDivmodU64()=default
Default construct an invalid FastDivmodU64.