Browse Source

Implement real::is_negative().

legacy
Sam Hocevar 7 years ago
parent
commit
d89a4c9e02
2 changed files with 26 additions and 26 deletions
  1. +1
    -0
      src/lol/math/real.h
  2. +25
    -26
      src/math/real.cpp

+ 1
- 0
src/lol/math/real.h View File

@@ -54,6 +54,7 @@ public:
Real(char const *str); Real(char const *str);


LOL_ATTR_NODISCARD bool is_zero() const { return m_mantissa.count() == 0; } 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_nan() const { return m_nan; }
LOL_ATTR_NODISCARD bool is_inf() const { return m_inf; } LOL_ATTR_NODISCARD bool is_inf() const { return m_inf; }




+ 25
- 26
src/math/real.cpp View File

@@ -155,7 +155,7 @@ template<> real::operator double() const
union { double d; uint64_t x; } u; union { double d; uint64_t x; } u;


/* Get sign */ /* Get sign */
u.x = (m_sign ? 1 : 0) << 11;
u.x = (is_negative() ? 1 : 0) << 11;


/* Compute new exponent (FIXME: handle Inf/NaN) */ /* Compute new exponent (FIXME: handle Inf/NaN) */
int64_t e = m_exponent + ((1 << 10) - 1); 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, /* Ensure both arguments are positive. Otherwise, switch signs,
* or replace + with -. */ * or replace + with -. */
if (m_sign)
if (is_negative())
return -(-*this + -x); return -(-*this + -x);


if (x.m_sign)
if (x.is_negative())
return *this - (-x); return *this - (-x);


/* Ensure *this has the larger exponent (no need for the mantissa to /* 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, /* Ensure both arguments are positive. Otherwise, switch signs,
* or replace - with +. */ * or replace - with +. */
if (m_sign)
if (is_negative())
return -(-*this + x); return -(-*this + x);


if (x.m_sign)
if (x.is_negative())
return (*this) + (-x); return (*this) + (-x);


/* Ensure *this is larger than x */ /* Ensure *this is larger than x */
@@ -476,7 +476,7 @@ template<> real real::operator *(real const &x) const
real ret; real ret;


/* The sign is easy to compute */ /* 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 any operand is zero, return zero. FIXME: 0 * Inf? */
if (is_zero() || x.is_zero()) 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 template<> bool real::operator <(real const &x) const
{ {
/* Ensure we are positive */ /* Ensure we are positive */
if (m_sign)
if (is_negative())
return -*this > -x; return -*this > -x;


/* If x is zero or negative, we can’t be < 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; return false;


/* If we are zero, we must be < x */ /* 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 template<> bool real::operator >(real const &x) const
{ {
/* Ensure we are positive */ /* Ensure we are positive */
if (m_sign)
if (is_negative())
return -*this < -x; return -*this < -x;


/* If x is zero, we’re > x iff we’re non-zero since we’re positive */ /* 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(); return !is_zero();


/* If x is strictly negative, we’re > x */ /* If x is strictly negative, we’re > x */
if (x.m_sign)
if (x.is_negative())
return true; return true;


/* If we are zero, we can’t be > x */ /* If we are zero, we can’t be > x */
@@ -715,7 +715,7 @@ template<> real sqrt(real const &x)
return x; return x;


/* if negative, return NaN */ /* if negative, return NaN */
if (x.m_sign)
if (x.is_negative())
{ {
real ret; real ret;
ret.m_nan = true; 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), /* 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. */ * with the property that M is in [1..2[, so fast_log() applies here. */
real tmp; real tmp;
if (x.m_sign || x.is_zero())
if (x.is_negative() || x.is_zero())
{ {
tmp.m_nan = true; tmp.m_nan = true;
return tmp; return tmp;
@@ -965,7 +965,7 @@ template<> real log2(real const &x)
{ {
/* Strategy for log2(x): see log(x). */ /* Strategy for log2(x): see log(x). */
real tmp; real tmp;
if (x.m_sign || x.is_zero())
if (x.is_negative() || x.is_zero())
{ {
tmp.m_nan = true; tmp.m_nan = true;
return tmp; return tmp;
@@ -1104,7 +1104,7 @@ template<> real nextafter(real const &x, real const &y)
return y; return y;


/* Ensure x is positive. */ /* Ensure x is positive. */
if (x.m_sign)
if (x.is_negative())
return -nextafter(-x, -y); return -nextafter(-x, -y);


/* FIXME: broken for now */ /* FIXME: broken for now */
@@ -1187,7 +1187,7 @@ template<> real fmod(real const &x, real const &y)


template<> real sin(real const &x) 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); real absx = fmod(fabs(x), real::R_PI() * 2);
if (absx > real::R_PI()) if (absx > real::R_PI())
@@ -1246,7 +1246,7 @@ template<> real tan(real const &x)
return cos(y) / sin(y); 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 /* 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 * 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)); fact2 *= (real)((i + 1) * (i + 1));
} }


if (is_negative)
if (x.is_negative())
ret = -ret; ret = -ret;


if (around_zero) if (around_zero)
ret = is_asin ? ret : real::R_PI_2() - ret; ret = is_asin ? ret : real::R_PI_2() - ret;
else 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) if (is_asin)
ret = real::R_PI_2() - adjust - ret * 2; ret = real::R_PI_2() - adjust - ret * 2;
else else
@@ -1291,13 +1291,12 @@ static inline real asinacos(real const &x, int is_asin, bool is_negative)


template<> real asin(real const &x) 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) template<> real acos(real const &x)
{ {
return asinacos(x, 0, x.m_sign);
return asinacos(x, 0);
} }


template<> real atan(real const &x) template<> real atan(real const &x)
@@ -1407,14 +1406,14 @@ template<> real atan2(real const &y, real const &x)
{ {
if (!y) if (!y)
{ {
if (!x.m_sign)
if (!x.is_negative())
return y; return y;
return y.m_sign ? -real::R_PI() : real::R_PI();
return y.is_negative() ? -real::R_PI() : real::R_PI();
} }


if (!x) 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 */ /* 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 template<> void real::sxprintf(char *str) const
{ {
if (m_sign)
if (is_negative())
*str++ = '-'; *str++ = '-';
str += std::sprintf(str, "0x1."); str += std::sprintf(str, "0x1.");
for (int i = 0; i < bigit_count(); ++i) for (int i = 0; i < bigit_count(); ++i)
@@ -1498,7 +1497,7 @@ template<> void real::sprintf(char *str, int ndigits) const
{ {
real x = *this; real x = *this;


if (x.m_sign)
if (x.is_negative())
{ {
*str++ = '-'; *str++ = '-';
x = -x; x = -x;


Loading…
Cancel
Save