/****************************************************************************** class integer Integers of arbitrary length and some of their logical and arithmetic operations. Copyright: Jyrki Katajainen Department of Computing University of Copenhagen DK-2100 Copenehagen East, Denmark e-mail: jyrki@di.ku.dk Version: 1.5 January - February 1999 The multiplication subroutines written by: ##### e-mail: ##### Changes made to version 1.0: 9 February 1999 Christian Boesgaard friend integer operator+(const integer&, const integer&); friend integer operator*(const integer&, const integer&); friend ostream& operator<<(ostream&, const integer&); ==> friend integer operator+<>(const integer&, const integer&); friend integer operator*<>(const integer&, const integer&); friend ostream& operator<< <>(ostream&, const integer&); Tommy New operations implemented operator-: written by Tommy. Observe that this computes max(0, x - y). operator== operator!= operator< operator> operator<= operator<= Jarl Friis for (r = s_end - 1; (r != s_begin - 1) && *r == word(T(0)); --r) ==> for (r = s_end - 1; (r != s_begin - 1) && *r == T(0); --r) Changes made to version 1.1 9 February 1999 "S|ren Chr. Skov" for (r = s_end - 1; (r != s_begin - 1) && *r == T(0); --r) ==> for (r = s_end - 1; (r != s_begin - 1) && *r == word(T(0)); --r) Changes made to version 1.2 10 February 1999 Yesterday's first aid was a solution, but not the solution. for (r = s_end - 1; (r != s_begin - 1) && *r == word(T(0)); --r) ==> for (r = s_end - 1; (r != s_begin - 1) && word(*r) == word(T(0)); --r) Changes made to version 1.3 10 February 1999 Jarl Friis The main program is now in the form proposed by Jarl. Changes made to version 1.4 14 February 1999 Christian Boesgaard Christian corrected operator< and operator>. I have to admit that I had never time to test the logical operators. I thought they were trivial. Phy, phy, Jyrki. ******************************************************************************/ #include // defines vector #include // defines min #include // defines pair #include "word.cc" // defines word template class integer { public: integer(); integer(T); integer(const integer&); template integer(In, In); integer& operator=(const integer&); friend bool operator==<>(const integer&, const integer&); friend bool operator!=<>(const integer&, const integer&); friend bool operator< <>(const integer&, const integer&); friend bool operator> <>(const integer&, const integer&); friend bool operator<=<>(const integer&, const integer&); friend bool operator>=<>(const integer&, const integer&); friend integer operator+<>(const integer&, const integer&); friend integer operator-<>(const integer&, const integer&); // max(0, x - y) friend pair > operator-<>(const integer&, const integer&); friend integer operator*<>(const integer&, const integer&); friend ostream& operator<< <>(ostream&, const integer&); private: vector > vec; void init(const integer&); }; template void integer::init(const integer& x) { typedef vector >::size_type index; (*this).vec = vector >(); for (index i = 0; i < x.vec.size(); ++i) (*this).vec.push_back(x.vec[i]); } // constructors template integer::integer() { (*this).vec = vector >(); } template integer::integer(T v) { if (v == T(0)) (*this).vec = vector >(); else (*this).vec = vector >(1, word(v)); } template integer::integer(const integer& x) { (*this).init(x); } template template integer::integer(In s_begin, In s_end) { typedef vector >::size_type index; (*this).vec = vector >(); In r; for (r = s_end - 1; (r != s_begin - 1) && word(*r) == word(T(0)); --r) ; r++; In p = s_begin; for (index i = 0; p != r; ++p, ++i) { (*this).vec.push_back(word(*p)); } } // assignment template integer& integer::operator=(const integer& rhs) { if (this == &rhs) return *this; init(rhs); return *this; } // logical operations template bool operator==(const integer& x, const integer& y) { typedef vector >::size_type index; index m = x.vec.size(); index n = y.vec.size(); if (m != n) return false; else { for (index i = 0; i < n; ++i) { if (x.vec[i] != y.vec[i]) return false; } return true; } } template bool operator!=(const integer& x, const integer& y) { return !(x == y); } template bool operator<(const integer& x, const integer& y) { typedef vector >::size_type index; index m = x.vec.size(); index n = y.vec.size(); if (m < n) return true; else if (m > n) return false; else { for (index i = n; i > 0; i--){ if (x.vec[i - 1] != y.vec[i - 1]) { return (x.vec[i - 1] < y.vec[i - 1]); }; }; return false; }; } template bool operator>(const integer& x, const integer& y) { typedef vector >::size_type index; index m = x.vec.size(); index n = y.vec.size(); if (m > n) return true; else if (m < n) return false; else { for (index i = n; i > 0; i--){ if (x.vec[i - 1] != y.vec[i - 1]) { return (x.vec[i - 1] > y.vec[i - 1]); }; }; return false; }; } template bool operator<=(const integer& x, const integer& y) { return !(x > y); } template bool operator>=(const integer& x, const integer& y) { return !(x < y); } // addition template integer operator+(const integer& x, const integer& y) { typedef vector >::size_type index; typedef pair, word > word_pair; index m = min(x.vec.size(), y.vec.size()); index n = max(x.vec.size(), y.vec.size()); vector > v(n + 1, word(T(0))); word carry = word(T(0)); for (index i = 0; i < m; ++i) { word_pair p = x.vec[i] + y.vec[i]; word_pair q = p.second + carry; word_pair r = p.first + q.first; carry = r.second; v[i] = q.second; } if (x.vec.size() > m) { for (index i = m; i < n; ++i) { word_pair p = x.vec[i] + carry; carry = p.first; v[i] = p.second; } } else { for (index i = m; i < n; ++i) { word_pair p = y.vec[i] + carry; carry = p.first; v[i] = p.second; } } v[n] = carry; return integer(v.begin(), v.end()); } // subtraction; computes max(0, x - y) template integer operator-(const integer& x, const integer& y) { typedef vector >::size_type index; typedef pair, word > word_pair; typedef pair > signed_word; index m = y.vec.size(); index n = x.vec.size(); if (m > n) return integer(); vector > v(n, word(T(0))); word borrow = word(T(0)); word maxword = word(T(~0)); for (index i = 0; i < m; ++i) { word_pair q = y.vec[i] + borrow; if (q.first == word(T(1))) { // q.second == 0 borrow = word(T(1)); v[i] = x.vec[i]; } else { signed_word sw = x.vec[i] - q.second; if (sw.first == minus) { borrow = word(T(1)); signed_word pp = maxword - q.second; word_pair t = pp.second + x.vec[i]; word_pair u = t.second + word(T(1)); v[i] = u.second; } else { borrow = word(T(0)); v[i] = sw.second; } } } for (index i=m; i(T(1)); v[i] = maxword; } else { borrow = word(T(0)); v[i] = sw.second; } } if (borrow == word(T(0))) return integer(v.begin(), v.end()); else return integer(); } // multiplication #if SCHOOL template integer operator*(const integer& x, const integer& y) { cerr << "Not yet implemented!" << endl; exit(7); } #else template integer operator*(const integer& x, const integer& y) { cerr << "Not yet implemented!" << endl; exit(7); } #endif // outputting template ostream& operator<<(ostream& out, const integer& x) { typedef vector >::size_type index; if (x.vec.size() == 0) out << word(T(0)); else for (index i = x.vec.size(); i > 0; --i) { out << x.vec[i - 1]; if (i != 0) out << '\t'; } return out; } #if defined(UNIT_TEST_INTEGER) int main() { integer x = integer((unsigned char)(189)); integer x2 = x + x; integer x4 = x2 + x2; integer x3 = x4 - x; integer y = x - x2; integer p1 = x * x; integer p2 = x * p1; integer p3 = p1 * x; integer p4 = p1 * p1; integer p5 = p3 * p1; integer p6 = p1 * p3; cout << "x = " << x << endl; cout << "x + x = " << x2 << endl; cout << "2x + 2x = " << x4 << endl; cout << "4x - x = " << x3 << endl; cout << "max(0, x - 2x) = " << y << endl; cout << "x * x = " << p1 << endl; cout << "x * (x * x) = " << p2 << endl; cout << "(x * x) * x = " << p3 << endl; cout << "(x * x) * (x * x) = " << p4 << endl; cout << "((x * x) * x) * (x * x)= " << p5 << endl; cout << "(x * x) * ((x * x) * x) = " << p6 << endl; return(0); } /* freja> g++ -Wall -DUNIT_TEST_INTEGER -DSCHOOL=1 integer.cc freja> a.out x = 189 x + x = 1 122 2x + 2x = 2 244 4x - x = 2 55 max(0, x - 2x) = 0 x * x = 139 137 x * (x * x) = 103 4 37 (x * x) * x = 103 4 37 (x * x) * (x * x) = 76 14 15 81 ((x * x) * x) * (x * x)= 56 38 97 78 205 (x * x) * ((x * x) * x) = 56 38 97 78 205 freja> g++ -Wall -DUNIT_TEST_INTEGER -DSCHOOL=0 integer.cc freja> a.out x = 189 x + x = 1 122 2x + 2x = 2 244 4x - x = 2 55 max(0, x - 2x) = 0 x * x = 139 137 x * (x * x) = 103 4 37 (x * x) * x = 103 4 37 (x * x) * (x * x) = 76 14 15 81 ((x * x) * x) * (x * x)= 56 38 97 78 205 (x * x) * ((x * x) * x) = 56 38 97 78 205 */ #endif