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