File indexing completed on 2025-01-18 09:42:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
0011 #define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
0012
0013 #include <functional>
0014
0015 #include "boost/numeric/conversion/detail/meta.hpp"
0016 #include "boost/numeric/conversion/detail/conversion_traits.hpp"
0017 #include "boost/numeric/conversion/bounds.hpp"
0018
0019 #include "boost/type_traits/is_same.hpp"
0020
0021 #include "boost/mpl/integral_c.hpp"
0022
0023 namespace boost { namespace numeric { namespace convdetail
0024 {
0025
0026 typedef mpl::integral_c<std::float_round_style, std::round_toward_zero> round2zero_c ;
0027 typedef mpl::integral_c<std::float_round_style, std::round_to_nearest> round2nearest_c ;
0028 typedef mpl::integral_c<std::float_round_style, std::round_toward_infinity> round2inf_c ;
0029 typedef mpl::integral_c<std::float_round_style, std::round_toward_neg_infinity> round2neg_inf_c ;
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 template<class RoundStyle,class RoundToZero,class RoundToNearest,class RoundToInf,class RoundToNegInf>
0041 struct for_round_style
0042 {
0043 typedef ct_switch4<RoundStyle
0044 , round2zero_c, round2nearest_c, round2inf_c
0045 , RoundToZero , RoundToNearest , RoundToInf , RoundToNegInf
0046 > selector ;
0047
0048 typedef typename selector::type type ;
0049 } ;
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 struct non_applicable { typedef mpl::false_ do_apply ; } ;
0082 struct applicable { typedef mpl::true_ do_apply ; } ;
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096 template<class Traits>
0097 struct LT_LoT : applicable
0098 {
0099 typedef typename Traits::target_type T ;
0100 typedef typename Traits::source_type S ;
0101 typedef typename Traits::argument_type argument_type ;
0102
0103 static range_check_result apply ( argument_type s )
0104 {
0105 return s < static_cast<S>(bounds<T>::lowest()) ? cNegOverflow : cInRange ;
0106 }
0107 } ;
0108
0109
0110
0111 template<class Traits>
0112 struct LT_Zero : applicable
0113 {
0114 typedef typename Traits::source_type S ;
0115 typedef typename Traits::argument_type argument_type ;
0116
0117 static range_check_result apply ( argument_type s )
0118 {
0119 return s < static_cast<S>(0) ? cNegOverflow : cInRange ;
0120 }
0121 } ;
0122
0123
0124
0125 template<class Traits>
0126 struct LE_PrevLoT : applicable
0127 {
0128 typedef typename Traits::target_type T ;
0129 typedef typename Traits::source_type S ;
0130 typedef typename Traits::argument_type argument_type ;
0131
0132 static range_check_result apply ( argument_type s )
0133 {
0134 return s <= static_cast<S>(bounds<T>::lowest()) - static_cast<S>(1.0)
0135 ? cNegOverflow : cInRange ;
0136 }
0137 } ;
0138
0139
0140
0141 template<class Traits>
0142 struct LT_HalfPrevLoT : applicable
0143 {
0144 typedef typename Traits::target_type T ;
0145 typedef typename Traits::source_type S ;
0146 typedef typename Traits::argument_type argument_type ;
0147
0148 static range_check_result apply ( argument_type s )
0149 {
0150 return s < static_cast<S>(bounds<T>::lowest()) - static_cast<S>(0.5)
0151 ? cNegOverflow : cInRange ;
0152 }
0153 } ;
0154
0155
0156
0157 template<class Traits>
0158 struct GT_HiT : applicable
0159 {
0160 typedef typename Traits::target_type T ;
0161 typedef typename Traits::source_type S ;
0162 typedef typename Traits::argument_type argument_type ;
0163
0164 static range_check_result apply ( argument_type s )
0165 {
0166 return s > static_cast<S>(bounds<T>::highest())
0167 ? cPosOverflow : cInRange ;
0168 }
0169 } ;
0170
0171
0172
0173 template<class Traits>
0174 struct GE_SuccHiT : applicable
0175 {
0176 typedef typename Traits::target_type T ;
0177 typedef typename Traits::source_type S ;
0178 typedef typename Traits::argument_type argument_type ;
0179
0180 static range_check_result apply ( argument_type s )
0181 {
0182 return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(1.0)
0183 ? cPosOverflow : cInRange ;
0184 }
0185 } ;
0186
0187
0188
0189 template<class Traits>
0190 struct GT_HalfSuccHiT : applicable
0191 {
0192 typedef typename Traits::target_type T ;
0193 typedef typename Traits::source_type S ;
0194 typedef typename Traits::argument_type argument_type ;
0195
0196 static range_check_result apply ( argument_type s )
0197 {
0198 return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(0.5)
0199 ? cPosOverflow : cInRange ;
0200 }
0201 } ;
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 template<class PredA, class PredB>
0216 struct applyBoth
0217 {
0218 typedef typename PredA::argument_type argument_type ;
0219
0220 static range_check_result apply ( argument_type s )
0221 {
0222 range_check_result r = PredA::apply(s) ;
0223 if ( r == cInRange )
0224 r = PredB::apply(s);
0225 return r ;
0226 }
0227 } ;
0228
0229 template<class PredA, class PredB>
0230 struct combine
0231 {
0232 typedef applyBoth<PredA,PredB> Both ;
0233 typedef void NNone ;
0234
0235 typedef typename PredA::do_apply do_applyA ;
0236 typedef typename PredB::do_apply do_applyB ;
0237
0238 typedef typename for_both<do_applyA, do_applyB, Both, PredA, PredB, NNone>::type type ;
0239 } ;
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 template<class Traits>
0263 struct dummy_range_checker
0264 {
0265 typedef typename Traits::argument_type argument_type ;
0266
0267 static range_check_result out_of_range ( argument_type ) { return cInRange ; }
0268 static void validate_range ( argument_type ) {}
0269 } ;
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 template<class Traits, class IsNegOverflow, class IsPosOverflow, class OverflowHandler>
0280 struct generic_range_checker
0281 {
0282 typedef OverflowHandler overflow_handler ;
0283
0284 typedef typename Traits::argument_type argument_type ;
0285
0286 static range_check_result out_of_range ( argument_type s )
0287 {
0288 typedef typename combine<IsNegOverflow,IsPosOverflow>::type Predicate ;
0289
0290 return Predicate::apply(s);
0291 }
0292
0293 static void validate_range ( argument_type s )
0294 { OverflowHandler()( out_of_range(s) ) ; }
0295 } ;
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 template<class Traits,class OverflowHandler>
0306 struct GetRC_Sig2Sig_or_Unsig2Unsig
0307 {
0308 typedef dummy_range_checker<Traits> Dummy ;
0309
0310 typedef LT_LoT<Traits> Pred1 ;
0311 typedef GT_HiT<Traits> Pred2 ;
0312
0313 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
0314
0315 typedef typename Traits::subranged subranged ;
0316
0317 typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
0318 } ;
0319
0320 template<class Traits, class OverflowHandler>
0321 struct GetRC_Sig2Unsig
0322 {
0323 typedef LT_Zero<Traits> Pred1 ;
0324 typedef GT_HiT <Traits> Pred2 ;
0325
0326 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ChoiceA ;
0327
0328 typedef generic_range_checker<Traits,Pred1,non_applicable,OverflowHandler> ChoiceB ;
0329
0330 typedef typename Traits::target_type T ;
0331 typedef typename Traits::source_type S ;
0332
0333 typedef typename subranged_Unsig2Sig<S,T>::type oposite_subranged ;
0334
0335 typedef typename mpl::not_<oposite_subranged>::type positively_subranged ;
0336
0337 typedef typename mpl::if_<positively_subranged,ChoiceA,ChoiceB>::type type ;
0338 } ;
0339
0340 template<class Traits, class OverflowHandler>
0341 struct GetRC_Unsig2Sig
0342 {
0343 typedef GT_HiT<Traits> Pred1 ;
0344
0345 typedef generic_range_checker<Traits,non_applicable,Pred1,OverflowHandler> type ;
0346 } ;
0347
0348 template<class Traits,class OverflowHandler>
0349 struct GetRC_Int2Int
0350 {
0351 typedef GetRC_Sig2Sig_or_Unsig2Unsig<Traits,OverflowHandler> Sig2SigQ ;
0352 typedef GetRC_Sig2Unsig <Traits,OverflowHandler> Sig2UnsigQ ;
0353 typedef GetRC_Unsig2Sig <Traits,OverflowHandler> Unsig2SigQ ;
0354 typedef Sig2SigQ Unsig2UnsigQ ;
0355
0356 typedef typename Traits::sign_mixture sign_mixture ;
0357
0358 typedef typename
0359 for_sign_mixture<sign_mixture,Sig2SigQ,Sig2UnsigQ,Unsig2SigQ,Unsig2UnsigQ>::type
0360 selector ;
0361
0362 typedef typename selector::type type ;
0363 } ;
0364
0365 template<class Traits>
0366 struct GetRC_Int2Float
0367 {
0368 typedef dummy_range_checker<Traits> type ;
0369 } ;
0370
0371 template<class Traits, class OverflowHandler, class Float2IntRounder>
0372 struct GetRC_Float2Int
0373 {
0374 typedef LE_PrevLoT <Traits> Pred1 ;
0375 typedef GE_SuccHiT <Traits> Pred2 ;
0376 typedef LT_HalfPrevLoT<Traits> Pred3 ;
0377 typedef GT_HalfSuccHiT<Traits> Pred4 ;
0378 typedef GT_HiT <Traits> Pred5 ;
0379 typedef LT_LoT <Traits> Pred6 ;
0380
0381 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ToZero ;
0382 typedef generic_range_checker<Traits,Pred3,Pred4,OverflowHandler> ToNearest ;
0383 typedef generic_range_checker<Traits,Pred1,Pred5,OverflowHandler> ToInf ;
0384 typedef generic_range_checker<Traits,Pred6,Pred2,OverflowHandler> ToNegInf ;
0385
0386 typedef typename Float2IntRounder::round_style round_style ;
0387
0388 typedef typename for_round_style<round_style,ToZero,ToNearest,ToInf,ToNegInf>::type type ;
0389 } ;
0390
0391 template<class Traits, class OverflowHandler>
0392 struct GetRC_Float2Float
0393 {
0394 typedef dummy_range_checker<Traits> Dummy ;
0395
0396 typedef LT_LoT<Traits> Pred1 ;
0397 typedef GT_HiT<Traits> Pred2 ;
0398
0399 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
0400
0401 typedef typename Traits::subranged subranged ;
0402
0403 typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
0404 } ;
0405
0406 template<class Traits, class OverflowHandler, class Float2IntRounder>
0407 struct GetRC_BuiltIn2BuiltIn
0408 {
0409 typedef GetRC_Int2Int<Traits,OverflowHandler> Int2IntQ ;
0410 typedef GetRC_Int2Float<Traits> Int2FloatQ ;
0411 typedef GetRC_Float2Int<Traits,OverflowHandler,Float2IntRounder> Float2IntQ ;
0412 typedef GetRC_Float2Float<Traits,OverflowHandler> Float2FloatQ ;
0413
0414 typedef typename Traits::int_float_mixture int_float_mixture ;
0415
0416 typedef typename for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ>::type selector ;
0417
0418 typedef typename selector::type type ;
0419 } ;
0420
0421 template<class Traits, class OverflowHandler, class Float2IntRounder>
0422 struct GetRC
0423 {
0424 typedef GetRC_BuiltIn2BuiltIn<Traits,OverflowHandler,Float2IntRounder> BuiltIn2BuiltInQ ;
0425
0426 typedef dummy_range_checker<Traits> Dummy ;
0427
0428 typedef mpl::identity<Dummy> DummyQ ;
0429
0430 typedef typename Traits::udt_builtin_mixture udt_builtin_mixture ;
0431
0432 typedef typename for_udt_builtin_mixture<udt_builtin_mixture,BuiltIn2BuiltInQ,DummyQ,DummyQ,DummyQ>::type selector ;
0433
0434 typedef typename selector::type type ;
0435 } ;
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 template<class Traits>
0453 struct trivial_converter_impl : public dummy_range_checker<Traits>
0454 {
0455 typedef Traits traits ;
0456
0457 typedef typename Traits::source_type source_type ;
0458 typedef typename Traits::argument_type argument_type ;
0459 typedef typename Traits::result_type result_type ;
0460
0461 static result_type low_level_convert ( argument_type s ) { return s ; }
0462 static source_type nearbyint ( argument_type s ) { return s ; }
0463 static result_type convert ( argument_type s ) { return s ; }
0464 } ;
0465
0466
0467
0468
0469
0470 template<class Traits,class RangeChecker,class RawConverter,class Float2IntRounder>
0471 struct rounding_converter : public RangeChecker
0472 ,public Float2IntRounder
0473 ,public RawConverter
0474 {
0475 typedef RangeChecker RangeCheckerBase ;
0476 typedef Float2IntRounder Float2IntRounderBase ;
0477 typedef RawConverter RawConverterBase ;
0478
0479 typedef Traits traits ;
0480
0481 typedef typename Traits::source_type source_type ;
0482 typedef typename Traits::argument_type argument_type ;
0483 typedef typename Traits::result_type result_type ;
0484
0485 static result_type convert ( argument_type s )
0486 {
0487 RangeCheckerBase::validate_range(s);
0488 source_type s1 = Float2IntRounderBase::nearbyint(s);
0489 return RawConverterBase::low_level_convert(s1);
0490 }
0491 } ;
0492
0493
0494
0495
0496
0497 template<class Traits,class RangeChecker,class RawConverter>
0498 struct non_rounding_converter : public RangeChecker
0499 ,public RawConverter
0500 {
0501 typedef RangeChecker RangeCheckerBase ;
0502 typedef RawConverter RawConverterBase ;
0503
0504 typedef Traits traits ;
0505
0506 typedef typename Traits::source_type source_type ;
0507 typedef typename Traits::argument_type argument_type ;
0508 typedef typename Traits::result_type result_type ;
0509
0510 static source_type nearbyint ( argument_type s ) { return s ; }
0511
0512 static result_type convert ( argument_type s )
0513 {
0514 RangeCheckerBase::validate_range(s);
0515 return RawConverterBase::low_level_convert(s);
0516 }
0517 } ;
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 template<class Traits,class OverflowHandler,class Float2IntRounder,class RawConverter, class UserRangeChecker>
0529 struct get_non_trivial_converter
0530 {
0531 typedef GetRC<Traits,OverflowHandler,Float2IntRounder> InternalRangeCheckerQ ;
0532
0533 typedef is_same<UserRangeChecker,UseInternalRangeChecker> use_internal_RC ;
0534
0535 typedef mpl::identity<UserRangeChecker> UserRangeCheckerQ ;
0536
0537 typedef typename
0538 mpl::eval_if<use_internal_RC,InternalRangeCheckerQ,UserRangeCheckerQ>::type
0539 RangeChecker ;
0540
0541 typedef non_rounding_converter<Traits,RangeChecker,RawConverter> NonRounding ;
0542 typedef rounding_converter<Traits,RangeChecker,RawConverter,Float2IntRounder> Rounding ;
0543
0544 typedef mpl::identity<NonRounding> NonRoundingQ ;
0545 typedef mpl::identity<Rounding> RoundingQ ;
0546
0547 typedef typename Traits::int_float_mixture int_float_mixture ;
0548
0549 typedef typename
0550 for_int_float_mixture<int_float_mixture, NonRoundingQ, NonRoundingQ, RoundingQ, NonRoundingQ>::type
0551 selector ;
0552
0553 typedef typename selector::type type ;
0554 } ;
0555
0556 template< class Traits
0557 ,class OverflowHandler
0558 ,class Float2IntRounder
0559 ,class RawConverter
0560 ,class UserRangeChecker
0561 >
0562 struct get_converter_impl
0563 {
0564 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT( 0x0561 ) )
0565
0566
0567 typedef Traits Traits ;
0568 typedef OverflowHandler OverflowHandler ;
0569 typedef Float2IntRounder Float2IntRounder ;
0570 typedef RawConverter RawConverter ;
0571 typedef UserRangeChecker UserRangeChecker ;
0572 #endif
0573
0574 typedef trivial_converter_impl<Traits> Trivial ;
0575 typedef mpl::identity <Trivial> TrivialQ ;
0576
0577 typedef get_non_trivial_converter< Traits
0578 ,OverflowHandler
0579 ,Float2IntRounder
0580 ,RawConverter
0581 ,UserRangeChecker
0582 > NonTrivialQ ;
0583
0584 typedef typename Traits::trivial trivial ;
0585
0586 typedef typename mpl::eval_if<trivial,TrivialQ,NonTrivialQ>::type type ;
0587 } ;
0588
0589 } } }
0590
0591 #endif
0592
0593