File indexing completed on 2025-01-18 09:39:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP
0019 #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP
0020
0021 #include <boost/config.hpp>
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 # pragma once
0024 #endif
0025
0026 #include <boost/limits.hpp>
0027 #include <boost/type_traits/type_identity.hpp>
0028 #include <boost/type_traits/conditional.hpp>
0029 #include <boost/type_traits/make_unsigned.hpp>
0030 #include <boost/type_traits/is_signed.hpp>
0031 #include <boost/type_traits/is_integral.hpp>
0032 #include <boost/type_traits/is_arithmetic.hpp>
0033 #include <boost/type_traits/is_base_of.hpp>
0034 #include <boost/type_traits/is_float.hpp>
0035 #include <boost/type_traits/remove_volatile.hpp>
0036
0037 #include <boost/numeric/conversion/cast.hpp>
0038
0039 namespace boost { namespace detail {
0040
0041 template <class Source >
0042 struct detect_precision_loss
0043 {
0044 typedef Source source_type;
0045 typedef boost::numeric::Trunc<Source> Rounder;
0046 typedef typename conditional<
0047 boost::is_arithmetic<Source>::value, Source, Source const&
0048 >::type argument_type ;
0049
0050 static inline source_type nearbyint(argument_type s, bool& is_ok) noexcept {
0051 const source_type near_int = Rounder::nearbyint(s);
0052 if (near_int && is_ok) {
0053 const source_type orig_div_round = s / near_int;
0054 const source_type eps = std::numeric_limits<source_type>::epsilon();
0055
0056 is_ok = !((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps);
0057 }
0058
0059 return s;
0060 }
0061
0062 typedef typename Rounder::round_style round_style;
0063 };
0064
0065 template <typename Base, class Source>
0066 struct fake_precision_loss: public Base
0067 {
0068 typedef Source source_type ;
0069 typedef typename conditional<
0070 boost::is_arithmetic<Source>::value, Source, Source const&
0071 >::type argument_type ;
0072
0073 static inline source_type nearbyint(argument_type s, bool& ) noexcept {
0074 return s;
0075 }
0076 };
0077
0078 struct nothrow_overflow_handler
0079 {
0080 inline bool operator() ( boost::numeric::range_check_result r ) const noexcept {
0081 return (r == boost::numeric::cInRange);
0082 }
0083 };
0084
0085 template <typename Target, typename Source>
0086 inline bool noexcept_numeric_convert(const Source& arg, Target& result) noexcept {
0087 typedef boost::numeric::converter<
0088 Target,
0089 Source,
0090 boost::numeric::conversion_traits<Target, Source >,
0091 nothrow_overflow_handler,
0092 detect_precision_loss<Source >
0093 > converter_orig_t;
0094
0095 typedef typename boost::conditional<
0096 boost::is_base_of< detect_precision_loss<Source >, converter_orig_t >::value,
0097 converter_orig_t,
0098 fake_precision_loss<converter_orig_t, Source>
0099 >::type converter_t;
0100
0101 bool res = nothrow_overflow_handler()(converter_t::out_of_range(arg));
0102 if (res) {
0103 result = converter_t::low_level_convert(converter_t::nearbyint(arg, res));
0104 }
0105
0106 return res;
0107 }
0108
0109 template <typename Target, typename Source>
0110 struct lexical_cast_dynamic_num_not_ignoring_minus
0111 {
0112 static inline bool try_convert(const Source &arg, Target& result) noexcept {
0113 return noexcept_numeric_convert<Target, Source >(arg, result);
0114 }
0115 };
0116
0117 template <typename Target, typename Source>
0118 struct lexical_cast_dynamic_num_ignoring_minus
0119 {
0120 static inline bool try_convert(const Source &arg, Target& result) noexcept {
0121 typedef typename boost::conditional<
0122 boost::is_float<Source>::value,
0123 boost::type_identity<Source>,
0124 boost::make_unsigned<Source>
0125 >::type usource_lazy_t;
0126 typedef typename usource_lazy_t::type usource_t;
0127
0128 if (arg < 0) {
0129 const bool res = noexcept_numeric_convert<Target, usource_t>(0u - arg, result);
0130 result = static_cast<Target>(0u - result);
0131 return res;
0132 } else {
0133 return noexcept_numeric_convert<Target, usource_t>(arg, result);
0134 }
0135 }
0136 };
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 template <typename Target, typename Source>
0157 struct dynamic_num_converter_impl
0158 {
0159 typedef typename boost::remove_volatile<Source>::type source_type;
0160
0161 static inline bool try_convert(source_type arg, Target& result) noexcept {
0162 typedef typename boost::conditional<
0163 boost::is_unsigned<Target>::value &&
0164 (boost::is_signed<source_type>::value || boost::is_float<source_type>::value) &&
0165 !(boost::is_same<source_type, bool>::value) &&
0166 !(boost::is_same<Target, bool>::value),
0167 lexical_cast_dynamic_num_ignoring_minus<Target, source_type>,
0168 lexical_cast_dynamic_num_not_ignoring_minus<Target, source_type>
0169 >::type caster_type;
0170
0171 return caster_type::try_convert(arg, result);
0172 }
0173 };
0174
0175 }}
0176
0177 #endif
0178