16 #ifndef INLCUDE_MOLASSEMBLER_TEMPLE_CONSTEXPR_MATH_H
17 #define INLCUDE_MOLASSEMBLER_TEMPLE_CONSTEXPR_MATH_H
23 #include <type_traits>
26 namespace Molassembler {
31 template<
typename T,
typename U>
32 using enableIfFloatingWithReturn = std::enable_if_t<
33 std::is_floating_point<T>::value,
37 template<
typename T,
typename U>
38 using enableIfIntegralWithReturn = std::enable_if_t<
39 std::is_integral<T>::value,
43 template<
typename T,
typename U>
44 using enableIfArithmeticWithReturn = std::enable_if_t<
45 std::is_arithmetic<T>::value,
49 template<
typename FloatingPo
int>
51 std::is_floating_point<FloatingPoint>::value,
53 > isnan(
const FloatingPoint x) {
62 template<
typename ... Bools>
63 constexpr
bool XOR(Bools ... bools);
68 inline constexpr Traits::enableIfArithmeticWithReturn<T, T>
abs(T x) noexcept;
72 constexpr Traits::enableIfArithmeticWithReturn<T, T>
max(T a, T b) noexcept;
76 constexpr Traits::enableIfArithmeticWithReturn<T, T>
min(T a, T b) noexcept;
82 constexpr Traits::enableIfFloatingWithReturn<T, T>
toRadians(T inDegrees) noexcept;
86 constexpr Traits::enableIfFloatingWithReturn<T, T>
toDegrees(T inRadians) noexcept;
89 template<
typename T,
typename U>
90 constexpr Traits::enableIfFloatingWithReturn<T, T>
fmod(T value, U divider) noexcept;
94 constexpr Traits::enableIfFloatingWithReturn<T, long>
ceil(T value) noexcept;
98 constexpr Traits::enableIfFloatingWithReturn<T, int>
floor(T value) noexcept;
102 constexpr Traits::enableIfArithmeticWithReturn<T, T>
pow(T base,
unsigned exponent) noexcept;
105 constexpr Traits::enableIfArithmeticWithReturn<T, double>
pow(T base,
int exponent) noexcept;
109 constexpr Traits::enableIfFloatingWithReturn<T, T>
sqrt(T x);
113 constexpr Traits::enableIfIntegralWithReturn<T, T>
factorial(T x);
117 constexpr Traits::enableIfFloatingWithReturn<T, T>
ln(T x);
121 constexpr Traits::enableIfFloatingWithReturn<T, T>
log10(T x);
125 constexpr Traits::enableIfFloatingWithReturn<T, T>
log(T x, T base);
133 constexpr Traits::enableIfFloatingWithReturn<T, T>
asin(T x);
137 constexpr Traits::enableIfFloatingWithReturn<T, T>
acos(T x);
141 constexpr Traits::enableIfFloatingWithReturn<T, T>
atan(T x);
149 constexpr
unsigned TPPSum() {
154 template<
typename T1,
typename...
T>
155 constexpr
unsigned TPPSum(T1 a, T ... pack) {
156 return a + TPPSum(pack ...);
169 throw "Ln domain error: x <= 0";
172 const T epsilon = std::numeric_limits<T>::epsilon();
180 const T iterationMultiplier = countingPower * countingPower;
190 for(
unsigned n = 3; Temple::Math::abs(previous - value) > epsilon; n += 2) {
195 countingPower *= iterationMultiplier;
198 value += 2 * countingPower / n;
210 if(!(0.0 <= x && x <= 1.0)) {
211 throw "Asin approximation domain error: only applicable for 0 < x < 1!";
215 const T x4 = x2 * x2;
219 - Math::sqrt(1 - x) * (
223 - 0.0501743046 * x2 * x
225 - 0.0170881256 * x4 * x
226 + 0.0066700901 * x4 * x2
227 - 0.0012624911 * x4 * x2 * x
234 template<
typename ... Bools>
235 constexpr
bool XOR(Bools ... bools) {
236 return Detail::TPPSum(bools ...) == 1;
240 PURITY_STRONG inline constexpr Traits::enableIfArithmeticWithReturn<T, T>
abs(
const T x) noexcept {
241 return (
x >= 0) ?
x : -
x;
245 PURITY_STRONG constexpr Traits::enableIfArithmeticWithReturn<T, T>
max(
const T a,
const T b) noexcept {
246 return (a > b) ? a : b;
250 PURITY_STRONG constexpr Traits::enableIfArithmeticWithReturn<T, T>
min(
const T a,
const T b) noexcept {
251 return (a < b) ? a : b;
256 return M_PI * inDegrees / 180;
261 return 180 * inRadians / M_PI;
264 template<
typename T,
typename U>
265 PURITY_STRONG constexpr Traits::enableIfFloatingWithReturn<T, T>
fmod(
const T value,
const U divider) noexcept {
267 while (divider < remainder) {
268 remainder -= divider;
274 PURITY_STRONG constexpr Traits::enableIfFloatingWithReturn<T, long>
ceil(
const T value) noexcept {
276 const auto truncated =
static_cast<long>(
value);
280 const double eps = 1e-12;
285 if(truncated <
value) {
286 return truncated + 1;
295 const auto truncated =
static_cast<int>(
value);
297 if(truncated >
value) {
298 return truncated - 1;
306 PURITY_STRONG constexpr Traits::enableIfArithmeticWithReturn<T, T>
pow(
const T base,
const unsigned exponent) noexcept {
313 for(
unsigned n = 1; n < exponent; n++) {
321 PURITY_STRONG constexpr
T recPow(
const T base,
const unsigned exponent) noexcept {
330 if(exponent % 2 == 0) {
331 auto halfProblem = recPow(base, exponent / 2);
332 return halfProblem * halfProblem;
335 return base * recPow(base, exponent - 1);
343 PURITY_STRONG constexpr Traits::enableIfArithmeticWithReturn<T, double>
pow(
const T base,
const int exponent) noexcept {
345 return 1.0 /
pow(base,
static_cast<unsigned>(Temple::Math::abs(exponent)));
352 return pow(base,
static_cast<unsigned>(exponent));
360 throw "Square-root domain error: Only real if x >= 0!";
363 const T epsilon = std::numeric_limits<T>::epsilon();
367 while(Temple::Math::abs(previous -
value) > epsilon) {
381 throw "Factorial domain error!";
393 unsigned decimalReduction = 0;
396 while(
abs(calcX) > 10) {
398 decimalReduction += 1;
402 if(Math::abs(calcX / 10 - 1) < Math::abs(calcX - 1)) {
404 decimalReduction += 1;
407 return Detail::lnSeries(calcX) + decimalReduction * M_LN10;
413 throw "Log10 domain error!";
419 return ln(
x) / M_LN10;
423 PURITY_STRONG constexpr Traits::enableIfFloatingWithReturn<T, T> log(
const T x,
const T base) {
425 throw "Log domain error!";
431 return ln(
x) /
ln(base);
441 if(!(-1 <=
x &&
x <= 1)) {
442 throw "Inverse sine domain error: only real if -1 < x < 1!";
445 if(Temple::Math::abs(
x) > 0.90) {
446 return (
x >= 0) ? Detail::asinApprox(
x) : -Detail::asinApprox(-
x);
449 const T epsilon = std::numeric_limits<T>::epsilon();
452 T upper_factorial = 1;
453 T lower_factorial = 1;
456 for(
unsigned n = 1; Temple::Math::abs(term) > epsilon; ++n) {
457 upper_factorial *= 2 * (n - 1) + 1;
458 lower_factorial *= 2 * n;
461 upper_factorial / lower_factorial
462 ) *
pow(
x, 2 * n + 1) / (2 * n + 1);
464 if(Traits::isnan(term)) {
476 if(!(-1 <=
x &&
x <= 1)) {
477 throw "Inverse cosine domain error: only real if -1 <= x <= 1!";
480 return M_PI / 2 -
asin(
x);
485 if(!(-M_PI / 2 <
x &&
x < M_PI / 2)) {
486 throw "Inverse cosine domain error: only real if -1 < x < 1!";
std::ostream & log(const Level &decisionLevel)
Fetch a log handle with a logging level.
constexpr Traits::enableIfFloatingWithReturn< T, int > floor(T value) noexcept
Floor function.
Definition: Math.h:293
constexpr Traits::enableIfFloatingWithReturn< T, T > sqrt(T x)
Square root.
Definition: Math.h:358
constexpr Traits::enableIfFloatingWithReturn< T, T > toRadians(T inDegrees) noexcept
Convert angular degrees to radians.
Definition: Math.h:255
constexpr Traits::enableIfFloatingWithReturn< T, long > ceil(T value) noexcept
Ceiling function, no overflow check.
Definition: Math.h:274
constexpr Traits::enableIfArithmeticWithReturn< T, T > abs(T x) noexcept
Absolute value.
Definition: Math.h:240
constexpr Traits::enableIfFloatingWithReturn< T, T > ln(T x)
Natural logarithm.
Definition: Math.h:392
constexpr Traits::enableIfFloatingWithReturn< T, T > atan(T x)
Inverse tangens.
Definition: Math.h:484
constexpr Traits::enableIfIntegralWithReturn< T, T > factorial(T x)
Factorial.
Definition: Math.h:379
constexpr Traits::enableIfFloatingWithReturn< T, T > fmod(T value, U divider) noexcept
module function for arbitrary types
Definition: Math.h:265
constexpr Traits::enableIfFloatingWithReturn< T, T > log10(T x)
Base-10 logarithm.
Definition: Math.h:411
constexpr Traits::enableIfFloatingWithReturn< T, T > toDegrees(T inRadians) noexcept
Convert angular radians to degrees.
Definition: Math.h:260
constexpr Traits::enableIfFloatingWithReturn< T, T > acos(T x)
Inverse cosine.
Definition: Math.h:475
constexpr bool XOR(Bools ... bools)
Template parameter-pack exclusive or of booleans.
Definition: Math.h:235
constexpr Traits::enableIfFloatingWithReturn< T, T > asin(T x)
Definition: Math.h:440
constexpr Traits::enableIfArithmeticWithReturn< T, T > pow(T base, unsigned exponent) noexcept
Power of a number.
Definition: Math.h:306
Defines a set of useful preprocessor macros.
#define PURITY_STRONG
Definition: Preprocessor.h:65
constexpr auto max(const ContainerType &container)
Composable max function. Returns the smallest value of any container.
Definition: Numeric.h:188
constexpr auto min(const ContainerType &container)
Composable min_element function. Returns the smallest value of any container.
Definition: Numeric.h:164