Browse Source

math: remove some hardcoded stuff from the real numbers implementation.

legacy
Sam Hocevar 7 years ago
parent
commit
17db5be5c8
3 changed files with 104 additions and 76 deletions
  1. +14
    -8
      src/lol/math/real.h
  2. +89
    -67
      src/math/real.cpp
  3. +1
    -1
      src/t/math/real.cpp

+ 14
- 8
src/lol/math/real.h View File

@@ -132,8 +132,9 @@ public:
template<int K> friend Real<K> degrees(Real<K> const &x); template<int K> friend Real<K> degrees(Real<K> const &x);
template<int K> friend Real<K> radians(Real<K> const &x); template<int K> friend Real<K> radians(Real<K> const &x);


void hexprint() const;
void xprint() const;
void print(int ndigits = 150) const; void print(int ndigits = 150) const;
void sxprintf(char *str) const;
void sprintf(char *str, int ndigits = 150) const; void sprintf(char *str, int ndigits = 150) const;


/* Additional operators using base C++ types */ /* Additional operators using base C++ types */
@@ -202,16 +203,20 @@ public:
static Real<N> const& R_MIN(); static Real<N> const& R_MIN();
static Real<N> const& R_MAX(); static Real<N> const& R_MAX();


private:
uint32_t *m_mantissa;
uint32_t m_signexp;

public:
/* XXX: changing this requires tuning real::fres (the number of /* XXX: changing this requires tuning real::fres (the number of
* Newton-Raphson iterations) and real::print (the number of printed * Newton-Raphson iterations) and real::print (the number of printed
* digits) */ * digits) */
static int const BIGITS = N;
static int const BIGIT_BITS = 32;
static int const TOTAL_BITS = BIGITS * BIGIT_BITS;
static int const BIGIT_COUNT = N;
static int const BIGIT_BITS = 8 * sizeof(*m_mantissa);
static int const TOTAL_BITS = BIGIT_COUNT * BIGIT_BITS;


private:
uint32_t *m_mantissa;
uint32_t m_signexp;
static int const EXPONENT_BITS = 8 * sizeof(m_signexp) - 1;
static int const EXPONENT_BIAS = (1 << (EXPONENT_BITS - 1)) - 1;
}; };


/* /*
@@ -333,8 +338,9 @@ template<> real fract(real const &x);
template<> real degrees(real const &x); template<> real degrees(real const &x);
template<> real radians(real const &x); template<> real radians(real const &x);


template<> void real::hexprint() const;
template<> void real::xprint() const;
template<> void real::print(int ndigits) const; template<> void real::print(int ndigits) const;
template<> void real::sxprintf(char *str) const;
template<> void real::sprintf(char *str, int ndigits) const; template<> void real::sprintf(char *str, int ndigits) const;


} /* namespace lol */ } /* namespace lol */


+ 89
- 67
src/math/real.cpp View File

@@ -79,15 +79,15 @@ LOL_CONSTANT_GETTER(R_SQRT1_2, R_SQRT2() / 2);


template<> real::Real() template<> real::Real()
{ {
m_mantissa = new uint32_t[BIGITS];
memset(m_mantissa, 0, BIGITS * sizeof(uint32_t));
m_mantissa = new uint32_t[BIGIT_COUNT];
memset(m_mantissa, 0, BIGIT_COUNT * sizeof(uint32_t));
m_signexp = 0; m_signexp = 0;
} }


template<> real::Real(real const &x) template<> real::Real(real const &x)
{ {
m_mantissa = new uint32_t[BIGITS];
memcpy(m_mantissa, x.m_mantissa, BIGITS * sizeof(uint32_t));
m_mantissa = new uint32_t[BIGIT_COUNT];
memcpy(m_mantissa, x.m_mantissa, BIGIT_COUNT * sizeof(uint32_t));
m_signexp = x.m_signexp; m_signexp = x.m_signexp;
} }


