/
mpeval_p.h
110 lines (85 loc) · 4.91 KB
/
mpeval_p.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// [MathPresso]
// Mathematical Expression Parser and JIT Compiler.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _MATHPRESSO_MPEVAL_P_H
#define _MATHPRESSO_MPEVAL_P_H
// [Dependencies]
#include "./mathpresso_p.h"
namespace mathpresso {
// ============================================================================
// [mathpresso::Evaluation]
// ============================================================================
//! DP-FP binary representation and utilities.
union DoubleBits {
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
static MATHPRESSO_INLINE DoubleBits fromDouble(double val) { DoubleBits u; u.d = val; return u; }
static MATHPRESSO_INLINE DoubleBits fromUInt64(uint64_t val) { DoubleBits u; u.u = val; return u; }
MATHPRESSO_INLINE bool isNan() const { return ((hi & 0x7FF00000U)) == 0x7FF00000U && ((hi & 0x000FFFFFU) | lo) != 0x00000000U; }
MATHPRESSO_INLINE void setNan() { u = MATHPRESSO_UINT64_C(0x7FF8000000000000); }
MATHPRESSO_INLINE bool isInf() const { return (hi & 0x7FFFFFFFU) == 0x7FF00000U && lo == 0x00000000U; }
MATHPRESSO_INLINE void setInf() { u = MATHPRESSO_UINT64_C(0x7FF0000000000000); }
MATHPRESSO_INLINE bool isFinite() const { return (hi & 0x7FF00000U) != 0x7FF00000U; }
//! Value as uint64_t.
uint64_t u;
//! Value as `double`.
double d;
#if MATHPRESSO_ARCH_LE
struct { uint32_t lo; uint32_t hi; };
#else
struct { uint32_t hi; uint32_t lo; };
#endif
};
// The `a != a` condition is used to handle NaN values properly. If one of `a`
// and `b` is NaN the result should be NaN. When `T` isn't a floating point the
// condition should be removed by C++ compiler.
template<typename T> MATHPRESSO_INLINE T mpMin(T a, T b) { return (a != a) | (a < b) ? a : b; }
template<typename T> MATHPRESSO_INLINE T mpMax(T a, T b) { return (a != a) | (a > b) ? a : b; }
static MATHPRESSO_INLINE double mpGetNan() { static const DoubleBits value = { MATHPRESSO_UINT64_C(0x7FF8000000000000) }; return value.d; }
static MATHPRESSO_INLINE double mpGetInf() { static const DoubleBits value = { MATHPRESSO_UINT64_C(0x7FF0000000000000) }; return value.d; }
static MATHPRESSO_INLINE bool mpIsNan(double x) { return DoubleBits::fromDouble(x).isNan(); }
static MATHPRESSO_INLINE bool mpIsInf(double x) { return DoubleBits::fromDouble(x).isInf(); }
static MATHPRESSO_INLINE bool mpIsFinite(double x) { return DoubleBits::fromDouble(x).isFinite(); }
static MATHPRESSO_INLINE double mpRound(double x) {
double y = ::floor(x);
return y + (x - y >= 0.5 ? double(1.0) : double(0.0));
}
static MATHPRESSO_INLINE double mpRoundEven(double x) { return ::rint(x); }
static MATHPRESSO_INLINE double mpTrunc(double x) { return ::trunc(x); }
static MATHPRESSO_INLINE double mpFloor(double x) { return ::floor(x); }
static MATHPRESSO_INLINE double mpCeil(double x) { return ::ceil(x); }
static MATHPRESSO_INLINE double mpSignBit(double x) { return DoubleBits::fromDouble(x).hi >= 0x80000000U; }
static MATHPRESSO_INLINE double mpCopySign(double x, double y) {
DoubleBits bits = DoubleBits::fromDouble(x);
bits.hi &= 0x7FFFFFFFU;
bits.hi |= DoubleBits::fromDouble(y).hi & 0x80000000U;
return bits.d;
}
static MATHPRESSO_INLINE double mpAvg(double x, double y) { return (x + y) * 0.5; }
static MATHPRESSO_INLINE double mpMod(double x, double y) { return fmod(x, y); }
static MATHPRESSO_INLINE double mpAbs(double x) { return ::fabs(x); }
static MATHPRESSO_INLINE double mpExp(double x) { return ::exp(x); }
static MATHPRESSO_INLINE double mpPow(double x, double y) { return ::pow(x, y); }
static MATHPRESSO_INLINE double mpLog(double x) { return ::log(x); }
static MATHPRESSO_INLINE double mpLog2(double x) { return ::log2(x); }
static MATHPRESSO_INLINE double mpLog10(double x) { return ::log10(x); }
static MATHPRESSO_INLINE double mpSqrt(double x) { return ::sqrt(x); }
static MATHPRESSO_INLINE double mpFrac(double x) { return x - mpFloor(x); }
static MATHPRESSO_INLINE double mpRecip(double x) { return 1.0 / x; }
static MATHPRESSO_INLINE double mpSin(double x) { return ::sin(x); }
static MATHPRESSO_INLINE double mpCos(double x) { return ::cos(x); }
static MATHPRESSO_INLINE double mpTan(double x) { return ::tan(x); }
static MATHPRESSO_INLINE double mpSinh(double x) { return ::sinh(x); }
static MATHPRESSO_INLINE double mpCosh(double x) { return ::cosh(x); }
static MATHPRESSO_INLINE double mpTanh(double x) { return ::tanh(x); }
static MATHPRESSO_INLINE double mpAsin(double x) { return ::asin(x); }
static MATHPRESSO_INLINE double mpAcos(double x) { return ::acos(x); }
static MATHPRESSO_INLINE double mpAtan(double x) { return ::atan(x); }
static MATHPRESSO_INLINE double mpAtan2(double y, double x) { return ::atan2(y, x); }
static MATHPRESSO_INLINE double mpHypot(double x, double y) { return ::hypot(x, y); }
} // mathpresso namespace
#endif // _MATHPRESSO_MPEVAL_P_H