#ifndef FLOATINGPOINT_H #define FLOATINGPOINT_H #include "../Assertions.h" template struct FP { T val; public: FP(int val) : val(val) {;} FP(size_t val) : val(val) {;} FP(float val) : val(val) {;} FP(double val) : val(val) {;} FP(const FP& o) : val(o.val) {;} FP(const FP& o) : val(o.val) {;} FP(const volatile FP& o) : val(o.val) {;} FP(const volatile FP& o) : val(o.val) {;} //template explicit FP(const FP& o) : val(o.val) {;} //operator FP() const {return FP(val);} operator FP() const {return FP(val);} operator float() const {return static_cast(val);} operator double() const {return static_cast(val);} FP& operator += (const FP o) { checkAddSub(val, o.val); val += o.val; return *this; } FP& operator -= (const FP o) { checkAddSub(val, o.val); val -= o.val; return *this; } FP& operator *= (const FP o) { val *= o.val; return *this; } FP& operator /= (const FP o) { val /= o.val; return *this; } /** -------- X -------- */ FP operator - () const { return FP(-val); } FP operator + (const FP o) const { checkAddSub(val, o.val); return FP(val+o.val); } FP operator - (const FP o) const { checkAddSub(val, o.val); return FP(val-o.val); } FP operator * (const FP o) const { return FP(val*o.val); } FP operator / (const FP o) const { return FP(val/o.val); } FP& operator = (const FP o) { this->val = o; return *this; } volatile FP& operator = (const FP& o) volatile { this->val = o; return *this; } bool operator == (const FP o) const { return val == o.val; } bool operator != (const FP o) const { return val != o.val; } friend std::ostream& operator << (std::ostream& stream, const FP& fp) { stream << fp.val; return stream; } private: static inline void checkAddSub(const T a, const T b) { const int x = expDiff(a,b); Assert::isTrue(x <= 8, "invalid precision for +/-"); } static inline int expDiff(const T a, const T b) { int x, y; frexp(a, &x); frexp(b, &y); const int d = (std::max(x,y) - std::min(x,y)) / 3; // 3 exponents in binary per 10 in decimal? return d; } }; inline FP operator + (const FP& a, const FP& b) {return FP(a.val + b.val);} inline FP operator + (const FP& a, const FP& b) {return FP(a.val + b.val);} inline FP operator + (const FP& a, const float b) {return a + FP(b);} inline FP operator + (const float a, const FP& b) {return FP(a) + b;} inline FP operator + (const FP& a, const double b) {return a + FP(b);} inline FP operator + (const double a, const FP& b) {return FP(a) + b;} inline FP operator + (const FP& a, const float b) {return a + FP(b);} inline FP operator + (const float a, const FP& b) {return FP(a) + b;} inline FP operator + (const FP& a, const double b) {return a + FP(b);} inline FP operator + (const double a, const FP& b) {return FP(a) + b;} inline FP operator - (const FP& a, const FP& b) {return FP(a.val - b.val);} inline FP operator - (const FP& a, const FP& b) {return FP(a.val - b.val);} inline FP operator - (const FP& a, const float b) {return a - FP(b);} inline FP operator - (const float a, const FP& b) {return FP(a) - b;} inline FP operator - (const FP& a, const double b) {return a - FP(b);} inline FP operator - (const double a, const FP& b) {return FP(a) - b;} inline FP operator - (const FP& a, const float b) {return a - FP(b);} inline FP operator - (const float a, const FP& b) {return FP(a) - b;} inline FP operator - (const FP& a, const double b) {return a - FP(b);} inline FP operator - (const double a, const FP& b) {return FP(a) - b;} inline FP operator / (const FP& a, const FP& b) {return FP(a.val / b.val);} inline FP operator / (const FP& a, const FP& b) {return FP(a.val / b.val);} inline FP operator / (const FP& a, const float b) {return a / FP(b);} inline FP operator / (const float a, const FP& b) {return FP(a) / b;} inline FP operator / (const FP& a, const double b) {return a / FP(b);} inline FP operator / (const double a, const FP& b) {return FP(a) / b;} inline FP operator / (const FP& a, const float b) {return a / FP(b);} inline FP operator / (const float a, const FP& b) {return FP(a) / b;} inline FP operator / (const FP& a, const double b) {return a / FP(b);} inline FP operator / (const double a, const FP& b) {return FP(a) / b;} inline FP operator * (const FP& a, const FP& b) {return FP(a.val * b.val);} inline FP operator * (const FP& a, const FP& b) {return FP(a.val * b.val);} inline FP operator * (const FP& a, const float b) {return a * FP(b);} inline FP operator * (const float a, const FP& b) {return FP(a) * b;} inline FP operator * (const FP& a, const double b) {return a * FP(b);} inline FP operator * (const double a, const FP& b) {return FP(a) * b;} inline FP operator * (const FP& a, const float b) {return a * FP(b);} inline FP operator * (const float a, const FP& b) {return FP(a) * b;} inline FP operator * (const FP& a, const double b) {return a * FP(b);} inline FP operator * (const double a, const FP& b) {return FP(a) * b;} inline FP operator / (const FP& a, const int b) {return a / FP(b);} inline FP operator / (const FP& a, const size_t b) {return a / FP(b);} inline FP operator / (const FP& a, const int b) {return a / FP(b);} inline FP operator / (const FP& a, const size_t b) {return a / FP(b);} //template FP operator + (const FP& a, const U b) {return a + FP(b);} //template FP operator + (const U a, const FP& b) {return FP(a) + b;} //template FP operator - (const FP& a, const U b) {return a - FP(b);} //template FP operator - (const U a, const FP& b) {return FP(a) - b;} //template FP operator * (const FP& a, const U b) {return a * FP(b);} //template FP operator * (const U a, const FP& b) {return FP(a) * b;} //template FP operator / (const FP& a, const U b) {return a / FP(b);} //template FP operator / (const U a, const FP& b) {return FP(a) / b;} namespace std { template FP pow (const FP& x, const FP& y) { return FP(std::pow(x.val, y.val)); } template FP pow (const FP& x, const T& y) { return FP(std::pow(x.val, y)); } template FP sqrt (const FP x) { return FP(std::sqrt(x.val)); } template bool isnan(FP x) { return std::isnan(x.val); } } #ifdef WITH_FP using FPFloat = FP; using FPDouble = FP; using FPDefault = FPFloat; #else using FPFloat = float; using FPDouble = double; using FPDefault = double; #endif #endif // FLOATINGPOINT_H