rational: update with more operators
This commit is contained in:
parent
33ee3ec11c
commit
8840bae7b0
@ -334,6 +334,7 @@ TEST_BIN = \
|
|||||||
test/pool \
|
test/pool \
|
||||||
test/rand \
|
test/rand \
|
||||||
test/range \
|
test/range \
|
||||||
|
test/rational \
|
||||||
test/region \
|
test/region \
|
||||||
test/ripemd \
|
test/ripemd \
|
||||||
test/sha1 \
|
test/sha1 \
|
||||||
|
108
rational.cpp
108
rational.cpp
@ -16,85 +16,151 @@
|
|||||||
|
|
||||||
#include "rational.hpp"
|
#include "rational.hpp"
|
||||||
|
|
||||||
|
#include "maths.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
using util::rational;
|
using util::rational;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
rational<T>::rational (T _n, T _d):
|
rational<T>::rational (T _n, T _d):
|
||||||
n (_n),
|
n (_n),
|
||||||
d (_d)
|
d (_d)
|
||||||
{ ; }
|
{
|
||||||
|
if (n < 0 && d < 0) {
|
||||||
|
n *= -1;
|
||||||
|
d *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
rational<T>::rational (T v):
|
||||||
|
n (v),
|
||||||
|
d (1)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename T>
|
||||||
bool
|
bool
|
||||||
rational<T>::operator== (const rational<T> &rhs) {
|
rational<T>::operator== (const rational<T> rhs) const
|
||||||
|
{
|
||||||
return rhs.n == n && rhs.d == d;
|
return rhs.n == n && rhs.d == d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
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;
|
return static_cast<float> (n) / d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
rational<T>::operator double (void) const {
|
rational<T>::operator double (void) const
|
||||||
|
{
|
||||||
return static_cast<double> (n) / d;
|
return static_cast<double> (n) / d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
rational<T>::operator int (void) const {
|
rational<T>
|
||||||
return n / d;
|
rational<T>::reduced (void) const
|
||||||
|
{
|
||||||
|
auto x = gcd (abs (n), abs (d));
|
||||||
|
|
||||||
|
return { n / x, d / x };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
rational<T>
|
rational<T>
|
||||||
rational<T>::inverse (void) const {
|
rational<T>::inverse (void) const
|
||||||
|
{
|
||||||
return rational<T> { d, n };
|
return rational<T> { d, n };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename U>
|
|
||||||
rational<T>
|
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 };
|
return { rhs * n, d };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename U>
|
|
||||||
rational<T>
|
rational<T>
|
||||||
rational<T>::operator/ (const U &rhs) const {
|
rational<T>::operator/ (const T rhs) const
|
||||||
|
{
|
||||||
return { n, rhs * d };
|
return { n, rhs * d };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename U>
|
template <typename T>
|
||||||
rational<T>
|
rational<T>
|
||||||
util::operator/ (U lhs, rational<T> rhs) {
|
util::operator/ (T lhs, rational<T> rhs) {
|
||||||
return rhs.inverse () * lhs;
|
return rhs.inverse () * lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
namespace util {
|
template struct util::rational<uint32_t>;
|
||||||
template struct rational<uint32_t>;
|
template struct util::rational< int32_t>;
|
||||||
template struct 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
|
#ifndef __UTIL_RATIONAL_HPP
|
||||||
#define __UTIL_RATIONAL_HPP
|
#define __UTIL_RATIONAL_HPP
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct rational {
|
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;
|
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 float (void) const;
|
||||||
explicit operator double (void) const;
|
explicit operator double (void) const;
|
||||||
explicit operator int (void) const;
|
|
||||||
|
rational<T> reduced (void) const;
|
||||||
|
|
||||||
rational<T> inverse (void) const;
|
rational<T> inverse (void) const;
|
||||||
rational<T>& invert (void);
|
rational<T>& invert (void);
|
||||||
|
|
||||||
template <typename U> rational<T> operator* (const U&) const;
|
rational<T> operator+ (T) 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;
|
||||||
|
|
||||||
T n;
|
T n;
|
||||||
T d;
|
T d;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T>
|
||||||
rational<T> operator/ (U, rational<T>);
|
rational<T> operator/ (T, rational<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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