X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Fparanoidnumber.h;h=29e15d599dd73f3f14f4d6dc3be997dee02a33cc;hp=b15292275c81a23e9f3caa8bc5d39f1e5023d675;hb=HEAD;hpb=03cc1b0a0d0705e0b1d92e13fdb18608c7a00272 diff --git a/src/paranoidnumber.h b/src/paranoidnumber.h index b152922..29e15d5 100644 --- a/src/paranoidnumber.h +++ b/src/paranoidnumber.h @@ -16,12 +16,18 @@ // but let's not do that... -#define PARANOID_CACHE_RESULTS +//#define PARANOID_CACHE_RESULTS //#define PARANOID_USE_ARENA -#define PARANOID_SIZE_LIMIT 0 +#define PARANOID_SIZE_LIMIT 4 +// Define to compare all ops against double ops and check within epsilon +//#define PARANOID_COMPARE_EPSILON 1e-6 +#ifdef PARANOID_COMPARE_EPSILON +#define CompareForSanity(...) ParanoidNumber::CompareForSanityEx(__func__, __FILE__, __LINE__, __VA_ARGS__) +#endif + namespace IPDF { typedef enum {ADD, SUBTRACT, MULTIPLY, DIVIDE, NOP} Optype; @@ -83,10 +89,11 @@ namespace IPDF ParanoidNumber(PARANOID_DIGIT_T value=0) : m_value(value), m_next() { #ifdef PARANOID_SIZE_LIMIT - m_size = 0; + m_size = 1; #endif #ifdef PARANOID_CACHE_RESULTS m_cached_result = value; + m_cache_valid = true; #endif } @@ -98,6 +105,7 @@ namespace IPDF #endif #ifdef PARANOID_CACHE_RESULTS m_cached_result = cpy.m_cached_result; + m_cache_valid = cpy.m_cache_valid; #endif for (int i = 0; i < NOP; ++i) { @@ -107,6 +115,9 @@ namespace IPDF m_next[i].push_back(new ParanoidNumber(*next)); // famous last words... } } + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(cpy.Digit(), cpy.Digit()); + #endif //assert(SanityCheck()); } @@ -134,6 +145,8 @@ namespace IPDF // Like this one. It isn't const. double ToDouble() const {return (double)Digit();} + operator double() const {return ToDouble();} + // This one is probably const. bool Floating() const { @@ -167,49 +180,78 @@ namespace IPDF // None of these are actually const - bool operator<(const ParanoidNumber & a) const {return ToDouble() < a.ToDouble();} - bool operator<=(const ParanoidNumber & a) const {return this->operator<(a) || this->operator==(a);} - bool operator>(const ParanoidNumber & a) const {return !(this->operator<=(a));} - bool operator>=(const ParanoidNumber & a) const {return !(this->operator<(a));} - bool operator==(const ParanoidNumber & a) const {return ToDouble() == a.ToDouble();} - bool operator!=(const ParanoidNumber & a) const {return !(this->operator==(a));} + bool operator<(const ParanoidNumber & a) const {return Digit() < a.Digit();} + bool operator<=(const ParanoidNumber & a) const {return Digit() <= a.Digit();} + bool operator>(const ParanoidNumber & a) const {return Digit() > a.Digit();} + bool operator>=(const ParanoidNumber & a) const {return Digit() >= a.Digit();} + bool operator==(const ParanoidNumber & a) const {return Digit() == a.Digit();} + bool operator!=(const ParanoidNumber & a) const {return Digit() != a.Digit();} ParanoidNumber operator-() const { - ParanoidNumber neg(0); - neg -= *this; + ParanoidNumber neg(*this); + neg.Negate(); + #ifdef PARANOID_COMPARE_EPSILON + neg.CompareForSanity(-Digit(), Digit()); + #endif return neg; } + void Negate(); + + ParanoidNumber operator+(const ParanoidNumber & a) const { ParanoidNumber result(*this); result += a; + #ifdef PARANOID_COMPARE_EPSILON + result.CompareForSanity(Digit()+a.Digit(), a.Digit()); + #endif return result; } ParanoidNumber operator-(const ParanoidNumber & a) const { ParanoidNumber result(*this); result -= a; + #ifdef PARANOID_COMPARE_EPSILON + result.CompareForSanity(Digit()-a.Digit(), a.Digit()); + #endif return result; } ParanoidNumber operator*(const ParanoidNumber & a) const { ParanoidNumber result(*this); result *= a; + #ifdef PARANOID_COMPARE_EPSILON + result.CompareForSanity(Digit()*a.Digit(), a.Digit()); + #endif return result; } ParanoidNumber operator/(const ParanoidNumber & a) const { ParanoidNumber result(*this); result /= a; + #ifdef PARANOID_COMPARE_EPSILON + result.CompareForSanity(Digit()/a.Digit(), a.Digit()); + #endif return result; } std::string Str() const; - - + #ifdef PARANOID_COMPARE_EPSILON + inline void CompareForSanityEx(const char * func, const char * file, int line, const digit_t & compare, const digit_t & arg, const digit_t & eps = PARANOID_COMPARE_EPSILON) + { + if (!SanityCheck()) + Fatal("This is insane!"); + if (fabs(Digit() - compare) > eps) + { + Error("Called via %s(%lf) (%s:%d)", func, arg, file, line); + Error("Failed: %s", Str().c_str()); + Fatal("This: %.30lf vs Expected: %.30lf", Digit(), compare); + } + } + #endif std::string PStr() const; @@ -227,6 +269,7 @@ namespace IPDF digit_t m_value; #ifdef PARANOID_CACHE_RESULTS digit_t m_cached_result; + bool m_cache_valid; #endif std::vector m_next[4]; #ifdef PARANOID_SIZE_LIMIT @@ -237,7 +280,7 @@ namespace IPDF class Arena { public: - Arena(int64_t block_size = 10000000); + Arena(int64_t block_size = 10000); ~Arena(); void * allocate(size_t bytes); @@ -270,7 +313,7 @@ template T ParanoidNumber::Convert() const { #ifdef PARANOID_CACHE_RESULTS - if (!isnan((float(m_cached_result)))) + if (m_cache_valid) return (T)m_cached_result; #endif T value(m_value); @@ -291,6 +334,8 @@ T ParanoidNumber::Convert() const + + } #endif //_PARANOIDNUMBER_H