fix to_string(FloatType): support inf, NaN; bug(digit count)

This commit is contained in:
bolero-MURAKAMI 2013-08-05 22:18:02 +09:00
parent 99547d3fe7
commit 9883dacfe2
2 changed files with 59 additions and 38 deletions

View file

@ -75,37 +75,37 @@ namespace sprout {
// //
// float_digits // float_digits
// //
template<typename FloatType>
inline SPROUT_CONSTEXPR int
float_digits_impl(FloatType val, FloatType n) {
return val / n < 1 ? 0
: 1 + sprout::detail::float_digits_impl(val, n * FloatType(10))
;
}
template< template<
typename FloatType, typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
> >
inline SPROUT_CONSTEXPR int inline SPROUT_CONSTEXPR int
float_digits_impl(FloatType val) {
return val < 1 ? 0
: 1 + sprout::detail::float_digits_impl(val / 10)
;
}
template<typename FloatType>
inline SPROUT_CONSTEXPR int
float_digits(FloatType val) { float_digits(FloatType val) {
return val < 0 return val < 0
? val > -1 ? 1 : 1 + sprout::detail::float_digits_impl(-val / 10) ? val > -1 ? 1 : 1 + sprout::detail::float_digits_impl(-val, FloatType(10))
: val < 1 ? 1 : 1 + sprout::detail::float_digits_impl(val / 10) : val < 1 ? 1 : 1 + sprout::detail::float_digits_impl(val, FloatType(10))
; ;
} }
// //
// float_digit_at // float_digit_at
// //
template< template<typename FloatType>
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int inline SPROUT_CONSTEXPR int
float_digit_of_impl(FloatType val) { float_digit_of_impl(FloatType val) {
return static_cast<int>((val - sprout::math::floor(val)) * 10); return static_cast<int>((val - sprout::math::floor(val)) * 10);
} }
template<typename FloatType> template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR int inline SPROUT_CONSTEXPR int
float_digit_at(FloatType val, int digits) { float_digit_at(FloatType val, int digits) {
return sprout::detail::float_digit_of_impl(val / sprout::detail::float_pow10<FloatType>(digits + 1)); return sprout::detail::float_digit_of_impl(val / sprout::detail::float_pow10<FloatType>(digits + 1));
@ -114,15 +114,15 @@ namespace sprout {
// //
// float_round_at // float_round_at
// //
template< template<typename FloatType>
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType inline SPROUT_CONSTEXPR FloatType
float_round_impl(FloatType val, FloatType p10) { float_round_impl(FloatType val, FloatType p10) {
return sprout::math::round(val * p10) / p10; return sprout::math::round(val * p10) / p10;
} }
template<typename FloatType> template<
typename FloatType,
typename sprout::enabler_if<std::is_floating_point<FloatType>::value>::type = sprout::enabler
>
inline SPROUT_CONSTEXPR FloatType inline SPROUT_CONSTEXPR FloatType
float_round_at(FloatType val, int digits) { float_round_at(FloatType val, int digits) {
return sprout::detail::float_round_impl(val, sprout::detail::float_pow10<FloatType>(digits)); return sprout::detail::float_round_impl(val, sprout::detail::float_pow10<FloatType>(digits));

View file

@ -8,6 +8,9 @@
#include <sprout/index_tuple/metafunction.hpp> #include <sprout/index_tuple/metafunction.hpp>
#include <sprout/string/string.hpp> #include <sprout/string/string.hpp>
#include <sprout/type_traits/enabler_if.hpp> #include <sprout/type_traits/enabler_if.hpp>
#include <sprout/math/isinf.hpp>
#include <sprout/math/isnan.hpp>
#include <sprout/math/signbit.hpp>
#include <sprout/math/floor.hpp> #include <sprout/math/floor.hpp>
#include <sprout/detail/char_conversion.hpp> #include <sprout/detail/char_conversion.hpp>
#include <sprout/detail/math/int.hpp> #include <sprout/detail/math/int.hpp>
@ -34,8 +37,9 @@ namespace sprout {
template<typename Elem, typename FloatType, sprout::index_t... Indexes> template<typename Elem, typename FloatType, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value> inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value>
float_to_string_impl(FloatType val, bool negative, int digits, int v, sprout::index_tuple<Indexes...>) { float_to_string_impl(FloatType val, bool negative, int digits, int v, sprout::index_tuple<Indexes...>) {
typedef sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value> type;
return negative return negative
? sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value>{ ? type{
{ {
static_cast<Elem>('-'), static_cast<Elem>('-'),
(Indexes < digits ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, digits - 1 - Indexes)) (Indexes < digits ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, digits - 1 - Indexes))
@ -47,7 +51,7 @@ namespace sprout {
}, },
static_cast<std::size_t>(digits + 2 + sprout::detail::decimal_places_length) static_cast<std::size_t>(digits + 2 + sprout::detail::decimal_places_length)
} }
: sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value>{ : type{
{ {
(Indexes < digits ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, digits - 1 - Indexes)) (Indexes < digits ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, digits - 1 - Indexes))
: Indexes == digits ? static_cast<Elem>('.') : Indexes == digits ? static_cast<Elem>('.')
@ -79,11 +83,19 @@ namespace sprout {
> >
inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value> inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value>
float_to_string(FloatType val) { float_to_string(FloatType val) {
return sprout::detail::float_to_string<Elem>( typedef sprout::basic_string<Elem, sprout::printed_float_digits<FloatType>::value> type;
return sprout::math::isinf(val) ? sprout::math::signbit(val)
? type{{static_cast<Elem>('-'), static_cast<Elem>('i'), static_cast<Elem>('n'), static_cast<Elem>('f')}, 4}
: type{{static_cast<Elem>('i'), static_cast<Elem>('n'), static_cast<Elem>('f')}, 3}
: sprout::math::isnan(val) ? sprout::math::signbit(val)
? type{{static_cast<Elem>('-'), static_cast<Elem>('n'), static_cast<Elem>('a'), static_cast<Elem>('n')}, 4}
: type{{static_cast<Elem>('n'), static_cast<Elem>('a'), static_cast<Elem>('n')}, 3}
: sprout::detail::float_to_string<Elem>(
sprout::detail::float_round_at(val < 0 ? -val : val, sprout::detail::decimal_places_length), sprout::detail::float_round_at(val < 0 ? -val : val, sprout::detail::decimal_places_length),
val < 0, sprout::math::signbit(val),
sprout::detail::float_digits(val) sprout::detail::float_digits(val)
); )
;
} }
namespace detail { namespace detail {
@ -111,8 +123,9 @@ namespace sprout {
template<typename Elem, typename FloatType, sprout::index_t... Indexes> template<typename Elem, typename FloatType, sprout::index_t... Indexes>
inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value> inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value>
float_to_string_exp(FloatType val, bool negative, int exponent10, int e10_digits, sprout::index_tuple<Indexes...>) { float_to_string_exp(FloatType val, bool negative, int exponent10, int e10_digits, sprout::index_tuple<Indexes...>) {
typedef sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value> type;
return negative return negative
? sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value>{ ? type{
{ {
static_cast<Elem>('-'), static_cast<Elem>('-'),
(Indexes == 0 ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, 0)) (Indexes == 0 ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, 0))
@ -128,7 +141,7 @@ namespace sprout {
}, },
static_cast<std::size_t>(5 + sprout::detail::decimal_places_length + e10_digits) static_cast<std::size_t>(5 + sprout::detail::decimal_places_length + e10_digits)
} }
: sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value>{ : type{
{ {
(Indexes == 0 ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, 0)) (Indexes == 0 ? sprout::detail::int_to_char<Elem>(sprout::detail::float_digit_at(val, 0))
: Indexes == 1 ? static_cast<Elem>('.') : Indexes == 1 ? static_cast<Elem>('.')
@ -156,16 +169,24 @@ namespace sprout {
> >
inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value> inline SPROUT_CONSTEXPR sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value>
float_to_string_exp(FloatType val) { float_to_string_exp(FloatType val) {
return sprout::detail::float_to_string_exp<Elem>( typedef sprout::basic_string<Elem, sprout::printed_float_exp_digits<FloatType>::value> type;
return sprout::math::isinf(val) ? sprout::math::signbit(val)
? type{{static_cast<Elem>('-'), static_cast<Elem>('i'), static_cast<Elem>('n'), static_cast<Elem>('f')}, 4}
: type{{static_cast<Elem>('i'), static_cast<Elem>('n'), static_cast<Elem>('f')}, 3}
: sprout::math::isnan(val) ? sprout::math::signbit(val)
? type{{static_cast<Elem>('-'), static_cast<Elem>('n'), static_cast<Elem>('a'), static_cast<Elem>('n')}, 4}
: type{{static_cast<Elem>('n'), static_cast<Elem>('a'), static_cast<Elem>('n')}, 3}
: sprout::detail::float_to_string_exp<Elem>(
sprout::detail::float_round_at( sprout::detail::float_round_at(
(val < 0 ? -val : val) / sprout::detail::float_pow10<FloatType>(sprout::detail::float_exponent10(val)), (val < 0 ? -val : val) / sprout::detail::float_pow10<FloatType>(sprout::detail::float_exponent10(val)),
sprout::detail::decimal_places_length sprout::detail::decimal_places_length
), ),
val < 0, sprout::math::signbit(val),
sprout::detail::float_exponent10(val), sprout::detail::float_exponent10(val),
NS_SSCRISK_CEL_OR_SPROUT::max(sprout::detail::int_digits(sprout::detail::float_exponent10(val)), 2), NS_SSCRISK_CEL_OR_SPROUT::max(sprout::detail::int_digits(sprout::detail::float_exponent10(val)), 2),
sprout::make_index_tuple<sprout::printed_float_exp_digits<FloatType>::value - 1>::make() sprout::make_index_tuple<sprout::printed_float_exp_digits<FloatType>::value - 1>::make()
); )
;
} }
// //