@@ -95,7 +95,7 @@ template<> real const &real::operator =(real const &x)
{ {
if (&x != this) if (&x != this)
{ {
memcpy(m_mantissa, x.m_mantissa, BIGITS * sizeof(uint32_t));
memcpy(m_mantissa, x.m_mantissa, BIGIT_COUNT * sizeof(uint32_t));
m_signexp = x.m_signexp; m_signexp = x.m_signexp;
} }


@@ -133,13 +133,13 @@ template<> real::Real(double d)
m_signexp = sign | 0x7fffffffu; m_signexp = sign | 0x7fffffffu;
break; break;
default: default:
m_signexp = sign | (exponent + (1 << 30) - (1 << 10));
m_signexp = sign | (exponent + EXPONENT_BIAS - ((1 << 10) - 1));
break; break;
} }


m_mantissa[0] = (uint32_t)(u.x >> 20); m_mantissa[0] = (uint32_t)(u.x >> 20);
m_mantissa[1] = (uint32_t)(u.x << 12); m_mantissa[1] = (uint32_t)(u.x << 12);
memset(m_mantissa + 2, 0, (BIGITS - 2) * sizeof(m_mantissa[0]));
memset(m_mantissa + 2, 0, (BIGIT_COUNT - 2) * sizeof(m_mantissa[0]));
} }


template<> real::Real(long double f) template<> real::Real(long double f)
@@ -166,7 +166,7 @@ template<> real::operator double() const


/* Compute new exponent */ /* Compute new exponent */
uint32_t exponent = (m_signexp << 1) >> 1; uint32_t exponent = (m_signexp << 1) >> 1;
int e = (int)exponent - (1 << 30) + (1 << 10);
int e = (int)exponent - EXPONENT_BIAS + ((1 << 10) - 1);


if (e < 0) if (e < 0)
u.x <<= 52; u.x <<= 52;
@@ -316,19 +316,19 @@ template<> real real::operator +(real const &x) const


real ret; real ret;


int e1 = m_signexp - (1 << 30) + 1;
int e2 = x.m_signexp - (1 << 30) + 1;
int e1 = m_signexp - EXPONENT_BIAS;
int e2 = x.m_signexp - EXPONENT_BIAS;


int bigoff = (e1 - e2) / BIGIT_BITS; int bigoff = (e1 - e2) / BIGIT_BITS;
int off = e1 - e2 - bigoff * BIGIT_BITS; int off = e1 - e2 - bigoff * BIGIT_BITS;


if (bigoff > BIGITS)
if (bigoff > BIGIT_COUNT)
return *this; return *this;


ret.m_signexp = m_signexp; ret.m_signexp = m_signexp;


