fix complex, rational

This commit is contained in:
bolero-MURAKAMI 2012-08-29 01:16:12 +09:00
parent cdb10c0fbe
commit 6b3f7ad894
19 changed files with 1568 additions and 1360 deletions

View file

@ -1,588 +1,12 @@
#ifndef SPROUT_COMPLEX_HPP
#define SPROUT_COMPLEX_HPP
#include <iosfwd>
#include <ios>
#include <sprout/config.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/abs.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/cos.hpp>
#include <sprout/math/atan2.hpp>
#include <sprout/math/sinh.hpp>
#include <sprout/math/cosh.hpp>
#include <sprout/math/exp.hpp>
#include <sprout/math/log.hpp>
#include <sprout/math/pow.hpp>
#include <sprout/math/sqrt.hpp>
#include <sprout/math/ceil.hpp>
#include <sprout/math/floor.hpp>
#include <sprout/math/trunc.hpp>
#include <sprout/math/round.hpp>
namespace sprout {
template<typename T>
class complex;
template<typename T>
SPROUT_CONSTEXPR T norm(sprout::complex<T> const& x);
//
// complex
//
template<typename T>
class complex {
public:
typedef T value_type;
private:
T re_;
T im_;
public:
SPROUT_CONSTEXPR complex(T const& re = T(), T const& im = T())
: re_(re)
, im_(im)
{}
SPROUT_CONSTEXPR complex(complex const&) = default;
template<typename X>
SPROUT_CONSTEXPR complex(complex<X> const& other)
: re_(other.real())
, im_(other.imag())
{}
SPROUT_CONSTEXPR T real() const {
return re_;
}
void real(T re) {
re_ = re;
}
SPROUT_CONSTEXPR T imag() const{
return im_;
}
void imag(T im) {
im_ = im;
}
complex<T>& operator=(T const& rhs) {
re_ = rhs;
im_ = T();
return *this;
}
complex<T>& operator+=(T const& rhs) {
re_ += rhs;
return *this;
}
complex<T>& operator-=(T const& rhs) {
re_ -= rhs;
return *this;
}
complex<T>& operator*=(T const& rhs) {
re_ *= rhs;
im_ *= rhs;
return *this;
}
complex<T>& operator/=(T const& rhs) {
re_ /= rhs;
im_ /= rhs;
return *this;
}
complex& operator=(complex const&) = default;
template<typename X>
complex<T>& operator=(complex<X> const& rhs) {
re_ = rhs.real();
im_ = rhs.imag();
return *this;
}
template<typename X>
complex<T>& operator+=(complex<X> const& rhs) {
re_ += rhs.real();
im_ += rhs.imag();
return *this;
}
template<typename X>
complex<T>& operator-=(complex<X> const& rhs) {
re_ -= rhs.real();
im_ -= rhs.imag();
return *this;
}
template<typename X>
complex<T>& operator*=(complex<X> const& rhs) {
return *this = complex<T>(
re_ * rhs.real() - im_ * rhs.imag(),
re_ * rhs.imag() + im_ * rhs.real()
);
}
template<typename X>
complex<T>& operator/=(complex<X> const& rhs) {
T n = sprout::norm(rhs);
return *this = complex<T>(
(re_ * rhs.real() + im_ * rhs.imag()) / n,
(im_ * rhs.real() - re_ * rhs.imag()) / n
);
}
};
// 26.4.6, operators:
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs.real() + rhs.real(),
lhs.imag() + rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() + rhs,
lhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs + rhs.real(),
rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs.real() - rhs.real(),
lhs.imag() - rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() - rhs,
lhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs - rhs.real(),
-rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs.real() * rhs.real() - lhs.imag() * rhs.imag(),
lhs.real() * rhs.imag() + lhs.imag() * rhs.real()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() * rhs,
lhs.imag() * rhs
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs * rhs.real(),
lhs * rhs.imag()
);
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> divides_impl(
sprout::complex<T> const& lhs,
sprout::complex<T> const& rhs,
T const& n
)
{
return sprout::complex<T>(
(lhs.real() * rhs.real() + lhs.imag() * rhs.imag()) / n,
(lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / n
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> divides_impl(
T const& lhs,
sprout::complex<T> const& rhs,
T const& n
)
{
return sprout::complex<T>(
lhs * rhs.real() / n,
-lhs * rhs.imag() / n
);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::detail::divides_impl(lhs, rhs, sprout::norm(rhs));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() / rhs,
lhs.imag() / rhs
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::detail::divides_impl(lhs, rhs, sprout::norm(rhs));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(sprout::complex<T> const& x) {
return x;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& x) {
return sprout::complex<T>(-x.real(), -x.imag());
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator==(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator==(sprout::complex<T> const& lhs, T const& rhs) {
return lhs.real() == rhs && lhs.imag() == T();
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator==(T const& lhs, sprout::complex<T> const& rhs) {
return lhs == rhs.real() && T() == rhs.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator!=(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return !(lhs == rhs);
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator!=(sprout::complex<T> const& lhs, T const& rhs) {
return !(lhs == rhs);
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator!=(T const& lhs, sprout::complex<T> const& rhs) {
return !(lhs == rhs);
}
template<typename T, typename Char, typename Traits>
std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& lhs, sprout::complex<T>& rhs) {
T re, im;
Char ch;
lhs >> ch;
if (ch == '(') {
lhs >> re >> ch;
if (ch == ',') {
lhs >> im >> ch;
if (ch == ')') {
rhs = sprout::complex<T>(re, im);
} else {
lhs.setstate(std::ios_base::failbit);
}
} else if (ch == ')') {
rhs = re;
} else {
lhs.setstate(std::ios_base::failbit);
}
} else {
lhs.putback(ch);
lhs >> re;
rhs = re;
}
return lhs;
}
template<typename T, typename Char, typename Traits>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& lhs, sprout::complex<T> const& rhs) {
return lhs << '(' << rhs.real() << ',' << rhs.imag() << ')';
}
// 26.4.7, values:
template<typename T>
inline SPROUT_CONSTEXPR T real(sprout::complex<T> const& x) {
return x.real();
}
template<typename T>
inline SPROUT_CONSTEXPR T imag(sprout::complex<T> const& x) {
return x.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR T abs(sprout::complex<T> const& x) {
return sprout::sqrt(sprout::norm(x));
}
template<typename T>
inline SPROUT_CONSTEXPR T arg(sprout::complex<T> const& x) {
return sprout::atan2(x.imag(), x.real());
}
template<typename T>
inline SPROUT_CONSTEXPR T norm(sprout::complex<T> const& x) {
return x.real() * x.real() + x.imag() * x.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> conj(sprout::complex<T> const& x) {
return sprout::complex<T>(x.real(), -x.imag());
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> proj_impl(sprout::complex<T> const& x, T const& den) {
return sprout::complex<T>(
T(2) * x.real() / den,
T(2) * x.imag() / den
);
}
} // detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> proj(sprout::complex<T> const& x) {
return sprout::detail::proj_impl(
x,
sprout::norm(x) + T(1)
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> polar(T const& rho, T const& theta = 0) {
return sprout::complex<T>(rho * sprout::cos(theta), rho * sprout::sin(theta));
}
// 26.4.8, transcendentals:
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> acos(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> asin(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> atan(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> acosh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> asinh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> atanh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> cos(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> cosh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> exp(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> log(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> log10(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, T const& y);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, sprout::complex<T> const& y);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> pow(T const& x, sprout::complex<T> const& y);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> sin(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> sinh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> sqrt(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> tan(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> tanh(sprout::complex<T> const& x);
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> acos_impl(sprout::complex<T> const& t) {
return sprout::complex<T>(sprout::math::half_pi<T>() - t.real(), -t.imag());
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> acos(sprout::complex<T> const& x) {
return sprout::detail::acos_impl(sprout::asin(x));
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> asin_impl(sprout::complex<T> const& t) {
return sprout::complex<T>(t.imag(), -t.real());
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> asin(sprout::complex<T> const& x) {
return sprout::detail::asin_impl(sprout::asinh(sprout::complex<T>(-x.imag(), x.real())));
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atan_impl_1(
sprout::complex<T> const& x,
T const& r2,
T const& z,
T const& num,
T const& den
)
{
return sprout::complex<T>(
T(0.5) * sprout::atan2(T(2) * x.real(), z),
T(0.25) * sprout::log((r2 + num * num) / (r2 + den * den))
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atan_impl(
sprout::complex<T> const& x,
T const& r2
)
{
return sprout::detail::atan_impl_1(
x,
r2,
T(1) - r2 - x.imag() * x.imag(),
x.imag() + T(1),
x.imag() - T(1)
);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atan(sprout::complex<T> const& x) {
return sprout::detail::atan_impl(x, x.real() * x.real());
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> acosh(sprout::complex<T> const& x) {
return T(2) * sprout::log(sprout::sqrt(T(0.5) * (x + T(1))) + sprout::sqrt(T(0.5) * (x - T(1))));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> asinh(sprout::complex<T> const& x) {
return sprout::log(
sprout::sqrt(
sprout::complex<T>(
(x.real() - x.imag()) * (x.real() + x.imag()) + T(1),
T(2) * x.real() * x.imag()
)
)
+ x
);
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atanh_impl_1(
sprout::complex<T> const& x,
T const& i2,
T const& z,
T const& num,
T const& den
)
{
return sprout::complex<T>(
T(0.25) * (sprout::log(i2 + num * num) - sprout::log(i2 + den * den)),
T(0.5) * sprout::atan2(T(2) * x.imag(), z)
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atanh_impl(
sprout::complex<T> const& x,
T const& i2
)
{
return sprout::detail::atanh_impl_1(
x,
i2,
T(1) - i2 - x.real() * x.real(),
T(1) + x.imag(),
T(1) - x.imag()
);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atanh(sprout::complex<T> const& x) {
return sprout::detail::atanh_impl(x, x.imag() * x.imag());
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> cos(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::cos(x.real()) * sprout::cosh(x.imag()),
-(sprout::sin(x.real()) * sprout::sinh(x.imag()))
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> cosh(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::cosh(x.real()) * sprout::cos(x.imag()),
sprout::sinh(x.real()) * sprout::sin(x.imag())
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> exp(sprout::complex<T> const& x) {
return sprout::polar(sprout::exp(x.real()), x.imag());
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> log(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::log(sprout::abs(x)), sprout::arg(x));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> log10(sprout::complex<T> const& x) {
return sprout::log(x) / sprout::log(T(10));
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow_impl(sprout::complex<T> const& t, T const& y) {
return sprout::polar(sprout::exp(y * t.real()), y * t.imag());
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, T const& y) {
return x == T() ? T()
: x.imag() == T() && x.real() > T() ? sprout::pow(x.real(), y)
: sprout::detail::pow_impl(sprout::log(x), y)
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, sprout::complex<T> const& y) {
return x == T() ? T()
: sprout::exp(y * sprout::log(x))
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow(T const& x, sprout::complex<T> const& y) {
return x > T() ? sprout::polar(sprout::pow(x, y.real()), y.imag() * sprout::log(x))
: sprout::pow(sprout::complex<T>(x), y)
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sin(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::sin(x.real()) * sprout::cosh(x.imag()),
sprout::cos(x.real()) * sprout::sinh(x.imag())
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sinh(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::sinh(x.real()) * sprout::cos(x.imag()),
sprout::cosh(x.real()) * sprout::sin(x.imag())
);
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_1(sprout::complex<T> const& x, T const& t) {
return sprout::complex<T>(t, x.imag() < T() ? -t : t);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_2_1(sprout::complex<T> const& x, T const& t, T const& u) {
return x.real() > T() ? sprout::complex<T>(u, x.imag() / t)
: sprout::complex<T>(sprout::abs(x.imag()) / t, x.imag() < T() ? -u : u)
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_2(sprout::complex<T> const& x, T const& t) {
return sprout::detail::sqrt_impl_2_1(x, t, t / 2);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt(sprout::complex<T> const& x) {
return x.real() == T() ? sprout::detail::sqrt_impl_1(x, sprout::sqrt(abs(x.imag()) / 2))
: sprout::detail::sqrt_impl_2(x, sprout::sqrt(2 * (sprout::abs(x) + sprout::abs(x.real()))))
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> tan(sprout::complex<T> const& x) {
return sprout::sin(x) / sprout::cos(x);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> tanh(sprout::complex<T> const& x) {
return sprout::sinh(x) / sprout::cosh(x);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> ceil(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::ceil(x.real()), sprout::ceil(x.imag()));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> floor(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::floor(x.real()), sprout::floor(x.imag()));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> trunc(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::trunc(x.real()), sprout::trunc(x.imag()));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> round(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::round(x.real()), sprout::round(x.imag()));
}
} // namespace sprout
#include <sprout/complex/complex.hpp>
#include <sprout/complex/operators.hpp>
#include <sprout/complex/values.hpp>
#include <sprout/complex/transcendentals.hpp>
#include <sprout/complex/nearest.hpp>
#include <sprout/complex/hash.hpp>
#endif // #ifndef SPROUT_COMPLEX_HPP

110
sprout/complex/complex.hpp Normal file
View file

@ -0,0 +1,110 @@
#ifndef SPROUT_COMPLEX_COMPLEX_HPP
#define SPROUT_COMPLEX_COMPLEX_HPP
#include <sprout/config.hpp>
namespace sprout {
template<typename T>
class complex;
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR T complex_norm(sprout::complex<T> const& x) {
return x.real() * x.real() + x.imag() * x.imag();
}
} // namespace detail
//
// complex
//
template<typename T>
class complex {
public:
typedef T value_type;
private:
T re_;
T im_;
public:
SPROUT_CONSTEXPR complex(T const& re = T(), T const& im = T())
: re_(re)
, im_(im)
{}
SPROUT_CONSTEXPR complex(complex const&) = default;
template<typename X>
SPROUT_CONSTEXPR complex(complex<X> const& other)
: re_(other.real())
, im_(other.imag())
{}
SPROUT_CONSTEXPR T real() const {
return re_;
}
void real(T re) {
re_ = re;
}
SPROUT_CONSTEXPR T imag() const{
return im_;
}
void imag(T im) {
im_ = im;
}
complex<T>& operator=(T const& rhs) {
re_ = rhs;
im_ = T();
return *this;
}
complex<T>& operator+=(T const& rhs) {
re_ += rhs;
return *this;
}
complex<T>& operator-=(T const& rhs) {
re_ -= rhs;
return *this;
}
complex<T>& operator*=(T const& rhs) {
re_ *= rhs;
im_ *= rhs;
return *this;
}
complex<T>& operator/=(T const& rhs) {
re_ /= rhs;
im_ /= rhs;
return *this;
}
complex& operator=(complex const&) = default;
template<typename X>
complex<T>& operator=(complex<X> const& rhs) {
re_ = rhs.real();
im_ = rhs.imag();
return *this;
}
template<typename X>
complex<T>& operator+=(complex<X> const& rhs) {
re_ += rhs.real();
im_ += rhs.imag();
return *this;
}
template<typename X>
complex<T>& operator-=(complex<X> const& rhs) {
re_ -= rhs.real();
im_ -= rhs.imag();
return *this;
}
template<typename X>
complex<T>& operator*=(complex<X> const& rhs) {
return *this = complex<T>(
re_ * rhs.real() - im_ * rhs.imag(),
re_ * rhs.imag() + im_ * rhs.real()
);
}
template<typename X>
complex<T>& operator/=(complex<X> const& rhs) {
T n = sprout::detail::complex_norm(rhs);
return *this = complex<T>(
(re_ * rhs.real() + im_ * rhs.imag()) / n,
(im_ * rhs.real() - re_ * rhs.imag()) / n
);
}
};
} // namespace sprout
#endif // #ifndef SPROUT_COMPLEX_COMPLEX_HPP

19
sprout/complex/hash.hpp Normal file
View file

@ -0,0 +1,19 @@
#ifndef SPROUT_COMPLEX_HASH_HPP
#define SPROUT_COMPLEX_HASH_HPP
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/complex/complex.hpp>
#include <sprout/functional/hash/hash.hpp>
namespace sprout {
//
// hash_value
//
template<typename T>
inline SPROUT_CONSTEXPR std::size_t hash_value(sprout::complex<T> const& v) {
return sprout::hash_values(v.real(), v.imag());
}
} // namespace sprout
#endif // #ifndef SPROUT_COMPLEX_HASH_HPP

View file

@ -0,0 +1,30 @@
#ifndef SPROUT_COMPLEX_NEAREST_HPP
#define SPROUT_COMPLEX_NEAREST_HPP
#include <sprout/config.hpp>
#include <sprout/complex/complex.hpp>
#include <sprout/math/ceil.hpp>
#include <sprout/math/floor.hpp>
#include <sprout/math/trunc.hpp>
#include <sprout/math/round.hpp>
namespace sprout {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> ceil(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::ceil(x.real()), sprout::ceil(x.imag()));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> floor(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::floor(x.real()), sprout::floor(x.imag()));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> trunc(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::trunc(x.real()), sprout::trunc(x.imag()));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> round(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::round(x.real()), sprout::round(x.imag()));
}
} // namespace sprout
#endif // #ifndef SPROUT_COMPLEX_NEAREST_HPP

View file

@ -0,0 +1,179 @@
#ifndef SPROUT_COMPLEX_OPERATORS_HPP
#define SPROUT_COMPLEX_OPERATORS_HPP
#include <iosfwd>
#include <ios>
#include <sprout/config.hpp>
#include <sprout/complex/complex.hpp>
namespace sprout {
// 26.4.6, operators:
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs.real() + rhs.real(),
lhs.imag() + rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() + rhs,
lhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs + rhs.real(),
rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs.real() - rhs.real(),
lhs.imag() - rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() - rhs,
lhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs - rhs.real(),
-rhs.imag()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs.real() * rhs.real() - lhs.imag() * rhs.imag(),
lhs.real() * rhs.imag() + lhs.imag() * rhs.real()
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() * rhs,
lhs.imag() * rhs
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator*(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::complex<T>(
lhs * rhs.real(),
lhs * rhs.imag()
);
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> divides_impl(
sprout::complex<T> const& lhs,
sprout::complex<T> const& rhs,
T const& n
)
{
return sprout::complex<T>(
(lhs.real() * rhs.real() + lhs.imag() * rhs.imag()) / n,
(lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / n
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> divides_impl(
T const& lhs,
sprout::complex<T> const& rhs,
T const& n
)
{
return sprout::complex<T>(
lhs * rhs.real() / n,
-lhs * rhs.imag() / n
);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return sprout::detail::divides_impl(lhs, rhs, sprout::detail::complex_norm(rhs));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(sprout::complex<T> const& lhs, T const& rhs) {
return sprout::complex<T>(
lhs.real() / rhs,
lhs.imag() / rhs
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator/(T const& lhs, sprout::complex<T> const& rhs) {
return sprout::detail::divides_impl(lhs, rhs, sprout::detail::complex_norm(rhs));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator+(sprout::complex<T> const& x) {
return x;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> operator-(sprout::complex<T> const& x) {
return sprout::complex<T>(-x.real(), -x.imag());
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator==(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator==(sprout::complex<T> const& lhs, T const& rhs) {
return lhs.real() == rhs && lhs.imag() == T();
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator==(T const& lhs, sprout::complex<T> const& rhs) {
return lhs == rhs.real() && T() == rhs.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator!=(sprout::complex<T> const& lhs, sprout::complex<T> const& rhs) {
return !(lhs == rhs);
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator!=(sprout::complex<T> const& lhs, T const& rhs) {
return !(lhs == rhs);
}
template<typename T>
inline SPROUT_CONSTEXPR bool operator!=(T const& lhs, sprout::complex<T> const& rhs) {
return !(lhs == rhs);
}
template<typename T, typename Char, typename Traits>
std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& lhs, sprout::complex<T>& rhs) {
T re, im;
Char ch;
lhs >> ch;
if (ch == '(') {
lhs >> re >> ch;
if (ch == ',') {
lhs >> im >> ch;
if (ch == ')') {
rhs = sprout::complex<T>(re, im);
} else {
lhs.setstate(std::ios_base::failbit);
}
} else if (ch == ')') {
rhs = re;
} else {
lhs.setstate(std::ios_base::failbit);
}
} else {
lhs.putback(ch);
lhs >> re;
rhs = re;
}
return lhs;
}
template<typename T, typename Char, typename Traits>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& lhs, sprout::complex<T> const& rhs) {
return lhs << '(' << rhs.real() << ',' << rhs.imag() << ')';
}
} // namespace sprout
#endif // #ifndef SPROUT_COMPLEX_OPERATORS_HPP

View file

@ -0,0 +1,261 @@
#ifndef SPROUT_COMPLEX_TRANSCENDENTALS_HPP
#define SPROUT_COMPLEX_TRANSCENDENTALS_HPP
#include <sprout/config.hpp>
#include <sprout/complex/complex.hpp>
#include <sprout/complex/operators.hpp>
#include <sprout/complex/values.hpp>
#include <sprout/math/constants.hpp>
#include <sprout/math/abs.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/cos.hpp>
#include <sprout/math/atan2.hpp>
#include <sprout/math/sinh.hpp>
#include <sprout/math/cosh.hpp>
#include <sprout/math/exp.hpp>
#include <sprout/math/log.hpp>
#include <sprout/math/pow.hpp>
#include <sprout/math/sqrt.hpp>
namespace sprout {
// 26.4.8, transcendentals:
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> acos(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> asin(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> atan(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> acosh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> asinh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> atanh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> cos(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> cosh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> exp(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> log(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> log10(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, T const& y);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, sprout::complex<T> const& y);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> pow(T const& x, sprout::complex<T> const& y);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> sin(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> sinh(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> sqrt(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> tan(sprout::complex<T> const& x);
template<typename T>
SPROUT_CONSTEXPR sprout::complex<T> tanh(sprout::complex<T> const& x);
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> acos_impl(sprout::complex<T> const& t) {
return sprout::complex<T>(sprout::math::half_pi<T>() - t.real(), -t.imag());
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> acos(sprout::complex<T> const& x) {
return sprout::detail::acos_impl(sprout::asin(x));
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> asin_impl(sprout::complex<T> const& t) {
return sprout::complex<T>(t.imag(), -t.real());
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> asin(sprout::complex<T> const& x) {
return sprout::detail::asin_impl(sprout::asinh(sprout::complex<T>(-x.imag(), x.real())));
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atan_impl_1(
sprout::complex<T> const& x,
T const& r2,
T const& z,
T const& num,
T const& den
)
{
return sprout::complex<T>(
T(0.5) * sprout::atan2(T(2) * x.real(), z),
T(0.25) * sprout::log((r2 + num * num) / (r2 + den * den))
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atan_impl(
sprout::complex<T> const& x,
T const& r2
)
{
return sprout::detail::atan_impl_1(
x,
r2,
T(1) - r2 - x.imag() * x.imag(),
x.imag() + T(1),
x.imag() - T(1)
);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atan(sprout::complex<T> const& x) {
return sprout::detail::atan_impl(x, x.real() * x.real());
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> acosh(sprout::complex<T> const& x) {
return T(2) * sprout::log(sprout::sqrt(T(0.5) * (x + T(1))) + sprout::sqrt(T(0.5) * (x - T(1))));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> asinh(sprout::complex<T> const& x) {
return sprout::log(
sprout::sqrt(
sprout::complex<T>(
(x.real() - x.imag()) * (x.real() + x.imag()) + T(1),
T(2) * x.real() * x.imag()
)
)
+ x
);
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atanh_impl_1(
sprout::complex<T> const& x,
T const& i2,
T const& z,
T const& num,
T const& den
)
{
return sprout::complex<T>(
T(0.25) * (sprout::log(i2 + num * num) - sprout::log(i2 + den * den)),
T(0.5) * sprout::atan2(T(2) * x.imag(), z)
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atanh_impl(
sprout::complex<T> const& x,
T const& i2
)
{
return sprout::detail::atanh_impl_1(
x,
i2,
T(1) - i2 - x.real() * x.real(),
T(1) + x.imag(),
T(1) - x.imag()
);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> atanh(sprout::complex<T> const& x) {
return sprout::detail::atanh_impl(x, x.imag() * x.imag());
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> cos(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::cos(x.real()) * sprout::cosh(x.imag()),
-(sprout::sin(x.real()) * sprout::sinh(x.imag()))
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> cosh(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::cosh(x.real()) * sprout::cos(x.imag()),
sprout::sinh(x.real()) * sprout::sin(x.imag())
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> exp(sprout::complex<T> const& x) {
return sprout::polar(sprout::exp(x.real()), x.imag());
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> log(sprout::complex<T> const& x) {
return sprout::complex<T>(sprout::log(sprout::abs(x)), sprout::arg(x));
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> log10(sprout::complex<T> const& x) {
return sprout::log(x) / sprout::log(T(10));
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow_impl(sprout::complex<T> const& t, T const& y) {
return sprout::polar(sprout::exp(y * t.real()), y * t.imag());
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, T const& y) {
return x == T() ? T()
: x.imag() == T() && x.real() > T() ? sprout::pow(x.real(), y)
: sprout::detail::pow_impl(sprout::log(x), y)
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow(sprout::complex<T> const& x, sprout::complex<T> const& y) {
return x == T() ? T()
: sprout::exp(y * sprout::log(x))
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> pow(T const& x, sprout::complex<T> const& y) {
return x > T() ? sprout::polar(sprout::pow(x, y.real()), y.imag() * sprout::log(x))
: sprout::pow(sprout::complex<T>(x), y)
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sin(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::sin(x.real()) * sprout::cosh(x.imag()),
sprout::cos(x.real()) * sprout::sinh(x.imag())
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sinh(sprout::complex<T> const& x) {
return sprout::complex<T>(
sprout::sinh(x.real()) * sprout::cos(x.imag()),
sprout::cosh(x.real()) * sprout::sin(x.imag())
);
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_1(sprout::complex<T> const& x, T const& t) {
return sprout::complex<T>(t, x.imag() < T() ? -t : t);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_2_1(sprout::complex<T> const& x, T const& t, T const& u) {
return x.real() > T() ? sprout::complex<T>(u, x.imag() / t)
: sprout::complex<T>(sprout::abs(x.imag()) / t, x.imag() < T() ? -u : u)
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt_impl_2(sprout::complex<T> const& x, T const& t) {
return sprout::detail::sqrt_impl_2_1(x, t, t / 2);
}
} // namespace detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> sqrt(sprout::complex<T> const& x) {
return x.real() == T() ? sprout::detail::sqrt_impl_1(x, sprout::sqrt(abs(x.imag()) / 2))
: sprout::detail::sqrt_impl_2(x, sprout::sqrt(2 * (sprout::abs(x) + sprout::abs(x.real()))))
;
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> tan(sprout::complex<T> const& x) {
return sprout::sin(x) / sprout::cos(x);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> tanh(sprout::complex<T> const& x) {
return sprout::sinh(x) / sprout::cosh(x);
}
} // namespace sprout
#endif // #ifndef SPROUT_COMPLEX_TRANSCENDENTALS_HPP

63
sprout/complex/values.hpp Normal file
View file

@ -0,0 +1,63 @@
#ifndef SPROUT_COMPLEX_VALUES_HPP
#define SPROUT_COMPLEX_VALUES_HPP
#include <sprout/config.hpp>
#include <sprout/complex/complex.hpp>
#include <sprout/complex/operators.hpp>
#include <sprout/math/sin.hpp>
#include <sprout/math/cos.hpp>
#include <sprout/math/atan2.hpp>
#include <sprout/math/sqrt.hpp>
namespace sprout {
template<typename T>
SPROUT_CONSTEXPR T norm(sprout::complex<T> const& x);
// 26.4.7, values:
template<typename T>
inline SPROUT_CONSTEXPR T real(sprout::complex<T> const& x) {
return x.real();
}
template<typename T>
inline SPROUT_CONSTEXPR T imag(sprout::complex<T> const& x) {
return x.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR T abs(sprout::complex<T> const& x) {
return sprout::sqrt(sprout::norm(x));
}
template<typename T>
inline SPROUT_CONSTEXPR T arg(sprout::complex<T> const& x) {
return sprout::atan2(x.imag(), x.real());
}
template<typename T>
inline SPROUT_CONSTEXPR T norm(sprout::complex<T> const& x) {
return x.real() * x.real() + x.imag() * x.imag();
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> conj(sprout::complex<T> const& x) {
return sprout::complex<T>(x.real(), -x.imag());
}
namespace detail {
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> proj_impl(sprout::complex<T> const& x, T const& den) {
return sprout::complex<T>(
T(2) * x.real() / den,
T(2) * x.imag() / den
);
}
} // detail
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> proj(sprout::complex<T> const& x) {
return sprout::detail::proj_impl(
x,
sprout::norm(x) + T(1)
);
}
template<typename T>
inline SPROUT_CONSTEXPR sprout::complex<T> polar(T const& rho, T const& theta = 0) {
return sprout::complex<T>(rho * sprout::cos(theta), rho * sprout::sin(theta));
}
} // namespace sprout
#endif // #ifndef SPROUT_COMPLEX_VALUES_HPP

View file

@ -10,27 +10,76 @@
#include <sprout/type_traits/enabler_if.hpp>
namespace sprout {
namespace hash_detail {
struct enable_hash_value {
public:
typedef std::size_t type;
};
template<typename T, typename Enable = void>
struct basic_numbers {};
template<typename T>
struct basic_numbers<
T,
typename std::enable_if<
(std::is_integral<T>::value && sizeof(T) <= sizeof(std::size_t))
>::type
>
: public sprout::hash_detail::enable_hash_value
{};
template<typename T, typename Enable = void>
struct long_numbers {};
template<typename T>
struct long_numbers<
T,
typename std::enable_if<
(std::is_integral<T>::value && std::is_signed<T>::value && sizeof(T) > sizeof(std::size_t))
>::type
>
: public sprout::hash_detail::enable_hash_value
{};
template<typename T, typename Enable = void>
struct ulong_numbers {};
template<typename T>
struct ulong_numbers<
T,
typename std::enable_if<
(std::is_integral<T>::value && std::is_unsigned<T>::value && sizeof(T) > sizeof(std::size_t))
>::type
>
: public sprout::hash_detail::enable_hash_value
{};
template<typename T, typename Enable = void>
struct float_numbers {};
template<typename T>
struct float_numbers<
T,
typename std::enable_if<
(std::is_floating_point<T>::value)
>::type
>
: public sprout::hash_detail::enable_hash_value
{};
} // namespace hash_detail
//
// hash_value
//
inline SPROUT_CONSTEXPR std::size_t hash_value(bool v);
inline SPROUT_CONSTEXPR std::size_t hash_value(char v);
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned char v);
inline SPROUT_CONSTEXPR std::size_t hash_value(signed char v);
inline SPROUT_CONSTEXPR std::size_t hash_value(char16_t v);
inline SPROUT_CONSTEXPR std::size_t hash_value(char32_t v);
inline SPROUT_CONSTEXPR std::size_t hash_value(wchar_t v);
inline SPROUT_CONSTEXPR std::size_t hash_value(short v);
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned short v);
inline SPROUT_CONSTEXPR std::size_t hash_value(int v);
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned int v);
inline SPROUT_CONSTEXPR std::size_t hash_value(long v);
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned long v);
inline SPROUT_CONSTEXPR std::size_t hash_value(long long v);
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned long long v);
//inline SPROUT_CONSTEXPR std::size_t hash_value(float v);
//inline SPROUT_CONSTEXPR std::size_t hash_value(double v);
//inline SPROUT_CONSTEXPR std::size_t hash_value(long double v);
template<typename T>
inline SPROUT_CONSTEXPR typename sprout::hash_detail::basic_numbers<T>::type
hash_value(T);
template<typename T>
inline SPROUT_CONSTEXPR typename sprout::hash_detail::long_numbers<T>::type
hash_value(T);
template<typename T>
inline SPROUT_CONSTEXPR typename sprout::hash_detail::ulong_numbers<T>::type
hash_value(T);
// template<typename T>
// inline SPROUT_CONSTEXPR typename sprout::hash_detail::float_numbers<T>::type
// hash_value(T);
template<
typename T,
typename sprout::enabler_if<std::is_pointer<typename std::remove_reference<T>::type>::value>::type
@ -104,51 +153,26 @@ namespace sprout {
//
// hash_value
//
inline SPROUT_CONSTEXPR std::size_t hash_value(bool v) {
template<typename T>
inline SPROUT_CONSTEXPR typename sprout::hash_detail::basic_numbers<T>::type
hash_value(T v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(char v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned char v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(signed char v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(char16_t v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(char32_t v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(wchar_t v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(short v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned short v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(int v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned int v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(long v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned long v) {
return static_cast<std::size_t>(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(long long v) {
template<typename T>
inline SPROUT_CONSTEXPR typename sprout::hash_detail::long_numbers<T>::type
hash_value(T v) {
return sprout::hash_detail::hash_value_signed(v);
}
inline SPROUT_CONSTEXPR std::size_t hash_value(unsigned long long v) {
template<typename T>
inline SPROUT_CONSTEXPR typename sprout::hash_detail::ulong_numbers<T>::type
hash_value(T v) {
return sprout::hash_detail::hash_value_unsigned(v);
}
// template<typename T>
// inline SPROUT_CONSTEXPR typename sprout::hash_detail::float_numbers<T>::type
// hash_value(T v) {
// return sprout::hash_detail::hash_value_float(v);
// }
template<
typename T,
typename sprout::enabler_if<std::is_pointer<typename std::remove_reference<T>::type>::value>::type = sprout::enabler

View file

@ -9,7 +9,7 @@
namespace sprout {
template<typename Container>
inline SPROUT_CONSTEXPR std::size_t hash_value(sprout::pit<Container> const& v) {
return sprout::to_hash(v.elem);
return sprout::hash_range(v.begin(), v.end());
}
} // namespace sprout

View file

@ -1,725 +1,14 @@
#ifndef SPROUT_RATIONAL_HPP
#define SPROUT_RATIONAL_HPP
#include <limits>
#include <utility>
#include <stdexcept>
#include <ios>
#include <iostream>
#include <sprout/config.hpp>
#include <sprout/cstdlib/abs.hpp>
#include <sprout/math/gcd.hpp>
#include <sprout/detail/call_traits.hpp>
#include <sprout/detail/io/ios_state.hpp>
namespace sprout {
//
// bad_rational
//
class bad_rational
: public std::domain_error
{
public:
explicit bad_rational()
: std::domain_error("bad rational: zero denominator")
{}
};
template<typename IntType>
class rational;
namespace detail {
struct rational_private_constructor_tag {};
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType> make_rational(
typename sprout::detail::call_traits<IntType>::param_type n,
typename sprout::detail::call_traits<IntType>::param_type d,
sprout::detail::rational_private_constructor_tag
);
} // namespace detail
namespace detail {
template<typename IntType>
class rational_impl {
protected:
typedef IntType int_type;
typedef typename sprout::detail::call_traits<IntType>::param_type param_type;
protected:
IntType num_;
IntType den_;
protected:
SPROUT_CONSTEXPR rational_impl()
: num_(0)
, den_(1)
{}
rational_impl(rational_impl const&) = default;
SPROUT_CONSTEXPR rational_impl(param_type n)
: num_(n)
, den_(1)
{}
SPROUT_CONSTEXPR rational_impl(param_type n, param_type d)
: num_(n)
, den_(d)
{}
SPROUT_CONSTEXPR rational_impl(param_type n, param_type d, param_type g)
: num_(n / g)
, den_(d / g)
{}
};
} // namespace detail
//
// rational
//
template<typename IntType>
class rational
: private sprout::detail::rational_impl<IntType>
{
static_assert(std::numeric_limits<IntType>::is_specialized, "std::numeric_limits<IntType>::is_specialized");
public:
typedef IntType int_type;
typedef typename sprout::detail::call_traits<IntType>::param_type param_type;
private:
struct private_constructor_tag {};
typedef sprout::detail::rational_impl<IntType> base_type;
private:
static SPROUT_CONSTEXPR IntType normalize_g_1(IntType den, IntType g) {
return den / g < 0 ? -g : g;
}
static SPROUT_CONSTEXPR IntType normalize_g(IntType num, IntType den) {
return den == 0 ? throw sprout::bad_rational()
: num == 0 ? den
: normalize_g_1(den, sprout::math::gcd(num, den))
;
}
private:
using base_type::num_;
using base_type::den_;
private:
SPROUT_CONSTEXPR rational(param_type n, param_type d, private_constructor_tag)
: base_type(n, d)
{}
public:
SPROUT_CONSTEXPR rational()
: base_type()
{}
rational(rational const&) = default;
SPROUT_CONSTEXPR rational(param_type n)
: base_type(n)
{}
SPROUT_CONSTEXPR rational(param_type n, param_type d)
: base_type(n, d, normalize_g(n, d))
{}
rational& operator=(rational const&) = default;
rational& operator=(param_type n) {
return assign(n, 1);
}
rational& assign(param_type n, param_type d) {
using std::swap;
rational temp(n, d);
swap(temp, *this);
return *this;
}
SPROUT_CONSTEXPR IntType numerator() const {
return num_;
}
SPROUT_CONSTEXPR IntType denominator() const {
return den_;
}
rational& operator+=(rational const& rhs) {
IntType g = sprout::math::gcd(den_, rhs.den_);
den_ /= g;
num_ = num_ * (rhs.den_ / g) + rhs.num_ * den_;
g = sprout::math::gcd(num_, g);
num_ /= g;
den_ *= rhs.den_ / g;
return *this;
}
rational& operator-=(rational const& rhs) {
IntType g = sprout::math::gcd(den_, rhs.den_);
den_ /= g;
num_ = num_ * (rhs.den_ / g) - rhs.num_ * den_;
g = sprout::math::gcd(num_, g);
num_ /= g;
den_ *= rhs.den_ / g;
return *this;
}
rational& operator*=(rational const& rhs) {
IntType gcd1 = sprout::math::gcd(num_, rhs.den_);
IntType gcd2 = sprout::math::gcd(rhs.num_, den_);
num_ =(num_ / gcd1) * (rhs.num_ / gcd2);
den_ =(den_ / gcd2) * (rhs.den_ / gcd1);
return *this;
}
rational& operator/=(rational const& rhs) {
if (rhs.num_ == IntType(0)) {
throw bad_rational();
}
if (num_ == IntType(0)) {
return *this;
}
IntType gcd1 = sprout::math::gcd(num_, rhs.num_);
IntType gcd2 = sprout::math::gcd(rhs.den_, den_);
num_ =(num_ / gcd1) * (rhs.den_ / gcd2);
den_ =(den_ / gcd2) * (rhs.num_ / gcd1);
if (den_ < IntType(0)) {
num_ = -num_;
den_ = -den_;
}
return *this;
}
rational& operator+=(param_type rhs) {
return *this += rational(rhs);
}
rational& operator-=(param_type rhs) {
return *this -= rational(rhs);
}
rational& operator*=(param_type rhs) {
return *this *= rational(rhs);
}
rational& operator/=(param_type rhs) {
return *this /= rational(rhs);
}
rational& operator++() {
num_ += den_;
return *this;
}
rational& operator--() {
num_ -= den_;
return *this;
}
rational operator++(int) {
rational result(*this);
++*this;
return result;
}
rational operator--(int) {
rational result(*this);
--*this;
return result;
}
SPROUT_CONSTEXPR bool operator!() const {
return !num_;
}
SPROUT_CONSTEXPR operator bool() const {
return num_ != 0;
}
public:
friend sprout::rational<IntType> sprout::detail::make_rational<IntType>(
typename sprout::detail::call_traits<IntType>::param_type n,
typename sprout::detail::call_traits<IntType>::param_type d,
sprout::detail::rational_private_constructor_tag
);
};
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType> make_rational(
typename sprout::detail::call_traits<IntType>::param_type n,
typename sprout::detail::call_traits<IntType>::param_type d,
sprout::detail::rational_private_constructor_tag
)
{
return sprout::rational<IntType>(
n, d,
typename sprout::rational<IntType>::private_constructor_tag()
);
}
} // namespace detail
//
// operator+
// operator-
//
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(rational<IntType> const& r) {
return r;
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(rational<IntType> const& r) {
return sprout::detail::make_rational<IntType>(
-r.numerator(), r.denominator(),
sprout::detail::rational_private_constructor_tag()
);
}
//
// operator+
// operator-
// operator*
// operator/
//
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl_3(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return sprout::detail::make_rational<IntType>(
num / g, den * (rhs.denominator() / g),
sprout::detail::rational_private_constructor_tag()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl_2(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return rational_add_impl_3(
rhs,
sprout::math::gcd(num, g), den, num
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl_1(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g, IntType den
)
{
return rational_add_impl_2(
rhs,
g, den, lhs.numerator() * (rhs.denominator() / g) + rhs.numerator() * den
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g
)
{
return rational_add_impl_1(
lhs, rhs,
g, lhs.denominator() / g
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_add_impl(
lhs, rhs,
sprout::math::gcd(lhs.denominator(), rhs.denominator())
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs + sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) + rhs;
}
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl_3(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return sprout::detail::make_rational<IntType>(
num / g, den * (rhs.denominator() / g),
sprout::detail::rational_private_constructor_tag()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl_2(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return rational_sub_impl_3(
rhs,
sprout::math::gcd(num, g), den, num
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl_1(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g, IntType den
)
{
return rational_sub_impl_2(
rhs,
g, den, lhs.numerator() * (rhs.denominator() / g) - rhs.numerator() * den
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g
)
{
return rational_sub_impl_1(
lhs, rhs,
g, lhs.denominator() / g
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_sub_impl(
lhs, rhs,
sprout::math::gcd(lhs.denominator(), rhs.denominator())
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs - sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) - rhs;
}
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_mul_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType gcd1, IntType gcd2
)
{
return sprout::detail::make_rational<IntType>(
(lhs.numerator() / gcd1) * (rhs.numerator() / gcd2),
(lhs.denominator() / gcd2) * (rhs.denominator() / gcd1),
sprout::detail::rational_private_constructor_tag()
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator*(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_mul_impl(
lhs, rhs,
sprout::math::gcd(lhs.numerator(), rhs.denominator()),
sprout::math::gcd(rhs.numerator(), lhs.denominator())
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator*(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs * sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator*(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) * rhs;
}
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_div_impl_1(IntType num, IntType den) {
return den < IntType(0) ? sprout::detail::make_rational<IntType>(
-num, -den,
sprout::detail::rational_private_constructor_tag()
)
: sprout::detail::make_rational<IntType>(
num, den,
sprout::detail::rational_private_constructor_tag()
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_div_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType gcd1, IntType gcd2
)
{
return sprout::detail::rational_div_impl_1(
(lhs.numerator() / gcd1) * (rhs.denominator() / gcd2),
(lhs.denominator() / gcd2) * (rhs.numerator() / gcd1)
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator/(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return rhs.numerator() == IntType(0) ? throw sprout::bad_rational()
: lhs.numerator() == IntType(0) ? lhs
: sprout::detail::rational_div_impl(
lhs, rhs,
sprout::math::gcd(lhs.numerator(), rhs.numerator()),
sprout::math::gcd(rhs.denominator(), lhs.denominator())
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator/(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs / sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator/(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) / rhs;
}
//
// operator==
// operator!=
//
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator==(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return lhs.numerator() == rhs.numerator() && lhs.denominator() == rhs.denominator();
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator==(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs.denominator() == IntType(1) && lhs.numerator() == rhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator==(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return rhs == lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator!=(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return !(lhs == rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator!=(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return !(lhs == rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator!=(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return !(lhs == rhs);
}
//
// operator<
// operator>
// operator<=
// operator>=
//
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl_2(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType d1, IntType q1, IntType r1,
IntType d2, IntType q2, IntType r2,
unsigned reverse = 0
)
{
return q1 != q2 ? reverse ? q1 > q2 : q1 < q2
: r1 == IntType(0) || r2 == IntType(0)
? r1 == r2 ? false
: (r1 != IntType(0)) != static_cast<bool>(reverse ^ 1)
: sprout::detail::rational_less_impl_2(
lhs, rhs,
r1, d1 / r1, d1 % r1,
r2, d2 / r2, d2 % r2,
reverse ^ 1
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl_1(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType d1, IntType q1, IntType r1,
IntType d2, IntType q2, IntType r2
)
{
return r2 < IntType(0) ? sprout::detail::rational_less_impl_1(
lhs, rhs,
d1, q1, r1,
d2, q2 - 1, r2 + d2
)
: sprout::detail::rational_less_impl_2(
lhs, rhs,
d1, q1, r1,
d2, q2, r2
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType d1, IntType q1, IntType r1
)
{
return r1 < IntType(0) ? sprout::detail::rational_less_impl(
lhs, rhs,
d1, q1 - 1, r1 + d1
)
: sprout::detail::rational_less_impl_1(
lhs, rhs,
d1, q1, r1,
rhs.denominator(), rhs.numerator() / rhs.denominator(), rhs.numerator() % rhs.denominator()
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl(
sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs,
IntType q, IntType r
)
{
return r < IntType(0) ? sprout::detail::rational_less_impl(
lhs, rhs,
r + lhs.denominator(), q - 1
)
: q < rhs
;
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_less_impl(
lhs, rhs,
lhs.denominator(), lhs.numerator() / lhs.denominator(), lhs.numerator() % lhs.denominator()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return sprout::detail::rational_less_impl(
lhs, rhs,
lhs.numerator() / lhs.denominator(), lhs.numerator() % lhs.denominator()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return lhs != rhs && !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return rhs < lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return rhs < lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return rhs < lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<=(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<=(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<=(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>=(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return !(lhs < rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>=(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return !(lhs < rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>=(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return !(lhs < rhs);
}
//
// operator>>
// operator<<
//
template<typename Elem, typename Traits, typename IntType>
inline std::basic_istream<Elem, Traits>&
operator>>(std::basic_istream<Elem, Traits>& lhs, sprout::rational<IntType>& rhs) {
IntType n = IntType(0);
IntType d = IntType(1);
Elem c = 0;
sprout::detail::io::ios_flags_saver saver(lhs);
lhs >> n;
c = lhs.get();
if (c != Elem('/')) {
lhs.clear(std::istream::badbit);
}
lhs >> std::noskipws;
lhs >> d;
if (lhs) {
rhs.assign(n, d);
}
return lhs;
}
template<typename Elem, typename Traits, typename IntType>
inline std::basic_ostream<Elem, Traits>&
operator<<(std::basic_ostream<Elem, Traits>& lhs, sprout::rational<IntType> const& rhs) {
return lhs << rhs.numerator() << Elem('/') << rhs.denominator();
}
//
// rational_cast
//
template<typename T, typename IntType>
inline SPROUT_CONSTEXPR T
rational_cast(sprout::rational<IntType> const& src) {
return static_cast<T>(src.numerator()) / static_cast<T>(src.denominator());
}
//
// abs
//
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
abs(sprout::rational<IntType> const& x) {
return x.numerator() >= IntType(0) ? x
: sprout::detail::make_rational<IntType>(
-x.numerator(), x.denominator(),
sprout::detail::rational_private_constructor_tag()
)
;
}
} // namespace sprout
#include <sprout/rational/rational.hpp>
#include <sprout/rational/arithmetic.hpp>
#include <sprout/rational/comparison.hpp>
#include <sprout/rational/io.hpp>
#include <sprout/rational/conversion.hpp>
#include <sprout/rational/exceptions.hpp>
#include <sprout/rational/hash.hpp>
#include <sprout/rational/values.hpp>
#endif // SPROUT_RATIONAL_HPP

View file

@ -0,0 +1,258 @@
#ifndef SPROUT_RATIONAL_ARITHMETIC_HPP
#define SPROUT_RATIONAL_ARITHMETIC_HPP
#include <sprout/config.hpp>
#include <sprout/rational/rational.hpp>
#include <sprout/rational/exceptions.hpp>
#include <sprout/math/gcd.hpp>
namespace sprout {
//
// operator+
// operator-
//
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(rational<IntType> const& r) {
return r;
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(rational<IntType> const& r) {
return sprout::detail::make_rational<IntType>(
-r.numerator(), r.denominator(),
sprout::detail::rational_private_constructor_tag()
);
}
//
// operator+
// operator-
// operator*
// operator/
//
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl_3(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return sprout::detail::make_rational<IntType>(
num / g, den * (rhs.denominator() / g),
sprout::detail::rational_private_constructor_tag()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl_2(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return rational_add_impl_3(
rhs,
sprout::math::gcd(num, g), den, num
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl_1(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g, IntType den
)
{
return rational_add_impl_2(
rhs,
g, den, lhs.numerator() * (rhs.denominator() / g) + rhs.numerator() * den
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_add_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g
)
{
return rational_add_impl_1(
lhs, rhs,
g, lhs.denominator() / g
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_add_impl(
lhs, rhs,
sprout::math::gcd(lhs.denominator(), rhs.denominator())
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs + sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator+(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) + rhs;
}
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl_3(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return sprout::detail::make_rational<IntType>(
num / g, den * (rhs.denominator() / g),
sprout::detail::rational_private_constructor_tag()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl_2(
sprout::rational<IntType> const& rhs,
IntType g, IntType den, IntType num
)
{
return rational_sub_impl_3(
rhs,
sprout::math::gcd(num, g), den, num
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl_1(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g, IntType den
)
{
return rational_sub_impl_2(
rhs,
g, den, lhs.numerator() * (rhs.denominator() / g) - rhs.numerator() * den
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_sub_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType g
)
{
return rational_sub_impl_1(
lhs, rhs,
g, lhs.denominator() / g
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_sub_impl(
lhs, rhs,
sprout::math::gcd(lhs.denominator(), rhs.denominator())
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs - sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator-(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) - rhs;
}
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_mul_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType gcd1, IntType gcd2
)
{
return sprout::detail::make_rational<IntType>(
(lhs.numerator() / gcd1) * (rhs.numerator() / gcd2),
(lhs.denominator() / gcd2) * (rhs.denominator() / gcd1),
sprout::detail::rational_private_constructor_tag()
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator*(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_mul_impl(
lhs, rhs,
sprout::math::gcd(lhs.numerator(), rhs.denominator()),
sprout::math::gcd(rhs.numerator(), lhs.denominator())
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator*(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs * sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator*(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) * rhs;
}
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_div_impl_1(IntType num, IntType den) {
return den < IntType(0) ? sprout::detail::make_rational<IntType>(
-num, -den,
sprout::detail::rational_private_constructor_tag()
)
: sprout::detail::make_rational<IntType>(
num, den,
sprout::detail::rational_private_constructor_tag()
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
rational_div_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType gcd1, IntType gcd2
)
{
return sprout::detail::rational_div_impl_1(
(lhs.numerator() / gcd1) * (rhs.denominator() / gcd2),
(lhs.denominator() / gcd2) * (rhs.numerator() / gcd1)
);
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator/(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return rhs.numerator() == IntType(0) ? throw sprout::bad_rational()
: lhs.numerator() == IntType(0) ? lhs
: sprout::detail::rational_div_impl(
lhs, rhs,
sprout::math::gcd(lhs.numerator(), rhs.numerator()),
sprout::math::gcd(rhs.denominator(), lhs.denominator())
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator/(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs / sprout::rational<IntType>(rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
operator/(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return sprout::rational<IntType>(lhs) / rhs;
}
} // namespace sprout
#endif // SPROUT_RATIONAL_ARITHMETIC_HPP

View file

@ -0,0 +1,196 @@
#ifndef SPROUT_RATIONAL_COMPARISON_HPP
#define SPROUT_RATIONAL_COMPARISON_HPP
#include <sprout/config.hpp>
#include <sprout/rational/rational.hpp>
namespace sprout {
//
// operator==
// operator!=
//
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator==(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return lhs.numerator() == rhs.numerator() && lhs.denominator() == rhs.denominator();
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator==(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return lhs.denominator() == IntType(1) && lhs.numerator() == rhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator==(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return rhs == lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator!=(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return !(lhs == rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator!=(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return !(lhs == rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator!=(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return !(lhs == rhs);
}
//
// operator<
// operator>
// operator<=
// operator>=
//
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl_2(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType d1, IntType q1, IntType r1,
IntType d2, IntType q2, IntType r2,
unsigned reverse = 0
)
{
return q1 != q2 ? reverse ? q1 > q2 : q1 < q2
: r1 == IntType(0) || r2 == IntType(0)
? r1 == r2 ? false
: (r1 != IntType(0)) != static_cast<bool>(reverse ^ 1)
: sprout::detail::rational_less_impl_2(
lhs, rhs,
r1, d1 / r1, d1 % r1,
r2, d2 / r2, d2 % r2,
reverse ^ 1
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl_1(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType d1, IntType q1, IntType r1,
IntType d2, IntType q2, IntType r2
)
{
return r2 < IntType(0) ? sprout::detail::rational_less_impl_1(
lhs, rhs,
d1, q1, r1,
d2, q2 - 1, r2 + d2
)
: sprout::detail::rational_less_impl_2(
lhs, rhs,
d1, q1, r1,
d2, q2, r2
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl(
sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs,
IntType d1, IntType q1, IntType r1
)
{
return r1 < IntType(0) ? sprout::detail::rational_less_impl(
lhs, rhs,
d1, q1 - 1, r1 + d1
)
: sprout::detail::rational_less_impl_1(
lhs, rhs,
d1, q1, r1,
rhs.denominator(), rhs.numerator() / rhs.denominator(), rhs.numerator() % rhs.denominator()
)
;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
rational_less_impl(
sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs,
IntType q, IntType r
)
{
return r < IntType(0) ? sprout::detail::rational_less_impl(
lhs, rhs,
r + lhs.denominator(), q - 1
)
: q < rhs
;
}
} // namespace detail
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return sprout::detail::rational_less_impl(
lhs, rhs,
lhs.denominator(), lhs.numerator() / lhs.denominator(), lhs.numerator() % lhs.denominator()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return sprout::detail::rational_less_impl(
lhs, rhs,
lhs.numerator() / lhs.denominator(), lhs.numerator() % lhs.denominator()
);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return lhs != rhs && !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return rhs < lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return rhs < lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return rhs < lhs;
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<=(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<=(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator<=(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return !(rhs < lhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>=(sprout::rational<IntType> const& lhs, sprout::rational<IntType> const& rhs) {
return !(lhs < rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>=(sprout::rational<IntType> const& lhs, typename sprout::rational<IntType>::param_type rhs) {
return !(lhs < rhs);
}
template<typename IntType>
inline SPROUT_CONSTEXPR bool
operator>=(typename sprout::rational<IntType>::param_type lhs, sprout::rational<IntType> const& rhs) {
return !(lhs < rhs);
}
} // namespace sprout
#endif // SPROUT_RATIONAL_COMPARISON_HPP

View file

@ -0,0 +1,18 @@
#ifndef SPROUT_RATIONAL_CONVERSION_HPP
#define SPROUT_RATIONAL_CONVERSION_HPP
#include <sprout/config.hpp>
#include <sprout/rational/rational.hpp>
namespace sprout {
//
// rational_cast
//
template<typename T, typename IntType>
inline SPROUT_CONSTEXPR T
rational_cast(sprout::rational<IntType> const& src) {
return static_cast<T>(src.numerator()) / static_cast<T>(src.denominator());
}
} // namespace sprout
#endif // SPROUT_RATIONAL_CONVERSION_HPP

View file

@ -0,0 +1,21 @@
#ifndef SPROUT_RATIONAL_EXCEPTIONS_HPP
#define SPROUT_RATIONAL_EXCEPTIONS_HPP
#include <stdexcept>
#include <sprout/config.hpp>
namespace sprout {
//
// bad_rational
//
class bad_rational
: public std::domain_error
{
public:
explicit bad_rational()
: std::domain_error("bad rational: zero denominator")
{}
};
} // namespace sprout
#endif // SPROUT_RATIONAL_EXCEPTIONS_HPP

19
sprout/rational/hash.hpp Normal file
View file

@ -0,0 +1,19 @@
#ifndef SPROUT_RATIONAL_HASH_HPP
#define SPROUT_RATIONAL_HASH_HPP
#include <cstddef>
#include <sprout/config.hpp>
#include <sprout/rational/rational.hpp>
#include <sprout/functional/hash/hash.hpp>
namespace sprout {
//
// hash_value
//
template<typename T>
inline SPROUT_CONSTEXPR std::size_t hash_value(sprout::rational<T> const& v) {
return sprout::hash_values(v.numerator(), v.denominator());
}
} // namespace sprout
#endif // SPROUT_RATIONAL_HASH_HPP

41
sprout/rational/io.hpp Normal file
View file

@ -0,0 +1,41 @@
#ifndef SPROUT_RATIONAL_IO_HPP
#define SPROUT_RATIONAL_IO_HPP
#include <ios>
#include <iostream>
#include <sprout/config.hpp>
#include <sprout/rational/rational.hpp>
#include <sprout/detail/io/ios_state.hpp>
namespace sprout {
//
// operator>>
// operator<<
//
template<typename Elem, typename Traits, typename IntType>
inline std::basic_istream<Elem, Traits>&
operator>>(std::basic_istream<Elem, Traits>& lhs, sprout::rational<IntType>& rhs) {
IntType n = IntType(0);
IntType d = IntType(1);
Elem c = 0;
sprout::detail::io::ios_flags_saver saver(lhs);
lhs >> n;
c = lhs.get();
if (c != Elem('/')) {
lhs.clear(std::istream::badbit);
}
lhs >> std::noskipws;
lhs >> d;
if (lhs) {
rhs.assign(n, d);
}
return lhs;
}
template<typename Elem, typename Traits, typename IntType>
inline std::basic_ostream<Elem, Traits>&
operator<<(std::basic_ostream<Elem, Traits>& lhs, sprout::rational<IntType> const& rhs) {
return lhs << rhs.numerator() << Elem('/') << rhs.denominator();
}
} // namespace sprout
#endif // SPROUT_RATIONAL_IO_HPP

View file

@ -0,0 +1,222 @@
#ifndef SPROUT_RATIONAL_RATIONAL_HPP
#define SPROUT_RATIONAL_RATIONAL_HPP
#include <limits>
#include <utility>
#include <sprout/config.hpp>
#include <sprout/rational/exceptions.hpp>
#include <sprout/math/gcd.hpp>
#include <sprout/detail/call_traits.hpp>
namespace sprout {
template<typename IntType>
class rational;
namespace detail {
struct rational_private_constructor_tag {};
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType> make_rational(
typename sprout::detail::call_traits<IntType>::param_type n,
typename sprout::detail::call_traits<IntType>::param_type d,
sprout::detail::rational_private_constructor_tag
);
} // namespace detail
namespace detail {
template<typename IntType>
class rational_impl {
protected:
typedef IntType int_type;
typedef typename sprout::detail::call_traits<IntType>::param_type param_type;
protected:
IntType num_;
IntType den_;
protected:
SPROUT_CONSTEXPR rational_impl()
: num_(0)
, den_(1)
{}
rational_impl(rational_impl const&) = default;
SPROUT_CONSTEXPR rational_impl(param_type n)
: num_(n)
, den_(1)
{}
SPROUT_CONSTEXPR rational_impl(param_type n, param_type d)
: num_(n)
, den_(d)
{}
SPROUT_CONSTEXPR rational_impl(param_type n, param_type d, param_type g)
: num_(n / g)
, den_(d / g)
{}
};
} // namespace detail
//
// rational
//
template<typename IntType>
class rational
: private sprout::detail::rational_impl<IntType>
{
static_assert(std::numeric_limits<IntType>::is_specialized, "std::numeric_limits<IntType>::is_specialized");
public:
typedef IntType int_type;
typedef typename sprout::detail::call_traits<IntType>::param_type param_type;
private:
struct private_constructor_tag {};
typedef sprout::detail::rational_impl<IntType> base_type;
private:
static SPROUT_CONSTEXPR IntType normalize_g_1(IntType den, IntType g) {
return den / g < 0 ? -g : g;
}
static SPROUT_CONSTEXPR IntType normalize_g(IntType num, IntType den) {
return den == 0 ? throw sprout::bad_rational()
: num == 0 ? den
: normalize_g_1(den, sprout::math::gcd(num, den))
;
}
private:
using base_type::num_;
using base_type::den_;
private:
SPROUT_CONSTEXPR rational(param_type n, param_type d, private_constructor_tag)
: base_type(n, d)
{}
public:
SPROUT_CONSTEXPR rational()
: base_type()
{}
rational(rational const&) = default;
SPROUT_CONSTEXPR rational(param_type n)
: base_type(n)
{}
SPROUT_CONSTEXPR rational(param_type n, param_type d)
: base_type(n, d, normalize_g(n, d))
{}
rational& operator=(rational const&) = default;
rational& operator=(param_type n) {
return assign(n, 1);
}
rational& assign(param_type n, param_type d) {
using std::swap;
rational temp(n, d);
swap(temp, *this);
return *this;
}
SPROUT_CONSTEXPR IntType numerator() const {
return num_;
}
SPROUT_CONSTEXPR IntType denominator() const {
return den_;
}
rational& operator+=(rational const& rhs) {
IntType g = sprout::math::gcd(den_, rhs.den_);
den_ /= g;
num_ = num_ * (rhs.den_ / g) + rhs.num_ * den_;
g = sprout::math::gcd(num_, g);
num_ /= g;
den_ *= rhs.den_ / g;
return *this;
}
rational& operator-=(rational const& rhs) {
IntType g = sprout::math::gcd(den_, rhs.den_);
den_ /= g;
num_ = num_ * (rhs.den_ / g) - rhs.num_ * den_;
g = sprout::math::gcd(num_, g);
num_ /= g;
den_ *= rhs.den_ / g;
return *this;
}
rational& operator*=(rational const& rhs) {
IntType gcd1 = sprout::math::gcd(num_, rhs.den_);
IntType gcd2 = sprout::math::gcd(rhs.num_, den_);
num_ =(num_ / gcd1) * (rhs.num_ / gcd2);
den_ =(den_ / gcd2) * (rhs.den_ / gcd1);
return *this;
}
rational& operator/=(rational const& rhs) {
if (rhs.num_ == IntType(0)) {
throw bad_rational();
}
if (num_ == IntType(0)) {
return *this;
}
IntType gcd1 = sprout::math::gcd(num_, rhs.num_);
IntType gcd2 = sprout::math::gcd(rhs.den_, den_);
num_ =(num_ / gcd1) * (rhs.den_ / gcd2);
den_ =(den_ / gcd2) * (rhs.num_ / gcd1);
if (den_ < IntType(0)) {
num_ = -num_;
den_ = -den_;
}
return *this;
}
rational& operator+=(param_type rhs) {
return *this += rational(rhs);
}
rational& operator-=(param_type rhs) {
return *this -= rational(rhs);
}
rational& operator*=(param_type rhs) {
return *this *= rational(rhs);
}
rational& operator/=(param_type rhs) {
return *this /= rational(rhs);
}
rational& operator++() {
num_ += den_;
return *this;
}
rational& operator--() {
num_ -= den_;
return *this;
}
rational operator++(int) {
rational result(*this);
++*this;
return result;
}
rational operator--(int) {
rational result(*this);
--*this;
return result;
}
SPROUT_CONSTEXPR bool operator!() const {
return !num_;
}
SPROUT_CONSTEXPR operator bool() const {
return num_ != 0;
}
public:
friend sprout::rational<IntType> sprout::detail::make_rational<IntType>(
typename sprout::detail::call_traits<IntType>::param_type n,
typename sprout::detail::call_traits<IntType>::param_type d,
sprout::detail::rational_private_constructor_tag
);
};
namespace detail {
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType> make_rational(
typename sprout::detail::call_traits<IntType>::param_type n,
typename sprout::detail::call_traits<IntType>::param_type d,
sprout::detail::rational_private_constructor_tag
)
{
return sprout::rational<IntType>(
n, d,
typename sprout::rational<IntType>::private_constructor_tag()
);
}
} // namespace detail
} // namespace sprout
#endif // SPROUT_RATIONAL_RATIONAL_HPP

View file

@ -0,0 +1,24 @@
#ifndef SPROUT_RATIONAL_VALUES_HPP
#define SPROUT_RATIONAL_VALUES_HPP
#include <sprout/config.hpp>
#include <sprout/rational/rational.hpp>
#include <sprout/cstdlib/abs.hpp>
namespace sprout {
//
// abs
//
template<typename IntType>
inline SPROUT_CONSTEXPR sprout::rational<IntType>
abs(sprout::rational<IntType> const& x) {
return x.numerator() >= IntType(0) ? x
: sprout::detail::make_rational<IntType>(
-x.numerator(), x.denominator(),
sprout::detail::rational_private_constructor_tag()
)
;
}
} // namespace sprout
#endif // SPROUT_RATIONAL_VALUES_HPP

View file

@ -1,6 +1,7 @@
#ifndef SPROUT_UTILITY_PAIR_HPP
#define SPROUT_UTILITY_PAIR_HPP
#include <cstddef>
#include <utility>
#include <type_traits>
#include <sprout/config.hpp>
@ -9,6 +10,7 @@
#include <sprout/utility/move.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/functional/ref.hpp>
#include <sprout/functional/hash/hash.hpp>
namespace sprout {
// Copyright (C) 2011 RiSK (sscrisk)
@ -143,7 +145,7 @@ namespace sprout {
// swap
//
template<class T1, class T2>
inline void swap(pair<T1, T2>& x, pair<T1, T2>& y) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(x.swap(y))) {
inline void swap(sprout::pair<T1, T2>& x, sprout::pair<T1, T2>& y) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(x.swap(y))) {
x.swap(y);
}
@ -164,6 +166,14 @@ namespace sprout {
sprout::forward<T2>(y)
);
}
//
// hash_value
//
template<typename T1, typename T2>
inline SPROUT_CONSTEXPR std::size_t hash_value(sprout::pair<T1, T2> const& v) {
return sprout::hash_values(v.first, v.second);
}
} // namespace sprout
namespace sprout {