diff --git a/src/lol/math/real.h b/src/lol/math/real.h index 2af5f162..e2190c03 100644 --- a/src/lol/math/real.h +++ b/src/lol/math/real.h @@ -54,6 +54,7 @@ public: Real(char const *str); LOL_ATTR_NODISCARD bool is_zero() const { return m_mantissa.count() == 0; } + LOL_ATTR_NODISCARD bool is_negative() const { return m_sign; } LOL_ATTR_NODISCARD bool is_nan() const { return m_nan; } LOL_ATTR_NODISCARD bool is_inf() const { return m_inf; } diff --git a/src/math/real.cpp b/src/math/real.cpp index d54c61bb..f2fdda5d 100644 --- a/src/math/real.cpp +++ b/src/math/real.cpp @@ -155,7 +155,7 @@ template<> real::operator double() const union { double d; uint64_t x; } u; /* Get sign */ - u.x = (m_sign ? 1 : 0) << 11; + u.x = (is_negative() ? 1 : 0) << 11; /* Compute new exponent (FIXME: handle Inf/NaN) */ int64_t e = m_exponent + ((1 << 10) - 1); @@ -305,10 +305,10 @@ template<> real real::operator +(real const &x) const /* Ensure both arguments are positive. Otherwise, switch signs, * or replace + with -. */ - if (m_sign) + if (is_negative()) return -(-*this + -x); - if (x.m_sign) + if (x.is_negative()) return *this - (-x); /* Ensure *this has the larger exponent (no need for the mantissa to @@ -373,10 +373,10 @@ template<> real real::operator -(real const &x) const /* Ensure both arguments are positive. Otherwise, switch signs, * or replace - with +. */ - if (m_sign) + if (is_negative()) return -(-*this + x); - if (x.m_sign) + if (x.is_negative()) return (*this) + (-x); /* Ensure *this is larger than x */ @@ -476,7 +476,7 @@ template<> real real::operator *(real const &x) const real ret; /* The sign is easy to compute */ - ret.m_sign = m_sign ^ x.m_sign; + ret.m_sign = is_negative() ^ x.is_negative(); /* If any operand is zero, return zero. FIXME: 0 * Inf? */ if (is_zero() || x.is_zero()) @@ -589,11 +589,11 @@ template<> bool real::operator !=(real const &x) const template<> bool real::operator <(real const &x) const { /* Ensure we are positive */ - if (m_sign) + if (is_negative()) return -*this > -x; /* If x is zero or negative, we can’t be < x */ - if (x.m_sign || x.is_zero()) + if (x.is_negative() || x.is_zero()) return false; /* If we are zero, we must be < x */ @@ -620,7 +620,7 @@ template<> bool real::operator <=(real const &x) const template<> bool real::operator >(real const &x) const { /* Ensure we are positive */ - if (m_sign) + if (is_negative()) return -*this < -x; /* If x is zero, we’re > x iff we’re non-zero since we’re positive */ @@ -628,7 +628,7 @@ template<> bool real::operator >(real const &x) const return !is_zero(); /* If x is strictly negative, we’re > x */ - if (x.m_sign) + if (x.is_negative()) return true; /* If we are zero, we can’t be > x */ @@ -715,7 +715,7 @@ template<> real sqrt(real const &x) return x; /* if negative, return NaN */ - if (x.m_sign) + if (x.is_negative()) { real ret; ret.m_nan = true; @@ -951,7 +951,7 @@ template<> real log(real const &x) /* Strategy for log(x): if x = 2^E*M then log(x) = E log(2) + log(M), * with the property that M is in [1..2[, so fast_log() applies here. */ real tmp; - if (x.m_sign || x.is_zero()) + if (x.is_negative() || x.is_zero()) { tmp.m_nan = true; return tmp; @@ -965,7 +965,7 @@ template<> real log2(real const &x) { /* Strategy for log2(x): see log(x). */ real tmp; - if (x.m_sign || x.is_zero()) + if (x.is_negative() || x.is_zero()) { tmp.m_nan = true; return tmp; @@ -1104,7 +1104,7 @@ template<> real nextafter(real const &x, real const &y) return y; /* Ensure x is positive. */ - if (x.m_sign) + if (x.is_negative()) return -nextafter(-x, -y); /* FIXME: broken for now */ @@ -1187,7 +1187,7 @@ template<> real fmod(real const &x, real const &y) template<> real sin(real const &x) { - bool switch_sign = x.m_sign; + bool switch_sign = x.is_negative(); real absx = fmod(fabs(x), real::R_PI() * 2); if (absx > real::R_PI()) @@ -1246,7 +1246,7 @@ template<> real tan(real const &x) return cos(y) / sin(y); } -static inline real asinacos(real const &x, int is_asin, bool is_negative) +static inline real asinacos(real const &x, int is_asin) { /* Strategy for asin(): in [-0.5..0.5], use a Taylor series around * zero. In [0.5..1], use asin(x) = π/2 - 2*asin(sqrt((1-x)/2)), and @@ -1272,14 +1272,14 @@ static inline real asinacos(real const &x, int is_asin, bool is_negative) fact2 *= (real)((i + 1) * (i + 1)); } - if (is_negative) + if (x.is_negative()) ret = -ret; if (around_zero) ret = is_asin ? ret : real::R_PI_2() - ret; else { - real adjust = is_negative ? real::R_PI() : real::R_0(); + real adjust = x.is_negative() ? real::R_PI() : real::R_0(); if (is_asin) ret = real::R_PI_2() - adjust - ret * 2; else @@ -1291,13 +1291,12 @@ static inline real asinacos(real const &x, int is_asin, bool is_negative) template<> real asin(real const &x) { - /* Pass m_sign because it is private… FIXME: implement is_negative() */ - return asinacos(x, 1, x.m_sign); + return asinacos(x, 1); } template<> real acos(real const &x) { - return asinacos(x, 0, x.m_sign); + return asinacos(x, 0); } template<> real atan(real const &x) @@ -1407,14 +1406,14 @@ template<> real atan2(real const &y, real const &x) { if (!y) { - if (!x.m_sign) + if (!x.is_negative()) return y; - return y.m_sign ? -real::R_PI() : real::R_PI(); + return y.is_negative() ? -real::R_PI() : real::R_PI(); } if (!x) { - return y.m_sign ? -real::R_PI() : real::R_PI(); + return y.is_negative() ? -real::R_PI() : real::R_PI(); } /* FIXME: handle the Inf and NaN cases */ @@ -1484,7 +1483,7 @@ template<> void real::print(int ndigits) const template<> void real::sxprintf(char *str) const { - if (m_sign) + if (is_negative()) *str++ = '-'; str += std::sprintf(str, "0x1."); for (int i = 0; i < bigit_count(); ++i) @@ -1498,7 +1497,7 @@ template<> void real::sprintf(char *str, int ndigits) const { real x = *this; - if (x.m_sign) + if (x.is_negative()) { *str++ = '-'; x = -x;