]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / karma / numeric / detail / numeric_utils.hpp
1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #if !defined(BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM)
7 #define BOOST_SPIRIT_KARMA_NUMERIC_UTILS_FEB_23_2007_0841PM
8
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12
13 #include <boost/config.hpp>
14 #include <boost/config/no_tr1/cmath.hpp>
15 #include <boost/limits.hpp>
16
17 #include <boost/type_traits/is_integral.hpp>
18 #include <boost/spirit/home/support/char_class.hpp>
19 #include <boost/spirit/home/support/unused.hpp>
20 #include <boost/spirit/home/support/numeric_traits.hpp>
21 #include <boost/spirit/home/support/detail/pow10.hpp>
22 #include <boost/spirit/home/support/detail/sign.hpp>
23 #include <boost/spirit/home/karma/detail/generate_to.hpp>
24 #include <boost/spirit/home/karma/detail/string_generate.hpp>
25
26 ///////////////////////////////////////////////////////////////////////////////
27 //
28 // The value BOOST_KARMA_NUMERICS_LOOP_UNROLL specifies, how to unroll the
29 // integer string generation loop (see below).
30 //
31 // Set the value to some integer in between 0 (no unrolling) and the
32 // largest expected generated integer string length (complete unrolling).
33 // If not specified, this value defaults to 6.
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 #if !defined(BOOST_KARMA_NUMERICS_LOOP_UNROLL)
37 #define BOOST_KARMA_NUMERICS_LOOP_UNROLL 6
38 #endif
39
40 #if BOOST_KARMA_NUMERICS_LOOP_UNROLL < 0
41 #error "Please set the BOOST_KARMA_NUMERICS_LOOP_UNROLL to a non-negative value!"
42 #endif
43
44 namespace boost { namespace spirit { namespace traits
45 {
46 ///////////////////////////////////////////////////////////////////////
47 //
48 // return the absolute value from a given number, avoiding over- and
49 // underflow
50 //
51 ///////////////////////////////////////////////////////////////////////
52 template <typename T, typename Enable/* = void*/>
53 struct absolute_value
54 {
55 typedef T type;
56 static T call (T n)
57 {
58 // allow for ADL to find the correct overloads for fabs
59 using namespace std;
60 return fabs(n);
61 }
62 };
63
64 #define BOOST_SPIRIT_ABSOLUTE_VALUE(signedtype, unsignedtype) \
65 template <> \
66 struct absolute_value<signedtype> \
67 { \
68 typedef unsignedtype type; \
69 static type call(signedtype n) \
70 { \
71 return static_cast<unsignedtype>((n >= 0) ? n : -n); \
72 } \
73 } \
74 /**/
75 #define BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsignedtype) \
76 template <> \
77 struct absolute_value<unsignedtype> \
78 { \
79 typedef unsignedtype type; \
80 static type call(unsignedtype n) \
81 { \
82 return n; \
83 } \
84 } \
85 /**/
86
87 BOOST_SPIRIT_ABSOLUTE_VALUE(signed char, unsigned char);
88 BOOST_SPIRIT_ABSOLUTE_VALUE(char, unsigned char);
89 BOOST_SPIRIT_ABSOLUTE_VALUE(short, unsigned short);
90 BOOST_SPIRIT_ABSOLUTE_VALUE(int, unsigned int);
91 BOOST_SPIRIT_ABSOLUTE_VALUE(long, unsigned long);
92 BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned char);
93 BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned short);
94 BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned int);
95 BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(unsigned long);
96 #ifdef BOOST_HAS_LONG_LONG
97 BOOST_SPIRIT_ABSOLUTE_VALUE(boost::long_long_type, boost::ulong_long_type);
98 BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED(boost::ulong_long_type);
99 #endif
100
101 #undef BOOST_SPIRIT_ABSOLUTE_VALUE
102 #undef BOOST_SPIRIT_ABSOLUTE_VALUE_UNSIGNED
103
104 template <>
105 struct absolute_value<float>
106 {
107 typedef float type;
108 static type call(float n)
109 {
110 return (spirit::detail::signbit)(n) ? -n : n;
111 }
112 };
113
114 template <>
115 struct absolute_value<double>
116 {
117 typedef double type;
118 static type call(double n)
119 {
120 return (spirit::detail::signbit)(n) ? -n : n;
121 }
122 };
123
124 template <>
125 struct absolute_value<long double>
126 {
127 typedef long double type;
128 static type call(long double n)
129 {
130 return (spirit::detail::signbit)(n) ? -n : n;
131 }
132 };
133
134 // specialization for pointers
135 template <typename T>
136 struct absolute_value<T*>
137 {
138 typedef std::size_t type;
139 static type call (T* p)
140 {
141 return std::size_t(p);
142 }
143 };
144
145 template <typename T>
146 inline typename absolute_value<T>::type
147 get_absolute_value(T n)
148 {
149 return absolute_value<T>::call(n);
150 }
151
152 ///////////////////////////////////////////////////////////////////////
153 template <typename T, typename Enable/* = void*/>
154 struct is_negative
155 {
156 static bool call(T n)
157 {
158 return (n < 0) ? true : false;
159 }
160 };
161
162 template <>
163 struct is_negative<float>
164 {
165 static bool call(float n)
166 {
167 return (spirit::detail::signbit)(n) ? true : false;
168 }
169 };
170
171 template <>
172 struct is_negative<double>
173 {
174 static bool call(double n)
175 {
176 return (spirit::detail::signbit)(n) ? true : false;
177 }
178 };
179
180 template <>
181 struct is_negative<long double>
182 {
183 static bool call(long double n)
184 {
185 return (spirit::detail::signbit)(n) ? true : false;
186 }
187 };
188
189 template <typename T>
190 inline bool test_negative(T n)
191 {
192 return is_negative<T>::call(n);
193 }
194
195 ///////////////////////////////////////////////////////////////////////
196 template <typename T, typename Enable/* = void*/>
197 struct is_zero
198 {
199 static bool call(T n)
200 {
201 return (n == 0) ? true : false;
202 }
203 };
204
205 template <>
206 struct is_zero<float>
207 {
208 static bool call(float n)
209 {
210 return (math::fpclassify)(n) == FP_ZERO;
211 }
212 };
213
214 template <>
215 struct is_zero<double>
216 {
217 static bool call(double n)
218 {
219 return (math::fpclassify)(n) == FP_ZERO;
220 }
221 };
222
223 template <>
224 struct is_zero<long double>
225 {
226 static bool call(long double n)
227 {
228 return (math::fpclassify)(n) == FP_ZERO;
229 }
230 };
231
232 template <typename T>
233 inline bool test_zero(T n)
234 {
235 return is_zero<T>::call(n);
236 }
237
238 ///////////////////////////////////////////////////////////////////////
239 template <typename T, typename Enable/* = void*/>
240 struct is_nan
241 {
242 static bool call(T n)
243 {
244 // NaN numbers are not equal to anything
245 return (n != n) ? true : false;
246 }
247 };
248
249 template <>
250 struct is_nan<float>
251 {
252 static bool call(float n)
253 {
254 return (math::fpclassify)(n) == FP_NAN;
255 }
256 };
257
258 template <>
259 struct is_nan<double>
260 {
261 static bool call(double n)
262 {
263 return (math::fpclassify)(n) == FP_NAN;
264 }
265 };
266
267 template <>
268 struct is_nan<long double>
269 {
270 static bool call(long double n)
271 {
272 return (math::fpclassify)(n) == FP_NAN;
273 }
274 };
275
276 template <typename T>
277 inline bool test_nan(T n)
278 {
279 return is_nan<T>::call(n);
280 }
281
282 ///////////////////////////////////////////////////////////////////////
283 template <typename T, typename Enable/* = void*/>
284 struct is_infinite
285 {
286 static bool call(T n)
287 {
288 if (!std::numeric_limits<T>::has_infinity)
289 return false;
290 return (n == std::numeric_limits<T>::infinity()) ? true : false;
291 }
292 };
293
294 template <>
295 struct is_infinite<float>
296 {
297 static bool call(float n)
298 {
299 return (math::fpclassify)(n) == FP_INFINITE;
300 }
301 };
302
303 template <>
304 struct is_infinite<double>
305 {
306 static bool call(double n)
307 {
308 return (math::fpclassify)(n) == FP_INFINITE;
309 }
310 };
311
312 template <>
313 struct is_infinite<long double>
314 {
315 static bool call(long double n)
316 {
317 return (math::fpclassify)(n) == FP_INFINITE;
318 }
319 };
320
321 template <typename T>
322 inline bool test_infinite(T n)
323 {
324 return is_infinite<T>::call(n);
325 }
326
327 ///////////////////////////////////////////////////////////////////////
328 struct cast_to_long
329 {
330 static long call(float n, mpl::false_)
331 {
332 return static_cast<long>(std::floor(n));
333 }
334
335 static long call(double n, mpl::false_)
336 {
337 return static_cast<long>(std::floor(n));
338 }
339
340 static long call(long double n, mpl::false_)
341 {
342 return static_cast<long>(std::floor(n));
343 }
344
345 template <typename T>
346 static long call(T n, mpl::false_)
347 {
348 // allow for ADL to find the correct overload for floor and
349 // lround
350 using namespace std;
351 return lround(floor(n));
352 }
353
354 template <typename T>
355 static long call(T n, mpl::true_)
356 {
357 return static_cast<long>(n);
358 }
359
360 template <typename T>
361 static long call(T n)
362 {
363 return call(n, mpl::bool_<is_integral<T>::value>());
364 }
365 };
366
367 ///////////////////////////////////////////////////////////////////////
368 struct truncate_to_long
369 {
370 static long call(float n, mpl::false_)
371 {
372 return test_negative(n) ? static_cast<long>(std::ceil(n)) :
373 static_cast<long>(std::floor(n));
374 }
375
376 static long call(double n, mpl::false_)
377 {
378 return test_negative(n) ? static_cast<long>(std::ceil(n)) :
379 static_cast<long>(std::floor(n));
380 }
381
382 static long call(long double n, mpl::false_)
383 {
384 return test_negative(n) ? static_cast<long>(std::ceil(n)) :
385 static_cast<long>(std::floor(n));
386 }
387
388 template <typename T>
389 static long call(T n, mpl::false_)
390 {
391 // allow for ADL to find the correct overloads for ltrunc
392 using namespace std;
393 return ltrunc(n);
394 }
395
396 template <typename T>
397 static long call(T n, mpl::true_)
398 {
399 return static_cast<long>(n);
400 }
401
402 template <typename T>
403 static long call(T n)
404 {
405 return call(n, mpl::bool_<is_integral<T>::value>());
406 }
407 };
408
409 ///////////////////////////////////////////////////////////////////////
410 //
411 // Traits class for radix specific number conversion
412 //
413 // Convert a digit from binary representation to character
414 // representation:
415 //
416 // static int call(unsigned n);
417 //
418 ///////////////////////////////////////////////////////////////////////
419 namespace detail
420 {
421 template <typename CharEncoding, typename Tag, bool radix_less_than_10>
422 struct convert_digit
423 {
424 static int call(unsigned n)
425 {
426 if (n <= 9)
427 return n + '0';
428
429 using spirit::char_class::convert;
430 return convert<CharEncoding>::to(Tag(), n - 10 + 'a');
431 }
432 };
433
434 template <>
435 struct convert_digit<unused_type, unused_type, false>
436 {
437 static int call(unsigned n)
438 {
439 if (n <= 9)
440 return n + '0';
441 return n - 10 + 'a';
442 }
443 };
444
445 template <typename CharEncoding, typename Tag>
446 struct convert_digit<CharEncoding, Tag, true>
447 {
448 static int call(unsigned n)
449 {
450 return n + '0';
451 }
452 };
453 }
454
455 template <unsigned Radix, typename CharEncoding, typename Tag>
456 struct convert_digit
457 : detail::convert_digit<CharEncoding, Tag, (Radix <= 10) ? true : false>
458 {};
459
460 ///////////////////////////////////////////////////////////////////////
461 template <unsigned Radix>
462 struct divide
463 {
464 template <typename T>
465 static T call(T& n, mpl::true_)
466 {
467 return n / Radix;
468 }
469
470 template <typename T>
471 static T call(T& n, mpl::false_)
472 {
473 // Allow ADL to find the correct overload for floor
474 using namespace std;
475 return floor(n / Radix);
476 }
477
478 template <typename T>
479 static T call(T& n, T const&, int)
480 {
481 return call(n, mpl::bool_<is_integral<T>::value>());
482 }
483
484 template <typename T>
485 static T call(T& n)
486 {
487 return call(n, mpl::bool_<is_integral<T>::value>());
488 }
489 };
490
491 // specialization for division by 10
492 template <>
493 struct divide<10>
494 {
495 template <typename T>
496 static T call(T& n, T, int, mpl::true_)
497 {
498 return n / 10;
499 }
500
501 template <typename T>
502 static T call(T, T& num, int exp, mpl::false_)
503 {
504 // Allow ADL to find the correct overload for floor
505 using namespace std;
506 return floor(num / spirit::traits::pow10<T>(exp));
507 }
508
509 template <typename T>
510 static T call(T& n, T& num, int exp)
511 {
512 return call(n, num, exp, mpl::bool_<is_integral<T>::value>());
513 }
514
515 template <typename T>
516 static T call(T& n)
517 {
518 return call(n, n, 1, mpl::bool_<is_integral<T>::value>());
519 }
520 };
521
522 ///////////////////////////////////////////////////////////////////////
523 template <unsigned Radix>
524 struct remainder
525 {
526 template <typename T>
527 static long call(T n, mpl::true_)
528 {
529 // this cast is safe since we know the result is not larger
530 // than Radix
531 return static_cast<long>(n % Radix);
532 }
533
534 template <typename T>
535 static long call(T n, mpl::false_)
536 {
537 // Allow ADL to find the correct overload for fmod
538 using namespace std;
539 return cast_to_long::call(fmod(n, T(Radix)));
540 }
541
542 template <typename T>
543 static long call(T n)
544 {
545 return call(n, mpl::bool_<is_integral<T>::value>());
546 }
547 };
548 }}}
549
550 namespace boost { namespace spirit { namespace karma
551 {
552 ///////////////////////////////////////////////////////////////////////////
553 //
554 // The int_inserter template takes care of the integer to string
555 // conversion. If specified, the loop is unrolled for better performance.
556 //
557 // Set the value BOOST_KARMA_NUMERICS_LOOP_UNROLL to some integer in
558 // between 0 (no unrolling) and the largest expected generated integer
559 // string length (complete unrolling).
560 // If not specified, this value defaults to 6.
561 //
562 ///////////////////////////////////////////////////////////////////////////
563 #define BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX(z, x, data) \
564 if (!traits::test_zero(n)) { \
565 int ch = radix_type::call(remainder_type::call(n)); \
566 n = divide_type::call(n, num, ++exp); \
567 /**/
568
569 #define BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX(z, x, data) \
570 *sink = char(ch); \
571 ++sink; \
572 } \
573 /**/
574
575 template <
576 unsigned Radix, typename CharEncoding = unused_type
577 , typename Tag = unused_type>
578 struct int_inserter
579 {
580 typedef traits::convert_digit<Radix, CharEncoding, Tag> radix_type;
581 typedef traits::divide<Radix> divide_type;
582 typedef traits::remainder<Radix> remainder_type;
583
584 template <typename OutputIterator, typename T>
585 static bool
586 call(OutputIterator& sink, T n, T& num, int exp)
587 {
588 // remainder_type::call returns n % Radix
589 int ch = radix_type::call(remainder_type::call(n));
590 n = divide_type::call(n, num, ++exp);
591
592 BOOST_PP_REPEAT(
593 BOOST_KARMA_NUMERICS_LOOP_UNROLL,
594 BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX, _);
595
596 if (!traits::test_zero(n))
597 call(sink, n, num, exp);
598
599 BOOST_PP_REPEAT(
600 BOOST_KARMA_NUMERICS_LOOP_UNROLL,
601 BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX, _);
602
603 *sink = char(ch);
604 ++sink;
605 return true;
606 }
607
608 // Common code for integer string representations
609 template <typename OutputIterator, typename T>
610 static bool
611 call(OutputIterator& sink, T n)
612 {
613 return call(sink, n, n, 0);
614 }
615
616 private:
617 // helper function returning the biggest number representable either in
618 // a boost::long_long_type (if this does exist) or in a plain long
619 // otherwise
620 #if defined(BOOST_HAS_LONG_LONG)
621 typedef boost::long_long_type biggest_long_type;
622 #else
623 typedef long biggest_long_type;
624 #endif
625
626 static biggest_long_type max_long()
627 {
628 return (std::numeric_limits<biggest_long_type>::max)();
629 }
630
631 public:
632 // Specialization for doubles and floats, falling back to long integers
633 // for representable values. These specializations speed up formatting
634 // of floating point numbers considerably as all the required
635 // arithmetics will be executed using integral data types.
636 template <typename OutputIterator>
637 static bool
638 call(OutputIterator& sink, long double n)
639 {
640 if (std::fabs(n) < max_long())
641 {
642 biggest_long_type l((biggest_long_type)n);
643 return call(sink, l, l, 0);
644 }
645 return call(sink, n, n, 0);
646 }
647 template <typename OutputIterator>
648 static bool
649 call(OutputIterator& sink, double n)
650 {
651 if (std::fabs(n) < max_long())
652 {
653 biggest_long_type l((biggest_long_type)n);
654 return call(sink, l, l, 0);
655 }
656 return call(sink, n, n, 0);
657 }
658 template <typename OutputIterator>
659 static bool
660 call(OutputIterator& sink, float n)
661 {
662 if (std::fabs(n) < max_long())
663 {
664 biggest_long_type l((biggest_long_type)n);
665 return call(sink, l, l, 0);
666 }
667 return call(sink, n, n, 0);
668 }
669 };
670
671 #undef BOOST_KARMA_NUMERICS_INNER_LOOP_PREFIX
672 #undef BOOST_KARMA_NUMERICS_INNER_LOOP_SUFFIX
673
674 ///////////////////////////////////////////////////////////////////////////
675 //
676 // The uint_inserter template takes care of the conversion of any integer
677 // to a string, while interpreting the number as an unsigned type.
678 //
679 ///////////////////////////////////////////////////////////////////////////
680 template <
681 unsigned Radix, typename CharEncoding = unused_type
682 , typename Tag = unused_type>
683 struct uint_inserter : int_inserter<Radix, CharEncoding, Tag>
684 {
685 typedef int_inserter<Radix, CharEncoding, Tag> base_type;
686
687 // Common code for integer string representations
688 template <typename OutputIterator, typename T>
689 static bool
690 call(OutputIterator& sink, T const& n)
691 {
692 typedef typename traits::absolute_value<T>::type type;
693 type un = type(n);
694 return base_type::call(sink, un, un, 0);
695 }
696 };
697
698 ///////////////////////////////////////////////////////////////////////////
699 //
700 // The sign_inserter template generates a sign for a given numeric value.
701 //
702 // The parameter forcesign allows to generate a sign even for positive
703 // numbers.
704 //
705 ///////////////////////////////////////////////////////////////////////////
706 struct sign_inserter
707 {
708 template <typename OutputIterator>
709 static bool
710 call_noforce(OutputIterator& sink, bool is_zero, bool is_negative,
711 bool sign_if_zero)
712 {
713 // generate a sign for negative numbers only
714 if (is_negative || (is_zero && sign_if_zero)) {
715 *sink = '-';
716 ++sink;
717 }
718 return true;
719 }
720
721 template <typename OutputIterator>
722 static bool
723 call_force(OutputIterator& sink, bool is_zero, bool is_negative,
724 bool sign_if_zero)
725 {
726 // generate a sign for all numbers except zero
727 if (!is_zero || sign_if_zero)
728 *sink = is_negative ? '-' : '+';
729 else
730 *sink = ' ';
731
732 ++sink;
733 return true;
734 }
735
736 template <typename OutputIterator>
737 static bool
738 call(OutputIterator& sink, bool is_zero, bool is_negative
739 , bool forcesign, bool sign_if_zero = false)
740 {
741 return forcesign ?
742 call_force(sink, is_zero, is_negative, sign_if_zero) :
743 call_noforce(sink, is_zero, is_negative, sign_if_zero);
744 }
745 };
746
747 ///////////////////////////////////////////////////////////////////////////
748 // These are helper functions for the real policies allowing to generate
749 // a single character and a string
750 ///////////////////////////////////////////////////////////////////////////
751 template <typename CharEncoding = unused_type, typename Tag = unused_type>
752 struct char_inserter
753 {
754 template <typename OutputIterator, typename Char>
755 static bool call(OutputIterator& sink, Char c)
756 {
757 return detail::generate_to(sink, c, CharEncoding(), Tag());
758 }
759 };
760
761 template <typename CharEncoding = unused_type, typename Tag = unused_type>
762 struct string_inserter
763 {
764 template <typename OutputIterator, typename String>
765 static bool call(OutputIterator& sink, String str)
766 {
767 return detail::string_generate(sink, str, CharEncoding(), Tag());
768 }
769 };
770
771 }}}
772
773 #endif