Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:47

0001 //  (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
0002 //  Use, modification, and distribution is subject to the Boost Software
0003 //  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0004 //  http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 //  See library home page at http://www.boost.org/libs/numeric/conversion
0007 //
0008 // Contact the author at: fernando_cacciola@hotmail.com
0009 //
0010 #ifndef BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
0011 #define BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
0012 
0013 #include <functional>
0014 #include <typeinfo> // for std::bad_cast
0015 
0016 #include <boost/config.hpp>
0017 #include <boost/config/no_tr1/cmath.hpp> // for std::floor and std::ceil
0018 #include <boost/throw_exception.hpp>
0019 
0020 #include "boost/type_traits/is_arithmetic.hpp"
0021 
0022 #include "boost/mpl/if.hpp"
0023 #include "boost/mpl/integral_c.hpp"
0024 
0025 namespace boost { namespace numeric
0026 {
0027 
0028 template<class S>
0029 struct Trunc
0030 {
0031   typedef S source_type ;
0032 
0033   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
0034 
0035   static source_type nearbyint ( argument_type s )
0036   {
0037 #if !defined(BOOST_NO_STDC_NAMESPACE)
0038     using std::floor ;
0039     using std::ceil  ;
0040 #endif
0041 
0042     return s < static_cast<S>(0) ? ceil(s) : floor(s) ;
0043   }
0044 
0045   typedef mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style ;
0046 } ;
0047 
0048 
0049 
0050 template<class S>
0051 struct Floor
0052 {
0053   typedef S source_type ;
0054 
0055   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
0056 
0057   static source_type nearbyint ( argument_type s )
0058   {
0059 #if !defined(BOOST_NO_STDC_NAMESPACE)
0060     using std::floor ;
0061 #endif
0062 
0063     return floor(s) ;
0064   }
0065 
0066   typedef mpl::integral_c< std::float_round_style, std::round_toward_neg_infinity> round_style ;
0067 } ;
0068 
0069 template<class S>
0070 struct Ceil
0071 {
0072   typedef S source_type ;
0073 
0074   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
0075 
0076   static source_type nearbyint ( argument_type s )
0077   {
0078 #if !defined(BOOST_NO_STDC_NAMESPACE)
0079     using std::ceil ;
0080 #endif
0081 
0082     return ceil(s) ;
0083   }
0084 
0085   typedef mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style ;
0086 } ;
0087 
0088 template<class S>
0089 struct RoundEven
0090 {
0091   typedef S source_type ;
0092 
0093   typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
0094 
0095   static source_type nearbyint ( argument_type s )
0096   {
0097     // Algorithm contributed by Guillaume Melquiond
0098 
0099 #if !defined(BOOST_NO_STDC_NAMESPACE)
0100     using std::floor ;
0101     using std::ceil  ;
0102 #endif
0103 
0104     // only works inside the range not at the boundaries
0105     S prev = floor(s);
0106     S next = ceil(s);
0107 
0108     S rt = (s - prev) - (next - s); // remainder type
0109 
0110     S const zero(0.0);
0111     S const two(2.0);
0112 
0113     if ( rt < zero )
0114       return prev;
0115     else if ( rt > zero )
0116       return next;
0117     else
0118     {
0119       bool is_prev_even = two * floor(prev / two) == prev ;
0120       return ( is_prev_even ? prev : next ) ;
0121     }
0122   }
0123 
0124   typedef mpl::integral_c< std::float_round_style, std::round_to_nearest> round_style ;
0125 } ;
0126 
0127 
0128 enum range_check_result
0129 {
0130   cInRange     = 0 ,
0131   cNegOverflow = 1 ,
0132   cPosOverflow = 2
0133 } ;
0134 
0135 class bad_numeric_cast : public std::bad_cast
0136 {
0137   public:
0138 
0139     const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
0140       {  return "bad numeric conversion: overflow"; }
0141 };
0142 
0143 class negative_overflow : public bad_numeric_cast
0144 {
0145   public:
0146 
0147     const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
0148       {  return "bad numeric conversion: negative overflow"; }
0149 };
0150 class positive_overflow : public bad_numeric_cast
0151 {
0152   public:
0153 
0154     const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
0155       { return "bad numeric conversion: positive overflow"; }
0156 };
0157 
0158 struct def_overflow_handler
0159 {
0160   void operator() ( range_check_result r ) // throw(negative_overflow,positive_overflow)
0161   {
0162 #ifndef BOOST_NO_EXCEPTIONS
0163     if ( r == cNegOverflow )
0164       throw negative_overflow() ;
0165     else if ( r == cPosOverflow )
0166            throw positive_overflow() ;
0167 #else
0168     if ( r == cNegOverflow )
0169       ::boost::throw_exception(negative_overflow()) ;
0170     else if ( r == cPosOverflow )
0171            ::boost::throw_exception(positive_overflow()) ;
0172 #endif
0173   }
0174 } ;
0175 
0176 struct silent_overflow_handler
0177 {
0178   void operator() ( range_check_result ) {} // throw()
0179 } ;
0180 
0181 template<class Traits>
0182 struct raw_converter
0183 {
0184   typedef typename Traits::result_type   result_type   ;
0185   typedef typename Traits::argument_type argument_type ;
0186 
0187   static result_type low_level_convert ( argument_type s ) { return static_cast<result_type>(s) ; }
0188 } ;
0189 
0190 struct UseInternalRangeChecker {} ;
0191 
0192 } } // namespace boost::numeric
0193 
0194 #endif