6namespace uni20::detail::native_math
11template <NativeReal R,
class Evaluate> R scaled_decimal_exponential(R x, Evaluate evaluate)
13 if (x > R(numeric_limits<R>::max_exponent / 4) || x < R(numeric_limits<R>::min_exponent / 4))
15 R half = evaluate(x / 2);
21template <NativeReal R>
struct portable_exponential_math
25 return scaled_decimal_exponential(x, [](R
value) {
return std::pow(R(10),
value); });
30 if (std::abs(x) <= R(0.5))
return std::expm1(x * log_two<R>);
31 return std::exp2(x) - R(1);
36 if (std::abs(x) <= R(0.5))
return std::expm1(x * std::numbers::ln10_v<R>);
37 return portable_exponential_math::exp10(x) - R(1);
40 template <
bool Binary>
static R log_base_p1(R x)
42 constexpr R inverse_log = Binary ? std::numbers::log2e_v<R> : std::numbers::log10e_v<R>;
43 if (std::abs(x) <= R(0.25) || !std::isfinite(x) || x <= R(-1))
return std::log1p(x) * inverse_log;
49 R low = (R(1) - (
sum - part)) + (x - part);
51 return std::fma(low /
sum, inverse_log, logarithm);
54 static R
log2p1(R x) {
return log_base_p1<true>(x); }
55 static R
log10p1(R x) {
return log_base_p1<false>(x); }
58template <NativeReal R>
struct exponential_math_provider : portable_exponential_math<R>
61#if UNI20_HAS_EXP10_FLOAT || UNI20_HAS_EXP2M1_FLOAT || UNI20_HAS_EXP10M1_FLOAT || UNI20_HAS_LOG2P1_FLOAT || \
62 UNI20_HAS_LOG10P1_FLOAT
63template <>
struct exponential_math_provider<float> : portable_exponential_math<float>
65#if UNI20_HAS_EXP10_FLOAT
66 static float exp10(
float x)
68 return scaled_decimal_exponential(x, [](
float value) { return ::exp10f(
value); });
71#if UNI20_HAS_EXP2M1_FLOAT
72 static float exp2m1(
float x) { return ::exp2m1f(x); }
74#if UNI20_HAS_EXP10M1_FLOAT
75 static float exp10m1(
float x) { return ::exp10m1f(x); }
77#if UNI20_HAS_LOG2P1_FLOAT
78 static float log2p1(
float x) { return ::log2p1f(x); }
80#if UNI20_HAS_LOG10P1_FLOAT
81 static float log10p1(
float x) { return ::log10p1f(x); }
86#if UNI20_HAS_EXP10_DOUBLE || UNI20_HAS_EXP2M1_DOUBLE || UNI20_HAS_EXP10M1_DOUBLE || UNI20_HAS_LOG2P1_DOUBLE || \
87 UNI20_HAS_LOG10P1_DOUBLE
88template <>
struct exponential_math_provider<double> : portable_exponential_math<double>
90#if UNI20_HAS_EXP10_DOUBLE
91 static double exp10(
double x)
93 return scaled_decimal_exponential(x, [](
double value) { return ::exp10(
value); });
96#if UNI20_HAS_EXP2M1_DOUBLE
97 static double exp2m1(
double x) { return ::exp2m1(x); }
99#if UNI20_HAS_EXP10M1_DOUBLE
100 static double exp10m1(
double x) { return ::exp10m1(x); }
102#if UNI20_HAS_LOG2P1_DOUBLE
103 static double log2p1(
double x) { return ::log2p1(x); }
105#if UNI20_HAS_LOG10P1_DOUBLE
106 static double log10p1(
double x) { return ::log10p1(x); }
111#if UNI20_HAS_EXP10_LONG_DOUBLE || UNI20_HAS_EXP2M1_LONG_DOUBLE || UNI20_HAS_EXP10M1_LONG_DOUBLE || \
112 UNI20_HAS_LOG2P1_LONG_DOUBLE || UNI20_HAS_LOG10P1_LONG_DOUBLE
113template <>
struct exponential_math_provider<long double> : portable_exponential_math<long double>
115#if UNI20_HAS_EXP10_LONG_DOUBLE
116 static long double exp10(
long double x)
118 return scaled_decimal_exponential(x, [](
long double value) { return ::exp10l(
value); });
121#if UNI20_HAS_EXP2M1_LONG_DOUBLE
122 static long double exp2m1(
long double x) { return ::exp2m1l(x); }
124#if UNI20_HAS_EXP10M1_LONG_DOUBLE
125 static long double exp10m1(
long double x) { return ::exp10m1l(x); }
127#if UNI20_HAS_LOG2P1_LONG_DOUBLE
128 static long double log2p1(
long double x) { return ::log2p1l(x); }
130#if UNI20_HAS_LOG10P1_LONG_DOUBLE
131 static long double log10p1(
long double x) { return ::log10p1l(x); }
136#if UNI20_HAS_FLOAT128 && (UNI20_HAS_EXP10_FLOAT128 || UNI20_HAS_EXP2M1_FLOAT128 || UNI20_HAS_EXP10M1_FLOAT128 || \
137 UNI20_HAS_LOG2P1_FLOAT128 || UNI20_HAS_LOG10P1_FLOAT128)
138template <>
struct exponential_math_provider<float128> : portable_exponential_math<float128>
140#if UNI20_HAS_EXP10_FLOAT128
141 static float128
exp10(float128 x)
143 return scaled_decimal_exponential(x, [](float128
value) { return ::exp10f128(
value); });
146#if UNI20_HAS_EXP2M1_FLOAT128
147 static float128
exp2m1(float128 x) { return ::exp2m1f128(x); }
149#if UNI20_HAS_EXP10M1_FLOAT128
150 static float128
exp10m1(float128 x) { return ::exp10m1f128(x); }
152#if UNI20_HAS_LOG2P1_FLOAT128
153 static float128
log2p1(float128 x) { return ::log2p1f128(x); }
155#if UNI20_HAS_LOG10P1_FLOAT128
156 static float128
log10p1(float128 x) { return ::log10p1f128(x); }
161template <NativeReal R> R
exp10(R x) {
return exponential_math_provider<R>::exp10(x); }
162template <NativeReal R> R
exp2m1(R x) {
return exponential_math_provider<R>::exp2m1(x); }
163template <NativeReal R> R
exp10m1(R x) {
return exponential_math_provider<R>::exp10m1(x); }
164template <NativeReal R> R
log2p1(R x) {
return exponential_math_provider<R>::log2p1(x); }
165template <NativeReal R> R
log10p1(R x) {
return exponential_math_provider<R>::log10p1(x); }
locale_t value
Definition data_table.cpp:49
constexpr detail::scalar_math::log2p1_fn log2p1
Base-two logarithm of one plus x, without rounding the sum first.
Definition math.hpp:636
constexpr detail::scalar_math::log10p1_fn log10p1
Base-ten logarithm of one plus x, without rounding the sum first.
Definition math.hpp:638
constexpr detail::scalar_math::exp10m1_fn exp10m1
Ten to the power x minus one, using the cancellation-safe provider.
Definition math.hpp:634
constexpr detail::scalar_math::exp2m1_fn exp2m1
Two to the power x minus one, using the cancellation-safe provider.
Definition math.hpp:632
constexpr detail::scalar_math::exp10_fn exp10
Base-ten exponential.
Definition math.hpp:630
void sum(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input)
Schedule a full sum into an explicit async scalar tensor.
Definition linalg/async/reductions.hpp:309
mpreal log10(mpreal const &x)
Base-ten logarithm; retain input precision or a supported exact result.
Definition mpreal.hpp:736