1
0
Fork 0
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:
bolero-MURAKAMI 2013-02-10 11:54:54 +09:00
parent 53b99b25f8
commit 434aa8d3c5
22 changed files with 812 additions and 74 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -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
View 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
View 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
View 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
View 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
View 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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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>