#ifndef IGMDK_LARGE_RATIONAL_H #define IGMDK_LARGE_RATIONAL_H #include "LargeNumber.h" #include "../Utils/Utils.h" #include "../Utils/Debug.h" #include "../Utils/Vector.h" using namespace std; namespace igmdk{ pair rationalize(double x) {//only support the usual binary (not decimal) assert(numeric_limits::radix == 2 && numeric_limits::digits <= numeric_limits::digits); int w = numeric_limits::digits, e; x = frexp(x, &e);//normalize x into [0.5, 1) long long mantissa = ldexp(x, w);//find x^53 return make_pair(mantissa, e - w); } struct Rational: public ArithmeticType { Number numerator, denominator; Rational(Number const& theNumerator = Number(0), Number const& theDenominator = Number(1)): numerator(theNumerator), denominator(theDenominator) { assert(!denominator.isZero()); reduce(); } Rational(double x): denominator(1), numerator(1) { pair mantissaExponent = rationalize(x); numerator = Number(mantissaExponent.first); int e = mantissaExponent.second; if(e < 0) denominator <<= -e; else if(e > 0) numerator <<= e; } void reduce() { Number g = gcd(numerator, denominator); numerator /= g; denominator /= g; } bool isZero()const{return numerator.isZero();} bool isMinus()const {return numerator.isNegative() != denominator.isNegative();} Rational operator-()const { Rational result = *this; result.numerator.negate(); return result; } Rational& operator+=(Rational const& rhs) { numerator = numerator * rhs.denominator + rhs.numerator * denominator; denominator *= rhs.denominator; reduce(); return *this; } Rational& operator-=(Rational const& rhs){return *this += -rhs;} Rational& operator*=(Rational const& rhs) { numerator *= rhs.numerator; denominator *= rhs.denominator; reduce(); return *this; } Rational& operator/=(Rational const& rhs) { assert(!rhs.isZero()); numerator *= rhs.denominator; denominator * rhs.numerator; reduce(); return *this; } int lg()const{return numerator.lg() - denominator.lg();} Number evaluate(Number const& scale = Number(1)) {return numerator * scale / denominator;} }; }//end namespace #endif