Browse Source

math: allow to create real numbers from long doubles

legacy
Sam Hocevar 9 years ago
parent
commit
10f244192c
3 changed files with 38 additions and 0 deletions
  1. +5
    -0
      src/lol/math/real.h
  2. +17
    -0
      src/math/real.cpp
  3. +16
    -0
      src/t/math/real.cpp

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

@@ -45,6 +45,7 @@ public:


Real(float f); Real(float f);
Real(double f); Real(double f);
Real(long double f);
Real(int32_t i); Real(int32_t i);
Real(uint32_t i); Real(uint32_t i);
Real(int64_t i); Real(int64_t i);
@@ -54,6 +55,7 @@ public:


operator float() const; operator float() const;
operator double() const; operator double() const;
operator long double() const;
operator int() const; operator int() const;
operator unsigned int() const; operator unsigned int() const;


@@ -171,6 +173,7 @@ public:
__LOL_REAL_OP_HELPER_INT(unsigned int) __LOL_REAL_OP_HELPER_INT(unsigned int)
__LOL_REAL_OP_HELPER_FLOAT(float) __LOL_REAL_OP_HELPER_FLOAT(float)
__LOL_REAL_OP_HELPER_FLOAT(double) __LOL_REAL_OP_HELPER_FLOAT(double)
__LOL_REAL_OP_HELPER_FLOAT(long double)


/* Constants */ /* Constants */
static Real<N> const& R_0(); static Real<N> const& R_0();
@@ -217,6 +220,7 @@ template<> real const &real::operator =(real const &x);
template<> real::~Real(); template<> real::~Real();
template<> real::Real(float f); template<> real::Real(float f);
template<> real::Real(double f); template<> real::Real(double f);
template<> real::Real(long double f);
template<> real::Real(int32_t i); template<> real::Real(int32_t i);
template<> real::Real(uint32_t i); template<> real::Real(uint32_t i);
template<> real::Real(int64_t i); template<> real::Real(int64_t i);
@@ -225,6 +229,7 @@ template<> real::Real(char const *str);


template<> real::operator float() const; template<> real::operator float() const;
template<> real::operator double() const; template<> real::operator double() const;
template<> real::operator long double() const;
template<> real::operator int() const; template<> real::operator int() const;
template<> real::operator unsigned int() const; template<> real::operator unsigned int() const;
template<> real real::operator +() const; template<> real real::operator +() const;


+ 17
- 0
src/math/real.cpp View File

@@ -136,6 +136,16 @@ template<> real::Real(double d)
memset(m_mantissa + 2, 0, (BIGITS - 2) * sizeof(m_mantissa[0])); memset(m_mantissa + 2, 0, (BIGITS - 2) * sizeof(m_mantissa[0]));
} }


template<> real::Real(long double f)
{
/* We don’t know the long double layout, so we split it into
* two doubles instead. */
double hi = double(f);
double lo = double(f - (long double)hi);;
new(this) real(hi);
*this += lo;
}

template<> real::operator float() const { return (float)(double)(*this); } template<> real::operator float() const { return (float)(double)(*this); }
template<> real::operator int() const { return (int)(double)(*this); } template<> real::operator int() const { return (int)(double)(*this); }
template<> real::operator unsigned() const { return (unsigned)(double)(*this); } template<> real::operator unsigned() const { return (unsigned)(double)(*this); }
@@ -175,6 +185,13 @@ template<> real::operator double() const
return u.d; return u.d;
} }


template<> real::operator long double() const
{
double hi = double(*this);
double lo = double(*this - hi);
return (long double)(hi) + (long double)(lo);
}

/* /*
* Create a real number from an ASCII representation * Create a real number from an ASCII representation
*/ */


+ 16
- 0
src/t/math/real.cpp View File

@@ -102,6 +102,22 @@ lolunit_declare_fixture(real_test)
lolunit_assert_doubles_equal(a6, 1234567876543210.0, 0.0); lolunit_assert_doubles_equal(a6, 1234567876543210.0, 0.0);
} }


lolunit_declare_test(long_double_to_real)
{
real r((long double)1 / 3);

// Count how many bits are correct
int ok_bits = 0;
while (int(r) == 0)
{
r = (r * 4) - 1;
ok_bits += 2;
}

// 64 bits means our precision is better than double
lolunit_assert_greater(ok_bits, 64);
}

lolunit_declare_test(init) lolunit_declare_test(init)
{ {
real r; real r;


Loading…
Cancel
Save