6namespace uni20::detail::native_math
12template <NativeReal R>
struct portable_pi_math
16 if (!std::isfinite(x))
return numeric_limits<R>::quiet_NaN();
18 R r = std::remquo(x, R(0.5), &q);
20 if (r == R(0))
return q % 2 == 0 ? std::copysign(R(0), x) : (q == 1 ? R(1) : R(-1));
25 return std::sin(angle);
27 return std::cos(angle);
29 return -std::sin(angle);
31 return -std::cos(angle);
37 if (!std::isfinite(x))
return numeric_limits<R>::quiet_NaN();
39 R r = std::remquo(x, R(0.5), &q);
41 if (r == R(0))
return q % 2 != 0 ? R(0) : (q == 0 ? R(1) : R(-1));
46 return std::cos(angle);
48 return -std::sin(angle);
50 return -std::cos(angle);
52 return std::sin(angle);
58 if (!std::isfinite(x))
return numeric_limits<R>::quiet_NaN();
60 R r = std::remquo(x, R(0.5), &q);
64 if (q % 2 == 0)
return std::copysign(R(0), x);
65 return q == 1 ? numeric_limits<R>::infinity() : -numeric_limits<R>::infinity();
69 if (std::abs(r) == R(0.25))
return std::copysign(R(1), r);
70 R
value = std::tan(pi<R> * r);
76 if (x == R(0))
return x;
77 if (std::abs(x) == R(1))
return std::copysign(R(0.5), x);
78 return std::asin(x) / pi<R>;
83 if (x == R(0))
return R(0.5);
84 if (x == R(1))
return R(0);
85 if (x == R(-1))
return R(1);
86 return std::acos(x) / pi<R>;
91 if (x == R(0))
return x;
92 if (std::abs(x) == R(1))
return std::copysign(R(0.25), x);
93 if (std::isinf(x))
return std::copysign(R(0.5), x);
94 return std::atan(x) / pi<R>;
99 if (std::isnan(x) || std::isnan(y))
return numeric_limits<R>::quiet_NaN();
100 if (y == R(0))
return std::copysign(std::signbit(x) ? R(1) : R(0), y);
101 if (x == R(0))
return std::copysign(R(0.5), y);
104 if (std::abs(x) == std::abs(y))
return std::copysign(x > R(0) ? R(0.25) : R(0.75), y);
105 if (std::isinf(y))
return std::copysign(R(0.5), y);
106 if (std::isinf(x))
return std::copysign(x > R(0) ? R(0) : R(1), y);
107 return std::atan2(y, x) / pi<R>;
113template <NativeReal R>
struct pi_math_provider : portable_pi_math<R>
116#define UNI20_NATIVE_PI_FORWARD(TYPE, SUFFIX) \
117 static TYPE sinpi(TYPE x) { return ::sinpi##SUFFIX(x); } \
118 static TYPE cospi(TYPE x) { return ::cospi##SUFFIX(x); } \
119 static TYPE tanpi(TYPE x) { return ::tanpi##SUFFIX(x); }
120#define UNI20_NATIVE_PI_INVERSE(TYPE, SUFFIX) \
121 static TYPE asinpi(TYPE x) { return ::asinpi##SUFFIX(x); } \
122 static TYPE acospi(TYPE x) { return ::acospi##SUFFIX(x); } \
123 static TYPE atanpi(TYPE x) { return ::atanpi##SUFFIX(x); } \
124 static TYPE atan2pi(TYPE y, TYPE x) { return ::atan2pi##SUFFIX(y, x); }
126#if (UNI20_HAS_PI_TRIG_FLOAT || UNI20_HAS_PI_INVERSE_FLOAT)
127template <>
struct pi_math_provider<float> : portable_pi_math<float>
129#if UNI20_HAS_PI_TRIG_FLOAT
132#if UNI20_HAS_PI_INVERSE_FLOAT
138#if (UNI20_HAS_PI_TRIG_DOUBLE || UNI20_HAS_PI_INVERSE_DOUBLE)
139template <>
struct pi_math_provider<double> : portable_pi_math<double>
141#if UNI20_HAS_PI_TRIG_DOUBLE
144#if UNI20_HAS_PI_INVERSE_DOUBLE
150#if (UNI20_HAS_PI_TRIG_LONG_DOUBLE || UNI20_HAS_PI_INVERSE_LONG_DOUBLE)
151template <>
struct pi_math_provider<long double> : portable_pi_math<long double>
153#if UNI20_HAS_PI_TRIG_LONG_DOUBLE
156#if UNI20_HAS_PI_INVERSE_LONG_DOUBLE
162#if UNI20_HAS_FLOAT128 && (UNI20_HAS_PI_TRIG_FLOAT128 || UNI20_HAS_PI_INVERSE_FLOAT128)
163template <>
struct pi_math_provider<float128> : portable_pi_math<float128>
165#if UNI20_HAS_PI_TRIG_FLOAT128
168#if UNI20_HAS_PI_INVERSE_FLOAT128
174#undef UNI20_NATIVE_PI_FORWARD
175#undef UNI20_NATIVE_PI_INVERSE
177template <NativeReal R> R
sinpi(R x) {
return pi_math_provider<R>::sinpi(x); }
178template <NativeReal R> R
cospi(R x) {
return pi_math_provider<R>::cospi(x); }
179template <NativeReal R> R
tanpi(R x) {
return pi_math_provider<R>::tanpi(x); }
180template <NativeReal R> R
asinpi(R x) {
return pi_math_provider<R>::asinpi(x); }
181template <NativeReal R> R
acospi(R x) {
return pi_math_provider<R>::acospi(x); }
182template <NativeReal R> R
atanpi(R x) {
return pi_math_provider<R>::atanpi(x); }
183template <NativeReal R, NativeReal S>
auto atan2pi(R y, S x)
185 using T = std::common_type_t<R, S>;
186 return pi_math_provider<T>::atan2pi(T(y), T(x));
locale_t value
Definition data_table.cpp:49
constexpr detail::scalar_math::asinpi_fn asinpi
Principal arcsine divided by pi.
Definition math.hpp:646
constexpr detail::scalar_math::atanpi_fn atanpi
Principal arctangent divided by pi.
Definition math.hpp:650
constexpr detail::scalar_math::sinpi_fn sinpi
Sine of pi times x, with argument reduction before multiplication by pi.
Definition math.hpp:640
constexpr detail::scalar_math::atan2pi_fn atan2pi
Quadrant-aware arctangent divided by pi.
Definition math.hpp:664
constexpr detail::scalar_math::acospi_fn acospi
Principal arccosine divided by pi.
Definition math.hpp:648
constexpr detail::scalar_math::tanpi_fn tanpi
Tangent of pi times x, with argument reduction before multiplication by pi.
Definition math.hpp:644
constexpr detail::scalar_math::cospi_fn cospi
Cosine of pi times x, with argument reduction before multiplication by pi.
Definition math.hpp:642
#define UNI20_NATIVE_PI_FORWARD(TYPE, SUFFIX)
Definition native_pi_math.hpp:116
#define UNI20_NATIVE_PI_INVERSE(TYPE, SUFFIX)
Definition native_pi_math.hpp:120