Ver código fonte

math: ensure real::fabs() is never chosen over std::fabs() for arguments

that are not explicitly real, even with namespace mistakes.
legacy
Sam Hocevar sam 13 anos atrás
pai
commit
8bea4cf189
6 arquivos alterados com 281 adições e 189 exclusões
  1. +1
    -0
      src/debug/sphere.cpp
  2. +168
    -86
      src/lol/math/real.h
  3. +1
    -1
      src/lol/math/vector.h
  4. +1
    -0
      src/lol/unit.h
  5. +84
    -84
      src/real.cpp
  6. +26
    -18
      test/unit/trig.cpp

+ 1
- 0
src/debug/sphere.cpp Ver arquivo

@@ -152,6 +152,7 @@ void DebugSphere::TickDraw(float deltams)
#endif

int const ndiv = 2;
using std::log;
int const ntriangles = 20 * (1 << (ndiv * 2))
* (int)(log(1.0f / 0.01f) / log(1.1f) + 0.9999f);



+ 168
- 86
src/lol/math/real.h Ver arquivo

@@ -24,101 +24,107 @@
namespace lol
{

class real
/*
* The base class for reals. The only real reason for making this a template
* class is so we can have implicit constructors ("real x = 1" works) but
* avoid accidental implicit conversions ("int x = 1; sqrt(x)" will never
* call real::sqrt).
*/
template<int N> class Real
{
public:
real();
real(real const &x);
real const &operator =(real const &x);
~real();
Real();
Real(Real<N> const &x);
Real const &operator =(Real<N> const &x);
~Real();

real(float f);
real(double f);
real(int i);
real(unsigned int i);
Real(float f);
Real(double f);
Real(int i);
Real(unsigned int i);

real(char const *str);
Real(char const *str);

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

real operator +() const;
real operator -() const;
real operator +(real const &x) const;
real operator -(real const &x) const;
real operator *(real const &x) const;
real operator /(real const &x) const;
real const &operator +=(real const &x);
real const &operator -=(real const &x);
real const &operator *=(real const &x);
real const &operator /=(real const &x);
bool operator ==(real const &x) const;
bool operator !=(real const &x) const;
bool operator <(real const &x) const;
bool operator >(real const &x) const;
bool operator <=(real const &x) const;
bool operator >=(real const &x) const;
Real<N> operator +() const;
Real<N> operator -() const;
Real<N> operator +(Real<N> const &x) const;
Real<N> operator -(Real<N> const &x) const;
Real<N> operator *(Real<N> const &x) const;
Real<N> operator /(Real<N> const &x) const;
Real<N> const &operator +=(Real<N> const &x);
Real<N> const &operator -=(Real<N> const &x);
Real<N> const &operator *=(Real<N> const &x);
Real<N> const &operator /=(Real<N> const &x);
bool operator ==(Real<N> const &x) const;
bool operator !=(Real<N> const &x) const;
bool operator <(Real<N> const &x) const;
bool operator >(Real<N> const &x) const;
bool operator <=(Real<N> const &x) const;
bool operator >=(Real<N> const &x) const;

bool operator !() const;
operator bool() const;

/* Trigonometric functions */
friend real sin(real const &x);
friend real cos(real const &x);
friend real tan(real const &x);
friend real asin(real const &x);
friend real acos(real const &x);
friend real atan(real const &x);
friend real atan2(real const &y, real const &x);
template<int M> friend Real<M> sin(Real<M> const &x);
template<int M> friend Real<M> cos(Real<M> const &x);
template<int M> friend Real<M> tan(Real<M> const &x);
template<int M> friend Real<M> asin(Real<M> const &x);
template<int M> friend Real<M> acos(Real<M> const &x);
template<int M> friend Real<M> atan(Real<M> const &x);
template<int M> friend Real<M> atan2(Real<M> const &y, Real<M> const &x);

/* Hyperbolic functions */
friend real sinh(real const &x);
friend real cosh(real const &x);
friend real tanh(real const &x);
template<int M> friend Real<M> sinh(Real<M> const &x);
template<int M> friend Real<M> cosh(Real<M> const &x);
template<int M> friend Real<M> tanh(Real<M> const &x);

/* Exponential and logarithmic functions */
friend real exp(real const &x);
friend real exp2(real const &x);
friend real log(real const &x);
friend real log2(real const &x);
friend real log10(real const &x);
friend real frexp(real const &x, int *exp);
friend real ldexp(real const &x, int exp);
friend real modf(real const &x, real *iptr);
friend real ulp(real const &x);
friend real nextafter(real const &x, real const &y);
template<int M> friend Real<M> exp(Real<M> const &x);
template<int M> friend Real<M> exp2(Real<M> const &x);
template<int M> friend Real<M> log(Real<M> const &x);
template<int M> friend Real<M> log2(Real<M> const &x);
template<int M> friend Real<M> log10(Real<M> const &x);
template<int M> friend Real<M> frexp(Real<M> const &x, int *exp);
template<int M> friend Real<M> ldexp(Real<M> const &x, int exp);
template<int M> friend Real<M> modf(Real<M> const &x, Real<M> *iptr);
template<int M> friend Real<M> ulp(Real<M> const &x);
template<int M> friend Real<M> nextafter(Real<M> const &x, Real<M> const &y);

/* Power functions */
friend real re(real const &x);
friend real sqrt(real const &x);
friend real cbrt(real const &x);
friend real pow(real const &x, real const &y);
friend real gamma(real const &x);
template<int M> friend Real<M> re(Real<M> const &x);
template<int M> friend Real<M> sqrt(Real<M> const &x);
template<int M> friend Real<M> cbrt(Real<M> const &x);
template<int M> friend Real<M> pow(Real<M> const &x, Real<M> const &y);
template<int M> friend Real<M> gamma(Real<M> const &x);

/* Rounding, absolute value, remainder etc. */
friend real ceil(real const &x);
friend real copysign(real const &x, real const &y);
friend real floor(real const &x);
friend real fabs(real const &x);
friend real round(real const &x);
friend real fmod(real const &x, real const &y);
template<int M> friend Real<M> ceil(Real<M> const &x);
template<int M> friend Real<M> copysign(Real<M> const &x, Real<M> const &y);
template<int M> friend Real<M> floor(Real<M> const &x);
template<int M> friend Real<M> fabs(Real<M> const &x);
template<int M> friend Real<M> round(Real<M> const &x);
template<int M> friend Real<M> fmod(Real<M> const &x, Real<N> const &y);

void hexprint() const;
void print(int ndigits = 150) const;

/* Additional operators using base C++ types */
#define __LOL_REAL_OP_HELPER_GENERIC(op, type) \
inline real operator op(type x) const { return *this op (real)x; } \
inline real const &operator op##=(type x) { return *this = (*this op x); }
inline Real<N> operator op(type x) const { return *this op (Real<N>)x; } \
inline Real<N> const &operator op##=(type x) { return *this = (*this op x); }
#define __LOL_REAL_OP_HELPER_FASTMULDIV(op, type) \
inline real operator op(type x) const \
inline Real<N> operator op(type x) const \
{ \
real tmp = *this; return tmp op##= x; \
Real<N> tmp = *this; return tmp op##= x; \
} \
inline real const &operator op##=(type x) \
inline Real<N> const &operator op##=(type x) \
{ \
/* If multiplying or dividing by a power of two, take a shortcut */ \
if ((m_signexp << 1) && x && !(x & (x - 1))) \
@@ -127,7 +133,7 @@ public:
m_signexp += 1 op 2 - 1; /* 1 if op is *, -1 if op is / */ \
} \
else \
*this = *this op (real)x; \
*this = *this op (Real<N>)x; \
return *this; \
}
#define __LOL_REAL_OP_HELPER_INT(type) \
@@ -147,32 +153,32 @@ public:
__LOL_REAL_OP_HELPER_FLOAT(double)

/* Constants */
static real const R_0;
static real const R_1;
static real const R_2;
static real const R_3;
static real const R_10;
static real const R_E;
static real const R_LOG2E;
static real const R_LOG10E;
static real const R_LN2;
static real const R_LN10;
static real const R_PI;
static real const R_PI_2;
static real const R_PI_3;
static real const R_PI_4;
static real const R_1_PI;
static real const R_2_PI;
static real const R_2_SQRTPI;
static real const R_SQRT2;
static real const R_SQRT3;
static real const R_SQRT1_2;
static Real<N> const R_0;
static Real<N> const R_1;
static Real<N> const R_2;
static Real<N> const R_3;
static Real<N> const R_10;
static Real<N> const R_E;
static Real<N> const R_LOG2E;
static Real<N> const R_LOG10E;
static Real<N> const R_LN2;
static Real<N> const R_LN10;
static Real<N> const R_PI;
static Real<N> const R_PI_2;
static Real<N> const R_PI_3;
static Real<N> const R_PI_4;
static Real<N> const R_1_PI;
static Real<N> const R_2_PI;
static Real<N> const R_2_SQRTPI;
static Real<N> const R_SQRT2;
static Real<N> const R_SQRT3;
static Real<N> const R_SQRT1_2;

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

private:
@@ -180,6 +186,82 @@ private:
uint32_t m_signexp;
};

