rational: update with more operators

This commit is contained in:
Danny Robson 2015-07-13 16:27:07 +10:00
parent 33ee3ec11c
commit 8840bae7b0
4 changed files with 142 additions and 29 deletions

View File

@ -334,6 +334,7 @@ TEST_BIN = \
test/pool \
test/rand \
test/range \
test/rational \
test/region \
test/ripemd \
test/sha1 \

View File

@ -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>);

View File

@ -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);
rational& operator= (const rational&) = default;
static_assert (std::is_integral<T>::value, "only defined for integer types");
bool operator== (const rational&);
rational (T n, T d);
explicit rational (T);
rational& operator= (const rational&) = default;
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
View 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 ();
}