#include #include using std::map; using std::ostream; template const base_t power(base_t x, exp_t n) { base_t r(1); while (n > exp_t(1)) { if (n % exp_t(2) == exp_t(1)) r *= x; n /= exp_t(2); x *= x; } return r*x; } template class bignum_t { public: virtual ~bignum_t() {} bignum_t() : factors() {} bignum_t(const base_t & p) : factors() { // FIXME: Needs to be factored first!!! factors[p] = exp_t(1); } bignum_t(const base_t & p, const exp_t & e) : factors() { // FIXME: Needs to be factored first!!! factors[p] = e; } bignum_t(const bignum_t & rhs) : factors(rhs.factors) {} bignum_t & operator = (const base_t & p) { // FIXME: Needs to be factored first!!! if (this->factors.size()) this->factors.clear(); factors[p] = exp_t(1); return *this; } bignum_t & operator = (const bignum_t & rhs) { if (this->factors.size()) this->factors.clear(); this->factors = rhs.factors; return *this; } friend ostream & operator << (ostream & lhs, \ const bignum_t & rhs) { for (typename map::const_iterator it=rhs.factors.begin();\ it != rhs.factors.end(); it++) { if (it != rhs.factors.begin()) lhs << "*"; lhs << it->first; //if (it->second > exp_t(1) || it->second < exp_t(-1)) lhs << "^" << it->second; } return lhs; } operator int32_t () { int32_t numerator = 1, denominator = 1; for (typename map::const_iterator it = this->factors.begin(); \ it != this->factors.end(); it++) { if (it->second > 0) numerator *= (int32_t) power(it->first, it->second); else denominator *= (int32_t) power(it->first, it->second); } return numerator / denominator; } operator double () { double numerator = 1.0, denominator = 1.0; for (typename map::const_iterator it = this->factors.begin(); \ it != this->factors.end(); it++) { if (it->second > 0) numerator *= (double) power(it->first, it->second); else denominator *= (double) power(it->first, it->second); } return numerator / denominator; } const bignum_t operator ~ () const { bignum_t temp(*this); for (typename map::iterator it = temp.factors.begin(); \ it != temp.factors.end(); it++) it->second *= exp_t(-1); return temp; } const bignum_t & operator ^ (const base_t & rhs) const { bignum_t temp(*this); for (typename map::iterator it = temp.factors.begin(); \ it != temp.factors.end(); it++) it->second *= rhs; return temp; } const bignum_t operator / (const bignum_t & rhs) const { return *this * ~rhs; } const bignum_t operator + (bignum_t addend2) const { bignum_t res, temp, addend1(*this); exp_t diff; // First we copy all the common factors into temp // so that our evaluation and subsequent factoring // is minimized. for (unsigned int j = 0; j < 2; j++) { for (typename map::iterator it1 = \ j ? addend2.factors.begin() : addend1.factors.begin() \ , it2; it1 != addend1.factors.end(); it1++) { it2 = j ? addend1[it1->first] : addend2[it1->first]; diff = exp_t(0); if (it1->second > 0 && it2->second > 0) { diff = (it1->second < it2->second) ? it1->second : it2->second; } else if (it1->second < 0 && it1->second < 0) { diff = (it1->second > it2->second) ? it1->second : it2->second; diff *= exp_t(-1); } if (diff != 0) { temp[it1->first] = diff; it1->second -= diff; it2->second -= diff; } } } // Now we find the lcm and remove it from the addends // and place it in the result // Now we evaluate the numerator // Now we just need to factor the numerator // which is all the factors with positive exponents. // ... Factorization goes here ... // Finally we multiply what we originally factored // out and return return res * temp; } const bignum_t operator * (const bignum_t & rhs) const { bignum_t temp(*this); for (typename map::const_iterator it = \ rhs.factors.begin(); it != rhs.factors.end(); it++) if ( ((bignum_t &) rhs).factors [it->first]) temp.factors[it->first] = it->second + \ ((bignum_t &) *this).factors[it->first]; return temp; } protected: map factors; }; typedef bignum_t bignum32; typedef bignum_t bignum64; using std::cout; using std::endl; int main() { bignum32 b2(5,2); bignum32 b(5,2); bignum32 b3 = b * b2; cout << (double) b3 << endl; /* bignum32 b, b2, b3; srand(time(NULL)); for (unsigned int i = 0; i < 1000; i++) { b = rand() % 1000 + 500; b2 = rand() % 500 + 1; b3 = b / b2; //std::cout << (int32_t) (b3) << std::endl << std::endl; } */ return 0; }