/*
* The real type used for real numbers
*/
typedef Real<16> real;

/*
* Mandatory forward declarations of template specialisations
*/
template<> real::Real();
template<> real::Real(real const &x);
template<> real const &real::operator =(real const &x);
template<> real::~Real();
template<> real::Real(float f);
template<> real::Real(double f);
template<> real::Real(int i);
template<> real::Real(unsigned int i);
template<> real::Real(char const *str);

template<> real::operator float() const;
template<> real::operator double() const;
template<> real::operator int() const;
template<> real::operator unsigned int() const;
template<> real real::operator +() const;
template<> real real::operator -() const;
template<> real real::operator +(real const &x) const;
template<> real real::operator -(real const &x) const;
template<> real real::operator *(real const &x) const;
template<> real real::operator /(real const &x) const;
template<> real const &real::operator +=(real const &x);
template<> real const &real::operator -=(real const &x);
template<> real const &real::operator *=(real const &x);
template<> real const &real::operator /=(real const &x);
template<> bool real::operator ==(real const &x) const;
template<> bool real::operator !=(real const &x) const;
template<> bool real::operator <(real const &x) const;
template<> bool real::operator >(real const &x) const;
template<> bool real::operator <=(real const &x) const;
template<> bool real::operator >=(real const &x) const;
template<> bool real::operator !() const;
template<> real::operator bool() const;

