]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
92f5a8d4 | 15 | #include <boost/config.hpp> |
7c673cae FG |
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 | ||
26 | namespace boost { namespace numeric | |
27 | { | |
28 | ||
29 | template<class S> | |
30 | struct 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 | ||
51 | template<class S> | |
52 | struct 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 | ||
70 | template<class S> | |
71 | struct 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 | ||
89 | template<class S> | |
90 | struct 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 | ||
129 | enum range_check_result | |
130 | { | |
131 | cInRange = 0 , | |
132 | cNegOverflow = 1 , | |
133 | cPosOverflow = 2 | |
134 | } ; | |
135 | ||
136 | class bad_numeric_cast : public std::bad_cast | |
137 | { | |
138 | public: | |
139 | ||
92f5a8d4 | 140 | virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
141 | { return "bad numeric conversion: overflow"; } |
142 | }; | |
143 | ||
144 | class negative_overflow : public bad_numeric_cast | |
145 | { | |
146 | public: | |
147 | ||
92f5a8d4 | 148 | virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
149 | { return "bad numeric conversion: negative overflow"; } |
150 | }; | |
151 | class positive_overflow : public bad_numeric_cast | |
152 | { | |
153 | public: | |
154 | ||
92f5a8d4 | 155 | virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW |
7c673cae FG |
156 | { return "bad numeric conversion: positive overflow"; } |
157 | }; | |
158 | ||
159 | struct 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 | ||
177 | struct silent_overflow_handler | |
178 | { | |
179 | void operator() ( range_check_result ) {} // throw() | |
180 | } ; | |
181 | ||
182 | template<class Traits> | |
183 | struct 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 | ||
191 | struct UseInternalRangeChecker {} ; | |
192 | ||
193 | } } // namespace boost::numeric | |
194 | ||
195 | #endif |