mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2024-12-23 21:25:49 +00:00
fix complex, rational
This commit is contained in:
parent
cdb10c0fbe
commit
6b3f7ad894
19 changed files with 1568 additions and 1360 deletions
|
@ -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
110
sprout/complex/complex.hpp
Normal 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
19
sprout/complex/hash.hpp
Normal 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
|
30
sprout/complex/nearest.hpp
Normal file
30
sprout/complex/nearest.hpp
Normal 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
|
179
sprout/complex/operators.hpp
Normal file
179
sprout/complex/operators.hpp
Normal 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
|
261
sprout/complex/transcendentals.hpp
Normal file
261
sprout/complex/transcendentals.hpp
Normal 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
63
sprout/complex/values.hpp
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
258
sprout/rational/arithmetic.hpp
Normal file
258
sprout/rational/arithmetic.hpp
Normal 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
|
196
sprout/rational/comparison.hpp
Normal file
196
sprout/rational/comparison.hpp
Normal 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
|
18
sprout/rational/conversion.hpp
Normal file
18
sprout/rational/conversion.hpp
Normal 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
|
21
sprout/rational/exceptions.hpp
Normal file
21
sprout/rational/exceptions.hpp
Normal 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
19
sprout/rational/hash.hpp
Normal 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
41
sprout/rational/io.hpp
Normal 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
|
222
sprout/rational/rational.hpp
Normal file
222
sprout/rational/rational.hpp
Normal 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
|
24
sprout/rational/values.hpp
Normal file
24
sprout/rational/values.hpp
Normal 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
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue