rational: update with more operators
This commit is contained in:
parent
33ee3ec11c
commit
8840bae7b0
@ -334,6 +334,7 @@ TEST_BIN = \
|
||||
test/pool \
|
||||
test/rand \
|
||||
test/range \
|
||||
test/rational \
|
||||
test/region \
|
||||
test/ripemd \
|
||||
test/sha1 \
|
||||
|
108
rational.cpp
108
rational.cpp
@ -16,85 +16,151 @@
|
||||
|
||||
#include "rational.hpp"
|
||||
|
||||
#include "maths.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using util::rational;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
rational<T>::rational (T _n, T _d):
|
||||
n (_n),
|
||||
d (_d)
|
||||
{ ; }
|
||||
{
|
||||
if (n < 0 && d < 0) {
|
||||
n *= -1;
|
||||
d *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
rational<T>::rational (T v):
|
||||
n (v),
|
||||
d (1)
|
||||
{ ; }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
bool
|
||||
rational<T>::operator== (const rational<T> &rhs) {
|
||||
rational<T>::operator== (const rational<T> rhs) const
|
||||
{
|
||||
return rhs.n == n && rhs.d == d;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
rational<T>::operator float (void) const {
|
||||
bool
|
||||
rational<T>::operator!= (const rational<T> rhs) const
|
||||
{
|
||||
return !operator== (rhs);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
bool
|
||||
rational<T>::operator< (const rational<T> rhs) const
|
||||
{
|
||||
return n * rhs.d < rhs.n * d;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
bool
|
||||
rational<T>::operator>= (const rational<T> rhs) const
|
||||
{
|
||||
return n * rhs.d >= rhs.n * d;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
rational<T>::operator float (void) const
|
||||
{
|
||||
return static_cast<float> (n) / d;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
rational<T>::operator double (void) const {
|
||||
rational<T>::operator double (void) const
|
||||
{
|
||||
return static_cast<double> (n) / d;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
rational<T>::operator int (void) const {
|
||||
return n / d;
|
||||
rational<T>
|
||||
rational<T>::reduced (void) const
|
||||
{
|
||||
auto x = gcd (abs (n), abs (d));
|
||||
|
||||
return { n / x, d / x };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
rational<T>
|
||||
rational<T>::inverse (void) const {
|
||||
rational<T>::inverse (void) const
|
||||
{
|
||||
return rational<T> { d, n };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
rational<T>
|
||||
rational<T>::operator* (const U &rhs) const {
|
||||
rational<T>::operator+ (const T rhs) const
|
||||
{
|
||||
return { n + rhs * d, d };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
rational<T>
|
||||
rational<T>::operator- (const T rhs) const
|
||||
{
|
||||
return { n - rhs * d, d };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
rational<T>
|
||||
rational<T>::operator* (const T rhs) const
|
||||
{
|
||||
return { rhs * n, d };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <typename U>
|
||||
rational<T>
|
||||
rational<T>::operator/ (const U &rhs) const {
|
||||
rational<T>::operator/ (const T rhs) const
|
||||
{
|
||||
return { n, rhs * d };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, typename U>
|
||||
template <typename T>
|
||||
rational<T>
|
||||
util::operator/ (U lhs, rational<T> rhs) {
|
||||
util::operator/ (T lhs, rational<T> rhs) {
|
||||
return rhs.inverse () * lhs;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace util {
|
||||
template struct rational<uint32_t>;
|
||||
template struct rational<int32_t>;
|
||||
template struct util::rational<uint32_t>;
|
||||
template struct util::rational< int32_t>;
|
||||
|
||||
template rational<uint32_t> operator/ (int, rational<uint32_t>);
|
||||
}
|
||||
template util::rational<uint32_t> util::operator/ (uint32_t, util::rational<uint32_t>);
|
||||
|
25
rational.hpp
25
rational.hpp
@ -17,30 +17,41 @@
|
||||
#ifndef __UTIL_RATIONAL_HPP
|
||||
#define __UTIL_RATIONAL_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace util {
|
||||
template <typename T>
|
||||
struct rational {
|
||||
rational (T _n, T _d);
|
||||
static_assert (std::is_integral<T>::value, "only defined for integer types");
|
||||
|
||||
rational (T n, T d);
|
||||
explicit rational (T);
|
||||
rational& operator= (const rational&) = default;
|
||||
|
||||
bool operator== (const rational&);
|
||||
bool operator== (rational) const;
|
||||
bool operator!= (rational) const;
|
||||
bool operator< (rational) const;
|
||||
bool operator>= (rational) const;
|
||||
|
||||
explicit operator float (void) const;
|
||||
explicit operator double (void) const;
|
||||
explicit operator int (void) const;
|
||||
|
||||
rational<T> reduced (void) const;
|
||||
|
||||
rational<T> inverse (void) const;
|
||||
rational<T>& invert (void);
|
||||
|
||||
template <typename U> rational<T> operator* (const U&) const;
|
||||
template <typename U> rational<T> operator/ (const U&) const;
|
||||
rational<T> operator+ (T) const;
|
||||
rational<T> operator- (T) const;
|
||||
rational<T> operator* (T) const;
|
||||
rational<T> operator/ (T) const;
|
||||
|
||||
T n;
|
||||
T d;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
rational<T> operator/ (U, rational<T>);
|
||||
template <typename T>
|
||||
rational<T> operator/ (T, rational<T>);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
35
test/rational.cpp
Normal file
35
test/rational.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "rational.hpp"
|
||||
#include "tap.hpp"
|
||||
|
||||
using util::rational;
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
util::TAP::logger tap;
|
||||
|
||||
{
|
||||
rational<int> val { -3, -2 };
|
||||
tap.expect (val.n == 3 && val.d == 2, "reduce double negatives at construction");
|
||||
}
|
||||
|
||||
{
|
||||
rational<int> val { 5 };
|
||||
tap.expect (val.n == 5 && val.d == 1, "scalar construction");
|
||||
}
|
||||
|
||||
{
|
||||
rational<int> a { 2, 3 };
|
||||
rational<int> b { 3, 2 };
|
||||
|
||||
tap.expect_eq (a.inverse (), b, "inversion and equality");
|
||||
}
|
||||
|
||||
{
|
||||
rational<int> val { 8, 12 };
|
||||
tap.expect_eq (val.reduced (), rational<int> { 2, 3 }, "factorisation");
|
||||
}
|
||||
|
||||
return tap.status ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user