uint64_t carry = 0; uint64_t carry = 0;
for (int i = BIGITS; i--; )
for (int i = BIGIT_COUNT; i--; )
{ {
carry += m_mantissa[i]; carry += m_mantissa[i];
if (i - bigoff >= 0) if (i - bigoff >= 0)
@@ -347,7 +347,7 @@ template<> real real::operator +(real const &x) const
if (carry) if (carry)
{ {
carry--; carry--;
for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
{ {
uint32_t tmp = ret.m_mantissa[i]; uint32_t tmp = ret.m_mantissa[i];
ret.m_mantissa[i] = ((uint32_t)carry << (BIGIT_BITS - 1)) ret.m_mantissa[i] = ((uint32_t)carry << (BIGIT_BITS - 1))
@@ -379,13 +379,13 @@ template<> real real::operator -(real const &x) const


real ret; real ret;


int e1 = m_signexp - (1 << 30) + 1;
int e2 = x.m_signexp - (1 << 30) + 1;
int e1 = m_signexp - EXPONENT_BIAS;
int e2 = x.m_signexp - EXPONENT_BIAS;


int bigoff = (e1 - e2) / BIGIT_BITS; int bigoff = (e1 - e2) / BIGIT_BITS;
int off = e1 - e2 - bigoff * BIGIT_BITS; int off = e1 - e2 - bigoff * BIGIT_BITS;


if (bigoff > BIGITS)
if (bigoff > BIGIT_COUNT)
return *this; return *this;


ret.m_signexp = m_signexp; ret.m_signexp = m_signexp;
@@ -394,16 +394,16 @@ template<> real real::operator -(real const &x) const
int64_t carry = 0; int64_t carry = 0;
for (int i = 0; i < bigoff; i++) for (int i = 0; i < bigoff; i++)
{ {
carry -= x.m_mantissa[BIGITS - 1 - i];
carry -= x.m_mantissa[BIGIT_COUNT - 1 - i];
/* Emulates a signed shift */ /* Emulates a signed shift */
carry >>= BIGIT_BITS; carry >>= BIGIT_BITS;
carry |= carry << BIGIT_BITS; carry |= carry << BIGIT_BITS;
} }
if (bigoff < BIGITS)
carry -= x.m_mantissa[BIGITS - 1 - bigoff] & (((int64_t)1 << off) - 1);
if (bigoff < BIGIT_COUNT)
carry -= x.m_mantissa[BIGIT_COUNT - 1 - bigoff] & (((int64_t)1 << off) - 1);
carry /= (int64_t)1 << off; carry /= (int64_t)1 << off;


for (int i = BIGITS; i--; )
for (int i = BIGIT_COUNT; i--; )
{ {
carry += m_mantissa[i]; carry += m_mantissa[i];
if (i - bigoff >= 0) if (i - bigoff >= 0)
@@ -427,7 +427,7 @@ template<> real real::operator -(real const &x) const
/* How much do we need to shift the mantissa? FIXME: this could /* How much do we need to shift the mantissa? FIXME: this could
* be computed above */ * be computed above */
off = 0; off = 0;
for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
{ {
if (!ret.m_mantissa[i]) if (!ret.m_mantissa[i])
{ {
@@ -439,7 +439,7 @@ template<> real real::operator -(real const &x) const
off++; off++;
break; break;
} }
if (off == BIGITS * BIGIT_BITS)
if (off == BIGIT_COUNT * BIGIT_BITS)
ret.m_signexp &= 0x80000000u; ret.m_signexp &= 0x80000000u;
else else
{ {
@@ -449,12 +449,12 @@ template<> real real::operator -(real const &x) const
bigoff = off / BIGIT_BITS; bigoff = off / BIGIT_BITS;
off -= bigoff * BIGIT_BITS; off -= bigoff * BIGIT_BITS;


for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
{ {
uint32_t tmp = 0; uint32_t tmp = 0;
if (i + bigoff < BIGITS)
if (i + bigoff < BIGIT_COUNT)
tmp |= ret.m_mantissa[i + bigoff] << off; tmp |= ret.m_mantissa[i + bigoff] << off;
if (off && i + bigoff + 1 < BIGITS)
if (off && i + bigoff + 1 < BIGIT_COUNT)
tmp |= ret.m_mantissa[i + bigoff + 1] >> (BIGIT_BITS - off); tmp |= ret.m_mantissa[i + bigoff + 1] >> (BIGIT_BITS - off);
ret.m_mantissa[i] = tmp; ret.m_mantissa[i] = tmp;
} }
@@ -476,19 +476,19 @@ template<> real real::operator *(real const &x) const
} }


ret.m_signexp = (m_signexp ^ x.m_signexp) & 0x80000000u; ret.m_signexp = (m_signexp ^ x.m_signexp) & 0x80000000u;
int e = (m_signexp & 0x7fffffffu) - (1 << 30) + 1
+ (x.m_signexp & 0x7fffffffu) - (1 << 30) + 1;
int e = (m_signexp & 0x7fffffffu) - EXPONENT_BIAS
+ (x.m_signexp & 0x7fffffffu) - EXPONENT_BIAS;


/* Accumulate low order product; no need to store it, we just /* Accumulate low order product; no need to store it, we just
* want the carry value */ * want the carry value */
uint64_t carry = 0, hicarry = 0, prev; uint64_t carry = 0, hicarry = 0, prev;
for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
{ {
for (int j = 0; j < i + 1; j++) for (int j = 0; j < i + 1; j++)
{ {
prev = carry; prev = carry;
carry += (uint64_t)m_mantissa[BIGITS - 1 - j]
* (uint64_t)x.m_mantissa[BIGITS - 1 + j - i];
carry += (uint64_t)m_mantissa[BIGIT_COUNT - 1 - j]
* (uint64_t)x.m_mantissa[BIGIT_COUNT - 1 + j - i];
if (carry < prev) if (carry < prev)
hicarry++; hicarry++;
} }
@@ -497,22 +497,22 @@ template<> real real::operator *(real const &x) const
hicarry >>= BIGIT_BITS; hicarry >>= BIGIT_BITS;
} }


for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
{ {
for (int j = i + 1; j < BIGITS; j++)
for (int j = i + 1; j < BIGIT_COUNT; j++)
{ {
prev = carry; prev = carry;
carry += (uint64_t)m_mantissa[BIGITS - 1 - j]
carry += (uint64_t)m_mantissa[BIGIT_COUNT - 1 - j]
* (uint64_t)x.m_mantissa[j - 1 - i]; * (uint64_t)x.m_mantissa[j - 1 - i];
if (carry < prev) if (carry < prev)
hicarry++; hicarry++;
} }
prev = carry; prev = carry;
carry += m_mantissa[BIGITS - 1 - i];
carry += x.m_mantissa[BIGITS - 1 - i];
carry += m_mantissa[BIGIT_COUNT - 1 - i];
carry += x.m_mantissa[BIGIT_COUNT - 1 - i];
if (carry < prev) if (carry < prev)
hicarry++; hicarry++;
ret.m_mantissa[BIGITS - 1 - i] = carry & 0xffffffffu;
ret.m_mantissa[BIGIT_COUNT - 1 - i] = carry & 0xffffffffu;
carry >>= BIGIT_BITS; carry >>= BIGIT_BITS;
carry |= hicarry << BIGIT_BITS; carry |= hicarry << BIGIT_BITS;
hicarry >>= BIGIT_BITS; hicarry >>= BIGIT_BITS;
@@ -522,7 +522,7 @@ template<> real real::operator *(real const &x) const
if (carry) if (carry)
{ {
carry--; carry--;
for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
{ {
uint32_t tmp = (uint32_t)ret.m_mantissa[i]; uint32_t tmp = (uint32_t)ret.m_mantissa[i];
ret.m_mantissa[i] = ((uint32_t)carry << (BIGIT_BITS - 1)) ret.m_mantissa[i] = ((uint32_t)carry << (BIGIT_BITS - 1))
@@ -532,7 +532,7 @@ template<> real real::operator *(real const &x) const
e++; e++;
} }


ret.m_signexp |= e + (1 << 30) - 1;
ret.m_signexp |= e + EXPONENT_BIAS;


return ret; return ret;
} }
@@ -574,7 +574,7 @@ template<> bool real::operator ==(real const &x) const
if (m_signexp != x.m_signexp) if (m_signexp != x.m_signexp)
return false; return false;


return memcmp(m_mantissa, x.m_mantissa, BIGITS * sizeof(uint32_t)) == 0;
return memcmp(m_mantissa, x.m_mantissa, BIGIT_COUNT * sizeof(uint32_t)) == 0;
} }


template<> bool real::operator !=(real const &x) const template<> bool real::operator !=(real const &x) const
@@ -595,7 +595,7 @@ template<> bool real::operator <(real const &x) const
if (m_signexp != x.m_signexp) if (m_signexp != x.m_signexp)
return m_signexp < x.m_signexp; return m_signexp < x.m_signexp;


for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
if (m_mantissa[i] != x.m_mantissa[i]) if (m_mantissa[i] != x.m_mantissa[i])
return m_mantissa[i] < x.m_mantissa[i]; return m_mantissa[i] < x.m_mantissa[i];


@@ -620,7 +620,7 @@ template<> bool real::operator >(real const &x) const
if (m_signexp != x.m_signexp) if (m_signexp != x.m_signexp)
return m_signexp > x.m_signexp; return m_signexp > x.m_signexp;


for (int i = 0; i < BIGITS; i++)
for (int i = 0; i < BIGIT_COUNT; i++)
if (m_mantissa[i] != x.m_mantissa[i]) if (m_mantissa[i] != x.m_mantissa[i])
return m_mantissa[i] > x.m_mantissa[i]; return m_mantissa[i] > x.m_mantissa[i];


@@ -685,9 +685,9 @@ template<> real inverse(real const &x)
exponent = -exponent + (v.x >> 23) - (u.x >> 23); exponent = -exponent + (v.x >> 23) - (u.x >> 23);
ret.m_signexp |= (exponent - 1) & 0x7fffffffu; ret.m_signexp |= (exponent - 1) & 0x7fffffffu;


/* FIXME: 1+log2(BIGITS) steps of Newton-Raphson seems to be enough for
/* FIXME: 1+log2(BIGIT_COUNT) steps of Newton-Raphson seems to be enough for
* convergence, but this hasn't been checked seriously. */ * convergence, but this hasn't been checked seriously. */
for (int i = 1; i <= real::BIGITS; i *= 2)
for (int i = 1; i <= real::BIGIT_COUNT; i *= 2)
ret = ret * (real::R_2() - ret * x); ret = ret * (real::R_2() - ret * x);


return ret; return ret;
@@ -724,14 +724,15 @@ template<> real sqrt(real const &x)
uint32_t sign = x.m_signexp & 0x80000000u; uint32_t sign = x.m_signexp & 0x80000000u;
ret.m_signexp = sign; ret.m_signexp = sign;


/* FIXME: these << 30 and << 29 should be use EXPONENT_BIAS instead */
uint32_t exponent = (x.m_signexp & 0x7fffffffu); uint32_t exponent = (x.m_signexp & 0x7fffffffu);
exponent = ((1 << 30) + (1 << 29) - 1) - (exponent + 1) / 2; exponent = ((1 << 30) + (1 << 29) - 1) - (exponent + 1) / 2;
exponent = exponent + (v.x >> 23) - (u.x >> 23); exponent = exponent + (v.x >> 23) - (u.x >> 23);
ret.m_signexp |= exponent & 0x7fffffffu; ret.m_signexp |= exponent & 0x7fffffffu;


/* FIXME: 1+log2(BIGITS) steps of Newton-Raphson seems to be enough for
/* FIXME: 1+log2(BIGIT_COUNT) steps of Newton-Raphson seems to be enough for
* convergence, but this hasn't been checked seriously. */ * convergence, but this hasn't been checked seriously. */
for (int i = 1; i <= real::BIGITS; i *= 2)
for (int i = 1; i <= real::BIGIT_COUNT; i *= 2)
{ {
ret = ret * (real::R_3() - ret * ret * x); ret = ret * (real::R_3() - ret * ret * x);
ret.m_signexp--; ret.m_signexp--;
@@ -762,13 +763,13 @@ template<> real cbrt(real const &x)
uint32_t sign = x.m_signexp & 0x80000000u; uint32_t sign = x.m_signexp & 0x80000000u;
ret.m_signexp = sign; ret.m_signexp = sign;


int exponent = (x.m_signexp & 0x7fffffffu) - (1 << 30) + 1;
int exponent = (x.m_signexp & 0x7fffffffu) - real::EXPONENT_BIAS;
exponent = exponent / 3 + (v.x >> 23) - (u.x >> 23); exponent = exponent / 3 + (v.x >> 23) - (u.x >> 23);
ret.m_signexp |= (exponent + (1 << 30) - 1) & 0x7fffffffu;
ret.m_signexp |= (exponent + real::EXPONENT_BIAS) & 0x7fffffffu;


/* FIXME: 1+log2(BIGITS) steps of Newton-Raphson seems to be enough for
* convergence, but this hasn't been checked seriously. */
for (int i = 1; i <= real::BIGITS; i *= 2)
/* FIXME: 1+log2(BIGIT_COUNT) steps of Newton-Raphson seems to be enough
* for convergence, but this hasn't been checked seriously. */
for (int i = 1; i <= real::BIGIT_COUNT; i *= 2)
{ {
static real third = inverse(real::R_3()); static real third = inverse(real::R_3());
ret = third * (x / (ret * ret) + (ret / 2)); ret = third * (x / (ret * ret) + (ret / 2));
@@ -850,7 +851,7 @@ template<> real gamma(real const &x)
* also be useful to sort the ck values by decreasing absolute value * also be useful to sort the ck values by decreasing absolute value
* and do the addition in this order. */ * and do the addition in this order. */
int a = (int)ceilf(logf(2) / logf(2 * F_PI) int a = (int)ceilf(logf(2) / logf(2 * F_PI)
* real::BIGITS * real::BIGIT_BITS);
* real::BIGIT_COUNT * real::BIGIT_BITS);


real ret = sqrt(real::R_PI() * 2); real ret = sqrt(real::R_PI() * 2);
real fact_k_1 = real::R_1(); real fact_k_1 = real::R_1();
@@ -945,8 +946,8 @@ template<> real log(real const &x)
tmp.m_mantissa[0] = 0xffffffffu; tmp.m_mantissa[0] = 0xffffffffu;
return tmp; return tmp;
} }
tmp.m_signexp = (1 << 30) - 1;
return (real)(int)(x.m_signexp - (1 << 30) + 1) * real::R_LN2()
tmp.m_signexp = real::EXPONENT_BIAS;
return (real)(int)(x.m_signexp - real::EXPONENT_BIAS) * real::R_LN2()
+ fast_log(tmp); + fast_log(tmp);
} }


@@ -960,8 +961,8 @@ template<> real log2(real const &x)
tmp.m_mantissa[0] = 0xffffffffu; tmp.m_mantissa[0] = 0xffffffffu;
return tmp; return tmp;
} }
tmp.m_signexp = (1 << 30) - 1;
return (real)(int)(x.m_signexp - (1 << 30) + 1)
tmp.m_signexp = real::EXPONENT_BIAS;
return (real)(int)(x.m_signexp - real::EXPONENT_BIAS)
+ fast_log(tmp) * real::R_LOG2E(); + fast_log(tmp) * real::R_LOG2E();
} }


@@ -1063,7 +1064,7 @@ template<> real frexp(real const &x, int *exp)
} }


real ret = x; real ret = x;
int exponent = (ret.m_signexp & 0x7fffffffu) - (1 << 30) + 1;
int exponent = (ret.m_signexp & 0x7fffffffu) - real::EXPONENT_BIAS;
*exp = exponent + 1; *exp = exponent + 1;
ret.m_signexp -= exponent + 1; ret.m_signexp -= exponent + 1;
return ret; return ret;
@@ -1125,9 +1126,9 @@ template<> real floor(real const &x)
return real::R_0(); return real::R_0();


real ret = x; real ret = x;
int exponent = x.m_signexp - (1 << 30) + 1;
int exponent = x.m_signexp - real::EXPONENT_BIAS;


for (int i = 0; i < real::BIGITS; i++)
for (int i = 0; i < real::BIGIT_COUNT; i++)
{ {
if (exponent <= 0) if (exponent <= 0)
ret.m_mantissa[i] = 0; ret.m_mantissa[i] = 0;
@@ -1419,15 +1420,16 @@ template<> real atan2(real const &y, real const &x)
return ret; return ret;
} }


template<> void real::hexprint() const
template<> void real::sxprintf(char *str) const;
template<> void real::sprintf(char *str, int ndigits) const;

template<> void real::xprint() const
{ {
std::printf("%08x", m_signexp);
for (int i = 0; i < BIGITS; i++)
std::printf(" %08x", m_mantissa[i]);
char buf[150]; /* 128 bigit digits + room for 0x1, the exponent, etc. */
real::sxprintf(buf);
std::printf("%s", buf);
} }


template<> void real::sprintf(char *str, int ndigits) const;

template<> void real::print(int ndigits) const template<> void real::print(int ndigits) const
{ {
char *buf = new char[ndigits + 32 + 10]; char *buf = new char[ndigits + 32 + 10];
@@ -1436,6 +1438,18 @@ template<> void real::print(int ndigits) const
delete[] buf; delete[] buf;
} }


template<> void real::sxprintf(char *str) const
{
if (m_signexp >> 31)
*str++ = '-';
str += std::sprintf(str, "0x1.");
for (int i = 0; i < BIGIT_COUNT; ++i)
str += std::sprintf(str, "%08x", m_mantissa[i]);
while (str[-1] == '0')
*--str = '\0';
str += std::sprintf(str, "p%d", (m_signexp & 0x7fffffffu) - EXPONENT_BIAS);
}

template<> void real::sprintf(char *str, int ndigits) const template<> void real::sprintf(char *str, int ndigits) const
{ {
real x = *this; real x = *this;
@@ -1485,15 +1499,23 @@ template<> void real::sprintf(char *str, int ndigits) const
static real load_min() static real load_min()
{ {
real ret = 1; real ret = 1;
return ldexp(ret, 2 - (1 << 30));
return ldexp(ret, 1 - real::EXPONENT_BIAS);
} }


static real load_max() static real load_max()
{ {
/* FIXME: the last bits of the mantissa are not properly handled in this
* code! So we fallback to a slow but exact method. */
#if 0
real ret = 1; real ret = 1;
/* FIXME: the last bits of the mantissa are not properly handled! */
ret = ldexp(ret, real::TOTAL_BITS - 1) - ret; ret = ldexp(ret, real::TOTAL_BITS - 1) - ret;
return ldexp(ret, (1 << 30) - (real::TOTAL_BITS - 1));
return ldexp(ret, real::EXPONENT_BIAS + 2 - real::TOTAL_BITS);
#endif
/* Generates 0x1.ffff..ffffp1073741823 */
char str[150];
std::sprintf(str, "0x1.%llx%llx%llx%llx%llx%llx%llx%llxp%d",
-1ll, -1ll, -1ll, -1ll, -1ll, -1ll, -1ll, -1ll, real::EXPONENT_BIAS);
return real(str);
} }


static real load_pi() static real load_pi()


+ 1
- 1
src/t/math/real.cpp View File

@@ -251,7 +251,7 @@ lolunit_declare_fixture(real_test)
/* 1 / 3 * 3 should be close to 1... check that it does not differ /* 1 / 3 * 3 should be close to 1... check that it does not differ
* by more than 2^-k where k is the number of bits in the mantissa. */ * by more than 2^-k where k is the number of bits in the mantissa. */
real a = real::R_1() / real::R_3() * real::R_3(); real a = real::R_1() / real::R_3() * real::R_3();
real b = ldexp(real::R_1() - a, real::BIGITS * real::BIGIT_BITS);
real b = ldexp(real::R_1() - a, real::TOTAL_BITS);


lolunit_assert_lequal((double)fabs(b), 1.0); lolunit_assert_lequal((double)fabs(b), 1.0);
} }


Loading…
Cancel
Save