1 // (c) 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)
6 // See library home page at http://www.boost.org/libs/numeric/conversion
8 // Contact the author at: fernando_cacciola@hotmail.com
10 #ifndef BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
11 #define BOOST_NUMERIC_CONVERSION_CONVERTER_POLICIES_FLC_12NOV2002_HPP
13 #include <typeinfo> // for std::bad_cast
15 #include <boost/config/no_tr1/cmath.hpp> // for std::floor and std::ceil
16 #include <boost/throw_exception.hpp>
20 #include "boost/type_traits/is_arithmetic.hpp"
22 #include "boost/mpl/if.hpp"
23 #include "boost/mpl/integral_c.hpp"
25 namespace boost { namespace numeric
31 typedef S source_type ;
33 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
35 static source_type nearbyint ( argument_type s )
37 #if !defined(BOOST_NO_STDC_NAMESPACE)
42 return s < static_cast<S>(0) ? ceil(s) : floor(s) ;
45 typedef mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style ;
53 typedef S source_type ;
55 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
57 static source_type nearbyint ( argument_type s )
59 #if !defined(BOOST_NO_STDC_NAMESPACE)
66 typedef mpl::integral_c< std::float_round_style, std::round_toward_neg_infinity> round_style ;
72 typedef S source_type ;
74 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
76 static source_type nearbyint ( argument_type s )
78 #if !defined(BOOST_NO_STDC_NAMESPACE)
85 typedef mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style ;
91 typedef S source_type ;
93 typedef typename mpl::if_< is_arithmetic<S>,S,S const&>::type argument_type ;
95 static source_type nearbyint ( argument_type s )
97 // Algorithm contributed by Guillaume Melquiond
99 #if !defined(BOOST_NO_STDC_NAMESPACE)
104 // only works inside the range not at the boundaries
108 S rt = (s - prev) - (next - s); // remainder type
115 else if ( rt > zero )
119 bool is_prev_even = two * floor(prev / two) == prev ;
120 return ( is_prev_even ? prev : next ) ;
124 typedef mpl::integral_c< std::float_round_style, std::round_to_nearest> round_style ;
128 enum range_check_result
135 class bad_numeric_cast : public std::bad_cast
139 virtual const char * what() const throw()
140 { return "bad numeric conversion: overflow"; }
143 class negative_overflow : public bad_numeric_cast
147 virtual const char * what() const throw()
148 { return "bad numeric conversion: negative overflow"; }
150 class positive_overflow : public bad_numeric_cast
154 virtual const char * what() const throw()
155 { return "bad numeric conversion: positive overflow"; }
158 struct def_overflow_handler
160 void operator() ( range_check_result r ) // throw(negative_overflow,positive_overflow)
162 #ifndef BOOST_NO_EXCEPTIONS
163 if ( r == cNegOverflow )
164 throw negative_overflow() ;
165 else if ( r == cPosOverflow )
166 throw positive_overflow() ;
168 if ( r == cNegOverflow )
169 ::boost::throw_exception(negative_overflow()) ;
170 else if ( r == cPosOverflow )
171 ::boost::throw_exception(positive_overflow()) ;
176 struct silent_overflow_handler
178 void operator() ( range_check_result ) {} // throw()
181 template<class Traits>
184 typedef typename Traits::result_type result_type ;
185 typedef typename Traits::argument_type argument_type ;
187 static result_type low_level_convert ( argument_type s ) { return static_cast<result_type>(s) ; }
190 struct UseInternalRangeChecker {} ;
192 } } // namespace boost::numeric