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
|