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 None ;
|
---|
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, None>::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 |
|
---|