annotate DEPENDENCIES/generic/include/boost/lexical_cast/detail/converter_numeric.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 // Copyright Kevlin Henney, 2000-2005.
Chris@102 2 // Copyright Alexander Nasonov, 2006-2010.
Chris@102 3 // Copyright Antony Polukhin, 2011-2014.
Chris@102 4 //
Chris@102 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@102 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@102 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@102 8 //
Chris@102 9 // what: lexical_cast custom keyword cast
Chris@102 10 // who: contributed by Kevlin Henney,
Chris@102 11 // enhanced with contributions from Terje Slettebo,
Chris@102 12 // with additional fixes and suggestions from Gennaro Prota,
Chris@102 13 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
Chris@102 14 // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
Chris@102 15 // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
Chris@102 16 // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
Chris@102 17
Chris@102 18 #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP
Chris@102 19 #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP
Chris@102 20
Chris@102 21 #include <boost/config.hpp>
Chris@102 22 #ifdef BOOST_HAS_PRAGMA_ONCE
Chris@102 23 # pragma once
Chris@102 24 #endif
Chris@102 25
Chris@102 26 #include <boost/limits.hpp>
Chris@102 27 #include <boost/mpl/if.hpp>
Chris@102 28 #include <boost/type_traits/ice.hpp>
Chris@102 29 #include <boost/type_traits/make_unsigned.hpp>
Chris@102 30 #include <boost/type_traits/is_signed.hpp>
Chris@102 31 #include <boost/type_traits/is_integral.hpp>
Chris@102 32 #include <boost/type_traits/is_arithmetic.hpp>
Chris@102 33 #include <boost/type_traits/is_base_of.hpp>
Chris@102 34 #include <boost/type_traits/is_float.hpp>
Chris@102 35
Chris@102 36 #include <boost/numeric/conversion/cast.hpp>
Chris@102 37
Chris@102 38 namespace boost { namespace detail {
Chris@102 39
Chris@102 40 template <class Source >
Chris@102 41 struct detect_precision_loss
Chris@102 42 {
Chris@102 43 typedef Source source_type;
Chris@102 44 typedef boost::numeric::Trunc<Source> Rounder;
Chris@102 45 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
Chris@102 46 boost::is_arithmetic<Source>, Source, Source const&
Chris@102 47 >::type argument_type ;
Chris@102 48
Chris@102 49 static inline source_type nearbyint(argument_type s, bool& is_ok) BOOST_NOEXCEPT {
Chris@102 50 const source_type near_int = Rounder::nearbyint(s);
Chris@102 51 if (near_int && is_ok) {
Chris@102 52 const source_type orig_div_round = s / near_int;
Chris@102 53 const source_type eps = std::numeric_limits<source_type>::epsilon();
Chris@102 54
Chris@102 55 is_ok = !((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps);
Chris@102 56 }
Chris@102 57
Chris@102 58 return s;
Chris@102 59 }
Chris@102 60
Chris@102 61 typedef typename Rounder::round_style round_style;
Chris@102 62 };
Chris@102 63
Chris@102 64 template <typename Base, class Source>
Chris@102 65 struct fake_precision_loss: public Base
Chris@102 66 {
Chris@102 67 typedef Source source_type ;
Chris@102 68 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
Chris@102 69 boost::is_arithmetic<Source>, Source, Source const&
Chris@102 70 >::type argument_type ;
Chris@102 71
Chris@102 72 static inline source_type nearbyint(argument_type s, bool& /*is_ok*/) BOOST_NOEXCEPT {
Chris@102 73 return s;
Chris@102 74 }
Chris@102 75 };
Chris@102 76
Chris@102 77 struct nothrow_overflow_handler
Chris@102 78 {
Chris@102 79 inline bool operator() ( boost::numeric::range_check_result r ) const BOOST_NOEXCEPT {
Chris@102 80 return (r == boost::numeric::cInRange);
Chris@102 81 }
Chris@102 82 };
Chris@102 83
Chris@102 84 template <typename Target, typename Source>
Chris@102 85 inline bool noexcept_numeric_convert(const Source& arg, Target& result) BOOST_NOEXCEPT {
Chris@102 86 typedef boost::numeric::converter<
Chris@102 87 Target,
Chris@102 88 Source,
Chris@102 89 boost::numeric::conversion_traits<Target, Source >,
Chris@102 90 nothrow_overflow_handler,
Chris@102 91 detect_precision_loss<Source >
Chris@102 92 > converter_orig_t;
Chris@102 93
Chris@102 94 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@102 95 boost::is_base_of< detect_precision_loss<Source >, converter_orig_t >::value,
Chris@102 96 converter_orig_t,
Chris@102 97 fake_precision_loss<converter_orig_t, Source>
Chris@102 98 >::type converter_t;
Chris@102 99
Chris@102 100 bool res = nothrow_overflow_handler()(converter_t::out_of_range(arg));
Chris@102 101 result = converter_t::low_level_convert(converter_t::nearbyint(arg, res));
Chris@102 102 return res;
Chris@102 103 }
Chris@102 104
Chris@102 105 template <typename Target, typename Source>
Chris@102 106 struct lexical_cast_dynamic_num_not_ignoring_minus
Chris@102 107 {
Chris@102 108 static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT {
Chris@102 109 return noexcept_numeric_convert<Target, Source >(arg, result);
Chris@102 110 }
Chris@102 111 };
Chris@102 112
Chris@102 113 template <typename Target, typename Source>
Chris@102 114 struct lexical_cast_dynamic_num_ignoring_minus
Chris@102 115 {
Chris@102 116 static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT {
Chris@102 117 typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if_c<
Chris@102 118 boost::is_float<Source>::value,
Chris@102 119 boost::mpl::identity<Source>,
Chris@102 120 boost::make_unsigned<Source>
Chris@102 121 >::type usource_t;
Chris@102 122
Chris@102 123 if (arg < 0) {
Chris@102 124 const bool res = noexcept_numeric_convert<Target, usource_t>(0u - arg, result);
Chris@102 125 result = static_cast<Target>(0u - result);
Chris@102 126 return res;
Chris@102 127 } else {
Chris@102 128 return noexcept_numeric_convert<Target, usource_t>(arg, result);
Chris@102 129 }
Chris@102 130 }
Chris@102 131 };
Chris@102 132
Chris@102 133 /*
Chris@102 134 * lexical_cast_dynamic_num follows the rules:
Chris@102 135 * 1) If Source can be converted to Target without precision loss and
Chris@102 136 * without overflows, then assign Source to Target and return
Chris@102 137 *
Chris@102 138 * 2) If Source is less than 0 and Target is an unsigned integer,
Chris@102 139 * then negate Source, check the requirements of rule 1) and if
Chris@102 140 * successful, assign static_casted Source to Target and return
Chris@102 141 *
Chris@102 142 * 3) Otherwise throw a bad_lexical_cast exception
Chris@102 143 *
Chris@102 144 *
Chris@102 145 * Rule 2) required because boost::lexical_cast has the behavior of
Chris@102 146 * stringstream, which uses the rules of scanf for conversions. And
Chris@102 147 * in the C99 standard for unsigned input value minus sign is
Chris@102 148 * optional, so if a negative number is read, no errors will arise
Chris@102 149 * and the result will be the two's complement.
Chris@102 150 */
Chris@102 151 template <typename Target, typename Source>
Chris@102 152 struct dynamic_num_converter_impl
Chris@102 153 {
Chris@102 154 static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT {
Chris@102 155 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@102 156 boost::type_traits::ice_and<
Chris@102 157 boost::is_unsigned<Target>::value,
Chris@102 158 boost::type_traits::ice_or<
Chris@102 159 boost::is_signed<Source>::value,
Chris@102 160 boost::is_float<Source>::value
Chris@102 161 >::value,
Chris@102 162 boost::type_traits::ice_not<
Chris@102 163 boost::is_same<Source, bool>::value
Chris@102 164 >::value,
Chris@102 165 boost::type_traits::ice_not<
Chris@102 166 boost::is_same<Target, bool>::value
Chris@102 167 >::value
Chris@102 168 >::value,
Chris@102 169 lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
Chris@102 170 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
Chris@102 171 >::type caster_type;
Chris@102 172
Chris@102 173 return caster_type::try_convert(arg, result);
Chris@102 174 }
Chris@102 175 };
Chris@102 176
Chris@102 177 }} // namespace boost::detail
Chris@102 178
Chris@102 179 #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP
Chris@102 180