[857] | 1 | // © Copyright Fernando Luis Cacciola Carballal 2000-2004
|
---|
| 2 | // Use, modification, and distribution is subject to the Boost Software
|
---|
| 3 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
---|
| 4 | // http://www.boost.org/LICENSE_1_0.txt)
|
---|
| 5 |
|
---|
| 6 | // See library home page at http://www.boost.org/libs/numeric/conversion
|
---|
| 7 | //
|
---|
| 8 | // Contact the author at: fernando_cacciola@hotmail.com
|
---|
| 9 | //
|
---|
| 10 | #ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
|
---|
| 11 | #define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
|
---|
| 12 |
|
---|
| 13 | #include <functional>
|
---|
| 14 |
|
---|
| 15 | #include "boost/numeric/conversion/detail/meta.hpp"
|
---|
| 16 | #include "boost/numeric/conversion/detail/conversion_traits.hpp"
|
---|
| 17 | #include "boost/numeric/conversion/bounds.hpp"
|
---|
| 18 |
|
---|
| 19 | #include "boost/type_traits/is_same.hpp"
|
---|
| 20 |
|
---|
| 21 | #include "boost/mpl/integral_c.hpp"
|
---|
| 22 |
|
---|
| 23 | namespace boost { namespace numeric { namespace convdetail
|
---|
| 24 | {
|
---|
| 25 | // Integral Constants representing rounding modes
|
---|
| 26 | typedef mpl::integral_c<std::float_round_style, std::round_toward_zero> round2zero_c ;
|
---|
| 27 | typedef mpl::integral_c<std::float_round_style, std::round_to_nearest> round2nearest_c ;
|
---|
| 28 | typedef mpl::integral_c<std::float_round_style, std::round_toward_infinity> round2inf_c ;
|
---|
| 29 | typedef mpl::integral_c<std::float_round_style, std::round_toward_neg_infinity> round2neg_inf_c ;
|
---|
| 30 |
|
---|
| 31 | // Metafunction:
|
---|
| 32 | //
|
---|
| 33 | // for_round_style<RoundStyle,RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf>::type
|
---|
| 34 | //
|
---|
| 35 | // {RoundStyle} Integral Constant specifying a round style as declared above.
|
---|
| 36 | // {RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf} arbitrary types.
|
---|
| 37 | //
|
---|
| 38 | // Selects one of the 4 types according to the value of RoundStyle.
|
---|
| 39 | //
|
---|
| 40 | template<class RoundStyle,class RoundToZero,class RoundToNearest,class RoundToInf,class RoundToNegInf>
|
---|
| 41 | struct for_round_style
|
---|
| 42 | {
|
---|
| 43 | typedef ct_switch4<RoundStyle
|
---|
| 44 | , round2zero_c, round2nearest_c, round2inf_c // round2neg_inf_c
|
---|
| 45 | , RoundToZero , RoundToNearest , RoundToInf , RoundToNegInf
|
---|
| 46 | > selector ;
|
---|
| 47 |
|
---|
| 48 | typedef typename selector::type type ;
|
---|
| 49 | } ;
|
---|
| 50 |
|
---|
| 51 |
|
---|
| 52 |
|
---|
| 53 |
|
---|
| 54 |
|
---|
| 55 |
|
---|
| 56 |
|
---|
| 57 |
|
---|
| 58 |
|
---|
| 59 |
|
---|
| 60 |
|
---|
| 61 |
|
---|
| 62 |
|
---|
| 63 |
|
---|
| 64 |
|
---|
| 65 |
|
---|
| 66 |
|
---|
| 67 |
|
---|
| 68 | //--------------------------------------------------------------------------
|
---|
| 69 | // Range Checking Logic.
|
---|
| 70 | //
|
---|
| 71 | // The range checking logic is built up by combining 1 or 2 predicates.
|
---|
| 72 | // Each predicate is encapsulated in a template class and exposes
|
---|
| 73 | // the static member function 'apply'.
|
---|
| 74 | //
|
---|
| 75 | //--------------------------------------------------------------------------
|
---|
| 76 |
|
---|
| 77 |
|
---|
| 78 | // Because a particular logic can combine either 1 or two predicates, the following
|
---|
| 79 | // tags are used to allow the predicate applier to receive 2 preds, but optimize away
|
---|
| 80 | // one of them if it is 'non-applicable'
|
---|
| 81 | struct non_applicable { typedef mpl::false_ do_apply ; } ;
|
---|
| 82 | struct applicable { typedef mpl::true_ do_apply ; } ;
|
---|
| 83 |
|
---|
| 84 |
|
---|
| 85 | //--------------------------------------------------------------------------
|
---|
| 86 | //
|
---|
| 87 | // Range Checking Logic implementations.
|
---|
| 88 | //
|
---|
| 89 | // The following classes, collectivelly named 'Predicates', are instantiated within
|
---|
| 90 | // the corresponding range checkers.
|
---|
| 91 | // Their static member function 'apply' is called to perform the actual range checking logic.
|
---|
| 92 | //--------------------------------------------------------------------------
|
---|
| 93 |
|
---|
| 94 | // s < Lowest(T) ? cNegOverflow : cInRange
|
---|
| 95 | //
|
---|
| 96 | template<class Traits>
|
---|
| 97 | struct LT_LoT : applicable
|
---|
| 98 | {
|
---|
| 99 | typedef typename Traits::target_type T ;
|
---|
| 100 | typedef typename Traits::source_type S ;
|
---|
| 101 | typedef typename Traits::argument_type argument_type ;
|
---|
| 102 |
|
---|
| 103 | static range_check_result apply ( argument_type s )
|
---|
| 104 | {
|
---|
| 105 | return s < static_cast<S>(bounds<T>::lowest()) ? cNegOverflow : cInRange ;
|
---|
| 106 | }
|
---|
| 107 | } ;
|
---|
| 108 |
|
---|
| 109 | // s < 0 ? cNegOverflow : cInRange
|
---|
| 110 | //
|
---|
| 111 | template<class Traits>
|
---|
| 112 | struct LT_Zero : applicable
|
---|
| 113 | {
|
---|
| 114 | typedef typename Traits::source_type S ;
|
---|
| 115 | typedef typename Traits::argument_type argument_type ;
|
---|
| 116 |
|
---|
| 117 | static range_check_result apply ( argument_type s )
|
---|
| 118 | {
|
---|
| 119 | return s < static_cast<S>(0) ? cNegOverflow : cInRange ;
|
---|
| 120 | }
|
---|
| 121 | } ;
|
---|
| 122 |
|
---|
| 123 | // s <= Lowest(T)-1 ? cNegOverflow : cInRange
|
---|
| 124 | //
|
---|
| 125 | template<class Traits>
|
---|
| 126 | struct LE_PrevLoT : applicable
|
---|
| 127 | {
|
---|
| 128 | typedef typename Traits::target_type T ;
|
---|
| 129 | typedef typename Traits::source_type S ;
|
---|
| 130 | typedef typename Traits::argument_type argument_type ;
|
---|
| 131 |
|
---|
| 132 | static range_check_result apply ( argument_type s )
|
---|
| 133 | {
|
---|
| 134 | return s <= static_cast<S>(bounds<T>::lowest()) - static_cast<S>(1.0)
|
---|
| 135 | ? cNegOverflow : cInRange ;
|
---|
| 136 | }
|
---|
| 137 | } ;
|
---|
| 138 |
|
---|
| 139 | // s < Lowest(T)-0.5 ? cNegOverflow : cInRange
|
---|
| 140 | //
|
---|
| 141 | template<class Traits>
|
---|
| 142 | struct LT_HalfPrevLoT : applicable
|
---|
| 143 | {
|
---|
| 144 | typedef typename Traits::target_type T ;
|
---|
| 145 | typedef typename Traits::source_type S ;
|
---|
| 146 | typedef typename Traits::argument_type argument_type ;
|
---|
| 147 |
|
---|
| 148 | static range_check_result apply ( argument_type s )
|
---|
| 149 | {
|
---|
| 150 | return s < static_cast<S>(bounds<T>::lowest()) - static_cast<S>(0.5)
|
---|
| 151 | ? cNegOverflow : cInRange ;
|
---|
| 152 | }
|
---|
| 153 | } ;
|
---|
| 154 |
|
---|
| 155 | // s > Highest(T) ? cPosOverflow : cInRange
|
---|
| 156 | //
|
---|
| 157 | template<class Traits>
|
---|
| 158 | struct GT_HiT : applicable
|
---|
| 159 | {
|
---|
| 160 | typedef typename Traits::target_type T ;
|
---|
| 161 | typedef typename Traits::source_type S ;
|
---|
| 162 | typedef typename Traits::argument_type argument_type ;
|
---|
| 163 |
|
---|
| 164 | static range_check_result apply ( argument_type s )
|
---|
| 165 | {
|
---|
| 166 | return s > static_cast<S>(bounds<T>::highest())
|
---|
| 167 | ? cPosOverflow : cInRange ;
|
---|
| 168 | }
|
---|
| 169 | } ;
|
---|
| 170 |
|
---|
| 171 | // s >= Lowest(T) + 1 ? cPosOverflow : cInRange
|
---|
| 172 | //
|
---|
| 173 | template<class Traits>
|
---|
| 174 | struct GE_SuccHiT : applicable
|
---|
| 175 | {
|
---|
| 176 | typedef typename Traits::target_type T ;
|
---|
| 177 | typedef typename Traits::source_type S ;
|
---|
| 178 | typedef typename Traits::argument_type argument_type ;
|
---|
| 179 |
|
---|
| 180 | static range_check_result apply ( argument_type s )
|
---|
| 181 | {
|
---|
| 182 | return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(1.0)
|
---|
| 183 | ? cPosOverflow : cInRange ;
|
---|
| 184 | }
|
---|
| 185 | } ;
|
---|
| 186 |
|
---|
| 187 | // s >= Lowest(T) + 0.5 ? cPosgOverflow : cInRange
|
---|
| 188 | //
|
---|
| 189 | template<class Traits>
|
---|
| 190 | struct GT_HalfSuccHiT : applicable
|
---|
| 191 | {
|
---|
| 192 | typedef typename Traits::target_type T ;
|
---|
| 193 | typedef typename Traits::source_type S ;
|
---|
| 194 | typedef typename Traits::argument_type argument_type ;
|
---|
| 195 |
|
---|
| 196 | static range_check_result apply ( argument_type s )
|
---|
| 197 | {
|
---|
| 198 | return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(0.5)
|
---|
| 199 | ? cPosOverflow : cInRange ;
|
---|
| 200 | }
|
---|
| 201 | } ;
|
---|
| 202 |
|
---|
| 203 |
|
---|
| 204 | //--------------------------------------------------------------------------
|
---|
| 205 | //
|
---|
| 206 | // Predicate Combiner.
|
---|
| 207 | //
|
---|
| 208 | // This helper classes are used to possibly combine the range checking logic
|
---|
| 209 | // individually performed by the predicates
|
---|
| 210 | //
|
---|
| 211 | //--------------------------------------------------------------------------
|
---|
| 212 |
|
---|
| 213 |
|
---|
| 214 | // Applies both predicates: first 'PredA', and if it equals 'cInRange', 'PredB'
|
---|
| 215 | template<class PredA, class PredB>
|
---|
| 216 | struct applyBoth
|
---|
| 217 | {
|
---|
| 218 | typedef typename PredA::argument_type argument_type ;
|
---|
| 219 |
|
---|
| 220 | static range_check_result apply ( argument_type s )
|
---|
| 221 | {
|
---|
| 222 | range_check_result r = PredA::apply(s) ;
|
---|
| 223 | if ( r == cInRange )
|
---|
| 224 | r = PredB::apply(s);
|
---|
| 225 | return r ;
|
---|
| 226 | }
|
---|
| 227 | } ;
|
---|
| 228 |
|
---|
| 229 | template<class PredA, class PredB>
|
---|
| 230 | struct combine
|
---|
| 231 | {
|
---|
| 232 | typedef applyBoth<PredA,PredB> Both ;
|
---|
| 233 | typedef void None ;
|
---|
| 234 |
|
---|
| 235 | typedef typename PredA::do_apply do_applyA ;
|
---|
| 236 | typedef typename PredB::do_apply do_applyB ;
|
---|
| 237 |
|
---|
| 238 | typedef typename for_both<do_applyA, do_applyB, Both, PredA, PredB, None>::type type ;
|
---|
| 239 | } ;
|
---|
| 240 |
|
---|
| 241 |
|
---|
| 242 |
|
---|
| 243 |
|
---|
| 244 |
|
---|
| 245 |
|
---|
| 246 |
|
---|
| 247 |
|
---|
| 248 |
|
---|
| 249 |
|
---|
| 250 |
|
---|
| 251 |
|
---|
| 252 | //--------------------------------------------------------------------------
|
---|
| 253 | // Range Checker classes.
|
---|
| 254 | //
|
---|
| 255 | // The following classes are VISIBLE base classes of the user-level converter<> class.
|
---|
| 256 | // They supply the optimized 'out_of_range()' and 'validate_range()' static member functions
|
---|
| 257 | // visible in the user interface.
|
---|
| 258 | //
|
---|
| 259 | //--------------------------------------------------------------------------
|
---|
| 260 |
|
---|
| 261 | // Dummy range checker.
|
---|
| 262 | template<class Traits>
|
---|
| 263 | struct dummy_range_checker
|
---|
| 264 | {
|
---|
| 265 | typedef typename Traits::argument_type argument_type ;
|
---|
| 266 |
|
---|
| 267 | static range_check_result out_of_range ( argument_type ) { return cInRange ; }
|
---|
| 268 | static void validate_range ( argument_type ) {}
|
---|
| 269 | } ;
|
---|
| 270 |
|
---|
| 271 | // Generic range checker.
|
---|
| 272 | //
|
---|
| 273 | // All the range checking logic for all possible combinations of source and target
|
---|
| 274 | // can be arranged in terms of one or two predicates, which test overflow on both neg/pos 'sides'
|
---|
| 275 | // of the ranges.
|
---|
| 276 | //
|
---|
| 277 | // These predicates are given here as IsNegOverflow and IsPosOverflow.
|
---|
| 278 | //
|
---|
| 279 | template<class Traits, class IsNegOverflow, class IsPosOverflow, class OverflowHandler>
|
---|
| 280 | struct generic_range_checker
|
---|
| 281 | {
|
---|
| 282 | typedef OverflowHandler overflow_handler ;
|
---|
| 283 |
|
---|
| 284 | typedef typename Traits::argument_type argument_type ;
|
---|
| 285 |
|
---|
| 286 | static range_check_result out_of_range ( argument_type s )
|
---|
| 287 | {
|
---|
| 288 | typedef typename combine<IsNegOverflow,IsPosOverflow>::type Predicate ;
|
---|
| 289 |
|
---|
| 290 | return Predicate::apply(s);
|
---|
| 291 | }
|
---|
| 292 |
|
---|
| 293 | static void validate_range ( argument_type s )
|
---|
| 294 | { OverflowHandler()( out_of_range(s) ) ; }
|
---|
| 295 | } ;
|
---|
| 296 |
|
---|
| 297 |
|
---|
| 298 |
|
---|
| 299 | //--------------------------------------------------------------------------
|
---|
| 300 | //
|
---|
| 301 | // Selectors for the optimized Range Checker class.
|
---|
| 302 | //
|
---|
| 303 | //--------------------------------------------------------------------------
|
---|
| 304 |
|
---|
| 305 | template<class Traits,class OverflowHandler>
|
---|
| 306 | struct GetRC_Sig2Sig_or_Unsig2Unsig
|
---|
| 307 | {
|
---|
| 308 | typedef dummy_range_checker<Traits> Dummy ;
|
---|
| 309 |
|
---|
| 310 | typedef LT_LoT<Traits> Pred1 ;
|
---|
| 311 | typedef GT_HiT<Traits> Pred2 ;
|
---|
| 312 |
|
---|
| 313 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
|
---|
| 314 |
|
---|
| 315 | typedef typename Traits::subranged subranged ;
|
---|
| 316 |
|
---|
| 317 | typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
|
---|
| 318 | } ;
|
---|
| 319 |
|
---|
| 320 | template<class Traits, class OverflowHandler>
|
---|
| 321 | struct GetRC_Sig2Unsig
|
---|
| 322 | {
|
---|
| 323 | typedef LT_Zero<Traits> Pred1 ;
|
---|
| 324 | typedef GT_HiT <Traits> Pred2 ;
|
---|
| 325 |
|
---|
| 326 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ChoiceA ;
|
---|
| 327 |
|
---|
| 328 | typedef generic_range_checker<Traits,Pred1,non_applicable,OverflowHandler> ChoiceB ;
|
---|
| 329 |
|
---|
| 330 | typedef typename Traits::target_type T ;
|
---|
| 331 | typedef typename Traits::source_type S ;
|
---|
| 332 |
|
---|
| 333 | typedef typename subranged_Unsig2Sig<S,T>::type oposite_subranged ;
|
---|
| 334 |
|
---|
| 335 | typedef typename mpl::not_<oposite_subranged>::type positively_subranged ;
|
---|
| 336 |
|
---|
| 337 | typedef typename mpl::if_<positively_subranged,ChoiceA,ChoiceB>::type type ;
|
---|
| 338 | } ;
|
---|
| 339 |
|
---|
| 340 | template<class Traits, class OverflowHandler>
|
---|
| 341 | struct GetRC_Unsig2Sig
|
---|
| 342 | {
|
---|
| 343 | typedef GT_HiT<Traits> Pred1 ;
|
---|
| 344 |
|
---|
| 345 | typedef generic_range_checker<Traits,non_applicable,Pred1,OverflowHandler> type ;
|
---|
| 346 | } ;
|
---|
| 347 |
|
---|
| 348 | template<class Traits,class OverflowHandler>
|
---|
| 349 | struct GetRC_Int2Int
|
---|
| 350 | {
|
---|
| 351 | typedef GetRC_Sig2Sig_or_Unsig2Unsig<Traits,OverflowHandler> Sig2SigQ ;
|
---|
| 352 | typedef GetRC_Sig2Unsig <Traits,OverflowHandler> Sig2UnsigQ ;
|
---|
| 353 | typedef GetRC_Unsig2Sig <Traits,OverflowHandler> Unsig2SigQ ;
|
---|
| 354 | typedef Sig2SigQ Unsig2UnsigQ ;
|
---|
| 355 |
|
---|
| 356 | typedef typename Traits::sign_mixture sign_mixture ;
|
---|
| 357 |
|
---|
| 358 | typedef typename
|
---|
| 359 | for_sign_mixture<sign_mixture,Sig2SigQ,Sig2UnsigQ,Unsig2SigQ,Unsig2UnsigQ>::type
|
---|
| 360 | selector ;
|
---|
| 361 |
|
---|
| 362 | typedef typename selector::type type ;
|
---|
| 363 | } ;
|
---|
| 364 |
|
---|
| 365 | template<class Traits>
|
---|
| 366 | struct GetRC_Int2Float
|
---|
| 367 | {
|
---|
| 368 | typedef dummy_range_checker<Traits> type ;
|
---|
| 369 | } ;
|
---|
| 370 |
|
---|
| 371 | template<class Traits, class OverflowHandler, class Float2IntRounder>
|
---|
| 372 | struct GetRC_Float2Int
|
---|
| 373 | {
|
---|
| 374 | typedef LE_PrevLoT <Traits> Pred1 ;
|
---|
| 375 | typedef GE_SuccHiT <Traits> Pred2 ;
|
---|
| 376 | typedef LT_HalfPrevLoT<Traits> Pred3 ;
|
---|
| 377 | typedef GT_HalfSuccHiT<Traits> Pred4 ;
|
---|
| 378 | typedef GT_HiT <Traits> Pred5 ;
|
---|
| 379 | typedef LT_LoT <Traits> Pred6 ;
|
---|
| 380 |
|
---|
| 381 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ToZero ;
|
---|
| 382 | typedef generic_range_checker<Traits,Pred3,Pred4,OverflowHandler> ToNearest ;
|
---|
| 383 | typedef generic_range_checker<Traits,Pred1,Pred5,OverflowHandler> ToInf ;
|
---|
| 384 | typedef generic_range_checker<Traits,Pred6,Pred2,OverflowHandler> ToNegInf ;
|
---|
| 385 |
|
---|
| 386 | typedef typename Float2IntRounder::round_style round_style ;
|
---|
| 387 |
|
---|
| 388 | typedef typename for_round_style<round_style,ToZero,ToNearest,ToInf,ToNegInf>::type type ;
|
---|
| 389 | } ;
|
---|
| 390 |
|
---|
| 391 | template<class Traits, class OverflowHandler>
|
---|
| 392 | struct GetRC_Float2Float
|
---|
| 393 | {
|
---|
| 394 | typedef dummy_range_checker<Traits> Dummy ;
|
---|
| 395 |
|
---|
| 396 | typedef LT_LoT<Traits> Pred1 ;
|
---|
| 397 | typedef GT_HiT<Traits> Pred2 ;
|
---|
| 398 |
|
---|
| 399 | typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
|
---|
| 400 |
|
---|
| 401 | typedef typename Traits::subranged subranged ;
|
---|
| 402 |
|
---|
| 403 | typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
|
---|
| 404 | } ;
|
---|
| 405 |
|
---|
| 406 | template<class Traits, class OverflowHandler, class Float2IntRounder>
|
---|
| 407 | struct GetRC_BuiltIn2BuiltIn
|
---|
| 408 | {
|
---|
| 409 | typedef GetRC_Int2Int<Traits,OverflowHandler> Int2IntQ ;
|
---|
| 410 | typedef GetRC_Int2Float<Traits> Int2FloatQ ;
|
---|
| 411 | typedef GetRC_Float2Int<Traits,OverflowHandler,Float2IntRounder> Float2IntQ ;
|
---|
| 412 | typedef GetRC_Float2Float<Traits,OverflowHandler> Float2FloatQ ;
|
---|
| 413 |
|
---|
| 414 | typedef typename Traits::int_float_mixture int_float_mixture ;
|
---|
| 415 |
|
---|
| 416 | typedef typename for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ>::type selector ;
|
---|
| 417 |
|
---|
| 418 | typedef typename selector::type type ;
|
---|
| 419 | } ;
|
---|
| 420 |
|
---|
| 421 | template<class Traits, class OverflowHandler, class Float2IntRounder>
|
---|
| 422 | struct GetRC
|
---|
| 423 | {
|
---|
| 424 | typedef GetRC_BuiltIn2BuiltIn<Traits,OverflowHandler,Float2IntRounder> BuiltIn2BuiltInQ ;
|
---|
| 425 |
|
---|
| 426 | typedef dummy_range_checker<Traits> Dummy ;
|
---|
| 427 |
|
---|
| 428 | typedef mpl::identity<Dummy> DummyQ ;
|
---|
| 429 |
|
---|
| 430 | typedef typename Traits::udt_builtin_mixture udt_builtin_mixture ;
|
---|
| 431 |
|
---|
| 432 | typedef typename for_udt_builtin_mixture<udt_builtin_mixture,BuiltIn2BuiltInQ,DummyQ,DummyQ,DummyQ>::type selector ;
|
---|
| 433 |
|
---|
| 434 | typedef typename selector::type type ;
|
---|
| 435 | } ;
|
---|
| 436 |
|
---|
| 437 |
|
---|
| 438 |
|
---|
| 439 |
|
---|
| 440 | //--------------------------------------------------------------------------
|
---|
| 441 | // Converter classes.
|
---|
| 442 | //
|
---|
| 443 | // The following classes are VISIBLE base classes of the user-level converter<> class.
|
---|
| 444 | // They supply the optimized 'nearbyint()' and 'convert()' static member functions
|
---|
| 445 | // visible in the user interface.
|
---|
| 446 | //
|
---|
| 447 | //--------------------------------------------------------------------------
|
---|
| 448 |
|
---|
| 449 | //
|
---|
| 450 | // Trivial Converter : used when (cv-unqualified) T == (cv-unqualified) S
|
---|
| 451 | //
|
---|
| 452 | template<class Traits>
|
---|
| 453 | struct trivial_converter_impl : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
|
---|
| 454 | ,BOOST_DEDUCED_TYPENAME Traits::result_type
|
---|
| 455 | >
|
---|
| 456 | ,public dummy_range_checker<Traits>
|
---|
| 457 | {
|
---|
| 458 | typedef Traits traits ;
|
---|
| 459 |
|
---|
| 460 | typedef typename Traits::source_type source_type ;
|
---|
| 461 | typedef typename Traits::argument_type argument_type ;
|
---|
| 462 | typedef typename Traits::result_type result_type ;
|
---|
| 463 |
|
---|
| 464 | static result_type low_level_convert ( argument_type s ) { return s ; }
|
---|
| 465 | static source_type nearbyint ( argument_type s ) { return s ; }
|
---|
| 466 | static result_type convert ( argument_type s ) { return s ; }
|
---|
| 467 | } ;
|
---|
| 468 |
|
---|
| 469 |
|
---|
| 470 | //
|
---|
| 471 | // Rounding Converter : used for float to integral conversions.
|
---|
| 472 | //
|
---|
| 473 | template<class Traits,class RangeChecker,class RawConverter,class Float2IntRounder>
|
---|
| 474 | struct rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
|
---|
| 475 | ,BOOST_DEDUCED_TYPENAME Traits::result_type
|
---|
| 476 | >
|
---|
| 477 | ,public RangeChecker
|
---|
| 478 | ,public Float2IntRounder
|
---|
| 479 | ,public RawConverter
|
---|
| 480 | {
|
---|
| 481 | typedef RangeChecker RangeCheckerBase ;
|
---|
| 482 | typedef Float2IntRounder Float2IntRounderBase ;
|
---|
| 483 | typedef RawConverter RawConverterBase ;
|
---|
| 484 |
|
---|
| 485 | typedef Traits traits ;
|
---|
| 486 |
|
---|
| 487 | typedef typename Traits::source_type source_type ;
|
---|
| 488 | typedef typename Traits::argument_type argument_type ;
|
---|
| 489 | typedef typename Traits::result_type result_type ;
|
---|
| 490 |
|
---|
| 491 | static result_type convert ( argument_type s )
|
---|
| 492 | {
|
---|
| 493 | RangeCheckerBase::validate_range(s);
|
---|
| 494 | source_type s1 = Float2IntRounderBase::nearbyint(s);
|
---|
| 495 | return RawConverterBase::low_level_convert(s1);
|
---|
| 496 | }
|
---|
| 497 | } ;
|
---|
| 498 |
|
---|
| 499 |
|
---|
| 500 | //
|
---|
| 501 | // Non-Rounding Converter : used for all other conversions.
|
---|
| 502 | //
|
---|
| 503 | template<class Traits,class RangeChecker,class RawConverter>
|
---|
| 504 | struct non_rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
|
---|
| 505 | ,BOOST_DEDUCED_TYPENAME Traits::result_type
|
---|
| 506 | >
|
---|
| 507 | ,public RangeChecker
|
---|
| 508 | ,public RawConverter
|
---|
| 509 | {
|
---|
| 510 | typedef RangeChecker RangeCheckerBase ;
|
---|
| 511 | typedef RawConverter RawConverterBase ;
|
---|
| 512 |
|
---|
| 513 | typedef Traits traits ;
|
---|
| 514 |
|
---|
| 515 | typedef typename Traits::source_type source_type ;
|
---|
| 516 | typedef typename Traits::argument_type argument_type ;
|
---|
| 517 | typedef typename Traits::result_type result_type ;
|
---|
| 518 |
|
---|
| 519 | static source_type nearbyint ( argument_type s ) { return s ; }
|
---|
| 520 |
|
---|
| 521 | static result_type convert ( argument_type s )
|
---|
| 522 | {
|
---|
| 523 | RangeCheckerBase::validate_range(s);
|
---|
| 524 | return RawConverterBase::low_level_convert(s);
|
---|
| 525 | }
|
---|
| 526 | } ;
|
---|
| 527 |
|
---|
| 528 |
|
---|
| 529 |
|
---|
| 530 |
|
---|
| 531 | //--------------------------------------------------------------------------
|
---|
| 532 | //
|
---|
| 533 | // Selectors for the optimized Converter class.
|
---|
| 534 | //
|
---|
| 535 | //--------------------------------------------------------------------------
|
---|
| 536 |
|
---|
| 537 | template<class Traits,class OverflowHandler,class Float2IntRounder,class RawConverter, class UserRangeChecker>
|
---|
| 538 | struct get_non_trivial_converter
|
---|
| 539 | {
|
---|
| 540 | typedef GetRC<Traits,OverflowHandler,Float2IntRounder> InternalRangeCheckerQ ;
|
---|
| 541 |
|
---|
| 542 | typedef is_same<UserRangeChecker,UseInternalRangeChecker> use_internal_RC ;
|
---|
| 543 |
|
---|
| 544 | typedef mpl::identity<UserRangeChecker> UserRangeCheckerQ ;
|
---|
| 545 |
|
---|
| 546 | typedef typename
|
---|
| 547 | mpl::eval_if<use_internal_RC,InternalRangeCheckerQ,UserRangeCheckerQ>::type
|
---|
| 548 | RangeChecker ;
|
---|
| 549 |
|
---|
| 550 | typedef non_rounding_converter<Traits,RangeChecker,RawConverter> NonRounding ;
|
---|
| 551 | typedef rounding_converter<Traits,RangeChecker,RawConverter,Float2IntRounder> Rounding ;
|
---|
| 552 |
|
---|
| 553 | typedef mpl::identity<NonRounding> NonRoundingQ ;
|
---|
| 554 | typedef mpl::identity<Rounding> RoundingQ ;
|
---|
| 555 |
|
---|
| 556 | typedef typename Traits::int_float_mixture int_float_mixture ;
|
---|
| 557 |
|
---|
| 558 | typedef typename
|
---|
| 559 | for_int_float_mixture<int_float_mixture, NonRoundingQ, NonRoundingQ, RoundingQ, NonRoundingQ>::type
|
---|
| 560 | selector ;
|
---|
| 561 |
|
---|
| 562 | typedef typename selector::type type ;
|
---|
| 563 | } ;
|
---|
| 564 |
|
---|
| 565 | template< class Traits
|
---|
| 566 | ,class OverflowHandler
|
---|
| 567 | ,class Float2IntRounder
|
---|
| 568 | ,class RawConverter
|
---|
| 569 | ,class UserRangeChecker
|
---|
| 570 | >
|
---|
| 571 | struct get_converter_impl
|
---|
| 572 | {
|
---|
| 573 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT( 0x0561 ) )
|
---|
| 574 | // bcc55 prefers sometimes template parameters to be explicit local types.
|
---|
| 575 | // (notice that is is illegal to reuse the names like this)
|
---|
| 576 | typedef Traits Traits ;
|
---|
| 577 | typedef OverflowHandler OverflowHandler ;
|
---|
| 578 | typedef Float2IntRounder Float2IntRounder ;
|
---|
| 579 | typedef RawConverter RawConverter ;
|
---|
| 580 | typedef UserRangeChecker UserRangeChecker ;
|
---|
| 581 | #endif
|
---|
| 582 |
|
---|
| 583 | typedef trivial_converter_impl<Traits> Trivial ;
|
---|
| 584 | typedef mpl::identity <Trivial> TrivialQ ;
|
---|
| 585 |
|
---|
| 586 | typedef get_non_trivial_converter< Traits
|
---|
| 587 | ,OverflowHandler
|
---|
| 588 | ,Float2IntRounder
|
---|
| 589 | ,RawConverter
|
---|
| 590 | ,UserRangeChecker
|
---|
| 591 | > NonTrivialQ ;
|
---|
| 592 |
|
---|
| 593 | typedef typename Traits::trivial trivial ;
|
---|
| 594 |
|
---|
| 595 | typedef typename mpl::eval_if<trivial,TrivialQ,NonTrivialQ>::type type ;
|
---|
| 596 | } ;
|
---|
| 597 |
|
---|
| 598 | } } } // namespace boost::numeric::convdetail
|
---|
| 599 |
|
---|
| 600 | #endif
|
---|
| 601 |
|
---|
| 602 |
|
---|