1-
21#pragma once
32
43#include " macros.hpp"
54#include < cmath>
65
7-
6+ /* *
7+ * @file logMath.hpp
8+ * @brief Base-selectable logarithm and exponential helpers with optional fast CUDA intrinsics.
9+ *
10+ * @details
11+ * This header provides a small, header-only utility for computing `log` and `exp` in either:
12+ * - natural base (e), or
13+ * - base-10 (ten),
14+ * and optionally using CUDA "fast math" intrinsics on device code.
15+ *
16+ * Key points:
17+ * - For `float` on CUDA device (`__CUDA_ARCH__`), `MathMode::fast` selects intrinsics such as
18+ * `__logf`, `__log10f`, `__expf`, `__exp10f` when available.
19+ * - For host code (and for non-fast mode), it falls back to standard `<cmath>` functions
20+ * like `::log`, `::log10`, `::exp`, `::expf`, `::logf`, `::log10f`.
21+ * - Some libcs (glibc) provide `exp10/exp10f` as extensions. When unavailable, base-10
22+ * exponentiation is implemented via `exp(x * ln(10))`.
23+ *
24+ * @note
25+ * The functions here assume their usual mathematical domains:
26+ * - `log(x)` requires `x > 0`.
27+ * - `exp(x)` is defined for all real `x` but may overflow for large `x`.
28+ *
29+ * @warning
30+ * When `MathMode::fast` is used on CUDA device, results may differ slightly from the
31+ * accurate host/standard-library implementations due to reduced precision/approximations.
32+ */
833
934namespace hpcReact
1035{
1136
37+ /* *
38+ * @def HPCREACT_HAS_EXP10
39+ * @brief Indicates whether `exp10/exp10f` are available as libc extensions.
40+ *
41+ * @details
42+ * glibc commonly provides `exp10` and `exp10f` as non-standard extensions. This macro is used to
43+ * select a direct call to those functions on host when available; otherwise a mathematically
44+ * equivalent fallback is used:
45+ * \f[
46+ * 10^x = e^{x \ln(10)}
47+ * \f]
48+ */
1249#if defined(__GLIBC__) // glibc provides exp10/exp10f as an extension
1350 #define HPCREACT_HAS_EXP10 1
1451#else
1552 #define HPCREACT_HAS_EXP10 0
1653#endif
1754
18- enum class LogBase { e, ten };
19- enum class MathMode { accurate, fast };
55+ /* *
56+ * @brief Enumerates the logarithm base used by the helper.
57+ */
58+ enum class LogBase
59+ {
60+ e, /* *< Natural logarithm base (ln). */
61+ ten /* *< Base-10 logarithm. */
62+ };
63+
64+ /* *
65+ * @brief Enumerates the math evaluation mode.
66+ *
67+ * @details
68+ * `fast` is only used for `float` on CUDA device code. On host (or for `double`), the
69+ * standard library functions are used.
70+ */
71+ enum class MathMode
72+ {
73+ accurate, /* *< Prefer standard-library implementations. */
74+ fast /* *< Prefer CUDA fast intrinsics for `float` on device when available. */
75+ };
2076
77+ /* *
78+ * @brief Base-selectable logarithm and exponential functions.
79+ *
80+ * @tparam Base Selects the logarithm/exp base:
81+ * - `LogBase::e` for natural base
82+ * - `LogBase::ten` for base-10
83+ * @tparam Mode Selects evaluation mode. See @ref MathMode.
84+ *
85+ * @details
86+ * Provides:
87+ * - `log(x)` returning \f$\ln(x)\f$ or \f$\log_{10}(x)\f$ depending on `Base`
88+ * - `exp(x)` returning \f$e^x\f$ or \f$10^x\f$ depending on `Base`
89+ *
90+ * The overload set covers `float` and `double`.
91+ */
2192template < LogBase Base, MathMode Mode = MathMode::accurate >
2293struct LogExp
2394{
24-
25- template <class T >
26- HPCREACT_HOST_DEVICE static constexpr
27- T ln10 ()
95+ /* *
96+ * @brief Compile-time constant for \f$\ln(10)\f$.
97+ *
98+ * @tparam T Floating-point type (typically `float` or `double`).
99+ * @return \f$\ln(10)\f$ as type `T`.
100+ *
101+ * @details
102+ * The literal is provided with long-double precision and cast to `T`.
103+ */
104+ template < class T >
105+ HPCREACT_HOST_DEVICE
106+ static constexpr T ln10 ()
28107 {
29108 return T (2 .3025850929940456840179914546843642L );
30109 }
31110
111+ /* *
112+ * @brief Conversion factor for derivatives with respect to `log(x)` vs `ln(x)`.
113+ *
114+ * @tparam T Floating-point type (typically `float` or `double`).
115+ * @return A constant factor depending on @p Base.
116+ *
117+ * @details
118+ * This returns the scalar \f$c\f$ such that:
119+ * \f[
120+ * \frac{d}{d(\log_b x)} = c \, \frac{d}{d(\ln x)}
121+ * \f]
122+ * where:
123+ * - if `Base == e`, then \f$c = 1\f$
124+ * - if `Base == ten`, then \f$c = \ln(10)\f$
125+ *
126+ * Equivalently, since \f$\log_{10}(x) = \ln(x) / \ln(10)\f$:
127+ * \f[
128+ * \frac{d}{d(\log_{10} x)} = \ln(10) \, \frac{d}{d(\ln x)}
129+ * \f]
130+ */
32131 template < typename T >
33132 HPCREACT_HOST_DEVICE
34- static constexpr inline
35- T dWrtLogConst ()
133+ static constexpr inline T dWrtLogConst ()
36134 {
37135 if constexpr ( Base == LogBase::e ) { return T (1.0 ); }
38136 else { return T (ln10<T>()); }
39137 }
40138
139+ // ***** log function *********************************************************************************************
41140
42-
43- // ***** log function *********************************************************************************************
44- HPCREACT_HOST_DEVICE
45- static inline
46- double log ( double const x )
141+ /* *
142+ * @brief Logarithm in the selected base for `double`.
143+ *
144+ * @param x Input value (must be > 0).
145+ * @return `ln(x)` if `Base == LogBase::e`, otherwise `log10(x)`.
146+ */
147+ HPCREACT_HOST_DEVICE
148+ static constexpr inline double log ( double const x )
47149 {
48- if constexpr ( Base == LogBase::e ) { return ::log (x ); }
49- else { return ::log10 (x ); }
150+ if constexpr ( Base == LogBase::e ) { return ::log ( x ); }
151+ else { return ::log10 ( x ); }
50152 }
51-
52- HPCREACT_HOST_DEVICE
53- static inline
54- float log ( float const x )
153+
154+ /* *
155+ * @brief Logarithm in the selected base for `float`.
156+ *
157+ * @param x Input value (must be > 0).
158+ * @return `ln(x)` if `Base == LogBase::e`, otherwise `log10(x)`.
159+ *
160+ * @details
161+ * On CUDA device code (`__CUDA_ARCH__`) and when `Mode == MathMode::fast`,
162+ * uses CUDA intrinsics:
163+ * - `__logf` / `__log10f`
164+ * Otherwise falls back to `<cmath>`:
165+ * - `::logf` / `::log10f`
166+ */
167+ HPCREACT_HOST_DEVICE
168+ static inline float log ( float const x )
55169 {
56170#if defined(__CUDA_ARCH__)
57171 if constexpr ( Mode == MathMode::fast )
58172 {
59- if constexpr ( Base == LogBase::e) { return __logf (x ); }
60- else { return __log10f (x ); }
173+ if constexpr ( Base == LogBase::e ) { return __logf ( x ); }
174+ else { return __log10f ( x ); }
61175 }
62176#endif
63- if constexpr ( Base == LogBase::e ) { return ::logf (x ); }
64- else { return ::log10f (x ); }
177+ if constexpr ( Base == LogBase::e ) { return ::logf ( x ); }
178+ else { return ::log10f ( x ); }
65179 }
66180
67- // ***** exp function *********************************************************************************************
68- HPCREACT_HOST_DEVICE
69- static inline
70- double exp ( double const x )
181+ // ***** exp function *********************************************************************************************
182+
183+ /* *
184+ * @brief Exponential in the selected base for `double`.
185+ *
186+ * @param x Exponent.
187+ * @return `exp(x)` if `Base == LogBase::e`, otherwise `10^x`.
188+ *
189+ * @details
190+ * For base-10:
191+ * - If `HPCREACT_HAS_EXP10` is true, uses `::exp10(x)` (glibc extension).
192+ * - Otherwise uses `::exp(x * ln(10))`.
193+ */
194+ HPCREACT_HOST_DEVICE
195+ static inline double exp ( double const x )
71196 {
72- if constexpr ( Base == LogBase::e)
73- {
74- return ::exp (x);
197+ if constexpr ( Base == LogBase::e )
198+ {
199+ return ::exp ( x );
75200 }
76201 else
77- {
78- #if HPCREACT_HAS_EXP10
79- return ::exp10 (x );
80- #else
81- return ::exp ( x * ln10<double >() ); ;
82- #endif
202+ {
203+ #if HPCREACT_HAS_EXP10
204+ return ::exp10 ( x );
205+ #else
206+ return ::exp ( x * ln10<double >() );
207+ #endif
83208 }
84209 }
85210
86-
87- HPCREACT_HOST_DEVICE
88- static inline
89- float exp ( float const x )
211+ /* *
212+ * @brief Exponential in the selected base for `float`.
213+ *
214+ * @param x Exponent.
215+ * @return `exp(x)` if `Base == LogBase::e`, otherwise `10^x`.
216+ *
217+ * @details
218+ * On CUDA device code (`__CUDA_ARCH__`) and when `Mode == MathMode::fast`,
219+ * uses CUDA intrinsics:
220+ * - `__expf` / `__exp10f`
221+ *
222+ * Otherwise:
223+ * - For base-e uses `::expf(x)`
224+ * - For base-10 uses `::exp10f(x)` if available (glibc extension), else `::expf(x * ln(10))`.
225+ */
226+ HPCREACT_HOST_DEVICE
227+ static inline float exp ( float const x )
90228 {
91229#if defined(__CUDA_ARCH__)
92230 if constexpr ( Mode == MathMode::fast )
93231 {
94- if constexpr ( Base == LogBase::e ) { return __expf (x ); }
95- else { return __exp10f (x ); }
232+ if constexpr ( Base == LogBase::e ) { return __expf ( x ); }
233+ else { return __exp10f ( x ); }
96234 }
97235#endif
98- if constexpr ( Base == LogBase::e)
99- {
100- return ::expf (x);
236+ if constexpr ( Base == LogBase::e )
237+ {
238+ return ::expf ( x );
101239 }
102240 else
103- {
241+ {
104242#if HPCREACT_HAS_EXP10
105- return ::exp10f (x );
243+ return ::exp10f ( x );
106244#else
107- return ::expf ( x * ln10<float >() );
245+ return ::expf ( x * ln10<float >() );
108246#endif
109247 }
110248 }
111249}; // struct LogExp
112250
113-
251+ /* *
252+ * @def HPC_REACT_LOG_TYPE
253+ * @brief Compile-time selection of the default `logmath` alias.
254+ *
255+ * @details
256+ * Values:
257+ * - `0`: natural log/exp (base-e), fast mode
258+ * - `1`: base-10 log/exp, fast mode (default)
259+ *
260+ * This macro is intended to allow build-time selection of the logarithm base used in code
261+ * that relies on the `hpcReact::logmath` alias.
262+ */
114263#if !defined(HPC_REACT_LOG_TYPE)
115264#define HPC_REACT_LOG_TYPE 1
116265#endif
117266
267+ /* *
268+ * @brief Default log/exp helper type selected by `HPC_REACT_LOG_TYPE`.
269+ *
270+ * @details
271+ * - `HPC_REACT_LOG_TYPE == 0` selects `LogBase::e`
272+ * - `HPC_REACT_LOG_TYPE == 1` selects `LogBase::ten`
273+ *
274+ * Both selections currently use `MathMode::fast`. Note that `MathMode::fast` only changes
275+ * behavior for `float` on CUDA device code.
276+ */
118277#if HPC_REACT_LOG_TYPE == 0
119278 using logmath = LogExp< LogBase::e, MathMode::fast >;
120279#elif HPC_REACT_LOG_TYPE == 1
121280 using logmath = LogExp< LogBase::ten, MathMode::fast >;
122281#endif
123282
124- } // namespace hpcReact
283+ } // namespace hpcReact
0 commit comments