mirror of
https://github.com/bolero-MURAKAMI/Sprout
synced 2024-11-12 21:09:01 +00:00
fix math: rounding function,etc...
This commit is contained in:
parent
53b99b25f8
commit
434aa8d3c5
22 changed files with 812 additions and 74 deletions
|
@ -11,6 +11,7 @@
|
|||
#include <sprout/utility/lvalue_forward.hpp>
|
||||
#include <sprout/tuple/tuple/tuple.hpp>
|
||||
#include <sprout/tuple/tuple/get.hpp>
|
||||
#include <sprout/tuple/tuple/make_tuple.hpp>
|
||||
#include <sprout/functional/ref.hpp>
|
||||
#include <sprout/functional/mem_fn.hpp>
|
||||
#include <sprout/functional/type_traits/weak_result_type.hpp>
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include <sprout/config.hpp>
|
||||
#include <sprout/functional/hash/hash_fwd.hpp>
|
||||
#include <sprout/math/fpclassify.hpp>
|
||||
#include <sprout/math/scalbn.hpp>
|
||||
#include <sprout/math/float_pair.hpp>
|
||||
#include <sprout/math/ldexp.hpp>
|
||||
#include <sprout/math/float2_sig_exp.hpp>
|
||||
#include <sprout/detail/integer/static_log2.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -21,7 +21,7 @@ namespace sprout {
|
|||
inline SPROUT_CONSTEXPR std::size_t
|
||||
float_hash_value_impl_4(T v, int exp, std::size_t seed, std::size_t length, std::size_t i = 0) {
|
||||
return i != length ? sprout::detail::float_hash_value_impl_4(
|
||||
sprout::math::scalbn(v - static_cast<T>(static_cast<std::size_t>(v)), std::numeric_limits<std::size_t>::digits),
|
||||
sprout::math::ldexp(v - static_cast<T>(static_cast<std::size_t>(v)), std::numeric_limits<std::size_t>::digits),
|
||||
exp, sprout::detail::hash_float_combine(seed, static_cast<std::size_t>(v)),
|
||||
length, i + 1
|
||||
)
|
||||
|
@ -32,7 +32,7 @@ namespace sprout {
|
|||
inline SPROUT_CONSTEXPR std::size_t
|
||||
float_hash_value_impl_3(T v, int exp) {
|
||||
return sprout::detail::float_hash_value_impl_4(
|
||||
sprout::math::scalbn(v - static_cast<T>(static_cast<std::size_t>(v)), std::numeric_limits<std::size_t>::digits),
|
||||
sprout::math::ldexp(v - static_cast<T>(static_cast<std::size_t>(v)), std::numeric_limits<std::size_t>::digits),
|
||||
exp, static_cast<std::size_t>(v),
|
||||
(std::numeric_limits<T>::digits * sprout::detail::static_log2<std::numeric_limits<T>::radix>::value + std::numeric_limits<std::size_t>::digits - 1)
|
||||
/ std::numeric_limits<std::size_t>::digits
|
||||
|
@ -41,7 +41,7 @@ namespace sprout {
|
|||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR std::size_t
|
||||
float_hash_value_impl_2(T v, int exp) {
|
||||
return sprout::detail::float_hash_value_impl_3(sprout::math::scalbn(v, std::numeric_limits<std::size_t>::digits), exp);
|
||||
return sprout::detail::float_hash_value_impl_3(sprout::math::ldexp(v, std::numeric_limits<std::size_t>::digits), exp);
|
||||
}
|
||||
template<typename T, typename P>
|
||||
inline SPROUT_CONSTEXPR std::size_t
|
||||
|
@ -55,7 +55,7 @@ namespace sprout {
|
|||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR std::size_t
|
||||
float_hash_value_impl(T v) {
|
||||
return sprout::detail::float_hash_value_impl_1<T>(sprout::math::float_pair(v));
|
||||
return sprout::detail::float_hash_value_impl_1<T>(sprout::math::float2_sig_exp(v));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef SPROUT_MATH_DETAIL_CONFIG_HPP
|
||||
#define SPROUT_MATH_DETAIL_CONFIG_HPP
|
||||
|
||||
#include <cfloat>
|
||||
#include <sprout/config.hpp>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
# include <cmath>
|
||||
|
@ -12,6 +13,12 @@
|
|||
# define NS_SPROUT_MATH_DETAIL sprout::math::detail
|
||||
#endif // #ifndef SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
|
||||
#if (FLT_RADIX == 2)
|
||||
# define SPROUT_FLT_RADIX_IS_2 1
|
||||
#else
|
||||
# define SPROUT_FLT_RADIX_IS_2 0
|
||||
#endif
|
||||
|
||||
#if SPROUT_NOERROR_LARGE_FLOAT_ROUNDING
|
||||
# define SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(e, x) (x)
|
||||
#else
|
||||
|
|
38
sprout/math/float2_exponent.hpp
Normal file
38
sprout/math/float2_exponent.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef SPROUT_MATH_FLOAT2_EXPONENT_HPP
|
||||
#define SPROUT_MATH_FLOAT2_EXPONENT_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/ilogb2.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
float2_exponent(FloatType x) {
|
||||
return sprout::math::ilogb2(x) + 1;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
float2_exponent(IntType x) {
|
||||
return sprout::math::detail::float2_exponent(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float2_exponent;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float2_exponent;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT2_EXPONENT_HPP
|
46
sprout/math/float2_sig_exp.hpp
Normal file
46
sprout/math/float2_sig_exp.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef SPROUT_MATH_FLOAT2_SIG_EXP_HPP
|
||||
#define SPROUT_MATH_FLOAT2_SIG_EXP_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/detail/pow.hpp>
|
||||
#include <sprout/math/float2_exponent.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/utility/pair/pair.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<T, int>
|
||||
float2_sig_exp_impl(T x, int exp) {
|
||||
return sprout::pair<T, int>(x / sprout::detail::pow_n(T(2), exp), exp);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
|
||||
float2_sig_exp(FloatType x) {
|
||||
return sprout::math::detail::float2_sig_exp_impl(x, sprout::math::float2_exponent(x));
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, int>
|
||||
float2_sig_exp(IntType x) {
|
||||
return sprout::math::detail::float2_sig_exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float2_sig_exp;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float2_sig_exp;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT2_SIG_EXP_HPP
|
39
sprout/math/float2_significand.hpp
Normal file
39
sprout/math/float2_significand.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef SPROUT_MATH_FLOAT2_SIGNIFICAND_HPP
|
||||
#define SPROUT_MATH_FLOAT2_SIGNIFICAND_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/detail/pow.hpp>
|
||||
#include <sprout/math/float2_exponent.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float2_significand(FloatType x) {
|
||||
return x / sprout::detail::pow_n(FloatType(2), sprout::math::float2_exponent(x));
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float2_significand(IntType x) {
|
||||
return sprout::math::detail::float_significand(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float2_significand;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float2_significand;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT2_SIGNIFICAND_HPP
|
45
sprout/math/float_frac_int.hpp
Normal file
45
sprout/math/float_frac_int.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef SPROUT_MATH_FLOAT_FRAC_INT_HPP
|
||||
#define SPROUT_MATH_FLOAT_FRAC_INT_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_integer_part.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#include <sprout/utility/pair/pair.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<T, T>
|
||||
float_frac_int_impl(T x, T ipart) {
|
||||
return sprout::pair<T, T>(x - ipart, ipart);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, FloatType>
|
||||
float_frac_int(FloatType x) {
|
||||
return sprout::math::detail::float_frac_int_impl(x, sprout::math::float_integer_part(x));
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, double>
|
||||
float_frac_int(IntType x) {
|
||||
return sprout::math::detail::float_frac_int(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_frac_int;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_frac_int;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_FRAC_INT_HPP
|
38
sprout/math/float_fractional_part.hpp
Normal file
38
sprout/math/float_fractional_part.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef SPROUT_MATH_FLOAT_FRACTIONAL_PART_HPP
|
||||
#define SPROUT_MATH_FLOAT_FRACTIONAL_PART_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/float_integer_part.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float_fractional_part(FloatType x) {
|
||||
return x - sprout::math::float_integer_part(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float_fractional_part(IntType x) {
|
||||
return sprout::math::detail::float_fractional_part(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_fractional_part;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_fractional_part;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_FRACTIONAL_PART_HPP
|
38
sprout/math/float_integer_part.hpp
Normal file
38
sprout/math/float_integer_part.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef SPROUT_MATH_FLOAT_INTEGER_PART_HPP
|
||||
#define SPROUT_MATH_FLOAT_INTEGER_PART_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/floor.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float_integer_part(FloatType x) {
|
||||
return sprout::math::floor(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float_integer_part(IntType x) {
|
||||
return sprout::math::detail::float_integer_part(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_integer_part;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_integer_part;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_INTEGER_PART_HPP
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef SPROUT_MATH_FLOAT_PAIR_HPP
|
||||
#define SPROUT_MATH_FLOAT_PAIR_HPP
|
||||
#ifndef SPROUT_MATH_FLOAT_SIG_EXP_HPP
|
||||
#define SPROUT_MATH_FLOAT_SIG_EXP_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
@ -15,7 +15,7 @@ namespace sprout {
|
|||
namespace detail {
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<T, int>
|
||||
float_pair_impl(T x, int exp) {
|
||||
float_sig_exp_impl(T x, int exp) {
|
||||
return sprout::pair<T, int>(x / sprout::detail::pow_n(T(std::numeric_limits<T>::radix), exp), exp);
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ namespace sprout {
|
|||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<FloatType, int>
|
||||
float_pair(FloatType x) {
|
||||
return sprout::math::detail::float_pair_impl(x, sprout::math::float_exponent(x));
|
||||
float_sig_exp(FloatType x) {
|
||||
return sprout::math::detail::float_sig_exp_impl(x, sprout::math::float_exponent(x));
|
||||
}
|
||||
|
||||
template<
|
||||
|
@ -33,15 +33,15 @@ namespace sprout {
|
|||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR sprout::pair<double, int>
|
||||
float_pair(IntType x) {
|
||||
return sprout::math::detail::float_pair(static_cast<double>(x));
|
||||
float_sig_exp(IntType x) {
|
||||
return sprout::math::detail::float_sig_exp(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_pair;
|
||||
using sprout::math::detail::float_sig_exp;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_pair;
|
||||
using sprout::math::float_sig_exp;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_PAIR_HPP
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_SIG_EXP_HPP
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef SPROUT_MATH_FLOAT_MANTISSA_HPP
|
||||
#define SPROUT_MATH_FLOAT_MANTISSA_HPP
|
||||
#ifndef SPROUT_MATH_FLOAT_SIGNIFICAND_HPP
|
||||
#define SPROUT_MATH_FLOAT_SIGNIFICAND_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
@ -17,7 +17,7 @@ namespace sprout {
|
|||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
float_mantissa(FloatType x) {
|
||||
float_significand(FloatType x) {
|
||||
return x / sprout::detail::pow_n(FloatType(std::numeric_limits<FloatType>::radix), sprout::math::float_exponent(x));
|
||||
}
|
||||
|
||||
|
@ -26,15 +26,15 @@ namespace sprout {
|
|||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
float_mantissa(IntType x) {
|
||||
return sprout::math::detail::float_mantissa(static_cast<double>(x));
|
||||
float_significand(IntType x) {
|
||||
return sprout::math::detail::float_significand(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::float_mantissa;
|
||||
using sprout::math::detail::float_significand;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::float_mantissa;
|
||||
using sprout::math::float_significand;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_MANTISSA_HPP
|
||||
#endif // #ifndef SPROUT_MATH_FLOAT_SIGNIFICAND_HPP
|
|
@ -7,8 +7,16 @@
|
|||
#include <sprout/math/scalbln.hpp>
|
||||
#include <sprout/math/ilogb.hpp>
|
||||
#include <sprout/math/logb.hpp>
|
||||
#include <sprout/math/ilogb2.hpp>
|
||||
#include <sprout/math/logb2.hpp>
|
||||
#include <sprout/math/float_significand.hpp>
|
||||
#include <sprout/math/float_exponent.hpp>
|
||||
#include <sprout/math/float_mantissa.hpp>
|
||||
#include <sprout/math/float_pair.hpp>
|
||||
#include <sprout/math/float_sig_exp.hpp>
|
||||
#include <sprout/math/float2_significand.hpp>
|
||||
#include <sprout/math/float2_exponent.hpp>
|
||||
#include <sprout/math/float2_sig_exp.hpp>
|
||||
#include <sprout/math/float_fractional_part.hpp>
|
||||
#include <sprout/math/float_integer_part.hpp>
|
||||
#include <sprout/math/float_frac_int.hpp>
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_FLOATING_POINT_HPP
|
||||
|
|
75
sprout/math/iceil.hpp
Normal file
75
sprout/math/iceil.hpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#ifndef SPROUT_MATH_ICEIL_HPP
|
||||
#define SPROUT_MATH_ICEIL_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
# include <sprout/math/ceil.hpp>
|
||||
#else
|
||||
# include <sprout/math/equal_to.hpp>
|
||||
#endif
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil_impl(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("iceil: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(FloatType x) {
|
||||
return sprout::math::detail::iceil_impl<To>(sprout::math::ceil(x));
|
||||
}
|
||||
#else
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil_impl(FloatType x, To x0) {
|
||||
return sprout::math::equal_to(x, x0) ? x0
|
||||
: x0 + 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("iceil: large float rounding."), static_cast<To>(x))
|
||||
: sprout::math::detail::iceil_impl(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iceil(IntType x) {
|
||||
return sprout::math::detail::iceil<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::iceil;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::iceil;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_ICEIL_HPP
|
75
sprout/math/ifloor.hpp
Normal file
75
sprout/math/ifloor.hpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#ifndef SPROUT_MATH_IFLOOR_HPP
|
||||
#define SPROUT_MATH_IFLOOR_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
# include <sprout/math/floor.hpp>
|
||||
#else
|
||||
# include <sprout/math/equal_to.hpp>
|
||||
#endif
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor_impl(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("ifloor: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(FloatType x) {
|
||||
return sprout::math::detail::ifloor_impl<To>(sprout::math::floor(x));
|
||||
}
|
||||
#else
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor_impl(FloatType x, To x0) {
|
||||
return sprout::math::equal_to(x, x0) ? x0
|
||||
: x0 - 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("ifloor: large float rounding."), static_cast<To>(x))
|
||||
: sprout::math::detail::ifloor_impl(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
ifloor(IntType x) {
|
||||
return sprout::math::detail::ifloor<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::ifloor;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ifloor;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_IFLOOR_HPP
|
71
sprout/math/ilogb2.hpp
Normal file
71
sprout/math/ilogb2.hpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#ifndef SPROUT_MATH_ILOGB2_HPP
|
||||
#define SPROUT_MATH_ILOGB2_HPP
|
||||
|
||||
#include <climits>
|
||||
#include <cfloat>
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#if SPROUT_FLT_RADIX_IS_2
|
||||
# include <sprout/math/ilogb.hpp>
|
||||
#else
|
||||
# include <sprout/math/logb2.hpp>
|
||||
# include <sprout/math/isnan.hpp>
|
||||
# include <sprout/math/isinf.hpp>
|
||||
# include <sprout/math/iszero.hpp>
|
||||
#endif
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_FLT_RADIX_IS_2
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(FloatType x) {
|
||||
return sprout::math::ilogb(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(IntType x) {
|
||||
return sprout::math::ilogb(x);
|
||||
}
|
||||
#else
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(FloatType x) {
|
||||
return sprout::math::iszero(x) ? FP_ILOGB0
|
||||
: sprout::math::isinf(x) ? INT_MAX
|
||||
: sprout::math::isnan(x) ? FP_ILOGBNAN
|
||||
: static_cast<int>(sprout::math::logb2(x))
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR int
|
||||
ilogb2(IntType x) {
|
||||
return sprout::math::detail::ilogb2(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::ilogb2;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::ilogb2;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_ILOGB2_HPP
|
83
sprout/math/iround.hpp
Normal file
83
sprout/math/iround.hpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#ifndef SPROUT_MATH_IROUND_HPP
|
||||
#define SPROUT_MATH_IROUND_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
# include <sprout/math/round.hpp>
|
||||
#else
|
||||
# include <sprout/math/equal_to.hpp>
|
||||
#endif
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround_impl(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("iround: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(FloatType x) {
|
||||
return sprout::math::detail::iround_impl<To>(sprout::math::round(x));
|
||||
}
|
||||
#else
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround_impl_positive(FloatType x, To x0) {
|
||||
return x - x0 < FloatType(0.5) ? x0
|
||||
: x0 + 1
|
||||
;
|
||||
}
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround_impl_nagative(FloatType x, To x0) {
|
||||
return x0 - x < FloatType(0.5) ? x0
|
||||
: x0 - 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("iround: large float irounding."), x)
|
||||
: x < 0 ? sprout::math::detail::iround_impl_nagative(x, static_cast<To>(x))
|
||||
: sprout::math::detail::iround_impl_positive(x, static_cast<To>(x))
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
iround(IntType x) {
|
||||
return sprout::math::detail::iround(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::iround;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::iround;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_IROUND_HPP
|
66
sprout/math/itrunc.hpp
Normal file
66
sprout/math/itrunc.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef SPROUT_MATH_ITRUNC_HPP
|
||||
#define SPROUT_MATH_ITRUNC_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
# include <sprout/math/trunc.hpp>
|
||||
#endif
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_USE_BUILTIN_CMATH_FUNCTION
|
||||
template<typename To, typename FloatType>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc_impl(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("itrunc: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(FloatType x) {
|
||||
return sprout::math::detail::itrunc_impl<To>(sprout::math::trunc(x));
|
||||
}
|
||||
#else
|
||||
template<
|
||||
typename To = int,
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(FloatType x) {
|
||||
return std::numeric_limits<To>::max() < x || std::numeric_limits<To>::min() > x
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("itrunc: large float rounding."), static_cast<To>(x))
|
||||
: static_cast<To>(x)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
template<
|
||||
typename To = int,
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value && std::is_integral<To>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR To
|
||||
itrunc(IntType x) {
|
||||
return sprout::math::detail::itrunc<To>(static_cast<double>(x));
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::itrunc;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::itrunc;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_ITRUNC_HPP
|
|
@ -1,39 +1,22 @@
|
|||
#ifndef SPROUT_MATH_LLROUND_HPP
|
||||
#define SPROUT_MATH_LLROUND_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/iround.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename FloatType>
|
||||
inline SPROUT_CONSTEXPR long long
|
||||
llround_impl_positive(FloatType x, long long x0) {
|
||||
return x - x0 < FloatType(0.5) ? x0
|
||||
: x0 + 1
|
||||
;
|
||||
}
|
||||
template<typename FloatType>
|
||||
inline SPROUT_CONSTEXPR long long
|
||||
llround_impl_nagative(FloatType x, long long x0) {
|
||||
return x0 - x < FloatType(0.5) ? x0
|
||||
: x0 - 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR long long
|
||||
llround(FloatType x) {
|
||||
return x < 0 ? sprout::math::detail::llround_impl_nagative(x, static_cast<long long>(x))
|
||||
: sprout::math::detail::llround_impl_positive(x, static_cast<long long>(x))
|
||||
;
|
||||
return sprout::math::iround<long long>(x);
|
||||
}
|
||||
|
||||
template<
|
||||
|
@ -42,7 +25,7 @@ namespace sprout {
|
|||
>
|
||||
inline SPROUT_CONSTEXPR long long
|
||||
llround(IntType x) {
|
||||
return static_cast<long long>(x);
|
||||
return sprout::math::iround<long long>(x);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/detail/pow.hpp>
|
||||
#include <sprout/math/log_a.hpp>
|
||||
#include <sprout/math/trunc.hpp>
|
||||
#include <sprout/math/itrunc.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
|
@ -79,13 +79,9 @@ namespace sprout {
|
|||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb_impl(T x, T exp) {
|
||||
return std::numeric_limits<std::intmax_t>::max() < exp || std::numeric_limits<std::intmax_t>::min() > exp
|
||||
? SPROUT_MATH_THROW_LARGE_FLOAT_ROUNDING(std::domain_error("trunc: large float rounding."), exp)
|
||||
: sprout::math::detail::logb_impl_1(
|
||||
x, sprout::detail::pow_n(T(std::numeric_limits<T>::radix), static_cast<std::intmax_t>(exp)),
|
||||
static_cast<T>(static_cast<std::intmax_t>(exp))
|
||||
)
|
||||
;
|
||||
return sprout::math::detail::logb_impl_1(
|
||||
x, sprout::detail::pow_n(T(std::numeric_limits<T>::radix), sprout::math::itrunc<std::intmax_t>(exp)), exp
|
||||
);
|
||||
}
|
||||
|
||||
template<
|
||||
|
|
142
sprout/math/logb2.hpp
Normal file
142
sprout/math/logb2.hpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
#ifndef SPROUT_MATH_LOGB2_HPP
|
||||
#define SPROUT_MATH_LOGB2_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
#if SPROUT_FLT_RADIX_IS_2
|
||||
# include <sprout/math/logb.hpp>
|
||||
#else
|
||||
# include <cstdint>
|
||||
# include <sprout/detail/pow.hpp>
|
||||
# include <sprout/math/log_a.hpp>
|
||||
# include <sprout/math/trunc.hpp>
|
||||
# include <sprout/math/itrunc.hpp>
|
||||
#endif
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
#if SPROUT_FLT_RADIX_IS_2
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb2(FloatType x) {
|
||||
return sprout::math::logb(x);
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb2(IntType x) {
|
||||
return sprout::math::logb(x);
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl_2_neg_lo(T x, T x0, T base, T exp) {
|
||||
return base < 1 ? sprout::math::detail::logb2_impl_2_neg_lo(
|
||||
x, x0 * 2, x / (x0 / 2), exp - 1
|
||||
)
|
||||
: exp
|
||||
;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl_2_neg_hi(T x, T x0, T base, T exp) {
|
||||
return !(base < 2) ? sprout::math::detail::logb2_impl_2_neg_hi(
|
||||
x, x0 / 2, x / (x0 * 2), exp + 1
|
||||
)
|
||||
: exp
|
||||
;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl_2_pos_lo(T x, T x0, T base, T exp) {
|
||||
return base < 1 ? sprout::math::detail::logb2_impl_2_pos_lo(
|
||||
x, x0 * 2, x / (x0 / 2), exp + 1
|
||||
)
|
||||
: exp
|
||||
;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl_2_pos_hi(T x, T x0, T base, T exp) {
|
||||
return !(base < 2) ? sprout::math::detail::logb2_impl_2_pos_hi(
|
||||
x, x0 / 2, x / (x0 * 2), exp - 1
|
||||
)
|
||||
: exp
|
||||
;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl_2(T x, T x0, T base, T exp) {
|
||||
return exp < 0
|
||||
? base < 1 ? sprout::math::detail::logb2_impl_2_neg_lo(
|
||||
x, x0 * 2, x / (x0 / 2), exp - 1
|
||||
)
|
||||
: !(base < 2) ? sprout::math::detail::logb2_impl_2_neg_hi(
|
||||
x, x0 / 2, x / (x0 * 2), exp + 1
|
||||
)
|
||||
: exp
|
||||
: base < 1 ? sprout::math::detail::logb2_impl_2_pos_lo(
|
||||
x, x0 * 2, x / (x0 / 2), exp + 1
|
||||
)
|
||||
: !(base < 2) ? sprout::math::detail::logb2_impl_2_pos_hi(
|
||||
x, x0 / 2, x / (x0 * 2), exp - 1
|
||||
)
|
||||
: exp
|
||||
;
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl_1(T x, T x0, T exp) {
|
||||
return sprout::math::detail::logb2_impl_2(x, x0, x / x0, exp);
|
||||
}
|
||||
template<typename T>
|
||||
inline SPROUT_CONSTEXPR T
|
||||
logb2_impl(T x, T exp) {
|
||||
return sprout::math::detail::logb2_impl_1(
|
||||
x, sprout::detail::pow_n(T(2), sprout::math::itrunc<std::intmax_t>(exp)), exp
|
||||
);
|
||||
}
|
||||
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR FloatType
|
||||
logb2(FloatType x) {
|
||||
return x < 0 ? sprout::math::detail::logb2_impl(
|
||||
-x, sprout::math::trunc(sprout::math::log_a(FloatType(2), -x))
|
||||
)
|
||||
: sprout::math::detail::logb2_impl(
|
||||
x, sprout::math::trunc(sprout::math::log_a(FloatType(2), x))
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
template<
|
||||
typename IntType,
|
||||
typename sprout::enabler_if<std::is_integral<IntType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR double
|
||||
logb2(IntType x) {
|
||||
return sprout::math::detail::logb2(static_cast<double>(x));
|
||||
}
|
||||
#endif
|
||||
} // namespace detail
|
||||
|
||||
using sprout::math::detail::logb2;
|
||||
} // namespace math
|
||||
|
||||
using sprout::math::logb2;
|
||||
} // namespace sprout
|
||||
|
||||
#endif // #ifndef SPROUT_MATH_LOGB2_HPP
|
|
@ -1,39 +1,22 @@
|
|||
#ifndef SPROUT_MATH_LROUND_HPP
|
||||
#define SPROUT_MATH_LROUND_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <sprout/config.hpp>
|
||||
#include <sprout/math/detail/config.hpp>
|
||||
#include <sprout/math/iround.hpp>
|
||||
#include <sprout/type_traits/enabler_if.hpp>
|
||||
|
||||
namespace sprout {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
template<typename FloatType>
|
||||
inline SPROUT_CONSTEXPR long
|
||||
lround_impl_positive(FloatType x, long x0) {
|
||||
return x - x0 < FloatType(0.5) ? x0
|
||||
: x0 + 1
|
||||
;
|
||||
}
|
||||
template<typename FloatType>
|
||||
inline SPROUT_CONSTEXPR long
|
||||
lround_impl_nagative(FloatType x, long x0) {
|
||||
return x0 - x < FloatType(0.5) ? x0
|
||||
: x0 - 1
|
||||
;
|
||||
}
|
||||
template<
|
||||
typename FloatType,
|
||||
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
|
||||
>
|
||||
inline SPROUT_CONSTEXPR long
|
||||
lround(FloatType x) {
|
||||
return x < 0 ? sprout::math::detail::lround_impl_nagative(x, static_cast<long>(x))
|
||||
: sprout::math::detail::lround_impl_positive(x, static_cast<long>(x))
|
||||
;
|
||||
return sprout::math::iround<long>(x);
|
||||
}
|
||||
|
||||
template<
|
||||
|
@ -42,7 +25,7 @@ namespace sprout {
|
|||
>
|
||||
inline SPROUT_CONSTEXPR long
|
||||
lround(IntType x) {
|
||||
return static_cast<long>(x);
|
||||
return sprout::math::iround<long>(x);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#include <sprout/math/floor.hpp>
|
||||
#include <sprout/math/trunc.hpp>
|
||||
#include <sprout/math/round.hpp>
|
||||
#include <sprout/math/iceil.hpp>
|
||||
#include <sprout/math/ifloor.hpp>
|
||||
#include <sprout/math/itrunc.hpp>
|
||||
#include <sprout/math/iround.hpp>
|
||||
#include <sprout/math/lround.hpp>
|
||||
#include <sprout/math/llround.hpp>
|
||||
|
||||
|
|
Loading…
Reference in a new issue