/****************************************************************************** class word A computer word with double-precision arithmetic operations. Type T can be one of the following unsigned long long int, unsigned long int, unsigned short int, and unsigned char. unsigned char could be used for debugging purposes and unsigned long long int or unsigned long int for the actual test runs. Copyright: Jyrki Katajainen Department of Computing University of Copenhagen DK-2100 Copenhagen East, Denmark e-mail: jyrki@di.ku.dk Version: 1.1 January - February 1999 Changes made to version 1.0: 8 Febuary 1999 return pair >(zero, word(0)); ==> return pair >(zero, word(T(0))); Christian Boesgaard cout << "a + a = " << p2.first << '\t' << p2.second << endl; ==> cout << "a + b = " << p2.first << '\t' << p2.second << endl; Christian Boesgaard friend bool operator==(const word&, const word&); friend pair, word > operator+(const word&, const word&); friend pair > operator-(const word&, const word&); friend pair, word > operator*(const word&, const word&); friend ostream& operator<<(ostream&, const word&); ==> friend bool operator==<>(const word&, const word&); friend pair, word > operator+<>(const word&, const word&); friend pair > operator-<>(const word&, const word&); friend pair, word > operator*<>(const word&, const word&); friend ostream& operator<< <>(ostream&, const word&); Tommy New operations implemented operator!= operator< operator> operator<= operator>= ******************************************************************************/ #if !defined(WORD) #define WORD #include // defines pair #include // defines ostream enum sign {zero, plus, minus}; ostream& operator<<(ostream& out, const sign& s) { if (s == minus) out << "-"; else out << ""; return out; } template class word { public: word(); word(T); word(const word&); word length() const; word most_significant_bit() const; word most_significant_half() const; word least_significant_half() const; word& operator>>=(const word&); word& operator<<=(const word&); word& operator=(const word&); friend bool operator==<>(const word&, const word&); friend bool operator!=<>(const word&, const word&); friend bool operator< <>(const word&, const word&); friend bool operator> <>(const word&, const word&); friend bool operator<=<>(const word&, const word&); friend bool operator>=<>(const word&, const word&); friend pair, word > operator+<>(const word&, const word&); friend pair > operator-<>(const word&, const word&); friend pair, word > operator*<>(const word&, const word&); friend ostream& operator<< <>(ostream&, const word&); private: enum {lambda_per_2 = 4 * sizeof(T), lambda_minus_1 = 8 * sizeof(T) - 1, lambda = 8 * sizeof(T)}; T value; }; template inline word::word() : value(T(0)) { } template inline word::word(T v) : value(v) { } template inline word::word(const word& w) { (*this).value = w.value; } template inline word word::length() const { // in bits; must be a power of 2 return word(lambda); } template inline word word::most_significant_bit() const { return word((*this).value >> T(lambda_minus_1)); } template inline word word::most_significant_half() const { return word((*this).value >> T(lambda_per_2)); } template inline word word::least_significant_half() const { T temp = (*this).value >> T(lambda_per_2); temp = temp << T(lambda_per_2); return word((*this).value - temp); } template inline word& word::operator>>=(const word& shift) { (*this).value = (*this).value >> shift.value; return *this; } template inline word& word::operator<<=(const word& shift) { (*this).value = (*this).value << shift.value; return *this; } template inline word& word::operator=(const word& rhs) { if (this == &rhs) return *this; (*this).value = rhs.value; return *this; } // logical operations template bool operator==(const word& x, const word& y) { return x.value == y.value; } template bool operator!=(const word& x, const word& y) { return x.value != y.value; } template bool operator<(const word& x, const word& y) { return x.value < y.value; } template bool operator>(const word& x, const word& y) { return x.value > y.value; } template bool operator<=(const word& x, const word& y) { return x.value <= y.value; } template bool operator>=(const word& x, const word& y) { return x.value >= y.value; } // addition template pair, word > operator+(const word& x, const word& y) { // Warning: & seems not to work properly. Therefore, I avoided it. const T len_minus_1 = x.length().value - T(1); const T two_to_len_minus_1 = T(1) << len_minus_1; word bit_x = x.most_significant_bit(); word bit_y = y.most_significant_bit(); word rest_x = x; if (x.value >= two_to_len_minus_1) rest_x = word(x.value - two_to_len_minus_1); word rest_y = y; if (y.value >= two_to_len_minus_1) rest_y = word(y.value - two_to_len_minus_1); word z = word(rest_x.value + rest_y.value); word bit_z = z.most_significant_bit(); word rest_z = z; if (z.value >= two_to_len_minus_1) rest_z = word(z.value - two_to_len_minus_1); T sum = bit_x.value + bit_y.value + bit_z.value; word carry = word(sum >> T(1)); sum = sum - carry.value - carry.value; T temp = sum << len_minus_1; word low_order_word = word(temp + rest_z.value); return pair, word >(carry, low_order_word); } // subtraction template pair > operator-(const word& x, const word& y) { if (x.value < y.value) { word z = word(y.value - x.value); return pair >(minus, z); } else if (x.value > y.value) { word z = word(x.value - y.value); return pair >(plus, z); } else { return pair >(zero, word(T(0))); } } // multiplication template pair, word > operator*(const word& x, const word& y) { const T half_len = x.length().value / T(2); word x_left = x.most_significant_half(); word x_right = x.least_significant_half(); word y_left = y.most_significant_half(); word y_right = y.least_significant_half(); word t_1 = word(x_right.value * y_right.value); word t_2 = word(x_right.value * y_left.value); word t_3 = word(x_left.value * y_right.value); word t_4 = word(x_left.value * y_left.value); word t_2_left = word(t_2.value >> half_len); word t_2_right_shifted = word(t_2.value << half_len); word t_3_left = word(t_3.value >> half_len); word t_3_right_shifted = word(t_3.value << half_len); pair, word > temp = t_1 + t_2_right_shifted; pair, word > sum = temp.second + t_3_right_shifted; word low_order_word = sum.second; T carry = temp.first.value + sum.first.value; word high_order_word = word(carry + t_2_left.value + t_3_left.value + t_4.value); return pair, word >(high_order_word, low_order_word); } // outputting template ostream& operator<<(ostream& out, const word& w) { long unsigned int temp = (long unsigned int)(w.value); out << temp; return out; } #endif #if defined(UNIT_TEST_WORD) int main() { word a = word((unsigned char)(189)); word b = word((unsigned char)(188)); cout << "a = " << a << endl; cout << "b = " << b << endl; pair, word > p1 = a + a; cout << "a + a = " << p1.first << '\t' << p1.second << endl; pair, word > p2 = a + b; cout << "a + b = " << p2.first << '\t' << p2.second << endl; pair > q1 = a - b; cout << "a - b = " << q1.first << '\t' << q1.second << endl; q1 = a - a; cout << "a - a = " << q1.first << '\t' << q1.second << endl; q1 = b - a; cout << "b - a = " << q1.first << '\t' << q1.second << endl; pair, word > r = a * a; cout << "a * a = " << r.first << '\t' << r.second << endl; return(0); } /* freja> g++ word.cc -DUNIT_TEST_WORD freja> a.out a = 189 b = 188 a + a = 1 122 a + b = 1 121 a - b = 1 1 a - a = 0 0 b - a = 2 1 a * a = 139 137 */ #endif