template<> real sin(real const &x);
template<> real cos(real const &x);
template<> real tan(real const &x);
template<> real asin(real const &x);
template<> real acos(real const &x);
template<> real atan(real const &x);
template<> real atan2(real const &y, real const &x);
template<> real sinh(real const &x);
template<> real cosh(real const &x);
template<> real tanh(real const &x);
template<> real exp(real const &x);
template<> real exp2(real const &x);
template<> real log(real const &x);
template<> real log2(real const &x);
template<> real log10(real const &x);
template<> real frexp(real const &x, int *exp);
template<> real ldexp(real const &x, int exp);
template<> real modf(real const &x, real *iptr);
template<> real ulp(real const &x);
template<> real nextafter(real const &x, real const &y);
template<> real re(real const &x);
template<> real sqrt(real const &x);
template<> real cbrt(real const &x);
template<> real pow(real const &x, real const &y);
template<> real gamma(real const &x);
template<> real ceil(real const &x);
template<> real copysign(real const &x, real const &y);
template<> real floor(real const &x);
template<> real fabs(real const &x);
template<> real round(real const &x);
template<> real fmod(real const &x, real const &y);

template<> void real::hexprint() const;
template<> void real::print(int ndigits) const;

} /* namespace lol */

#endif // __LOL_MATH_REAL_H__


+ 1
- 1
src/lol/math/vector.h Ver arquivo

@@ -1047,7 +1047,7 @@ static inline Quat<T> operator /(Quat<T> x, Quat<T> const &y)
tprefix \
inline double len(tname<type> const &a) \
{ \
using namespace std; \
using std::sqrt; \
return sqrt((double)sqlen(a)); \
} \
\


+ 1
- 0
src/lol/unit.h Ver arquivo

