| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 | /* * File:   dclxvi-20130329/checkdouble.h * Author: Ruben Niederhagen, Peter Schwabe * Public Domain */#ifndef CHECKDOUBLE_H#define CHECKDOUBLE_H#include <execinfo.h>#include <inttypes.h>#include <memory.h>#include <stdlib.h>#include <stdio.h>#include <math.h>#include "zout.hpp" #define MANTISSA_MAX ((1ULL << 53) - 1)class CheckDouble{  public: double v;          unsigned long long mmax;          CheckDouble()          {            v = NAN;            mmax = MANTISSA_MAX;          }          CheckDouble(const double a)          {            v = a;            mmax = (unsigned long long)fabs(a);          }          CheckDouble(const CheckDouble &a)          {            v = a.v;            mmax = a.mmax;          }          CheckDouble(const double a, const unsigned long long int mmax)          {            v = a;            this->mmax = mmax;          }          CheckDouble operator=(const CheckDouble &a)          {            v = a.v;            mmax = a.mmax;            return *this;          }          int operator==(const CheckDouble &a)const          {            return v == a.v;          }          int operator!=(const CheckDouble &a)const          {            return v != a.v;          }          CheckDouble operator+(const CheckDouble &a)const          {            if((mmax+a.mmax) > MANTISSA_MAX)            {              fprintf(stderr, "Overflow in %lf + %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            return CheckDouble(a.v+v, mmax+a.mmax);          }          CheckDouble operator+=(const CheckDouble &a)          {            if((mmax+a.mmax) > MANTISSA_MAX)            {              fprintf(stderr, "Overflow in %lf += %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            v += a.v;            mmax += a.mmax;            return *this;          }          CheckDouble operator-(const CheckDouble &a)const          {            if((mmax+a.mmax) > MANTISSA_MAX)            {              fprintf(stderr, "Overflow in %lf - %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            return CheckDouble(v-a.v, mmax+a.mmax);          }          CheckDouble operator-=(const CheckDouble &a)          {            if((mmax+a.mmax) > MANTISSA_MAX)            {              fprintf(stderr, "Overflow in %lf += %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            v -= a.v;            mmax += a.mmax;            return *this;          }          CheckDouble operator-()const          {            return CheckDouble(-v, mmax);          }          CheckDouble operator*(const CheckDouble &a)const          {            uint64_t l1 = mmax & 0xffffffff; //les 32 bits de poids faible            uint64_t l2 = a.mmax & 0xffffffff;            uint64_t u1 = mmax >> 32;            uint64_t u2 = a.mmax >> 32;            unsigned long long upper = u1 * u2;            if(upper != 0)            {				ecris(upper);              fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            unsigned long long mid = l1 * u2 + u1 * l2;            unsigned long long lower = l1 * l2;            if(lower >= MANTISSA_MAX)            {				ecris(lower);              fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            if(mid > (MANTISSA_MAX>>32))            {				ecris(mid);				zout(l1,l2,u1,u2);				zout(mid,(MANTISSA_MAX>>32));              fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            lower += (mid <<32);            if(lower > MANTISSA_MAX)            {				ecris(lower2);              fprintf(stderr, "Overflow in %lf * %lf\n", v,a.v);              fprintf(stderr, "Maximal values: %llu, %llu\n", mmax,a.mmax);              abort();            }            return CheckDouble(v*a.v, mmax*a.mmax);          }          CheckDouble operator/(const double &a)const          {            if(mmax/fabs(a) > MANTISSA_MAX)            {              fprintf(stderr, "Overflow in %lf / %lf\n", v,a);              fprintf(stderr, "Maximal values: %llu, %lf\n", mmax,a);              abort();            }            return CheckDouble(v/a, mmax/(unsigned long long)fabs(a)+1);          }          CheckDouble operator*=(const int b)           {            CheckDouble op((double) b, abs(b));            *this = *this * op;            return *this;          }          /*          friend CheckDouble operator*(const CheckDouble &a,const int b)           {            CheckDouble op((double) b, abs(b));            return op * a;          }          */                    friend CheckDouble operator*(const int32_t b, const CheckDouble &a)           {            CheckDouble op((double) b, abs(b));            return op * a;          }          friend int operator<(const CheckDouble &op1, const CheckDouble &op2)          {            return op1.v < op2.v;          }                    friend int operator<=(const CheckDouble &op1, const CheckDouble &op2)          {            return op1.v <= op2.v;          }          friend int operator>(const CheckDouble &op1, const CheckDouble &op2)          {            return op1.v > op2.v;          }          friend int operator>=(const CheckDouble &op1, const CheckDouble &op2)          {            return op1.v >= op2.v;          }          friend CheckDouble round(const CheckDouble &a)          {            return CheckDouble(round(a.v),a.mmax);          }                    friend CheckDouble trunc(const CheckDouble &a)          {            return CheckDouble(trunc(a.v),a.mmax);          }          friend CheckDouble remround(const CheckDouble &a, const double d)          {            double carry = round(a.v/d);            return CheckDouble(a.v - carry*d, (unsigned long long)((d+1)/2));          }          friend long long ftoll(const CheckDouble &arg)          {            return (long long)arg.v;          }          friend void setmax(CheckDouble &arg, unsigned long long max)          {            arg.mmax = max;          }          friend double todouble(const CheckDouble &arg)          {            return arg.v;          }};int printfoff(...);#endif // #ifndef CHECKDOUBLE_H
 |