epoc32/include/stdapis/boost/numeric/conversion/converter_policies.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100 (2010-03-31)
branchSymbian2
changeset 3 e1b950c65cb4
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_CONVERTER_POLICIES_FLC_12NOV2002_HPP
    11 #define BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
    12 
    13 #include <typeinfo> // for std::bad_cast
    14 
    15 #include <cmath> // for std::floor and std::ceil
    16 
    17 #include <functional>
    18 
    19 #include "boost/type_traits/is_arithmetic.hpp"
    20 
    21 #include "boost/mpl/if.hpp"
    22 #include "boost/mpl/integral_c.hpp"
    23 
    24 namespace boost { namespace numeric
    25 {
    26 
    27 template<class S>
    28 struct Trunc
    29 {
    30   typedef S source_type ;
    31 
    32   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
    33 
    34   static source_type nearbyint ( argument_type s )
    35   {
    36 #if !defined(BOOST_NO_STDC_NAMESPACE)
    37     using std::floor ;
    38     using std::ceil  ;
    39 #endif
    40 
    41     return s < static_cast<S>(0) ? ceil(s) : floor(s) ;
    42   }
    43 
    44   typedef mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style ;
    45 } ;
    46 
    47 
    48 
    49 template<class S>
    50 struct Floor
    51 {
    52   typedef S source_type ;
    53 
    54   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
    55 
    56   static source_type nearbyint ( argument_type s )
    57   {
    58 #if !defined(BOOST_NO_STDC_NAMESPACE)
    59     using std::floor ;
    60 #endif
    61 
    62     return floor(s) ;
    63   }
    64 
    65   typedef mpl::integral_c< std::float_round_style, std::round_toward_neg_infinity> round_style ;
    66 } ;
    67 
    68 template<class S>
    69 struct Ceil
    70 {
    71   typedef S source_type ;
    72 
    73   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
    74 
    75   static source_type nearbyint ( argument_type s )
    76   {
    77 #if !defined(BOOST_NO_STDC_NAMESPACE)
    78     using std::ceil ;
    79 #endif
    80 
    81     return ceil(s) ;
    82   }
    83 
    84   typedef mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style ;
    85 } ;
    86 
    87 template<class S>
    88 struct RoundEven
    89 {
    90   typedef S source_type ;
    91 
    92   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
    93 
    94   static source_type nearbyint ( argument_type s )
    95   {
    96     // Algorithm contributed by Guillaume Melquiond
    97 
    98 #if !defined(BOOST_NO_STDC_NAMESPACE)
    99     using std::floor ;
   100     using std::ceil  ;
   101 #endif
   102 
   103     // only works inside the range not at the boundaries
   104     S prev = floor(s);
   105     S next = ceil(s);
   106 
   107     S rt = (s - prev) - (next - s); // remainder type
   108 
   109     S const zero(0.0);
   110     S const two(2.0);
   111 
   112     if ( rt < zero )
   113       return prev;
   114     else if ( rt > zero )
   115       return next;
   116     else
   117     {
   118       bool is_prev_even = two * floor(prev / two) == prev ;
   119       return ( is_prev_even ? prev : next ) ;
   120     }
   121   }
   122 
   123   typedef mpl::integral_c< std::float_round_style, std::round_to_nearest> round_style ;
   124 } ;
   125 
   126 
   127 enum range_check_result
   128 {
   129   cInRange     = 0 ,
   130   cNegOverflow = 1 ,
   131   cPosOverflow = 2
   132 } ;
   133 
   134 class bad_numeric_cast : public std::bad_cast
   135 {
   136   public:
   137 
   138     virtual const char * what() const throw()
   139       {  return "bad numeric conversion: overflow"; }
   140 };
   141 
   142 class negative_overflow : public bad_numeric_cast
   143 {
   144   public:
   145 
   146     virtual const char * what() const throw()
   147       {  return "bad numeric conversion: negative overflow"; }
   148 };
   149 class positive_overflow : public bad_numeric_cast
   150 {
   151   public:
   152 
   153     virtual const char * what() const throw()
   154       { return "bad numeric conversion: positive overflow"; }
   155 };
   156 
   157 struct def_overflow_handler
   158 {
   159   void operator() ( range_check_result r ) // throw(negative_overflow,positive_overflow)
   160   {
   161     if ( r == cNegOverflow )
   162       throw negative_overflow() ;
   163     else if ( r == cPosOverflow )
   164            throw positive_overflow() ;
   165   }
   166 } ;
   167 
   168 struct silent_overflow_handler
   169 {
   170   void operator() ( range_check_result ) {} // throw()
   171 } ;
   172 
   173 template<class Traits>
   174 struct raw_converter
   175 {
   176   typedef typename Traits::result_type   result_type   ;
   177   typedef typename Traits::argument_type argument_type ;
   178 
   179   static result_type low_level_convert ( argument_type s ) { return static_cast<result_type>(s) ; }
   180 } ;
   181 
   182 struct UseInternalRangeChecker {} ;
   183 
   184 } } // namespace boost::numeric
   185 
   186 #endif