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

source code of include/boost/numeric/conversion/converter_policies.hpp