Chris@16
|
1 // (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
|
Chris@16
|
2 // Use, modification, and distribution is subject to the Boost Software
|
Chris@16
|
3 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 // See library home page at http://www.boost.org/libs/numeric/conversion
|
Chris@16
|
7 //
|
Chris@16
|
8 // Contact the author at: fernando_cacciola@hotmail.com
|
Chris@16
|
9 //
|
Chris@16
|
10 #ifndef BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
|
Chris@16
|
11 #define BOOST_NUMERIC_CONVERSION_DETAIL_CONVERTER_FLC_12NOV2002_HPP
|
Chris@16
|
12
|
Chris@16
|
13 #include <functional>
|
Chris@16
|
14
|
Chris@16
|
15 #include "boost/numeric/conversion/detail/meta.hpp"
|
Chris@16
|
16 #include "boost/numeric/conversion/detail/conversion_traits.hpp"
|
Chris@16
|
17 #include "boost/numeric/conversion/bounds.hpp"
|
Chris@16
|
18
|
Chris@16
|
19 #include "boost/type_traits/is_same.hpp"
|
Chris@16
|
20
|
Chris@16
|
21 #include "boost/mpl/integral_c.hpp"
|
Chris@16
|
22
|
Chris@16
|
23 namespace boost { namespace numeric { namespace convdetail
|
Chris@16
|
24 {
|
Chris@16
|
25 // Integral Constants representing rounding modes
|
Chris@16
|
26 typedef mpl::integral_c<std::float_round_style, std::round_toward_zero> round2zero_c ;
|
Chris@16
|
27 typedef mpl::integral_c<std::float_round_style, std::round_to_nearest> round2nearest_c ;
|
Chris@16
|
28 typedef mpl::integral_c<std::float_round_style, std::round_toward_infinity> round2inf_c ;
|
Chris@16
|
29 typedef mpl::integral_c<std::float_round_style, std::round_toward_neg_infinity> round2neg_inf_c ;
|
Chris@16
|
30
|
Chris@16
|
31 // Metafunction:
|
Chris@16
|
32 //
|
Chris@16
|
33 // for_round_style<RoundStyle,RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf>::type
|
Chris@16
|
34 //
|
Chris@16
|
35 // {RoundStyle} Integral Constant specifying a round style as declared above.
|
Chris@16
|
36 // {RoundToZero,RoundToNearest,RoundToInf,RoundToNegInf} arbitrary types.
|
Chris@16
|
37 //
|
Chris@16
|
38 // Selects one of the 4 types according to the value of RoundStyle.
|
Chris@16
|
39 //
|
Chris@16
|
40 template<class RoundStyle,class RoundToZero,class RoundToNearest,class RoundToInf,class RoundToNegInf>
|
Chris@16
|
41 struct for_round_style
|
Chris@16
|
42 {
|
Chris@16
|
43 typedef ct_switch4<RoundStyle
|
Chris@16
|
44 , round2zero_c, round2nearest_c, round2inf_c // round2neg_inf_c
|
Chris@16
|
45 , RoundToZero , RoundToNearest , RoundToInf , RoundToNegInf
|
Chris@16
|
46 > selector ;
|
Chris@16
|
47
|
Chris@16
|
48 typedef typename selector::type type ;
|
Chris@16
|
49 } ;
|
Chris@16
|
50
|
Chris@16
|
51
|
Chris@16
|
52
|
Chris@16
|
53
|
Chris@16
|
54
|
Chris@16
|
55
|
Chris@16
|
56
|
Chris@16
|
57
|
Chris@16
|
58
|
Chris@16
|
59
|
Chris@16
|
60
|
Chris@16
|
61
|
Chris@16
|
62
|
Chris@16
|
63
|
Chris@16
|
64
|
Chris@16
|
65
|
Chris@16
|
66
|
Chris@16
|
67
|
Chris@16
|
68 //--------------------------------------------------------------------------
|
Chris@16
|
69 // Range Checking Logic.
|
Chris@16
|
70 //
|
Chris@16
|
71 // The range checking logic is built up by combining 1 or 2 predicates.
|
Chris@16
|
72 // Each predicate is encapsulated in a template class and exposes
|
Chris@16
|
73 // the static member function 'apply'.
|
Chris@16
|
74 //
|
Chris@16
|
75 //--------------------------------------------------------------------------
|
Chris@16
|
76
|
Chris@16
|
77
|
Chris@16
|
78 // Because a particular logic can combine either 1 or two predicates, the following
|
Chris@16
|
79 // tags are used to allow the predicate applier to receive 2 preds, but optimize away
|
Chris@16
|
80 // one of them if it is 'non-applicable'
|
Chris@16
|
81 struct non_applicable { typedef mpl::false_ do_apply ; } ;
|
Chris@16
|
82 struct applicable { typedef mpl::true_ do_apply ; } ;
|
Chris@16
|
83
|
Chris@16
|
84
|
Chris@16
|
85 //--------------------------------------------------------------------------
|
Chris@16
|
86 //
|
Chris@16
|
87 // Range Checking Logic implementations.
|
Chris@16
|
88 //
|
Chris@16
|
89 // The following classes, collectivelly named 'Predicates', are instantiated within
|
Chris@16
|
90 // the corresponding range checkers.
|
Chris@16
|
91 // Their static member function 'apply' is called to perform the actual range checking logic.
|
Chris@16
|
92 //--------------------------------------------------------------------------
|
Chris@16
|
93
|
Chris@16
|
94 // s < Lowest(T) ? cNegOverflow : cInRange
|
Chris@16
|
95 //
|
Chris@16
|
96 template<class Traits>
|
Chris@16
|
97 struct LT_LoT : applicable
|
Chris@16
|
98 {
|
Chris@16
|
99 typedef typename Traits::target_type T ;
|
Chris@16
|
100 typedef typename Traits::source_type S ;
|
Chris@16
|
101 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
102
|
Chris@16
|
103 static range_check_result apply ( argument_type s )
|
Chris@16
|
104 {
|
Chris@16
|
105 return s < static_cast<S>(bounds<T>::lowest()) ? cNegOverflow : cInRange ;
|
Chris@16
|
106 }
|
Chris@16
|
107 } ;
|
Chris@16
|
108
|
Chris@16
|
109 // s < 0 ? cNegOverflow : cInRange
|
Chris@16
|
110 //
|
Chris@16
|
111 template<class Traits>
|
Chris@16
|
112 struct LT_Zero : applicable
|
Chris@16
|
113 {
|
Chris@16
|
114 typedef typename Traits::source_type S ;
|
Chris@16
|
115 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
116
|
Chris@16
|
117 static range_check_result apply ( argument_type s )
|
Chris@16
|
118 {
|
Chris@16
|
119 return s < static_cast<S>(0) ? cNegOverflow : cInRange ;
|
Chris@16
|
120 }
|
Chris@16
|
121 } ;
|
Chris@16
|
122
|
Chris@16
|
123 // s <= Lowest(T)-1 ? cNegOverflow : cInRange
|
Chris@16
|
124 //
|
Chris@16
|
125 template<class Traits>
|
Chris@16
|
126 struct LE_PrevLoT : applicable
|
Chris@16
|
127 {
|
Chris@16
|
128 typedef typename Traits::target_type T ;
|
Chris@16
|
129 typedef typename Traits::source_type S ;
|
Chris@16
|
130 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
131
|
Chris@16
|
132 static range_check_result apply ( argument_type s )
|
Chris@16
|
133 {
|
Chris@16
|
134 return s <= static_cast<S>(bounds<T>::lowest()) - static_cast<S>(1.0)
|
Chris@16
|
135 ? cNegOverflow : cInRange ;
|
Chris@16
|
136 }
|
Chris@16
|
137 } ;
|
Chris@16
|
138
|
Chris@16
|
139 // s < Lowest(T)-0.5 ? cNegOverflow : cInRange
|
Chris@16
|
140 //
|
Chris@16
|
141 template<class Traits>
|
Chris@16
|
142 struct LT_HalfPrevLoT : applicable
|
Chris@16
|
143 {
|
Chris@16
|
144 typedef typename Traits::target_type T ;
|
Chris@16
|
145 typedef typename Traits::source_type S ;
|
Chris@16
|
146 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
147
|
Chris@16
|
148 static range_check_result apply ( argument_type s )
|
Chris@16
|
149 {
|
Chris@16
|
150 return s < static_cast<S>(bounds<T>::lowest()) - static_cast<S>(0.5)
|
Chris@16
|
151 ? cNegOverflow : cInRange ;
|
Chris@16
|
152 }
|
Chris@16
|
153 } ;
|
Chris@16
|
154
|
Chris@16
|
155 // s > Highest(T) ? cPosOverflow : cInRange
|
Chris@16
|
156 //
|
Chris@16
|
157 template<class Traits>
|
Chris@16
|
158 struct GT_HiT : applicable
|
Chris@16
|
159 {
|
Chris@16
|
160 typedef typename Traits::target_type T ;
|
Chris@16
|
161 typedef typename Traits::source_type S ;
|
Chris@16
|
162 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
163
|
Chris@16
|
164 static range_check_result apply ( argument_type s )
|
Chris@16
|
165 {
|
Chris@16
|
166 return s > static_cast<S>(bounds<T>::highest())
|
Chris@16
|
167 ? cPosOverflow : cInRange ;
|
Chris@16
|
168 }
|
Chris@16
|
169 } ;
|
Chris@16
|
170
|
Chris@16
|
171 // s >= Lowest(T) + 1 ? cPosOverflow : cInRange
|
Chris@16
|
172 //
|
Chris@16
|
173 template<class Traits>
|
Chris@16
|
174 struct GE_SuccHiT : applicable
|
Chris@16
|
175 {
|
Chris@16
|
176 typedef typename Traits::target_type T ;
|
Chris@16
|
177 typedef typename Traits::source_type S ;
|
Chris@16
|
178 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
179
|
Chris@16
|
180 static range_check_result apply ( argument_type s )
|
Chris@16
|
181 {
|
Chris@16
|
182 return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(1.0)
|
Chris@16
|
183 ? cPosOverflow : cInRange ;
|
Chris@16
|
184 }
|
Chris@16
|
185 } ;
|
Chris@16
|
186
|
Chris@16
|
187 // s >= Lowest(T) + 0.5 ? cPosgOverflow : cInRange
|
Chris@16
|
188 //
|
Chris@16
|
189 template<class Traits>
|
Chris@16
|
190 struct GT_HalfSuccHiT : applicable
|
Chris@16
|
191 {
|
Chris@16
|
192 typedef typename Traits::target_type T ;
|
Chris@16
|
193 typedef typename Traits::source_type S ;
|
Chris@16
|
194 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
195
|
Chris@16
|
196 static range_check_result apply ( argument_type s )
|
Chris@16
|
197 {
|
Chris@16
|
198 return s >= static_cast<S>(bounds<T>::highest()) + static_cast<S>(0.5)
|
Chris@16
|
199 ? cPosOverflow : cInRange ;
|
Chris@16
|
200 }
|
Chris@16
|
201 } ;
|
Chris@16
|
202
|
Chris@16
|
203
|
Chris@16
|
204 //--------------------------------------------------------------------------
|
Chris@16
|
205 //
|
Chris@16
|
206 // Predicate Combiner.
|
Chris@16
|
207 //
|
Chris@16
|
208 // This helper classes are used to possibly combine the range checking logic
|
Chris@16
|
209 // individually performed by the predicates
|
Chris@16
|
210 //
|
Chris@16
|
211 //--------------------------------------------------------------------------
|
Chris@16
|
212
|
Chris@16
|
213
|
Chris@16
|
214 // Applies both predicates: first 'PredA', and if it equals 'cInRange', 'PredB'
|
Chris@16
|
215 template<class PredA, class PredB>
|
Chris@16
|
216 struct applyBoth
|
Chris@16
|
217 {
|
Chris@16
|
218 typedef typename PredA::argument_type argument_type ;
|
Chris@16
|
219
|
Chris@16
|
220 static range_check_result apply ( argument_type s )
|
Chris@16
|
221 {
|
Chris@16
|
222 range_check_result r = PredA::apply(s) ;
|
Chris@16
|
223 if ( r == cInRange )
|
Chris@16
|
224 r = PredB::apply(s);
|
Chris@16
|
225 return r ;
|
Chris@16
|
226 }
|
Chris@16
|
227 } ;
|
Chris@16
|
228
|
Chris@16
|
229 template<class PredA, class PredB>
|
Chris@16
|
230 struct combine
|
Chris@16
|
231 {
|
Chris@16
|
232 typedef applyBoth<PredA,PredB> Both ;
|
Chris@16
|
233 typedef void NNone ; // 'None' is defined as a macro in (/usr/X11R6/include/X11/X.h)
|
Chris@16
|
234
|
Chris@16
|
235 typedef typename PredA::do_apply do_applyA ;
|
Chris@16
|
236 typedef typename PredB::do_apply do_applyB ;
|
Chris@16
|
237
|
Chris@16
|
238 typedef typename for_both<do_applyA, do_applyB, Both, PredA, PredB, NNone>::type type ;
|
Chris@16
|
239 } ;
|
Chris@16
|
240
|
Chris@16
|
241
|
Chris@16
|
242
|
Chris@16
|
243
|
Chris@16
|
244
|
Chris@16
|
245
|
Chris@16
|
246
|
Chris@16
|
247
|
Chris@16
|
248
|
Chris@16
|
249
|
Chris@16
|
250
|
Chris@16
|
251
|
Chris@16
|
252 //--------------------------------------------------------------------------
|
Chris@16
|
253 // Range Checker classes.
|
Chris@16
|
254 //
|
Chris@16
|
255 // The following classes are VISIBLE base classes of the user-level converter<> class.
|
Chris@16
|
256 // They supply the optimized 'out_of_range()' and 'validate_range()' static member functions
|
Chris@16
|
257 // visible in the user interface.
|
Chris@16
|
258 //
|
Chris@16
|
259 //--------------------------------------------------------------------------
|
Chris@16
|
260
|
Chris@16
|
261 // Dummy range checker.
|
Chris@16
|
262 template<class Traits>
|
Chris@16
|
263 struct dummy_range_checker
|
Chris@16
|
264 {
|
Chris@16
|
265 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
266
|
Chris@16
|
267 static range_check_result out_of_range ( argument_type ) { return cInRange ; }
|
Chris@16
|
268 static void validate_range ( argument_type ) {}
|
Chris@16
|
269 } ;
|
Chris@16
|
270
|
Chris@16
|
271 // Generic range checker.
|
Chris@16
|
272 //
|
Chris@16
|
273 // All the range checking logic for all possible combinations of source and target
|
Chris@16
|
274 // can be arranged in terms of one or two predicates, which test overflow on both neg/pos 'sides'
|
Chris@16
|
275 // of the ranges.
|
Chris@16
|
276 //
|
Chris@16
|
277 // These predicates are given here as IsNegOverflow and IsPosOverflow.
|
Chris@16
|
278 //
|
Chris@16
|
279 template<class Traits, class IsNegOverflow, class IsPosOverflow, class OverflowHandler>
|
Chris@16
|
280 struct generic_range_checker
|
Chris@16
|
281 {
|
Chris@16
|
282 typedef OverflowHandler overflow_handler ;
|
Chris@16
|
283
|
Chris@16
|
284 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
285
|
Chris@16
|
286 static range_check_result out_of_range ( argument_type s )
|
Chris@16
|
287 {
|
Chris@16
|
288 typedef typename combine<IsNegOverflow,IsPosOverflow>::type Predicate ;
|
Chris@16
|
289
|
Chris@16
|
290 return Predicate::apply(s);
|
Chris@16
|
291 }
|
Chris@16
|
292
|
Chris@16
|
293 static void validate_range ( argument_type s )
|
Chris@16
|
294 { OverflowHandler()( out_of_range(s) ) ; }
|
Chris@16
|
295 } ;
|
Chris@16
|
296
|
Chris@16
|
297
|
Chris@16
|
298
|
Chris@16
|
299 //--------------------------------------------------------------------------
|
Chris@16
|
300 //
|
Chris@16
|
301 // Selectors for the optimized Range Checker class.
|
Chris@16
|
302 //
|
Chris@16
|
303 //--------------------------------------------------------------------------
|
Chris@16
|
304
|
Chris@16
|
305 template<class Traits,class OverflowHandler>
|
Chris@16
|
306 struct GetRC_Sig2Sig_or_Unsig2Unsig
|
Chris@16
|
307 {
|
Chris@16
|
308 typedef dummy_range_checker<Traits> Dummy ;
|
Chris@16
|
309
|
Chris@16
|
310 typedef LT_LoT<Traits> Pred1 ;
|
Chris@16
|
311 typedef GT_HiT<Traits> Pred2 ;
|
Chris@16
|
312
|
Chris@16
|
313 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
|
Chris@16
|
314
|
Chris@16
|
315 typedef typename Traits::subranged subranged ;
|
Chris@16
|
316
|
Chris@16
|
317 typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
|
Chris@16
|
318 } ;
|
Chris@16
|
319
|
Chris@16
|
320 template<class Traits, class OverflowHandler>
|
Chris@16
|
321 struct GetRC_Sig2Unsig
|
Chris@16
|
322 {
|
Chris@16
|
323 typedef LT_Zero<Traits> Pred1 ;
|
Chris@16
|
324 typedef GT_HiT <Traits> Pred2 ;
|
Chris@16
|
325
|
Chris@16
|
326 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ChoiceA ;
|
Chris@16
|
327
|
Chris@16
|
328 typedef generic_range_checker<Traits,Pred1,non_applicable,OverflowHandler> ChoiceB ;
|
Chris@16
|
329
|
Chris@16
|
330 typedef typename Traits::target_type T ;
|
Chris@16
|
331 typedef typename Traits::source_type S ;
|
Chris@16
|
332
|
Chris@16
|
333 typedef typename subranged_Unsig2Sig<S,T>::type oposite_subranged ;
|
Chris@16
|
334
|
Chris@16
|
335 typedef typename mpl::not_<oposite_subranged>::type positively_subranged ;
|
Chris@16
|
336
|
Chris@16
|
337 typedef typename mpl::if_<positively_subranged,ChoiceA,ChoiceB>::type type ;
|
Chris@16
|
338 } ;
|
Chris@16
|
339
|
Chris@16
|
340 template<class Traits, class OverflowHandler>
|
Chris@16
|
341 struct GetRC_Unsig2Sig
|
Chris@16
|
342 {
|
Chris@16
|
343 typedef GT_HiT<Traits> Pred1 ;
|
Chris@16
|
344
|
Chris@16
|
345 typedef generic_range_checker<Traits,non_applicable,Pred1,OverflowHandler> type ;
|
Chris@16
|
346 } ;
|
Chris@16
|
347
|
Chris@16
|
348 template<class Traits,class OverflowHandler>
|
Chris@16
|
349 struct GetRC_Int2Int
|
Chris@16
|
350 {
|
Chris@16
|
351 typedef GetRC_Sig2Sig_or_Unsig2Unsig<Traits,OverflowHandler> Sig2SigQ ;
|
Chris@16
|
352 typedef GetRC_Sig2Unsig <Traits,OverflowHandler> Sig2UnsigQ ;
|
Chris@16
|
353 typedef GetRC_Unsig2Sig <Traits,OverflowHandler> Unsig2SigQ ;
|
Chris@16
|
354 typedef Sig2SigQ Unsig2UnsigQ ;
|
Chris@16
|
355
|
Chris@16
|
356 typedef typename Traits::sign_mixture sign_mixture ;
|
Chris@16
|
357
|
Chris@16
|
358 typedef typename
|
Chris@16
|
359 for_sign_mixture<sign_mixture,Sig2SigQ,Sig2UnsigQ,Unsig2SigQ,Unsig2UnsigQ>::type
|
Chris@16
|
360 selector ;
|
Chris@16
|
361
|
Chris@16
|
362 typedef typename selector::type type ;
|
Chris@16
|
363 } ;
|
Chris@16
|
364
|
Chris@16
|
365 template<class Traits>
|
Chris@16
|
366 struct GetRC_Int2Float
|
Chris@16
|
367 {
|
Chris@16
|
368 typedef dummy_range_checker<Traits> type ;
|
Chris@16
|
369 } ;
|
Chris@16
|
370
|
Chris@16
|
371 template<class Traits, class OverflowHandler, class Float2IntRounder>
|
Chris@16
|
372 struct GetRC_Float2Int
|
Chris@16
|
373 {
|
Chris@16
|
374 typedef LE_PrevLoT <Traits> Pred1 ;
|
Chris@16
|
375 typedef GE_SuccHiT <Traits> Pred2 ;
|
Chris@16
|
376 typedef LT_HalfPrevLoT<Traits> Pred3 ;
|
Chris@16
|
377 typedef GT_HalfSuccHiT<Traits> Pred4 ;
|
Chris@16
|
378 typedef GT_HiT <Traits> Pred5 ;
|
Chris@16
|
379 typedef LT_LoT <Traits> Pred6 ;
|
Chris@16
|
380
|
Chris@16
|
381 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> ToZero ;
|
Chris@16
|
382 typedef generic_range_checker<Traits,Pred3,Pred4,OverflowHandler> ToNearest ;
|
Chris@16
|
383 typedef generic_range_checker<Traits,Pred1,Pred5,OverflowHandler> ToInf ;
|
Chris@16
|
384 typedef generic_range_checker<Traits,Pred6,Pred2,OverflowHandler> ToNegInf ;
|
Chris@16
|
385
|
Chris@16
|
386 typedef typename Float2IntRounder::round_style round_style ;
|
Chris@16
|
387
|
Chris@16
|
388 typedef typename for_round_style<round_style,ToZero,ToNearest,ToInf,ToNegInf>::type type ;
|
Chris@16
|
389 } ;
|
Chris@16
|
390
|
Chris@16
|
391 template<class Traits, class OverflowHandler>
|
Chris@16
|
392 struct GetRC_Float2Float
|
Chris@16
|
393 {
|
Chris@16
|
394 typedef dummy_range_checker<Traits> Dummy ;
|
Chris@16
|
395
|
Chris@16
|
396 typedef LT_LoT<Traits> Pred1 ;
|
Chris@16
|
397 typedef GT_HiT<Traits> Pred2 ;
|
Chris@16
|
398
|
Chris@16
|
399 typedef generic_range_checker<Traits,Pred1,Pred2,OverflowHandler> Normal ;
|
Chris@16
|
400
|
Chris@16
|
401 typedef typename Traits::subranged subranged ;
|
Chris@16
|
402
|
Chris@16
|
403 typedef typename mpl::if_<subranged,Normal,Dummy>::type type ;
|
Chris@16
|
404 } ;
|
Chris@16
|
405
|
Chris@16
|
406 template<class Traits, class OverflowHandler, class Float2IntRounder>
|
Chris@16
|
407 struct GetRC_BuiltIn2BuiltIn
|
Chris@16
|
408 {
|
Chris@16
|
409 typedef GetRC_Int2Int<Traits,OverflowHandler> Int2IntQ ;
|
Chris@16
|
410 typedef GetRC_Int2Float<Traits> Int2FloatQ ;
|
Chris@16
|
411 typedef GetRC_Float2Int<Traits,OverflowHandler,Float2IntRounder> Float2IntQ ;
|
Chris@16
|
412 typedef GetRC_Float2Float<Traits,OverflowHandler> Float2FloatQ ;
|
Chris@16
|
413
|
Chris@16
|
414 typedef typename Traits::int_float_mixture int_float_mixture ;
|
Chris@16
|
415
|
Chris@16
|
416 typedef typename for_int_float_mixture<int_float_mixture, Int2IntQ, Int2FloatQ, Float2IntQ, Float2FloatQ>::type selector ;
|
Chris@16
|
417
|
Chris@16
|
418 typedef typename selector::type type ;
|
Chris@16
|
419 } ;
|
Chris@16
|
420
|
Chris@16
|
421 template<class Traits, class OverflowHandler, class Float2IntRounder>
|
Chris@16
|
422 struct GetRC
|
Chris@16
|
423 {
|
Chris@16
|
424 typedef GetRC_BuiltIn2BuiltIn<Traits,OverflowHandler,Float2IntRounder> BuiltIn2BuiltInQ ;
|
Chris@16
|
425
|
Chris@16
|
426 typedef dummy_range_checker<Traits> Dummy ;
|
Chris@16
|
427
|
Chris@16
|
428 typedef mpl::identity<Dummy> DummyQ ;
|
Chris@16
|
429
|
Chris@16
|
430 typedef typename Traits::udt_builtin_mixture udt_builtin_mixture ;
|
Chris@16
|
431
|
Chris@16
|
432 typedef typename for_udt_builtin_mixture<udt_builtin_mixture,BuiltIn2BuiltInQ,DummyQ,DummyQ,DummyQ>::type selector ;
|
Chris@16
|
433
|
Chris@16
|
434 typedef typename selector::type type ;
|
Chris@16
|
435 } ;
|
Chris@16
|
436
|
Chris@16
|
437
|
Chris@16
|
438
|
Chris@16
|
439
|
Chris@16
|
440 //--------------------------------------------------------------------------
|
Chris@16
|
441 // Converter classes.
|
Chris@16
|
442 //
|
Chris@16
|
443 // The following classes are VISIBLE base classes of the user-level converter<> class.
|
Chris@16
|
444 // They supply the optimized 'nearbyint()' and 'convert()' static member functions
|
Chris@16
|
445 // visible in the user interface.
|
Chris@16
|
446 //
|
Chris@16
|
447 //--------------------------------------------------------------------------
|
Chris@16
|
448
|
Chris@16
|
449 //
|
Chris@16
|
450 // Trivial Converter : used when (cv-unqualified) T == (cv-unqualified) S
|
Chris@16
|
451 //
|
Chris@16
|
452 template<class Traits>
|
Chris@16
|
453 struct trivial_converter_impl : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
|
Chris@16
|
454 ,BOOST_DEDUCED_TYPENAME Traits::result_type
|
Chris@16
|
455 >
|
Chris@16
|
456 ,public dummy_range_checker<Traits>
|
Chris@16
|
457 {
|
Chris@16
|
458 typedef Traits traits ;
|
Chris@16
|
459
|
Chris@16
|
460 typedef typename Traits::source_type source_type ;
|
Chris@16
|
461 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
462 typedef typename Traits::result_type result_type ;
|
Chris@16
|
463
|
Chris@16
|
464 static result_type low_level_convert ( argument_type s ) { return s ; }
|
Chris@16
|
465 static source_type nearbyint ( argument_type s ) { return s ; }
|
Chris@16
|
466 static result_type convert ( argument_type s ) { return s ; }
|
Chris@16
|
467 } ;
|
Chris@16
|
468
|
Chris@16
|
469
|
Chris@16
|
470 //
|
Chris@16
|
471 // Rounding Converter : used for float to integral conversions.
|
Chris@16
|
472 //
|
Chris@16
|
473 template<class Traits,class RangeChecker,class RawConverter,class Float2IntRounder>
|
Chris@16
|
474 struct rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
|
Chris@16
|
475 ,BOOST_DEDUCED_TYPENAME Traits::result_type
|
Chris@16
|
476 >
|
Chris@16
|
477 ,public RangeChecker
|
Chris@16
|
478 ,public Float2IntRounder
|
Chris@16
|
479 ,public RawConverter
|
Chris@16
|
480 {
|
Chris@16
|
481 typedef RangeChecker RangeCheckerBase ;
|
Chris@16
|
482 typedef Float2IntRounder Float2IntRounderBase ;
|
Chris@16
|
483 typedef RawConverter RawConverterBase ;
|
Chris@16
|
484
|
Chris@16
|
485 typedef Traits traits ;
|
Chris@16
|
486
|
Chris@16
|
487 typedef typename Traits::source_type source_type ;
|
Chris@16
|
488 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
489 typedef typename Traits::result_type result_type ;
|
Chris@16
|
490
|
Chris@16
|
491 static result_type convert ( argument_type s )
|
Chris@16
|
492 {
|
Chris@16
|
493 RangeCheckerBase::validate_range(s);
|
Chris@16
|
494 source_type s1 = Float2IntRounderBase::nearbyint(s);
|
Chris@16
|
495 return RawConverterBase::low_level_convert(s1);
|
Chris@16
|
496 }
|
Chris@16
|
497 } ;
|
Chris@16
|
498
|
Chris@16
|
499
|
Chris@16
|
500 //
|
Chris@16
|
501 // Non-Rounding Converter : used for all other conversions.
|
Chris@16
|
502 //
|
Chris@16
|
503 template<class Traits,class RangeChecker,class RawConverter>
|
Chris@16
|
504 struct non_rounding_converter : public std::unary_function< BOOST_DEDUCED_TYPENAME Traits::argument_type
|
Chris@16
|
505 ,BOOST_DEDUCED_TYPENAME Traits::result_type
|
Chris@16
|
506 >
|
Chris@16
|
507 ,public RangeChecker
|
Chris@16
|
508 ,public RawConverter
|
Chris@16
|
509 {
|
Chris@16
|
510 typedef RangeChecker RangeCheckerBase ;
|
Chris@16
|
511 typedef RawConverter RawConverterBase ;
|
Chris@16
|
512
|
Chris@16
|
513 typedef Traits traits ;
|
Chris@16
|
514
|
Chris@16
|
515 typedef typename Traits::source_type source_type ;
|
Chris@16
|
516 typedef typename Traits::argument_type argument_type ;
|
Chris@16
|
517 typedef typename Traits::result_type result_type ;
|
Chris@16
|
518
|
Chris@16
|
519 static source_type nearbyint ( argument_type s ) { return s ; }
|
Chris@16
|
520
|
Chris@16
|
521 static result_type convert ( argument_type s )
|
Chris@16
|
522 {
|
Chris@16
|
523 RangeCheckerBase::validate_range(s);
|
Chris@16
|
524 return RawConverterBase::low_level_convert(s);
|
Chris@16
|
525 }
|
Chris@16
|
526 } ;
|
Chris@16
|
527
|
Chris@16
|
528
|
Chris@16
|
529
|
Chris@16
|
530
|
Chris@16
|
531 //--------------------------------------------------------------------------
|
Chris@16
|
532 //
|
Chris@16
|
533 // Selectors for the optimized Converter class.
|
Chris@16
|
534 //
|
Chris@16
|
535 //--------------------------------------------------------------------------
|
Chris@16
|
536
|
Chris@16
|
537 template<class Traits,class OverflowHandler,class Float2IntRounder,class RawConverter, class UserRangeChecker>
|
Chris@16
|
538 struct get_non_trivial_converter
|
Chris@16
|
539 {
|
Chris@16
|
540 typedef GetRC<Traits,OverflowHandler,Float2IntRounder> InternalRangeCheckerQ ;
|
Chris@16
|
541
|
Chris@16
|
542 typedef is_same<UserRangeChecker,UseInternalRangeChecker> use_internal_RC ;
|
Chris@16
|
543
|
Chris@16
|
544 typedef mpl::identity<UserRangeChecker> UserRangeCheckerQ ;
|
Chris@16
|
545
|
Chris@16
|
546 typedef typename
|
Chris@16
|
547 mpl::eval_if<use_internal_RC,InternalRangeCheckerQ,UserRangeCheckerQ>::type
|
Chris@16
|
548 RangeChecker ;
|
Chris@16
|
549
|
Chris@16
|
550 typedef non_rounding_converter<Traits,RangeChecker,RawConverter> NonRounding ;
|
Chris@16
|
551 typedef rounding_converter<Traits,RangeChecker,RawConverter,Float2IntRounder> Rounding ;
|
Chris@16
|
552
|
Chris@16
|
553 typedef mpl::identity<NonRounding> NonRoundingQ ;
|
Chris@16
|
554 typedef mpl::identity<Rounding> RoundingQ ;
|
Chris@16
|
555
|
Chris@16
|
556 typedef typename Traits::int_float_mixture int_float_mixture ;
|
Chris@16
|
557
|
Chris@16
|
558 typedef typename
|
Chris@16
|
559 for_int_float_mixture<int_float_mixture, NonRoundingQ, NonRoundingQ, RoundingQ, NonRoundingQ>::type
|
Chris@16
|
560 selector ;
|
Chris@16
|
561
|
Chris@16
|
562 typedef typename selector::type type ;
|
Chris@16
|
563 } ;
|
Chris@16
|
564
|
Chris@16
|
565 template< class Traits
|
Chris@16
|
566 ,class OverflowHandler
|
Chris@16
|
567 ,class Float2IntRounder
|
Chris@16
|
568 ,class RawConverter
|
Chris@16
|
569 ,class UserRangeChecker
|
Chris@16
|
570 >
|
Chris@16
|
571 struct get_converter_impl
|
Chris@16
|
572 {
|
Chris@16
|
573 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT( 0x0561 ) )
|
Chris@16
|
574 // bcc55 prefers sometimes template parameters to be explicit local types.
|
Chris@16
|
575 // (notice that is is illegal to reuse the names like this)
|
Chris@16
|
576 typedef Traits Traits ;
|
Chris@16
|
577 typedef OverflowHandler OverflowHandler ;
|
Chris@16
|
578 typedef Float2IntRounder Float2IntRounder ;
|
Chris@16
|
579 typedef RawConverter RawConverter ;
|
Chris@16
|
580 typedef UserRangeChecker UserRangeChecker ;
|
Chris@16
|
581 #endif
|
Chris@16
|
582
|
Chris@16
|
583 typedef trivial_converter_impl<Traits> Trivial ;
|
Chris@16
|
584 typedef mpl::identity <Trivial> TrivialQ ;
|
Chris@16
|
585
|
Chris@16
|
586 typedef get_non_trivial_converter< Traits
|
Chris@16
|
587 ,OverflowHandler
|
Chris@16
|
588 ,Float2IntRounder
|
Chris@16
|
589 ,RawConverter
|
Chris@16
|
590 ,UserRangeChecker
|
Chris@16
|
591 > NonTrivialQ ;
|
Chris@16
|
592
|
Chris@16
|
593 typedef typename Traits::trivial trivial ;
|
Chris@16
|
594
|
Chris@16
|
595 typedef typename mpl::eval_if<trivial,TrivialQ,NonTrivialQ>::type type ;
|
Chris@16
|
596 } ;
|
Chris@16
|
597
|
Chris@16
|
598 } } } // namespace boost::numeric::convdetail
|
Chris@16
|
599
|
Chris@16
|
600 #endif
|
Chris@16
|
601
|
Chris@16
|
602
|