mirror of
https://github.com/bolero-MURAKAMI/Sprout
synced 2025-08-03 12:49:50 +00:00
add sprout/rational.hpp
add sprout/math/common_factor.hpp
This commit is contained in:
parent
dc8cb3d14e
commit
5a9b2e4f7d
8 changed files with 1153 additions and 119 deletions
7
sprout/math/common_factor.hpp
Normal file
7
sprout/math/common_factor.hpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef SPROUT_MATH_COMMON_FACTOR_HPP
|
||||
#define SPROUT_MATH_COMMON_FACTOR_HPP
|
||||
|
||||
#include <sprout/math/gcd.hpp>
|
||||
#include <sprout/math/lcm.hpp>
|
||||
|
||||
#endif // SPROUT_MATH_COMMON_FACTOR_HPP
|
188
sprout/math/gcd.hpp
Normal file
188
sprout/math/gcd.hpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
#ifndef SPROUT_MATH_GCD_HPP
|
||||
#define SPROUT_MATH_GCD_HPP
|
||||
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/array.hpp>
|
||||
#include <sprout/cstdlib/abs.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename RingType>
|
||||
inline SPROUT_CONSTEXPR RingType
|
||||
gcd_euclidean(RingType a, RingType b) {
|
||||
return a == static_cast<RingType>(0) ? b
|
||||
: b % a == static_cast<RingType>(0) ? a
|
||||
: sprout::math::detail::gcd_euclidean(a % (b % a), b % a)
|
||||
;
|
||||
}
|
||||
|
||||
template<typename IntType>
|
||||
inline SPROUT_CONSTEXPR IntType
|
||||
gcd_integer_impl(IntType result) {
|
||||
return result < static_cast<IntType>(0) ? -result : result;
|
||||
}
|
||||
template<typename IntType>
|
||||
inline SPROUT_CONSTEXPR IntType
|
||||
gcd_integer(IntType const& a, IntType const& b) {
|
||||
return sprout::math::detail::gcd_integer_impl(
|
||||
sprout::math::detail::gcd_euclidean(a, b)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename BuiltInUnsigned>
|
||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which);
|
||||
template<typename BuiltInUnsigned>
|
||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||
gcd_binary_2_2(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||
return !(r[ which ] & 1u) ? sprout::math::detail::gcd_binary_2_2(
|
||||
shifts,
|
||||
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] >> 1)}}
|
||||
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] >> 1), r[1]}}
|
||||
,
|
||||
which
|
||||
)
|
||||
: r[!which] > r[which] ? sprout::math::detail::gcd_binary_2_1(
|
||||
shifts,
|
||||
which ^ 1u ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
||||
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
||||
,
|
||||
which ^ 1u
|
||||
)
|
||||
: sprout::math::detail::gcd_binary_2_1(
|
||||
shifts,
|
||||
which ? sprout::array<BuiltInUnsigned, 2>{{r[0], BuiltInUnsigned(r[1] - r[0])}}
|
||||
: sprout::array<BuiltInUnsigned, 2>{{BuiltInUnsigned(r[0] - r[1]), r[1]}}
|
||||
,
|
||||
which
|
||||
)
|
||||
;
|
||||
}
|
||||
template<typename BuiltInUnsigned>
|
||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||
gcd_binary_2_1(unsigned shifts, sprout::array<BuiltInUnsigned, 2> const& r, unsigned which) {
|
||||
return r[which] ? sprout::math::detail::gcd_binary_2_2(shifts, r, which)
|
||||
: r[!which] << shifts
|
||||
;
|
||||
}
|
||||
template<typename BuiltInUnsigned>
|
||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||
gcd_binary_1(BuiltInUnsigned u, BuiltInUnsigned v, unsigned shifts = 0) {
|
||||
return (!(u & 1u) && !(v & 1u)) ? sprout::math::detail::gcd_binary_1(u >> 1, v >> 1, shifts + 1)
|
||||
: sprout::math::detail::gcd_binary_2_2(
|
||||
shifts, sprout::array<BuiltInUnsigned, 2>{{u, v}}, static_cast<bool>(u & 1u)
|
||||
)
|
||||
;
|
||||
}
|
||||
template<typename BuiltInUnsigned>
|
||||
inline SPROUT_CONSTEXPR BuiltInUnsigned
|
||||
gcd_binary(BuiltInUnsigned u, BuiltInUnsigned v) {
|
||||
return u && v ? sprout::math::detail::gcd_binary_1(u, v)
|
||||
: u + v
|
||||
;
|
||||
}
|
||||
|
||||
template<typename T, bool IsSpecialized, bool IsSigned>
|
||||
struct gcd_optimal_evaluator_helper_t {
|
||||
public:
|
||||
SPROUT_CONSTEXPR T operator()(T const& a, T const& b) const {
|
||||
return sprout::math::detail::gcd_euclidean(a, b);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct gcd_optimal_evaluator_helper_t<T, true, true> {
|
||||
public:
|
||||
SPROUT_CONSTEXPR T operator()(T const& a, T const& b) const {
|
||||
return sprout::math::detail::gcd_integer(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct gcd_optimal_evaluator {
|
||||
public:
|
||||
SPROUT_CONSTEXPR T operator()(T const& a, T const& b) const {
|
||||
typedef std::numeric_limits<T> limits_type;
|
||||
typedef sprout::math::detail::gcd_optimal_evaluator_helper_t<
|
||||
T, limits_type::is_specialized, limits_type::is_signed
|
||||
> helper_type;
|
||||
return helper_type().operator()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
# define SPROUT_PRIVATE_GCD_UF(Ut) \
|
||||
template<> \
|
||||
struct gcd_optimal_evaluator<Ut> { \
|
||||
public: \
|
||||
SPROUT_CONSTEXPR Ut operator()(Ut a, Ut b) const { \
|
||||
return sprout::math::detail::gcd_binary(a, b); \
|
||||
} \
|
||||
}
|
||||
SPROUT_PRIVATE_GCD_UF(unsigned char);
|
||||
SPROUT_PRIVATE_GCD_UF(unsigned short);
|
||||
SPROUT_PRIVATE_GCD_UF(unsigned);
|
||||
SPROUT_PRIVATE_GCD_UF(unsigned long);
|
||||
SPROUT_PRIVATE_GCD_UF(unsigned long long);
|
||||
# if CHAR_MIN == 0
|
||||
SPROUT_PRIVATE_GCD_UF(char);
|
||||
# endif
|
||||
#undef SPROUT_PRIVATE_GCD_UF
|
||||
|
||||
# define SPROUT_PRIVATE_GCD_SF(St, Ut) \
|
||||
template<> \
|
||||
struct gcd_optimal_evaluator<St> { \
|
||||
public: \
|
||||
SPROUT_CONSTEXPR St operator()(St a, St b) const { \
|
||||
using sprout::abs; \
|
||||
return static_cast<St>(sprout::math::detail::gcd_optimal_evaluator<Ut>().operator()( \
|
||||
static_cast<Ut>(abs(a)), static_cast<Ut>(abs(b)) \
|
||||
)); \
|
||||
} \
|
||||
}
|
||||
SPROUT_PRIVATE_GCD_SF(signed char, unsigned char);
|
||||
SPROUT_PRIVATE_GCD_SF(short, unsigned short);
|
||||
SPROUT_PRIVATE_GCD_SF(int, unsigned);
|
||||
SPROUT_PRIVATE_GCD_SF(long, unsigned long);
|
||||
# if CHAR_MIN < 0
|
||||
SPROUT_PRIVATE_GCD_SF(char, unsigned char);
|
||||
# endif
|
||||
SPROUT_PRIVATE_GCD_SF(long long, unsigned long long);
|
||||
#undef SPROUT_PRIVATE_GCD_SF
|
||||
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
gcd_optimal(T const& a, T const& b) {
|
||||
return sprout::math::detail::gcd_optimal_evaluator<T>().operator()(a, b);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// gcd_evaluator
|
||||
//
|
||||
template<typename IntType>
|
||||
class gcd_evaluator {
|
||||
public:
|
||||
typedef IntType result_type;
|
||||
typedef IntType first_argument_type;
|
||||
typedef IntType second_argument_type;
|
||||
public:
|
||||
SPROUT_CONSTEXPR result_type
|
||||
operator()(first_argument_type const& a, second_argument_type const& b) const {
|
||||
return sprout::math::detail::gcd_optimal(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// gcd
|
||||
//
|
||||
template<typename IntType>
|
||||
inline SPROUT_CONSTEXPR IntType
|
||||
gcd(IntType const& a, IntType const& b) {
|
||||
return sprout::math::gcd_evaluator<IntType>().operator()(a, b);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // SPROUT_MATH_GCD_HPP
|
101
sprout/math/lcm.hpp
Normal file
101
sprout/math/lcm.hpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
#ifndef SPROUT_MATH_LCM_HPP
|
||||
#define SPROUT_MATH_LCM_HPP
|
||||
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/gcd.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename RingType>
|
||||
inline SPROUT_CONSTEXPR RingType
|
||||
lcm_euclidean_impl(RingType a, RingType b, RingType temp) {
|
||||
return temp != static_cast<RingType>(0) ? (a / temp * b)
|
||||
: static_cast<RingType>(0)
|
||||
;
|
||||
}
|
||||
template<typename RingType>
|
||||
inline SPROUT_CONSTEXPR RingType
|
||||
lcm_euclidean(RingType a, RingType b) {
|
||||
return sprout::math::detail::lcm_euclidean_impl(
|
||||
a, b, sprout::math::detail::gcd_euclidean(a, b)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename IntType>
|
||||
inline SPROUT_CONSTEXPR IntType
|
||||
lcm_integer_impl(IntType result) {
|
||||
return result < static_cast<IntType>(0) ? -result : result;
|
||||
}
|
||||
template<typename IntType>
|
||||
inline SPROUT_CONSTEXPR IntType
|
||||
lcm_integer(IntType const& a, IntType const& b) {
|
||||
return sprout::math::detail::lcm_integer_impl(
|
||||
sprout::math::detail::lcm_euclidean(a, b)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T, bool IsSpecialized, bool IsSigned>
|
||||
struct lcm_optimal_evaluator_helper_t {
|
||||
public:
|
||||
SPROUT_CONSTEXPR T operator()(T const& a, T const& b) const {
|
||||
return sprout::math::detail::lcm_euclidean(a, b);
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct lcm_optimal_evaluator_helper_t<T, true, true> {
|
||||
public:
|
||||
SPROUT_CONSTEXPR T operator()(T const& a, T const& b) const {
|
||||
return sprout::math::detail::lcm_integer(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct lcm_optimal_evaluator {
|
||||
public:
|
||||
SPROUT_CONSTEXPR T operator()(T const& a, T const& b) const {
|
||||
typedef std::numeric_limits<T> limits_type;
|
||||
typedef sprout::math::detail::lcm_optimal_evaluator_helper_t<
|
||||
T, limits_type::is_specialized, limits_type::is_signed
|
||||
> helper_type;
|
||||
return helper_type().operator()(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
lcm_optimal(T const& a, T const& b) {
|
||||
return sprout::math::detail::lcm_optimal_evaluator<T>().operator()(a, b);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// lcm_evaluator
|
||||
//
|
||||
template<typename IntType>
|
||||
class lcm_evaluator {
|
||||
public:
|
||||
typedef IntType result_type;
|
||||
typedef IntType first_argument_type;
|
||||
typedef IntType second_argument_type;
|
||||
public:
|
||||
SPROUT_CONSTEXPR result_type
|
||||
operator()(first_argument_type const& a, second_argument_type const& b) const {
|
||||
return sprout::math::detail::lcm_optimal(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// lcm
|
||||
//
|
||||
template<typename IntType>
|
||||
inline SPROUT_CONSTEXPR IntType
|
||||
lcm(IntType const& a, IntType const& b) {
|
||||
return sprout::math::lcm_evaluator<IntType>().operator()(a, b);
|
||||
}
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
|
||||
#endif // SPROUT_MATH_LCM_HPP
|
Loading…
Add table
Add a link
Reference in a new issue