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

Revision 857, 7.7 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_DETAIL_IS_SUBRANGED_FLC_12NOV2002_HPP
11#define BOOST_NUMERIC_CONVERSION_DETAIL_IS_SUBRANGED_FLC_12NOV2002_HPP
12
13#include "boost/config.hpp"
14#include "boost/limits.hpp"
15
16#include "boost/mpl/int.hpp"
17#include "boost/mpl/multiplies.hpp"
18#include "boost/mpl/less.hpp"
19#include "boost/mpl/equal_to.hpp"
20
21#include "boost/type_traits/is_same.hpp"
22
23#include "boost/numeric/conversion/detail/meta.hpp"
24#include "boost/numeric/conversion/detail/int_float_mixture.hpp"
25#include "boost/numeric/conversion/detail/sign_mixture.hpp"
26#include "boost/numeric/conversion/detail/udt_builtin_mixture.hpp"
27
28namespace boost { namespace numeric { namespace convdetail
29{
30  //---------------------------------------------------------------
31  // Implementations of the compile time predicate "T is subranged"
32  //---------------------------------------------------------------
33
34    // for integral to integral conversions
35    template<class T,class S>
36    struct subranged_Sig2Unsig
37    {
38      // Signed to unsigned conversions are 'subranged' because of possible loose
39      // of negative values.
40      typedef mpl::true_ type ;
41    } ;
42
43    // for unsigned integral to signed integral conversions
44    template<class T,class S>
45    struct subranged_Unsig2Sig
46    {
47       // IMPORTANT NOTE:
48       //
49       // This code assumes that signed/unsigned integral values are represented
50       // such that:
51       //
52       //  numeric_limits<signed T>::digits + 1 == numeric_limits<unsigned T>::digits
53       //
54       // The '+1' is required since numeric_limits<>::digits gives 1 bit less for signed integral types.
55       //
56       // This fact is used by the following logic:
57       //
58       //  if ( (numeric_limits<T>::digits+1) < (2*numeric_limits<S>::digits) )
59       //    then the conversion is subranged.
60       //
61
62       typedef mpl::int_< ::std::numeric_limits<S>::digits > S_digits ;
63       typedef mpl::int_< ::std::numeric_limits<T>::digits > T_digits ;
64
65       // T is signed, so take digits+1
66       typedef typename T_digits::next u_T_digits ;
67
68       typedef mpl::int_<2> Two ;
69
70       typedef typename mpl::multiplies<S_digits,Two>::type S_digits_times_2 ;
71
72       typedef typename mpl::less<u_T_digits,S_digits_times_2>::type type ;
73    } ;
74
75    // for integral to integral conversions of the same sign.
76    template<class T,class S>
77    struct subranged_SameSign
78    {
79       // An integral conversion of the same sign is subranged if digits(T) < digits(S).
80
81       typedef mpl::int_< ::std::numeric_limits<S>::digits > S_digits ;
82       typedef mpl::int_< ::std::numeric_limits<T>::digits > T_digits ;
83
84       typedef typename mpl::less<T_digits,S_digits>::type type ;
85    } ;
86
87    // for integral to float conversions
88    template<class T,class S>
89    struct subranged_Int2Float
90    {
91      typedef mpl::false_ type ;
92    } ;
93
94    // for float to integral conversions
95    template<class T,class S>
96    struct subranged_Float2Int
97    {
98      typedef mpl::true_ type ;
99    } ;
100
101    // for float to float conversions
102    template<class T,class S>
103    struct subranged_Float2Float
104    {
105      // If both T and S are floats,
106      // compare exponent bits and if they match, mantisa bits.
107
108      typedef mpl::int_< ::std::numeric_limits<S>::digits > S_mantisa ;
109      typedef mpl::int_< ::std::numeric_limits<T>::digits > T_mantisa ;
110
111      typedef mpl::int_< ::std::numeric_limits<S>::max_exponent > S_exponent ;
112      typedef mpl::int_< ::std::numeric_limits<T>::max_exponent > T_exponent ;
113
114      typedef typename mpl::less<T_exponent,S_exponent>::type T_smaller_exponent ;
115
116      typedef typename mpl::equal_to<T_exponent,S_exponent>::type equal_exponents ;
117
118      typedef mpl::less<T_mantisa,S_mantisa> T_smaller_mantisa ;
119
120      typedef mpl::eval_if<equal_exponents,T_smaller_mantisa,mpl::false_> not_bigger_exponent_case ;
121
122      typedef typename
123        mpl::eval_if<T_smaller_exponent,mpl::true_,not_bigger_exponent_case>::type
124          type ;
125    } ;
126
127    // for Udt to built-in conversions
128    template<class T,class S>
129    struct subranged_Udt2BuiltIn
130    {
131      typedef mpl::true_ type ;
132    } ;
133
134    // for built-in to Udt conversions
135    template<class T,class S>
136    struct subranged_BuiltIn2Udt
137    {
138      typedef mpl::false_ type ;
139    } ;
140
141    // for Udt to Udt conversions
142    template<class T,class S>
143    struct subranged_Udt2Udt
144    {
145      typedef mpl::false_ type ;
146    } ;
147
148  //-------------------------------------------------------------------
149  // Selectors for the implementations of the subranged predicate
150  //-------------------------------------------------------------------
151
152    template<class T,class S>
153    struct get_subranged_Int2Int
154    {
155      typedef subranged_SameSign<T,S>  Sig2Sig     ;
156      typedef subranged_Sig2Unsig<T,S> Sig2Unsig   ;
157      typedef subranged_Unsig2Sig<T,S> Unsig2Sig   ;
158      typedef Sig2Sig                  Unsig2Unsig ;
159
160      typedef typename get_sign_mixture<T,S>::type sign_mixture ;
161
162      typedef typename
163        for_sign_mixture<sign_mixture, Sig2Sig, Sig2Unsig, Unsig2Sig, Unsig2Unsig>::type
164           type ;
165    } ;
166
167    template<class T,class S>
168    struct get_subranged_BuiltIn2BuiltIn
169    {
170      typedef get_subranged_Int2Int<T,S> Int2IntQ ;
171
172      typedef subranged_Int2Float  <T,S> Int2Float   ;
173      typedef subranged_Float2Int  <T,S> Float2Int   ;
174      typedef subranged_Float2Float<T,S> Float2Float ;
175
176      typedef mpl::identity<Int2Float  > Int2FloatQ   ;
177      typedef mpl::identity<Float2Int  > Float2IntQ   ;
178      typedef mpl::identity<Float2Float> Float2FloatQ ;
179
180      typedef typename get_int_float_mixture<T,S>::type int_float_mixture ;
181
182      typedef for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ> for_ ;
183
184      typedef typename for_::type selected ;
185
186      typedef typename selected::type type ;
187    } ;
188
189    template<class T,class S>
190    struct get_subranged
191    {
192      typedef get_subranged_BuiltIn2BuiltIn<T,S> BuiltIn2BuiltInQ ;
193
194      typedef subranged_BuiltIn2Udt<T,S> BuiltIn2Udt ;
195      typedef subranged_Udt2BuiltIn<T,S> Udt2BuiltIn ;
196      typedef subranged_Udt2Udt<T,S>     Udt2Udt ;
197
198      typedef mpl::identity<BuiltIn2Udt> BuiltIn2UdtQ ;
199      typedef mpl::identity<Udt2BuiltIn> Udt2BuiltInQ ;
200      typedef mpl::identity<Udt2Udt    > Udt2UdtQ     ;
201
202      typedef typename get_udt_builtin_mixture<T,S>::type udt_builtin_mixture ;
203     
204      typedef typename
205        for_udt_builtin_mixture<udt_builtin_mixture, BuiltIn2BuiltInQ, BuiltIn2UdtQ, Udt2BuiltInQ, Udt2UdtQ>::type
206          selected ;
207
208      typedef typename selected::type selected2 ;
209 
210      typedef typename selected2::type type ;
211    } ;
212
213
214  //-------------------------------------------------------------------
215  // Top level implementation selector.
216  //-------------------------------------------------------------------
217  template<class T, class S>
218  struct get_is_subranged
219  {
220    typedef get_subranged<T,S>         non_trivial_case ;
221    typedef mpl::identity<mpl::false_> trivial_case ;
222
223    typedef is_same<T,S> is_trivial ;
224   
225    typedef typename mpl::if_<is_trivial,trivial_case,non_trivial_case>::type selected ;
226   
227    typedef typename selected::type type ;
228  } ;
229
230} } } // namespace boost::numeric::convdetail
231
232#endif
233
234
Note: See TracBrowser for help on using the repository browser.