source: NonGTP/Boost/boost/numeric/conversion/converter_policies.hpp @ 857

Revision 857, 4.3 KB checked in by igarcia, 19 years ago (diff)
Line 
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
24namespace boost { namespace numeric
25{
26
27template<class S>
28struct 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
49template<class S>
50struct 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
68template<class S>
69struct 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
87template<class S>
88struct 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
127enum range_check_result
128{
129  cInRange     = 0 ,
130  cNegOverflow = 1 ,
131  cPosOverflow = 2
132} ;
133
134class 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
142class 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};
149class 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
157struct 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
168struct silent_overflow_handler
169{
170  void operator() ( range_check_result ) {} // throw()
171} ;
172
173template<class Traits>
174struct 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
182struct UseInternalRangeChecker {} ;
183
184} } // namespace boost::numeric
185
186#endif
Note: See TracBrowser for help on using the repository browser.