@@ -269,6 +269,7 @@ public:
#define LOLUNIT_ASSERT_DOUBLES_EQUAL_GENERIC(msg, a, b, t) \
do { \
m_asserts++; \
using std::fabs; \
if (True() && fabs((a) - (b)) > fabs((t))) \
{ \
m_errorlog << std::endl << std::endl; \


+ 84
- 84
src/real.cpp Ver arquivo

@@ -33,20 +33,20 @@ using namespace std;
namespace lol
{

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

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_signexp = x.m_signexp;
}

real const &real::operator =(real const &x)
template<> real const &real::operator =(real const &x)
{
if (&x != this)
{
@@ -57,16 +57,16 @@ real const &real::operator =(real const &x)
return *this;
}

real::~real()
template<> real::~Real()
{
delete[] m_mantissa;
}

real::real(float f) { new(this) real((double)f); }
real::real(int i) { new(this) real((double)i); }
real::real(unsigned int i) { new(this) real((double)i); }
template<> real::Real(float f) { new(this) real((double)f); }
template<> real::Real(int i) { new(this) real((double)i); }
template<> real::Real(unsigned int i) { new(this) real((double)i); }

real::real(double d)
template<> real::Real(double d)
{
new(this) real();

@@ -93,11 +93,11 @@ real::real(double d)
memset(m_mantissa + 2, 0, (BIGITS - 2) * sizeof(m_mantissa[0]));
}

real::operator float() const { return (float)(double)(*this); }
real::operator int() const { return (int)(double)(*this); }
real::operator unsigned int() const { return (unsigned int)(double)(*this); }
template<> real::operator float() const { return (float)(double)(*this); }
template<> real::operator int() const { return (int)(double)(*this); }
template<> real::operator unsigned() const { return (unsigned)(double)(*this); }

real::operator double() const
template<> real::operator double() const
{
union { double d; uint64_t x; } u;

@@ -135,7 +135,7 @@ real::operator double() const
/*
* Create a real number from an ASCII representation
*/
real::real(char const *str)
template<> real::Real(char const *str)
{
real ret = 0;
int exponent = 0;
@@ -192,19 +192,19 @@ real::real(char const *str)
new(this) real(ret);
}

real real::operator +() const
template<> real real::operator +() const
{
return *this;
}

real real::operator -() const
template<> real real::operator -() const
{
real ret = *this;
ret.m_signexp ^= 0x80000000u;
return ret;
}

real real::operator +(real const &x) const
template<> real real::operator +(real const &x) const
{
if (x.m_signexp << 1 == 0)
return *this;
@@ -268,7 +268,7 @@ real real::operator +(real const &x) const
return ret;
}

real real::operator -(real const &x) const
template<> real real::operator -(real const &x) const
{
if (x.m_signexp << 1 == 0)
return *this;
@@ -372,7 +372,7 @@ real real::operator -(real const &x) const
return ret;
}

real real::operator *(real const &x) const
template<> real real::operator *(real const &x) const
{
real ret;

@@ -445,36 +445,36 @@ real real::operator *(real const &x) const
return ret;
}

real real::operator /(real const &x) const
template<> real real::operator /(real const &x) const
{
return *this * re(x);
}

real const &real::operator +=(real const &x)
template<> real const &real::operator +=(real const &x)
{
real tmp = *this;
return *this = tmp + x;
}

real const &real::operator -=(real const &x)
template<> real const &real::operator -=(real const &x)
{
real tmp = *this;
return *this = tmp - x;
}

real const &real::operator *=(real const &x)
template<> real const &real::operator *=(real const &x)
{
real tmp = *this;
return *this = tmp * x;
}

real const &real::operator /=(real const &x)
template<> real const &real::operator /=(real const &x)
{
real tmp = *this;
return *this = tmp / x;
}

bool real::operator ==(real const &x) const
template<> bool real::operator ==(real const &x) const
{
if ((m_signexp << 1) == 0 && (x.m_signexp << 1) == 0)
return true;
@@ -485,12 +485,12 @@ bool real::operator ==(real const &x) const
return memcmp(m_mantissa, x.m_mantissa, BIGITS * sizeof(uint32_t)) == 0;
}

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

bool real::operator <(real const &x) const
template<> bool real::operator <(real const &x) const
{
/* Ensure both numbers are positive */
if (m_signexp >> 31)
@@ -510,12 +510,12 @@ bool real::operator <(real const &x) const
return false;
}

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

bool real::operator >(real const &x) const
template<> bool real::operator >(real const &x) const
{
/* Ensure both numbers are positive */
if (m_signexp >> 31)
@@ -535,17 +535,17 @@ bool real::operator >(real const &x) const
return false;
}

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

bool real::operator !() const
template<> bool real::operator !() const
{
return !(bool)*this;
}

real::operator bool() const
template<> real::operator bool() const
{
/* A real is "true" if it is non-zero (exponent is non-zero) AND
* not NaN (exponent is not full bits OR higher order mantissa is zero) */
@@ -553,7 +553,7 @@ real::operator bool() const
return exponent && (~exponent || m_mantissa[0] == 0);
}

real re(real const &x)
template<> real re(real const &x)
{
if (!(x.m_signexp << 1))
{
@@ -586,7 +586,7 @@ real re(real const &x)
return ret;
}

real sqrt(real const &x)
template<> real sqrt(real const &x)
{
/* if zero, return x */
if (!(x.m_signexp << 1))
@@ -633,7 +633,7 @@ real sqrt(real const &x)
return ret * x;
}

real cbrt(real const &x)
template<> real cbrt(real const &x)
{
/* if zero, return x */
if (!(x.m_signexp << 1))
@@ -670,7 +670,7 @@ real cbrt(real const &x)
return ret;
}

real pow(real const &x, real const &y)
template<> real pow(real const &x, real const &y)
{
if (!y)
return real::R_1;
@@ -719,7 +719,7 @@ static real fast_fact(int x)
}
}

real gamma(real const &x)
template<> real gamma(real const &x)
{
/* We use Spouge's formula. FIXME: precision is far from acceptable,
* especially with large values. We need to compute this with higher
@@ -746,7 +746,7 @@ real gamma(real const &x)
return ret;
}

real fabs(real const &x)
template<> real fabs(real const &x)
{
real ret = x;
ret.m_signexp &= 0x7fffffffu;
@@ -786,7 +786,7 @@ static real fast_log(real const &x)
return z * sum * 4;
}

real log(real const &x)
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. */
@@ -802,7 +802,7 @@ real log(real const &x)
+ fast_log(tmp);
}

real log2(real const &x)
template<> real log2(real const &x)
{
/* Strategy for log2(x): see log(x). */
real tmp = x;
@@ -817,7 +817,7 @@ real log2(real const &x)
+ fast_log(tmp) * real::R_LOG2E;
}

real log10(real const &x)
template<> real log10(real const &x)
{
return log(x) * real::R_LOG10E;
}
@@ -843,7 +843,7 @@ static real fast_exp_sub(real const &x, real const &y)
return ret / fast_fact(i);
}

real exp(real const &x)
template<> real exp(real const &x)
{
/* Strategy for exp(x): the Taylor series does not converge very fast
* with large positive or negative values.
@@ -868,7 +868,7 @@ real exp(real const &x)
return x1;
}

real exp2(real const &x)
template<> real exp2(real const &x)
{
/* Strategy for exp2(x): see strategy in exp(). */
int e0 = x;
@@ -878,7 +878,7 @@ real exp2(real const &x)
return x1;
}

real sinh(real const &x)
template<> real sinh(real const &x)
{
/* We cannot always use (exp(x)-exp(-x))/2 because we'll lose
* accuracy near zero. We only use this identity for |x|>0.5. If
@@ -889,7 +889,7 @@ real sinh(real const &x)
return (x1 - x2) / 2;
}

real tanh(real const &x)
template<> real tanh(real const &x)
{
/* See sinh() for the strategy here */
bool near_zero = (fabs(x) < real::R_1 / 2);
@@ -899,14 +899,14 @@ real tanh(real const &x)
return (x1 - x2) / x3;
}

real cosh(real const &x)
template<> real cosh(real const &x)
{
/* No need to worry about accuracy here; maybe the last bit is slightly
* off, but that's about it. */
return (exp(x) + exp(-x)) / 2;
}

real frexp(real const &x, int *exp)
template<> real frexp(real const &x, int *exp)
{
if (!x)
{
@@ -921,7 +921,7 @@ real frexp(real const &x, int *exp)
return ret;
}

real ldexp(real const &x, int exp)
template<> real ldexp(real const &x, int exp)
{
real ret = x;
if (ret)
@@ -929,7 +929,7 @@ real ldexp(real const &x, int exp)
return ret;
}

real modf(real const &x, real *iptr)
template<> real modf(real const &x, real *iptr)
{
real absx = fabs(x);
real tmp = floor(absx);
@@ -938,7 +938,7 @@ real modf(real const &x, real *iptr)
return copysign(absx - tmp, x);
}

real ulp(real const &x)
template<> real ulp(real const &x)
{
real ret = real::R_1;
if (x)
@@ -948,7 +948,7 @@ real ulp(real const &x)
return ret;
}

real nextafter(real const &x, real const &y)
template<> real nextafter(real const &x, real const &y)
{
if (x == y)
return x;
@@ -958,7 +958,7 @@ real nextafter(real const &x, real const &y)
return x - ulp(x);
}

real copysign(real const &x, real const &y)
template<> real copysign(real const &x, real const &y)
{
real ret = x;
ret.m_signexp &= 0x7fffffffu;
@@ -966,7 +966,7 @@ real copysign(real const &x, real const &y)
return ret;
}

real floor(real const &x)
template<> real floor(real const &x)
{
/* Strategy for floor(x):
* - if negative, return -ceil(-x)
@@ -997,7 +997,7 @@ real floor(real const &x)
return ret;
}

real ceil(real const &x)
template<> real ceil(real const &x)
{
/* Strategy for ceil(x):
* - if negative, return -floor(-x)
@@ -1012,7 +1012,7 @@ real ceil(real const &x)
return ret + real::R_1;
}

real round(real const &x)
template<> real round(real const &x)
{
if (x < real::R_0)
return -round(-x);
@@ -1020,7 +1020,7 @@ real round(real const &x)
return floor(x + (real::R_1 / 2));
}

real fmod(real const &x, real const &y)
template<> real fmod(real const &x, real const &y)
{
if (!y)
return real::R_0; /* FIXME: return NaN */
@@ -1032,7 +1032,7 @@ real fmod(real const &x, real const &y)
return x - tmp * y;
}

real sin(real const &x)
template<> real sin(real const &x)
{
int switch_sign = x.m_signexp & 0x80000000u;

@@ -1065,12 +1065,12 @@ real sin(real const &x)
return ret;
}

real cos(real const &x)
template<> real cos(real const &x)
{
return sin(real::R_PI_2 - x);
}

real tan(real const &x)
template<> real tan(real const &x)
{
/* Constrain input to [-π,π] */
real y = fmod(x, real::R_PI);
@@ -1137,17 +1137,17 @@ static inline real asinacos(real const &x, int is_asin, int is_negative)
return ret;
}

real asin(real const &x)
template<> real asin(real const &x)
{
return asinacos(x, 1, x.m_signexp >> 31);
}

real acos(real const &x)
template<> real acos(real const &x)
{
return asinacos(x, 0, x.m_signexp >> 31);
}

real atan(real const &x)
template<> real atan(real const &x)
{
/* Computing atan(x): we choose a different Taylor series depending on
* the value of x to help with convergence.
@@ -1250,7 +1250,7 @@ real atan(real const &x)
return ret;
}

real atan2(real const &y, real const &x)
template<> real atan2(real const &y, real const &x)
{
if (!y)
{
@@ -1276,7 +1276,7 @@ real atan2(real const &y, real const &x)
return ret;
}

void real::hexprint() const
template<> void real::hexprint() const
{
printf("%08x", m_signexp);
for (int i = 0; i < BIGITS; i++)
@@ -1284,7 +1284,7 @@ void real::hexprint() const
printf("\n");
}

void real::print(int ndigits) const
template<> void real::print(int ndigits) const
{
real x = *this;

@@ -1350,11 +1350,11 @@ static real fast_pi()
return ret;
}

real const real::R_0 = (real)0.0;
real const real::R_1 = (real)1.0;
real const real::R_2 = (real)2.0;
real const real::R_3 = (real)3.0;
real const real::R_10 = (real)10.0;
template<> real const real::R_0 = (real)0.0;
template<> real const real::R_1 = (real)1.0;
template<> real const real::R_2 = (real)2.0;
template<> real const real::R_3 = (real)3.0;
template<> real const real::R_10 = (real)10.0;

/*
* Initialisation order is important here:
@@ -1364,21 +1364,21 @@ real const real::R_10 = (real)10.0;
* - exp() requires R_0, R_1, R_LN2
* - sqrt() requires R_3
*/
real const real::R_LN2 = fast_log(R_2);
real const real::R_LN10 = log(R_10);
real const real::R_LOG2E = re(R_LN2);
real const real::R_LOG10E = re(R_LN10);
real const real::R_E = exp(R_1);
real const real::R_PI = fast_pi();
real const real::R_PI_2 = R_PI / 2;
real const real::R_PI_3 = R_PI / R_3;
real const real::R_PI_4 = R_PI / 4;
real const real::R_1_PI = re(R_PI);
real const real::R_2_PI = R_1_PI * 2;
real const real::R_2_SQRTPI = re(sqrt(R_PI)) * 2;
real const real::R_SQRT2 = sqrt(R_2);
real const real::R_SQRT3 = sqrt(R_3);
real const real::R_SQRT1_2 = R_SQRT2 / 2;
template<> real const real::R_LN2 = fast_log(R_2);
template<> real const real::R_LN10 = log(R_10);
template<> real const real::R_LOG2E = re(R_LN2);
template<> real const real::R_LOG10E = re(R_LN10);
template<> real const real::R_E = exp(R_1);
template<> real const real::R_PI = fast_pi();
template<> real const real::R_PI_2 = R_PI / 2;
template<> real const real::R_PI_3 = R_PI / R_3;
template<> real const real::R_PI_4 = R_PI / 4;
template<> real const real::R_1_PI = re(R_PI);
template<> real const real::R_2_PI = R_1_PI * 2;
template<> real const real::R_2_SQRTPI = re(sqrt(R_PI)) * 2;
template<> real const real::R_SQRT2 = sqrt(R_2);
template<> real const real::R_SQRT3 = sqrt(R_3);
template<> real const real::R_SQRT1_2 = R_SQRT2 / 2;

} /* namespace lol */


+ 26
- 18
test/unit/trig.cpp Ver arquivo

@@ -24,6 +24,8 @@ LOLUNIT_FIXTURE(TrigTest)
{
LOLUNIT_TEST(Sin)
{
using std::fabs;

for (int i = -10000; i < 10000; i++)
{
double f = (double)i * (1.0 / 1000.0);
@@ -34,7 +36,7 @@ LOLUNIT_FIXTURE(TrigTest)
#endif
double b = lol_sin(f);
LOLUNIT_SET_CONTEXT(f);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11);
}

for (int i = -10000; i < 10000; i++)
@@ -47,12 +49,14 @@ LOLUNIT_FIXTURE(TrigTest)
#endif
double b = lol_sin(f);
LOLUNIT_SET_CONTEXT(f);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11);
}
}

LOLUNIT_TEST(Cos)
{
using std::fabs;

for (int i = -10000; i < 10000; i++)
{
double f = (double)i * (1.0 / 1000.0);
@@ -63,7 +67,7 @@ LOLUNIT_FIXTURE(TrigTest)
#endif
double b = lol_cos(f);
LOLUNIT_SET_CONTEXT(f);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11);
}

for (int i = -10000; i < 10000; i++)
@@ -76,12 +80,14 @@ LOLUNIT_FIXTURE(TrigTest)
#endif
double b = lol_cos(f);
LOLUNIT_SET_CONTEXT(f);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11);
}
}

