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);

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; }



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

@@ -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;


Loading…
Cancel
Save