Skip to content

Commit 3f5e8ee

Browse files
committed
implementing arithmetic operators for binary rational without concern of closure constraints
1 parent a61e64a commit 3f5e8ee

File tree

3 files changed

+258
-96
lines changed

3 files changed

+258
-96
lines changed

include/universal/number/rational/attributes.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,21 @@ namespace sw { namespace universal {
1717
// They should not be used for the core algorithms.
1818

1919
// free function sign
20-
template<unsigned nbits, typename bt>
21-
bool sign(const rational<nbits,bt>& v) {
20+
template<typename RationalType, std::enable_if_t<is_rational<RationalType>, bool> = true>
21+
bool sign(const RationalType& v) {
2222
return v.sign();
2323
}
2424

25+
template<typename RationalType, std::enable_if_t<is_rational<RationalType>,bool> = true>
26+
int scale(const RationalType& r) {
27+
return r.scale();
28+
}
29+
2530
// generate the maxneg through maxpos value range of a logarithmic number system configuration
2631
// the type of arithmetic, Modulo or Saturating, does not affect the range
27-
template<unsigned nbits, typename bt>
28-
std::string rational_range(const rational<nbits,bt>& v) {
29-
rational<nbits,bt> r{ v };
32+
template<typename RationalType, std::enable_if_t<is_rational<RationalType>, bool> = true>
33+
std::string rational_range(const RationalType& v) {
34+
RationalType r{ v };
3035
std::stringstream s;
3136
s << std::setw(45) << type_tag(r) << " : [ "
3237
<< r.maxneg() << " ... "

include/universal/number/rational/rational_impl.hpp

Lines changed: 140 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,12 @@ class rational {
106106
constexpr rational(signed char initial_value) { *this = initial_value; }
107107
constexpr rational(short initial_value) { *this = initial_value; }
108108
constexpr rational(int initial_value) { *this = initial_value; }
109+
constexpr rational(long initial_value) { *this = initial_value; }
109110
constexpr rational(long long initial_value) { *this = initial_value; }
111+
constexpr rational(unsigned char initial_value) { *this = initial_value; }
112+
constexpr rational(unsigned short initial_value) { *this = initial_value; }
113+
constexpr rational(unsigned int initial_value) { *this = initial_value; }
114+
constexpr rational(unsigned long initial_value) { *this = initial_value; }
110115
constexpr rational(unsigned long long initial_value) { *this = initial_value; }
111116
constexpr rational(float initial_value) { *this = initial_value; }
112117
constexpr rational(double initial_value) { *this = initial_value; }
@@ -115,17 +120,23 @@ class rational {
115120
constexpr rational& operator=(signed char rhs) { return convert_signed(rhs); }
116121
constexpr rational& operator=(short rhs) { return convert_signed(rhs); }
117122
constexpr rational& operator=(int rhs) { return convert_signed(rhs); }
123+
constexpr rational& operator=(long rhs) { return convert_signed(rhs); }
118124
constexpr rational& operator=(long long rhs) { return convert_signed(rhs); }
125+
constexpr rational& operator=(unsigned char rhs) { return convert_unsigned(rhs); }
126+
constexpr rational& operator=(unsigned short rhs) { return convert_unsigned(rhs); }
127+
constexpr rational& operator=(unsigned int rhs) { return convert_unsigned(rhs); }
128+
constexpr rational& operator=(unsigned long rhs) { return convert_unsigned(rhs); }
119129
constexpr rational& operator=(unsigned long long rhs) { return convert_unsigned(rhs); }
120130
constexpr rational& operator=(float rhs) { return convert_ieee754(rhs); }
121131
constexpr rational& operator=(double rhs) { return convert_ieee754(rhs); }
122132

123133
// explicit conversion operators
124-
// explicit conversion operators
134+
explicit operator char() const noexcept { return to_unsigned<char>(); }
125135
explicit operator unsigned short() const noexcept { return to_unsigned<unsigned short>(); }
126136
explicit operator unsigned int() const noexcept { return to_unsigned<unsigned int>(); }
127137
explicit operator unsigned long() const noexcept { return to_unsigned<unsigned long>(); }
128138
explicit operator unsigned long long() const noexcept { return to_unsigned<unsigned long long>(); }
139+
explicit operator signed char() const noexcept { return to_signed<signed char>(); }
129140
explicit operator short() const noexcept { return to_signed<short>(); }
130141
explicit operator int() const noexcept { return to_signed<int>(); }
131142
explicit operator long() const noexcept { return to_signed<long>(); }
@@ -149,6 +160,8 @@ class rational {
149160
// increment and decrement operators are not defined for rational
150161

151162
// in-place arithmetic assignment operators
163+
164+
// in-place addition
152165
rational& operator+=(const rational& rhs) {
153166
SignedBlockBinary x = n;
154167
SignedBlockBinary y = d;
@@ -167,27 +180,79 @@ class rational {
167180
normalize();
168181
return *this;
169182
}
170-
rational& operator+=(double rhs) { return *this += rational(rhs); }
183+
rational& operator+=(unsigned short rhs) { return *this += rational(rhs); }
184+
rational& operator+=(unsigned int rhs) { return *this += rational(rhs); }
185+
rational& operator+=(unsigned long rhs) { return *this += rational(rhs); }
186+
rational& operator+=(unsigned long long rhs) { return *this += rational(rhs); }
187+
rational& operator+=(short rhs) { return *this += rational(rhs); }
188+
rational& operator+=(int rhs) { return *this += rational(rhs); }
189+
rational& operator+=(long rhs) { return *this += rational(rhs); }
190+
rational& operator+=(long long rhs) { return *this += rational(rhs); }
191+
rational& operator+=(float rhs) { return *this += rational(rhs); }
192+
rational& operator+=(double rhs) { return *this += rational(rhs); }
193+
// in-place subtraction
171194
rational& operator-=(const rational& rhs) {
172-
173-
normalize();
195+
SignedBlockBinary x = n;
196+
SignedBlockBinary y = d;
197+
SignedBlockBinary v = rhs.n;
198+
SignedBlockBinary w = rhs.d;
199+
if (y == w) {
200+
SignedBlockBinary num = x - v;
201+
n = num;
202+
}
203+
else {
204+
SignedBlockBinary e = x * w - y * v;
205+
SignedBlockBinary f = y * w;
206+
n = e;
207+
d = f;
208+
}
209+
normalize();
174210
return *this;
175211
}
176-
rational& operator-=(double rhs) { return *this -= rational<nbits,bt>(rhs); }
212+
rational& operator-=(unsigned short rhs) { return *this -= rational(rhs); }
213+
rational& operator-=(unsigned int rhs) { return *this -= rational(rhs); }
214+
rational& operator-=(unsigned long rhs) { return *this -= rational(rhs); }
215+
rational& operator-=(unsigned long long rhs) { return *this -= rational(rhs); }
216+
rational& operator-=(short rhs) { return *this -= rational(rhs); }
217+
rational& operator-=(int rhs) { return *this -= rational(rhs); }
218+
rational& operator-=(long rhs) { return *this -= rational(rhs); }
219+
rational& operator-=(long long rhs) { return *this -= rational(rhs); }
220+
rational& operator-=(float rhs) { return *this -= rational(rhs); }
221+
rational& operator-=(double rhs) { return *this -= rational(rhs); }
222+
// in-place multiplication
177223
rational& operator*=(const rational& rhs) {
178224
n *= rhs.n;
179225
d *= rhs.d;
180226
normalize();
181227
return *this;
182228
}
183-
rational& operator*=(double rhs) { return *this *= rational<nbits,bt>(rhs); }
184-
rational& operator/=(const rational& rhs) {
229+
rational& operator*=(unsigned short rhs) { return *this *= rational(rhs); }
230+
rational& operator*=(unsigned int rhs) { return *this *= rational(rhs); }
231+
rational& operator*=(unsigned long rhs) { return *this *= rational(rhs); }
232+
rational& operator*=(unsigned long long rhs) { return *this *= rational(rhs); }
233+
rational& operator*=(short rhs) { return *this *= rational(rhs); }
234+
rational& operator*=(int rhs) { return *this *= rational(rhs); }
235+
rational& operator*=(long rhs) { return *this *= rational(rhs); }
236+
rational& operator*=(long long rhs) { return *this *= rational(rhs); }
237+
rational& operator*=(float rhs) { return *this *= rational(rhs); }
238+
rational& operator*=(double rhs) { return *this *= rational(rhs); }
239+
// in-place division
240+
rational& operator/=(const rational& rhs) {
185241
n *= rhs.d;
186242
d *= rhs.n;
187243
normalize();
188244
return *this;
189245
}
190-
rational& operator/=(double rhs) { return *this /= rational<nbits,bt>(rhs); }
246+
rational& operator/=(unsigned short rhs) { return *this /= rational(rhs); }
247+
rational& operator/=(unsigned int rhs) { return *this /= rational(rhs); }
248+
rational& operator/=(unsigned long rhs) { return *this /= rational(rhs); }
249+
rational& operator/=(unsigned long long rhs) { return *this /= rational(rhs); }
250+
rational& operator/=(short rhs) { return *this /= rational(rhs); }
251+
rational& operator/=(int rhs) { return *this /= rational(rhs); }
252+
rational& operator/=(long rhs) { return *this /= rational(rhs); }
253+
rational& operator/=(long long rhs) { return *this /= rational(rhs); }
254+
rational& operator/=(float rhs) { return *this /= rational(rhs); }
255+
rational& operator/=(double rhs) { return *this /= rational(rhs); }
191256

192257
// modifiers
193258
constexpr void clear() noexcept { n = 0; d = 1; }
@@ -266,8 +331,13 @@ class rational {
266331
a = b;
267332
b = r;
268333
}
269-
n /= (sign ? -b : b);
270-
d /= (dsign ? -b : b);
334+
n /= b;
335+
d /= b;
336+
if (sign && dsign) {
337+
// move the sign to the numerator
338+
n = -n; d = -d;
339+
}
340+
271341
}
272342

273343
////////////////////////////////////////////////////////////////////////////////////////////
@@ -382,7 +452,7 @@ class rational {
382452
uint64_t maxDownShift = find_msb(b);
383453
uint64_t scale = static_cast<uint64_t>(exponent);
384454
if (scale > maxUpShift) {
385-
if (maxUpShift < (scale - maxDownShift)) {
455+
if (scale > (maxUpShift + maxDownShift)) {
386456
// overflow, saturate to maxpos
387457
std::cerr << "overflow: scale = " << exponent << '\n';
388458
maxpos();
@@ -524,27 +594,86 @@ inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, const ratio
524594
sum += rhs;
525595
return sum;
526596
}
597+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, signed char rhs) { return lhs + rational<nbits, bt>(rhs); }
598+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, short rhs) { return lhs + rational<nbits, bt>(rhs); }
599+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, int rhs) { return lhs + rational<nbits, bt>(rhs); }
600+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, long rhs) { return lhs + rational<nbits, bt>(rhs); }
601+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, long long rhs) { return lhs + rational<nbits, bt>(rhs); }
602+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, float rhs) { return lhs + rational<nbits, bt>(rhs); }
603+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(const rational<nbits, bt>& lhs, double rhs) { return lhs + rational<nbits, bt>(rhs); }
604+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
605+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
606+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
607+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
608+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
609+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
610+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator+(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) + rhs; }
611+
527612
// BINARY SUBTRACTION
528613
template<unsigned nbits, typename bt>
529614
inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, const rational<nbits, bt>& rhs) {
530615
rational<nbits,bt> diff(lhs);
531616
diff -= rhs;
532617
return diff;
533618
}
619+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, signed char rhs) { return lhs - rational<nbits, bt>(rhs); }
620+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, short rhs) { return lhs - rational<nbits, bt>(rhs); }
621+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, int rhs) { return lhs - rational<nbits, bt>(rhs); }
622+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, long rhs) { return lhs - rational<nbits, bt>(rhs); }
623+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, long long rhs) { return lhs - rational<nbits, bt>(rhs); }
624+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, float rhs) { return lhs - rational<nbits, bt>(rhs); }
625+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(const rational<nbits, bt>& lhs, double rhs) { return lhs - rational<nbits, bt>(rhs); }
626+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
627+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
628+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
629+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
630+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
631+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
632+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator-(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) - rhs; }
633+
534634
// BINARY MULTIPLICATION
535635
template<unsigned nbits, typename bt>
536636
inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, const rational<nbits, bt>& rhs) {
537637
rational<nbits,bt> mul(lhs);
538638
mul *= rhs;
539639
return mul;
540640
}
641+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, signed char rhs) { return lhs * rational<nbits, bt>(rhs); }
642+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, short rhs) { return lhs * rational<nbits, bt>(rhs); }
643+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, int rhs) { return lhs * rational<nbits, bt>(rhs); }
644+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, long rhs) { return lhs * rational<nbits, bt>(rhs); }
645+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, long long rhs) { return lhs * rational<nbits, bt>(rhs); }
646+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, float rhs) { return lhs * rational<nbits, bt>(rhs); }
647+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(const rational<nbits, bt>& lhs, double rhs) { return lhs * rational<nbits, bt>(rhs); }
648+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
649+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
650+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
651+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
652+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) * rhs; }
653+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs)* rhs; }
654+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator*(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs)* rhs; }
655+
541656
// BINARY DIVISION
542657
template<unsigned nbits, typename bt>
543658
inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, const rational<nbits, bt>& rhs) {
544659
rational<nbits,bt> ratio(lhs);
545660
ratio /= rhs;
546661
return ratio;
547662
}
663+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, signed char rhs) { return lhs / rational<nbits, bt>(rhs); }
664+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, short rhs) { return lhs / rational<nbits, bt>(rhs); }
665+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, int rhs) { return lhs / rational<nbits, bt>(rhs); }
666+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, long rhs) { return lhs / rational<nbits, bt>(rhs); }
667+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, long long rhs) { return lhs / rational<nbits, bt>(rhs); }
668+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, float rhs) { return lhs / rational<nbits, bt>(rhs); }
669+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(const rational<nbits, bt>& lhs, double rhs) { return lhs / rational<nbits, bt>(rhs); }
670+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(signed char lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
671+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(short lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
672+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(int lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
673+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
674+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(long long lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
675+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(float lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
676+
template<unsigned nbits, typename bt> inline rational<nbits, bt> operator/(double lhs, const rational<nbits, bt>& rhs) { return rational<nbits, bt>(lhs) / rhs; }
548677

549678
/////////////////////////////////////////////////////////////////////////////////////////////////////////
550679
/// math functions

0 commit comments

Comments
 (0)