LOLUNIT_TEST(SinCos)
{
using std::fabs;

for (int i = -10000; i < 10000; i++)
{
double f = (double)i * (1.0 / 1000.0);
@@ -95,8 +101,8 @@ LOLUNIT_FIXTURE(TrigTest)
double b1, b2;
lol_sincos(f, &b1, &b2);
LOLUNIT_SET_CONTEXT(f);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, fabs(f) * 1e-11);
}

for (int i = -10000; i < 10000; i++)
@@ -112,13 +118,15 @@ LOLUNIT_FIXTURE(TrigTest)
double b1, b2;
lol_sincos(f, &b1, &b2);
LOLUNIT_SET_CONTEXT(f);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, fabs(f) * 1e-11);
}
}

LOLUNIT_TEST(Tan)
{
using std::fabs;

for (int i = -100000; i < 100000; i++)
{
double f = (double)i * (1.0 / 10000.0);
@@ -129,12 +137,12 @@ LOLUNIT_FIXTURE(TrigTest)
#endif
double b = lol_tan(f);
LOLUNIT_SET_CONTEXT(f);
if (std::fabs(a) > 1e4)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(a) * std::fabs(a) * 1e-11);
else if (std::fabs(a) > 1.0)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(a) * 1e-11);
if (fabs(a) > 1e4)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * fabs(a) * 1e-11);
else if (fabs(a) > 1.0)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * 1e-11);
else
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11);
}

for (int i = -10000; i < 10000; i++)
@@ -147,12 +155,12 @@ LOLUNIT_FIXTURE(TrigTest)
#endif
double b = lol_tan(f);
LOLUNIT_SET_CONTEXT(f);
if (std::fabs(a) > 1e4)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(a) * std::fabs(a) * 1e-11);
else if (std::fabs(a) > 1.0)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(a) * 1e-11);
if (fabs(a) > 1e4)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * fabs(a) * 1e-11);
else if (fabs(a) > 1.0)
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * 1e-11);
else
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, std::fabs(f) * 1e-11);
LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11);
}
}
};


Carregando…
Cancelar
Salvar