Browse Source

Implement real::R_INF and real::R_NAN.

legacy
Sam Hocevar 7 years ago
parent
commit
3025ea2207
2 changed files with 37 additions and 32 deletions
  1. +4
    -1
      src/lol/math/real.h
  2. +33
    -31
      src/math/real.cpp

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

@@ -185,7 +185,7 @@ public:
__LOL_REAL_OP_HELPER_FLOAT(long double) __LOL_REAL_OP_HELPER_FLOAT(long double)


/* Constants */ /* Constants */
static Real<T> const& R_0();
static Real<T> const R_0();
static Real<T> const& R_1(); static Real<T> const& R_1();
static Real<T> const& R_2(); static Real<T> const& R_2();
static Real<T> const& R_3(); static Real<T> const& R_3();
@@ -209,6 +209,9 @@ public:
static Real<T> const& R_SQRT3(); static Real<T> const& R_SQRT3();
static Real<T> const& R_SQRT1_2(); static Real<T> const& R_SQRT1_2();


static Real<T> const R_INF();
static Real<T> const R_NAN();

static Real<T> const& R_MIN(); static Real<T> const& R_MIN();
static Real<T> const& R_MAX(); static Real<T> const& R_MAX();




+ 33
- 31
src/math/real.cpp View File

@@ -38,6 +38,11 @@ static real load_min();
static real load_max(); static real load_max();
static real load_pi(); static real load_pi();


/* These getters do not need caching, their return values are small */
template<> real const real::R_0() { return real(); }
template<> real const real::R_INF() { real ret; ret.m_inf = true; return ret; }
template<> real const real::R_NAN() { real ret; ret.m_nan = true; return ret; }

#define LOL_CONSTANT_GETTER(name, value) \ #define LOL_CONSTANT_GETTER(name, value) \
template<> real const& real::name() \ template<> real const& real::name() \
{ \ { \
@@ -47,17 +52,16 @@ static real load_pi();
* the value with the desired precision. */ \ * the value with the desired precision. */ \
if (prev_bigit_count != DEFAULT_BIGIT_COUNT) \ if (prev_bigit_count != DEFAULT_BIGIT_COUNT) \
{ \ { \
ret = value; \
ret = (value); \
prev_bigit_count = DEFAULT_BIGIT_COUNT; \ prev_bigit_count = DEFAULT_BIGIT_COUNT; \
} \ } \
return ret; \ return ret; \
} }


LOL_CONSTANT_GETTER(R_0, (real)0.0);
LOL_CONSTANT_GETTER(R_1, (real)1.0);
LOL_CONSTANT_GETTER(R_2, (real)2.0);
LOL_CONSTANT_GETTER(R_3, (real)3.0);
LOL_CONSTANT_GETTER(R_10, (real)10.0);
LOL_CONSTANT_GETTER(R_1, real(1.0));
LOL_CONSTANT_GETTER(R_2, real(2.0));
LOL_CONSTANT_GETTER(R_3, real(3.0));
LOL_CONSTANT_GETTER(R_10, real(10.0));


LOL_CONSTANT_GETTER(R_MIN, load_min()); LOL_CONSTANT_GETTER(R_MIN, load_min());
LOL_CONSTANT_GETTER(R_MAX, load_max()); LOL_CONSTANT_GETTER(R_MAX, load_max());
@@ -573,6 +577,10 @@ template<> real const &real::operator /=(real const &x)


template<> bool real::operator ==(real const &x) const template<> bool real::operator ==(real const &x) const
{ {
/* If NaN is involved, return false */
if (is_nan() || x.is_nan())
return false;

/* If both zero, they are equal; if either is zero, they are different */ /* If both zero, they are equal; if either is zero, they are different */
if (is_zero() || x.is_zero()) if (is_zero() || x.is_zero())
return is_zero() && x.is_zero(); return is_zero() && x.is_zero();
@@ -583,11 +591,15 @@ template<> bool real::operator ==(real const &x) const


template<> bool real::operator !=(real const &x) const template<> bool real::operator !=(real const &x) const
{ {
return !(*this == x);
return !(is_nan() || x.is_nan() || *this == x);
} }


template<> bool real::operator <(real const &x) const template<> bool real::operator <(real const &x) const
{ {
/* If NaN is involved, return false */
if (is_nan() || x.is_nan())
return false;

/* Ensure we are positive */ /* Ensure we are positive */
if (is_negative()) if (is_negative())
return -*this > -x; return -*this > -x;
@@ -614,11 +626,15 @@ template<> bool real::operator <(real const &x) const


template<> bool real::operator <=(real const &x) const template<> bool real::operator <=(real const &x) const
{ {
return !(*this > x);
return !(is_nan() || x.is_nan() || *this > x);
} }


template<> bool real::operator >(real const &x) const template<> bool real::operator >(real const &x) const
{ {
/* If NaN is involved, return false */
if (is_nan() || x.is_nan())
return false;

/* Ensure we are positive */ /* Ensure we are positive */
if (is_negative()) if (is_negative())
return -*this < -x; return -*this < -x;
@@ -649,7 +665,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
{ {
return !(*this < x);
return !(is_nan() || x.is_nan() || *this < x);
} }


template<> bool real::operator !() const template<> bool real::operator !() const
@@ -684,11 +700,7 @@ template<> real inverse(real const &x)


/* If zero, return infinite */ /* If zero, return infinite */
if (x.is_zero()) if (x.is_zero())
{
ret.m_sign = x.m_sign;
ret.m_inf = true;
return ret;
}
return copysign(real::R_INF(), x);


/* Use the system's float inversion to approximate 1/x */ /* Use the system's float inversion to approximate 1/x */
union { float f; uint32_t x; } u = { 1.0f }; union { float f; uint32_t x; } u = { 1.0f };
@@ -716,11 +728,7 @@ template<> real sqrt(real const &x)


/* if negative, return NaN */ /* if negative, return NaN */
if (x.is_negative()) if (x.is_negative())
{
real ret;
ret.m_nan = true;
return ret;
}
return real::R_NAN();


int tweak = x.m_exponent & 1; int tweak = x.m_exponent & 1;


@@ -950,13 +958,10 @@ 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;
if (x.is_negative() || x.is_zero()) if (x.is_negative() || x.is_zero())
{
tmp.m_nan = true;
return tmp;
}
tmp = x;
return real::R_NAN();

real tmp(x);
tmp.m_exponent = 0; tmp.m_exponent = 0;
return real(x.m_exponent) * real::R_LN2() + fast_log(tmp); return real(x.m_exponent) * real::R_LN2() + fast_log(tmp);
} }
@@ -964,13 +969,10 @@ template<> real log(real const &x)
template<> real log2(real const &x) template<> real log2(real const &x)
{ {
/* Strategy for log2(x): see log(x). */ /* Strategy for log2(x): see log(x). */
real tmp;
if (x.is_negative() || x.is_zero()) if (x.is_negative() || x.is_zero())
{
tmp.m_nan = true;
return tmp;
}
tmp = x;
return real::R_NAN();

real tmp(x);
tmp.m_exponent = 0; tmp.m_exponent = 0;
return real(x.m_exponent) + fast_log(tmp) * real::R_LOG2E(); return real(x.m_exponent) + fast_log(tmp) * real::R_LOG2E();
} }


Loading…
Cancel
Save