Skip to content

Commit

Permalink
implementing arithmetic operators for binary rational without concern…
Browse files Browse the repository at this point in the history
… of closure constraints
  • Loading branch information
Ravenwater committed Nov 16, 2024
1 parent a61e64a commit 3f5e8ee
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 96 deletions.
15 changes: 10 additions & 5 deletions include/universal/number/rational/attributes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,21 @@ namespace sw { namespace universal {
// They should not be used for the core algorithms.

// free function sign
template<unsigned nbits, typename bt>
bool sign(const rational<nbits,bt>& v) {
template<typename RationalType, std::enable_if_t<is_rational<RationalType>, bool> = true>
bool sign(const RationalType& v) {
return v.sign();
}

template<typename RationalType, std::enable_if_t<is_rational<RationalType>,bool> = true>
int scale(const RationalType& r) {
return r.scale();
}

// generate the maxneg through maxpos value range of a logarithmic number system configuration
// the type of arithmetic, Modulo or Saturating, does not affect the range
template<unsigned nbits, typename bt>
std::string rational_range(const rational<nbits,bt>& v) {
rational<nbits,bt> r{ v };
template<typename RationalType, std::enable_if_t<is_rational<RationalType>, bool> = true>
std::string rational_range(const RationalType& v) {
RationalType r{ v };
std::stringstream s;
s << std::setw(45) << type_tag(r) << " : [ "
<< r.maxneg() << " ... "
Expand Down
151 changes: 140 additions & 11 deletions include/universal/number/rational/rational_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ class rational {
constexpr rational(signed char initial_value) { *this = initial_value; }
constexpr rational(short initial_value) { *this = initial_value; }
constexpr rational(int initial_value) { *this = initial_value; }
constexpr rational(long initial_value) { *this = initial_value; }
constexpr rational(long long initial_value) { *this = initial_value; }
constexpr rational(unsigned char initial_value) { *this = initial_value; }
constexpr rational(unsigned short initial_value) { *this = initial_value; }
constexpr rational(unsigned int initial_value) { *this = initial_value; }
constexpr rational(unsigned long initial_value) { *this = initial_value; }
constexpr rational(unsigned long long initial_value) { *this = initial_value; }
constexpr rational(float initial_value) { *this = initial_value; }
constexpr rational(double initial_value) { *this = initial_value; }
Expand All @@ -115,17 +120,23 @@ class rational {
constexpr rational& operator=(signed char rhs) { return convert_signed(rhs); }
constexpr rational& operator=(short rhs) { return convert_signed(rhs); }
constexpr rational& operator=(int rhs) { return convert_signed(rhs); }
constexpr rational& operator=(long rhs) { return convert_signed(rhs); }
constexpr rational& operator=(long long rhs) { return convert_signed(rhs); }
constexpr rational& operator=(unsigned char rhs) { return convert_unsigned(rhs); }
constexpr rational& operator=(unsigned short rhs) { return convert_unsigned(rhs); }
constexpr rational& operator=(unsigned int rhs) { return convert_unsigned(rhs); }
constexpr rational& operator=(unsigned long rhs) { return convert_unsigned(rhs); }
constexpr rational& operator=(unsigned long long rhs) { return convert_unsigned(rhs); }
constexpr rational& operator=(float rhs) { return convert_ieee754(rhs); }
constexpr rational& operator=(double rhs) { return convert_ieee754(rhs); }

// explicit conversion operators
// explicit conversion operators
explicit operator char() const noexcept { return to_unsigned<char>(); }
explicit operator unsigned short() const noexcept { return to_unsigned<unsigned short>(); }
explicit operator unsigned int() const noexcept { return to_unsigned<unsigned int>(); }
explicit operator unsigned long() const noexcept { return to_unsigned<unsigned long>(); }
explicit operator unsigned long long() const noexcept { return to_unsigned<unsigned long long>(); }
explicit operator signed char() const noexcept { return to_signed<signed char>(); }
explicit operator short() const noexcept { return to_signed<short>(); }
explicit operator int() const noexcept { return to_signed<int>(); }
explicit operator long() const noexcept { return to_signed<long>(); }
Expand All @@ -149,6 +160,8 @@ class rational {
// increment and decrement operators are not defined for rational

// in-place arithmetic assignment operators

// in-place addition
rational& operator+=(const rational& rhs) {
SignedBlockBinary x = n;
SignedBlockBinary y = d;
Expand All @@ -167,27 +180,79 @@ class rational {
normalize();
return *this;
}
rational& operator+=(double rhs) { return *this += rational(rhs); }
rational& operator+=(unsigned short rhs) { return *this += rational(rhs); }
rational& operator+=(unsigned int rhs) { return *this += rational(rhs); }
rational& operator+=(unsigned long rhs) { return *this += rational(rhs); }
rational& operator+=(unsigned long long rhs) { return *this += rational(rhs); }
rational& operator+=(short rhs) { return *this += rational(rhs); }
rational& operator+=(int rhs) { return *this += rational(rhs); }
rational& operator+=(long rhs) { return *this += rational(rhs); }
rational& operator+=(long long rhs) { return *this += rational(rhs); }
rational& operator+=(float rhs) { return *this += rational(rhs); }
rational& operator+=(double rhs) { return *this += rational(rhs); }
// in-place subtraction
rational& operator-=(const rational& rhs) {

normalize();
SignedBlockBinary x = n;
SignedBlockBinary y = d;
SignedBlockBinary v = rhs.n;
SignedBlockBinary w = rhs.d;
if (y == w) {
SignedBlockBinary num = x - v;
n = num;
}
else {
SignedBlockBinary e = x * w - y * v;
SignedBlockBinary f = y * w;
n = e;
d = f;
}
normalize();
return *this;
}
rational& operator-=(double rhs) { return *this -= rational<nbits,bt>(rhs); }
rational& operator-=(unsigned short rhs) { return *this -= rational(rhs); }
rational& operator-=(unsigned int rhs) { return *this -= rational(rhs); }
rational& operator-=(unsigned long rhs) { return *this -= rational(rhs); }
rational& operator-=(unsigned long long rhs) { return *this -= rational(rhs); }
rational& operator-=(short rhs) { return *this -= rational(rhs); }
rational& operator-=(int rhs) { return *this -= rational(rhs); }
rational& operator-=(long rhs) { return *this -= rational(rhs); }
rational& operator-=(long long rhs) { return *this -= rational(rhs); }
rational& operator-=(float rhs) { return *this -= rational(rhs); }
rational& operator-=(double rhs) { return *this -= rational(rhs); }
// in-place multiplication
rational& operator*=(const rational& rhs) {
n *= rhs.n;
d *= rhs.d;
normalize();
return *this;
}
rational& operator*=(double rhs) { return *this *= rational<nbits,bt>(rhs); }
rational& operator/=(const rational& rhs) {
rational& operator*=(unsigned short rhs) { return *this *= rational(rhs); }
rational& operator*=(unsigned int rhs) { return *this *= rational(rhs); }
rational& operator*=(unsigned long rhs) { return *this *= rational(rhs); }
rational& operator*=(unsigned long long rhs) { return *this *= rational(rhs); }
rational& operator*=(short rhs) { return *this *= rational(rhs); }
rational& operator*=(int rhs) { return *this *= rational(rhs); }
rational& operator*=(long rhs) { return *this *= rational(rhs); }
rational& operator*=(long long rhs) { return *this *= rational(rhs); }
rational& operator*=(float rhs) { return *this *= rational(rhs); }
rational& operator*=(double rhs) { return *this *= rational(rhs); }
// in-place division
rational& operator/=(const rational& rhs) {
n *= rhs.d;
d *= rhs.n;
normalize();
return *this;
}
rational& operator/=(double rhs) { return *this /= rational<nbits,bt>(rhs); }
rational& operator/=(unsigned short rhs) { return *this /= rational(rhs); }
rational& operator/=(unsigned int rhs) { return *this /= rational(rhs); }
rational& operator/=(unsigned long rhs) { return *this /= rational(rhs); }
rational& operator/=(unsigned long long rhs) { return *this /= rational(rhs); }
rational& operator/=(short rhs) { return *this /= rational(rhs); }
rational& operator/=(int rhs) { return *this /= rational(rhs); }
rational& operator/=(long rhs) { return *this /= rational(rhs); }
rational& operator/=(long long rhs) { return *this /= rational(rhs); }
rational& operator/=(float rhs) { return *this /= rational(rhs); }
rational& operator/=(double rhs) { return *this /= rational(rhs); }

// modifiers
constexpr void clear() noexcept { n = 0; d = 1; }
Expand Down Expand Up @@ -266,8 +331,13 @@ class rational {
a = b;
b = r;
}
n /= (sign ? -b : b);
d /= (dsign ? -b : b);
n /= b;
d /= b;
if (sign && dsign) {
// move the sign to the numerator
n = -n; d = -d;
}

}

////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -382,7 +452,7 @@ class rational {
uint64_t maxDownShift = find_msb(b);
uint64_t scale = static_cast<uint64_t>(exponent);
if (scale > maxUpShift) {
if (maxUpShift < (scale - maxDownShift)) {
if (scale > (maxUpShift + maxDownShift)) {
// overflow, saturate to maxpos
std::cerr << "overflow: scale = " << exponent << '\n';
maxpos();
Expand Down Expand Up @@ -524,27 +594,86 @@ inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, const ratio
sum += rhs;
return sum;
}
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, signed char rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, short rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, int rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, long rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, long long rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, float rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, double rhs) { return lhs + rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }

// BINARY SUBTRACTION
template<unsigned nbits, typename bt>
inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, const rational<nbits, bt>& rhs) {
rational<nbits,bt> diff(lhs);
diff -= rhs;
return diff;
}
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, signed char rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, short rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, int rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, long rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, long long rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, float rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, double rhs) { return lhs - rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }

// BINARY MULTIPLICATION
template<unsigned nbits, typename bt>
inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, const rational<nbits, bt>& rhs) {
rational<nbits,bt> mul(lhs);
mul *= rhs;
return mul;
}
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, signed char rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, short rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, int rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, long rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, long long rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, float rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, double rhs) { return lhs * rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs)* rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs)* rhs; }

// BINARY DIVISION
template<unsigned nbits, typename bt>
inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, const rational<nbits, bt>& rhs) {
rational<nbits,bt> ratio(lhs);
ratio /= rhs;
return ratio;
}
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, signed char rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, short rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, int rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, long rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, long long rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, float rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, double rhs) { return lhs / rational<nbits, bt>(rhs); }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }

/////////////////////////////////////////////////////////////////////////////////////////////////////////
/// math functions
Expand Down
Loading

0 comments on commit 3f5e8ee

Please sign in to comment.