epoc32/include/stdapis/boost/multi_index/detail/converter.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
parent 2 epoc32/include/stdapis/boost/numeric/conversion/detail/converter.hpp@2fe1408b6811
child 4 837f303aceeb
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
     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                   NNone ; // 'None' is defined as a macro in (/usr/X11R6/include/X11/X.h)
   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, NNone>::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