Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
18.numeric.special.float.cpp
Go to the documentation of this file.
1
32#include <rw/_defs.h>
33
34#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
35 // disable implicit inclusion to work around
36 // a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959)
37# define _RWSTD_NO_IMPLICIT_INCLUSION
38#endif
39
40
41#include <limits>
42
43#include <climits>
44#include <cstdlib> // for atof
45#include <cstdio> // for sprintf
46
47#include <float.h> // for constants, MSVC _fpclass, _isinf, _isnan
48#include <math.h> // for fpclassify, isinf, isnan
49
50#ifndef _RWSTD_NO_IEEEFP_H
51# include <ieeefp.h> // for fpclass, isnan
52#endif // _RWSTD_NO_IEEEFP_H
53
54#include <rw_driver.h>
55
56// use FLT_ROUNDS if available, otherwise (e.g., when <ieeefp.h> must
57// be #included to bring the macro in), fall back on our own macro
58#ifndef FLT_ROUNDS
59# define FLT_ROUNDS _RWSTD_FLT_ROUNDS
60#endif // FLT_ROUNDS
61
62
64// determine whether the architecture is little-endian or big-endian
65static const int endian_test = 1;
66
67// extern works around a SunPro 5.4 bug (PR #28124)
68extern const bool big_endian = !*(const char*)&endian_test;
69
70
72volatile float flt_zero = 0;
73volatile double dbl_zero = 0;
74
75#ifndef _RWSTD_NO_LONG_DOUBLE
76
77volatile long double ldbl_zero = 0;
78
79#endif // _RWSTD_NO_LONG_DOUBLE
80
81
83#if defined (_MSC_VER)
84
85const char* fpclass_name (int fpc)
86{
87 switch (fpc) {
88 case _FPCLASS_SNAN: return "_FPCLASS_SNAN";
89 case _FPCLASS_QNAN: return "_FPCLASS_QNAN";
90 case _FPCLASS_NINF: return "_FPCLASS_NINF";
91 case _FPCLASS_NN: return "_FPCLASS_NN";
92 case _FPCLASS_ND: return "_FPCLASS_ND";
93 case _FPCLASS_NZ: return "_FPCLASS_NZ";
94 case _FPCLASS_PZ: return "_FPCLASS_PZ";
95 case _FPCLASS_PD: return "_FPCLASS_PD";
96 case _FPCLASS_PN: return "_FPCLASS_PN";
97 case _FPCLASS_PINF: return "_FPCLASS_PINF";
98 }
99
100 static char buf [16];
101 std::sprintf (buf, "%#x", fpc);
102 return buf;
103}
104
105#elif defined (_RWSTD_OS_SUNOS)
106
107const char* fpclass_name (fpclass_t fpc)
108{
109 switch (fpc) {
110 case FP_SNAN: return "FP_SNAN";
111 case FP_QNAN: return "FP_QNAN";
112 case FP_NINF: return "FP_NINF";
113 case FP_PINF: return "FP_PINF";
114 case FP_NDENORM: return "FP_NDENORM";
115 case FP_PDENORM: return "FP_PDENORM";
116 case FP_NZERO: return "FP_NZERO";
117 case FP_PZERO: return "FP_PZERO";
118 case FP_NNORM: return "FP_NNORM";
119 case FP_PNORM: return "FP_PNORM";
120
121 }
122
123 static char buf [16];
124 std::sprintf (buf, "%#x", fpc);
125 return buf;
126}
127
128#elif defined (fpclassify) // C99 classification
129
130const char* fpclass_name (int fpc)
131{
132 switch (fpc) {
133# ifdef FP_INFINITE
134 case FP_INFINITE: return "FP_INFINITE";
135# endif
136# ifdef FP_NAN
137 case FP_NAN: return "FP_NAN";
138# endif
139# ifdef FP_NORMAL
140 case FP_NORMAL: return "FP_NORMAL";
141# endif
142# ifdef FP_SUBNORMAL
143 case FP_SUBNORMAL: return "FP_SUBNORMAL";
144# endif
145# ifdef FP_ZERO
146 case FP_ZERO: return "FP_ZERO";
147# endif
148 default: break;
149 }
150
151 static char buf [16];
152 std::sprintf (buf, "%#x", fpc);
153 return buf;
154}
155
156#endif
157
158
160#ifdef _MSC_VER
161
162inline int _fpclass (float val)
163{
164 long lval = *_RWSTD_REINTERPRET_CAST (long*, &val);
165
166 if (0 == (lval & 0x7FFFFFFF))
167 return lval ? _FPCLASS_NZ : _FPCLASS_PZ;
168
169 if (0 == (lval & 0x7F800000))
170 return (lval & 0x80000000) ? _FPCLASS_ND : _FPCLASS_PD;
171
172 if (0x7F800000 == (lval & 0x7FFFFFFF))
173 return (lval & 0x80000000) ? _FPCLASS_NINF : _FPCLASS_PINF;
174
175 if (0x7F800000 == (lval & 0x7F800000))
176 return (lval & 0x00400000) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
177
178 return (lval & 0x80000000) ? _FPCLASS_NN : _FPCLASS_PN;
179}
180
181inline int _fpclass (long double val)
182{
183 return _fpclass (double (val));
184}
185
186#endif
187
188template <class FloatT>
189void test_infinity (FloatT inf, FloatT max, const char *tname)
190{
191 if (!std::numeric_limits<FloatT>::traps) {
192
193 // infinity must be even greater than the maximum value
194 rw_assert (inf > max, 0, __LINE__,
195 "numeric_limits<%s>::infinity() > "
196 "numeric_limits<%s>::max()", tname, tname);
197
198 // multiplying infinity by anything other than 0.0 yields infinity
199 rw_assert (inf == inf * inf, 0, __LINE__,
200 "numeric_limits<%s>::infinity()", tname);
201 }
202
203#ifdef _MSC_VER
204
205 const int fpc = _fpclass (inf);
206 rw_assert (_FPCLASS_PINF == fpc, 0, __LINE__,
207 "_fpclass (numeric_limits<%s>::infinity()) == "
208 "%d (_FPCLASS_PINF), got %d (%s)",
209 tname, _FPCLASS_PINF, fpc, fpclass_name (fpc));
210
211#elif defined (_RWSTD_OS_SUNOS)
212
213 rw_assert (!finite (inf), 0, __LINE__,
214 "finite (numeric_limits<%s>::infinity()) == 0, "
215 "got non-zero", tname);
216
217 const fpclass_t fpc = fpclass (inf);
218 rw_assert (FP_PINF == fpclass (inf), 0, __LINE__,
219 "fpclass (numeric_limits<%s>::infinity()) == %d (FP_PINF), "
220 "got %d (%s)", tname, FP_PINF, fpc, fpclass_name (fpc));
221
222#else
223
224# ifdef isinf
225
226 rw_assert (isinf (inf), 0, __LINE__,
227 "isinf (numeric_limits<%s>::infinity()) != 0, got 0",
228 tname);
229
230# endif // isinf
231
232# ifdef fpclassify
233
234 const int fpc = fpclassify (inf);
235 rw_assert (FP_INFINITE == fpc, 0, __LINE__,
236 "fpclassify(numeric_limits<%s>::infinity()) == "
237 "%d (FP_INFINITE), got %d (%s)", tname,
238 FP_INFINITE, fpc, fpclass_name (fpc));
239
240# endif // fpclassify
241
242#endif
243
244}
245
246
248template <class FloatT>
249void test_quiet_NaN (FloatT qnan, FloatT qnan2, const char *tname)
250{
251 // NAN never compares equal to self or any other number
252 rw_assert (!(qnan == qnan2), 0, __LINE__,
253 "numeric_limits<%s>::quiet_NaN() != "
254 "numeric_limits<%1$s>::quiet_NaN()",
255 tname);
256
257 const FloatT inf = std::numeric_limits<FloatT>::infinity ();
258
259 rw_assert (!(qnan == inf), 0, __LINE__,
260 "numeric_limits<%s>::quiet_NaN() != "
261 "numeric_limits<%1$s>::infinity()",
262 tname);
263
264 rw_assert (!(qnan == -inf), 0, __LINE__,
265 "numeric_limits<%s>::quiet_NaN() != "
266 "-numeric_limits<%1$s>::infinity()",
267 tname);
268
269#ifdef _MSC_VER
270
271 rw_assert (0 != _isnan (qnan), 0, __LINE__,
272 "_isnan(numeric_limits<%s>::quiet_NaN()) != 0, got 0",
273 tname);
274
275 const int fpc = _fpclass (qnan);
276 rw_assert (_FPCLASS_QNAN == fpc, 0, __LINE__,
277 "_fpclass(numeric_limits<%s>::quiet_NaN()) == "
278 "%d (_FPCLASS_QNAN), got %d (%s)",
279 tname, _FPCLASS_QNAN, fpc, fpclass_name (fpc));
280
281#elif defined (_RWSTD_OS_SUNOS)
282
283 rw_assert (!finite (qnan), 0, __LINE__,
284 "finite(numeric_limits<%s>::quiet_NaN()) == 0, "
285 "got non-zero", tname);
286
287 const fpclass_t fpc = fpclass (qnan);
288 rw_assert (FP_QNAN == fpc, 0, __LINE__,
289 "fpclass(numeric_limits<%s>::infinity()) == %d (FP_QNAN), "
290 "got %d (%s)", tname, FP_QNAN, fpc, fpclass_name (fpc));
291
292#else
293
294# ifdef isnan
295
296 rw_assert (0 != isnan (qnan), 0, __LINE__,
297 "isnan(numeric_limits<%s>::quiet_NaN()) != 0, got 0",
298 tname);
299
300# endif // isnan
301
302# ifdef fpclassify
303
304 const int fpc = fpclassify (qnan);
305 rw_assert (FP_NAN == fpc, 0, __LINE__,
306 "fpclassify(numeric_limits<%s>::quiet_NaN()) == "
307 "%d (FP_NAN), got %d (%s)", tname,
308 FP_NAN, fpc, fpclass_name (fpc));
309
310# endif // fpclassify
311
312#endif
313
314}
315
316
318template <class FloatT>
319void test_signaling_NaN (FloatT snan, FloatT snan2, const char *tname)
320{
321 // NAN never compares equal to self or any other number
322 rw_assert (!(snan == snan2), 0, __LINE__,
323 "numeric_limits<%s>::signaling_NaN() != "
324 "numeric_limits<%1$s>::signaling_NaN()",
325 tname);
326
327 const FloatT inf = std::numeric_limits<FloatT>::infinity ();
328
329 rw_assert (!(snan == inf), 0, __LINE__,
330 "numeric_limits<%s>::signaling_NaN() != "
331 "numeric_limits<%1$s>::infinity()",
332 tname);
333
334 rw_assert (!(snan == -inf), 0, __LINE__,
335 "numeric_limits<%s>::signaling_NaN() != "
336 "-numeric_limits<%1$s>::infinity()",
337 tname);
338
339#ifdef _MSC_VER
340
341 rw_assert (0 != _isnan (snan), 0, __LINE__,
342 "_isnan (numeric_limits<%s>::signaling_NaN()) != 0, got 0",
343 tname);
344
345 const int fpc = _fpclass (snan);
346 rw_assert (_FPCLASS_SNAN == fpc, 0, __LINE__,
347 "_fpclass(numeric_limits<%s>::signaling_NaN()) == "
348 "%d (_FPCLASS_SNAN), got %d (%s)",
349 tname, _FPCLASS_SNAN, fpc, fpclass_name (fpc));
350
351#elif defined (_RWSTD_OS_SUNOS)
352
353 rw_assert (!finite (snan), 0, __LINE__,
354 "finite(numeric_limits<%s>::signaling_NaN()) == 0, "
355 "got non-zero", tname);
356
357 const fpclass_t fpc = fpclass (snan);
358 rw_assert (FP_SNAN == fpc, 0, __LINE__,
359 "fpclass(numeric_limits<%s>::signaling_NaN()) == %d "
360 "(FP_SNAN), got %d (%s)", tname,
361 FP_SNAN, fpc, fpclass_name (fpc));
362#else
363
364# ifdef isnan
365
366 rw_assert (0 != isnan (snan), 0, __LINE__,
367 "isnan(numeric_limits<%s>::signaling_NaN()) != 0, got 0",
368 tname);
369
370# endif // isnan
371
372# ifdef fpclassify
373
374 const int fpc = fpclassify (snan);
375 rw_assert (FP_NAN == fpc, 0, __LINE__,
376 "fpclassify(numeric_limits<%s>::signaling_NaN()) == "
377 "%d (FP_NAN), got %d (%s)", tname,
378 FP_NAN, fpc, fpclass_name (fpc));
379
380# endif // fpclassify
381
382#endif
383
384}
385
386
388template <class T>
390
391#if defined (__alpha) && !defined (__linux__) \
392 && !defined (__VMS) && defined (__DECCXX) && defined (__PURE_CNAME)
393
394extern "C" unsigned int read_rnd ();
395#define read_rnd read_rnd
396
397#endif // __alpha && !__linux__ && !__VMS && __DECCXX && __PURE_CNAME
398
399
402struct limits_values<float>
403{
404 static bool is_specialized () { return true; }
405
406 static float (min) () { return FLT_MIN; }
407 static float (max) () { return FLT_MAX; }
408
409 static int digits () { return FLT_MANT_DIG; }
410 static int digits10 () { return FLT_DIG; }
411 static bool is_signed () { return 0.0f - 1.0f < 0.0f; }
412 static bool is_integer () { return false; }
413 static bool is_exact () { return false; }
414 static int radix () { return FLT_RADIX; }
415
416 static float epsilon () { return FLT_EPSILON; }
417
418 static float round_error () {
419
420#ifdef __osf__
421 int rounding = FLT_ROUNDS;
422# ifdef read_rnd
423 if (rounding == std::round_indeterminate)
424 rounding = _RWSTD_STATIC_CAST (int, read_rnd ());
425# endif // read_rnd
426
427 switch (rounding) {
428 case std::round_toward_zero:
429 case std::round_toward_infinity:
430 case std::round_toward_neg_infinity:
431 return 1.0f;
432 default:
433 return 0.5f;
434 }
435#else
436 return 0.5f;
437#endif
438
439 }
440
441 static int min_exponent () { return FLT_MIN_EXP; }
442 static int min_exponent10 () { return FLT_MIN_10_EXP; }
443 static int max_exponent () { return FLT_MAX_EXP; }
444 static int max_exponent10 () { return FLT_MAX_10_EXP; }
445
446 static bool has_infinity () {
447 return true;
448 }
449
450 static bool has_quiet_NaN () {
451
452#if defined (NAN)
453 // 7.12, p5 of C99:
454 // The macro NAN is defined if and only if the implementation
455 // supports quiet NaNs for the float type. It expands to a
456 // constant expression of type float representing a quiet NaN.
457 return true;
458#else
459 return true;
460#endif
461
462 }
463
464
465 static bool has_signaling_NaN () {
466
467#if defined (FLT_SNAN)
468 return true;
469#else
470# ifndef _RWSTD_NO_SIGNALING_NAN
471 return true;
472# else
473 return false;
474# endif // _RWSTD_NO_SIGNALING_NAN
475#endif
476
477 }
478
479
480 static std::float_denorm_style has_denorm () {
481
482#if defined (_AIX) \
483 || defined (__hpux) \
484 || defined (__osf__) \
485 || defined (_MSC_VER)
486 return std::denorm_present;
487#else
488 return std::denorm_indeterminate;
489#endif
490 }
491
492
493 static bool has_denorm_loss () { return false; }
494
495
496 static float infinity () {
497
498#if defined (FLT_INFINITY)
499 return FLT_INFINITY;
500#elif defined (_RWSTD_NO_DBL_TRAPS)
501
502 float inf = float (std::atof ("inf"));
503 if (inf > FLT_MAX)
504 return inf;
505
506 inf = 1.0f / flt_zero;
507
508 return inf;
509
510#else
511 const union {
512 char bits [sizeof (float)];
513 float val;
514 } val = {
515 _RWSTD_FLT_INF_BITS
516 };
517
518 return val.val;
519#endif
520
521 }
522
523
524 static float quiet_NaN () {
525
526#if defined (NAN)
527 return NAN;
528#elif defined (FLT_QNAN)
529 return FLT_QNAN;
530#elif defined (_RWSTD_NO_DBL_TRAPS)
531
532 float nan = float (std::atof ("nan"));
533
534 if (nan != float (std::atof ("nan")))
535 return nan;
536
537 nan = float (dbl_zero / flt_zero);
538
539 return nan;
540
541#else
542 const union {
543 char bits [sizeof (float)];
544 float val;
545 } val = {
546 _RWSTD_FLT_QNAN_BITS
547 };
548
549 return val.val;
550
551#endif
552
553 }
554
555
556 static float signaling_NaN () {
557
558#if defined (FLT_SNAN)
559 return FLT_SNAN;
560#elif defined (_RWSTD_NO_DBL_TRAPS)
561
562 union {
563 float val;
564 char bits [sizeof (float)];
565 } snan;
566
567 snan.val = infinity ();
568
569# ifdef __hpux
570
571 if (big_endian) {
572 snan.bits [sizeof snan.val - 2] = '\xc0';
573 }
574 else {
575 snan.bits [1] = '\xc0';
576 }
577
578# else // if !defined (__hpux)
579
580 // convert infinity into a signaling NAN
581 // (toggle any bit in signifcand)
582 if (big_endian) {
583 snan.bits [sizeof snan.val - 1] |= 1;
584 }
585 else {
586 snan.bits [0] |= 1;
587 }
588
589# endif // __hpux
590
591 return snan.val;
592
593#else
594
595 const union {
596 char bits [sizeof (float)];
597 float val;
598 } val = {
599 _RWSTD_FLT_SNAN_BITS
600 };
601
602 return val.val;
603
604#endif
605
606 }
607
608
609 static float denorm_min () {
610
611#if defined (__FLT_DENORM_MIN__)
612 // gcc 3.x predefined macro
613 return __FLT_DENORM_MIN__;
614#elif defined (__osf__)
615 const unsigned short pos_denorm [] = { 0x0001, 0x0000 };
616 return *_RWSTD_REINTERPRET_CAST (const float*, pos_denorm);
617#else
618 // assume IEEE 754
619
620 static union {
621 float denorm_min;
622 char denorm_min_bits [sizeof (float)];
623 } u;
624
625 if (big_endian)
626 u.denorm_min_bits [sizeof (float) - 1] = '\001';
627 else
628 u.denorm_min_bits [0] = '\001';
629
630 return u.denorm_min;
631
632#endif
633
634 }
635
636
637 static bool is_iec559 () {
638
639#if defined (__osf__)
640
641 // Tru64 UNIX with Compaq C++: IEC 559 support is enabled
642 // by specifying the -ieee flag on the compiler command line
643
644# ifdef _IEEE_FP
645 return true;
646# else
647 return false;
648# endif // _IEEE_FP
649#else
650 return true;
651#endif
652
653 }
654
655
656 static bool is_bounded () { return true; }
657 static bool is_modulo () { return false; }
658
659 static bool traps () { return true; }
660 static bool tinyness_before () { return false; }
661
662
663 static std::float_round_style round_style () {
664
665#if defined (_AIX)
666 return std::round_to_nearest;
667#else
668 return _RWSTD_STATIC_CAST (std::float_round_style, FLT_ROUNDS);
669#endif
670 }
671
672};
673
674
678struct limits_values<double>
679{
680 static bool is_specialized () { return true; }
681
682 static double (min)() { return DBL_MIN; }
683 static double (max)() { return DBL_MAX; }
684
685 static int digits () { return DBL_MANT_DIG; }
686 static int digits10 () { return DBL_DIG; }
687 static bool is_signed () { return 0.0 - 1.0 < 0.0; }
688 static bool is_integer () { return false; }
689 static bool is_exact () { return false; }
690 static int radix () { return FLT_RADIX; }
691
692 static double epsilon () { return DBL_EPSILON; }
693
694
695 static double round_error () {
696
697#ifdef __osf__
698 int rounding = FLT_ROUNDS;
699# ifdef read_rnd
700 if (rounding == std::round_indeterminate)
701 rounding = _RWSTD_STATIC_CAST (int, read_rnd ());
702# endif // read_rnd
703 switch (rounding) {
704 case std::round_toward_zero:
705 case std::round_toward_infinity:
706 case std::round_toward_neg_infinity:
707 return 1.0;
708 default:
709 return 0.5;
710 }
711#else
712 return 0.5;
713#endif
714
715 }
716
717
718 static int min_exponent () { return DBL_MIN_EXP; }
719 static int min_exponent10 () { return DBL_MIN_10_EXP; }
720 static int max_exponent () { return DBL_MAX_EXP; }
721 static int max_exponent10 () { return DBL_MAX_10_EXP; }
722
723
724 static bool has_infinity () {
725 return true;
726 }
727
728
729 static bool has_quiet_NaN () {
730 return true;
731 }
732
733
734 static bool has_signaling_NaN () {
735
736#if defined DBL_SNAN
737 return true;
738#else
739# ifndef _RWSTD_NO_SIGNALING_NAN
740 return true;
741# else
742 return false;
743# endif // _RWSTD_NO_SIGNALING_NAN
744#endif
745
746 }
747
748
749 static std::float_denorm_style has_denorm () {
750#if defined (_AIX) \
751 || defined (__hpux) \
752 || defined (__osf__) \
753 || defined (_MSC_VER)
754 return std::denorm_present;
755#else
756 return std::denorm_indeterminate;
757#endif
758 }
759
760
761 static bool has_denorm_loss () { return false; }
762
763
764 static double infinity () {
765
766#if defined (DBL_INFINITY)
767 return DBL_INFINITY;
768#elif defined (_RWSTD_NO_DBL_TRAPS)
769
770 double inf = std::atof ("inf");
771 if (inf > DBL_MAX)
772 return inf;
773
774 inf = 1.0 / dbl_zero;
775
776 return inf;
777
778#else
779 const union {
780 char bits [sizeof (double)];
781 double val;
782 } val = {
783 _RWSTD_DBL_INF_BITS
784 };
785
786 return val.val;
787#endif
788
789 }
790
791
792 static double quiet_NaN () {
793
794#if defined (NAN)
795 return NAN;
796#elif defined (DBL_QNAN)
797 return DBL_QNAN;
798#elif defined (_RWSTD_NO_DBL_TRAPS)
799
800 double nan = std::atof ("nan");
801
802 if (nan != std::atof ("nan"))
803 return nan;
804
805 nan = flt_zero / dbl_zero;
806
807 return nan;
808
809#else
810 const union {
811 char bits [sizeof (double)];
812 double val;
813 } val = {
814 _RWSTD_DBL_QNAN_BITS
815 };
816
817 return val.val;
818
819#endif
820
821 }
822
823
824 static double signaling_NaN () {
825
826#if defined (DBL_SNAN)
827 return DBL_SNAN;
828#elif defined (_RWSTD_NO_DBL_TRAPS)
829
830 union {
831 double val;
832 char bits [sizeof (double)];
833 } snan;
834
835 snan.val = infinity ();
836
837# ifdef __hpux
838
839 if (big_endian) {
840 snan.bits [sizeof snan.val - 2] = '\xf8';
841 }
842 else {
843 snan.bits [1] = '\xf8';
844 }
845
846# else // if !defined (__hpux)
847
848 // convert infinity into a signaling NAN
849 // (toggle any bit in signifcand)
850 if (big_endian) {
851 snan.bits [sizeof snan.val - 1] |= 1;
852 }
853 else {
854 snan.bits [0] |= 1;
855 }
856
857# endif // __hpux
858
859 return snan.val;
860
861#else
862
863 const union {
864 char bits [sizeof (double)];
865 double val;
866 } val = {
867 _RWSTD_DBL_SNAN_BITS
868 };
869
870 return val.val;
871
872#endif
873
874 }
875
876
877 static double denorm_min () {
878
879#if defined (__DBL_DENORM_MIN__)
880 // gcc 3.x predefined macro
881 return __DBL_DENORM_MIN__;
882#elif defined (__osf__)
883 const unsigned short pos_denorm [] = { 0x0001, 0x0000 };
884 return *_RWSTD_REINTERPRET_CAST (const double*, pos_denorm);
885#else
886 // assume IEEE 754
887
888 static union {
889 double denorm_min;
890 char denorm_min_bits [sizeof (double)];
891 } u;
892
893 if (big_endian)
894 u.denorm_min_bits [sizeof (double) - 1] = '\001';
895 else
896 u.denorm_min_bits [0] = '\001';
897
898 return u.denorm_min;
899
900#endif
901
902 }
903
904
905 static bool is_iec559 () {
906
907#if defined (__osf__)
908# ifdef _IEEE_FP
909 return true;
910# else
911 return false;
912# endif // _IEEE_FP
913#else
914 return true;
915#endif
916
917 }
918
919
920 static bool is_bounded () { return true; }
921 static bool is_modulo () { return false; }
922
923 static bool traps () { return true; }
924 static bool tinyness_before () { return false; }
925
926
927 static std::float_round_style round_style () {
928
929#if defined (_AIX)
930 return std::round_to_nearest;
931#else
932 return _RWSTD_STATIC_CAST (std::float_round_style, FLT_ROUNDS);
933#endif
934
935 }
936
937};
938
939
943struct limits_values<long double>
944{
945 static bool is_specialized () { return true; }
946
947 static long double (min)() { return LDBL_MIN; }
948 static long double (max)() { return LDBL_MAX; }
949
950 static int digits () { return LDBL_MANT_DIG; }
951 static int digits10 () { return LDBL_DIG; }
952 static bool is_signed () { return 0.0 - 1.0 < 0.0; }
953 static bool is_integer () { return false; }
954 static bool is_exact () { return false; }
955 static int radix () { return FLT_RADIX; }
956
957 static long double epsilon () { return LDBL_EPSILON; }
958
959 static long double round_error () {
960
961#ifdef __osf__
962 int rounding = FLT_ROUNDS;
963# ifdef read_rnd
964 if (rounding == std::round_indeterminate)
965 rounding = _RWSTD_STATIC_CAST (int, read_rnd ());
966# endif // read_rnd
967 switch (rounding) {
968 case std::round_toward_zero:
969 case std::round_toward_infinity:
970 case std::round_toward_neg_infinity:
971 return 1.0;
972 default:
973 return 0.5;
974 }
975#else
976 return 0.5;
977#endif
978
979 }
980
981 static int min_exponent () { return LDBL_MIN_EXP; }
982 static int min_exponent10 () { return LDBL_MIN_10_EXP; }
983 static int max_exponent () { return LDBL_MAX_EXP; }
984 static int max_exponent10 () { return LDBL_MAX_10_EXP; }
985
986 static bool has_infinity () {
987 return true;
988 }
989
990 static bool has_quiet_NaN () {
991 return true;
992 }
993
994
995 static bool has_signaling_NaN () {
996
997#if defined (LDBL_SNAN)
998 return true;
999#else
1000# ifndef _RWSTD_NO_SIGNALING_NAN
1001 return true;
1002# else
1003 return false;
1004# endif // _RWSTD_NO_SIGNALING_NAN
1005#endif
1006
1007 }
1008
1009
1010 static std::float_denorm_style has_denorm () {
1011#if defined (_AIX) \
1012 || defined (__hpux) \
1013 || defined (__osf__) \
1014 || defined (_MSC_VER)
1015 return std::denorm_present;
1016#else
1017 return std::denorm_indeterminate;
1018#endif
1019 }
1020
1021 static bool has_denorm_loss () { return false; }
1022
1023
1024 static long double infinity () {
1025
1026#if defined (LDBL_INFINITY)
1027 return LDBL_INFINITY;
1028#elif defined (_RWSTD_NO_DBL_TRAPS)
1029
1030 long double inf = std::atof ("inf");
1031 if (inf > LDBL_MAX)
1032 return inf;
1033
1034 inf = (long double)1.0 / ldbl_zero;
1035
1036 return inf;
1037
1038#else
1039 const union {
1040 char bits [sizeof (long double)];
1041 long double val;
1042 } val = {
1043 _RWSTD_LDBL_INF_BITS
1044 };
1045
1046 return val.val;
1047#endif
1048
1049 }
1050
1051
1052 static long double quiet_NaN () {
1053
1054#if defined (NAN)
1055 return NAN;
1056#elif defined (LDBL_QNAN)
1057 return LDBL_QNAN;
1058#elif defined (_RWSTD_NO_DBL_TRAPS)
1059
1060 long double nan = std::atof ("nan");
1061
1062 if (nan != (long double)std::atof ("nan"))
1063 return nan;
1064
1065 nan = ldbl_zero / ldbl_zero;
1066
1067 return nan;
1068
1069#else
1070 const union {
1071 char bits [sizeof (long double)];
1072 long double val;
1073 } val = {
1074 _RWSTD_LDBL_QNAN_BITS
1075 };
1076
1077 return val.val;
1078
1079#endif
1080
1081 }
1082
1083
1084 static long double signaling_NaN () {
1085
1086#if defined (LDBL_SNAN)
1087 return LDBL_SNAN;
1088#elif defined (_RWSTD_NO_DBL_TRAPS)
1089
1090 union {
1091 long double val;
1092 char bits [sizeof (long double)];
1093 } snan;
1094
1095 snan.val = infinity ();
1096
1097# ifdef __hpux
1098
1099 if (big_endian) {
1100 snan.bits [sizeof snan.val - 3] = '\x80';
1101 }
1102 else {
1103 snan.bits [2] = '\x80';
1104 }
1105
1106# else // if !defined (__hpux)
1107
1108 // convert infinity into a signaling NAN
1109 // (toggle any bit in signifcand)
1110 if (big_endian) {
1111 snan.bits [sizeof snan.val - 1] |= 1;
1112 }
1113 else {
1114 snan.bits [0] |= 1;
1115 }
1116
1117# endif // __hpux
1118
1119 return snan.val;
1120
1121#else
1122
1123 const union {
1124 char bits [sizeof (long double)];
1125 long double val;
1126 } val = {
1127 _RWSTD_LDBL_SNAN_BITS
1128 };
1129
1130 return val.val;
1131
1132#endif
1133
1134 }
1135
1136
1137 static long double denorm_min () {
1138
1139#if defined (__LDBL_DENORM_MIN__)
1140 // gcc 3.x predefined macro
1141 return __LDBL_DENORM_MIN__;
1142#elif defined (__osf__)
1143 const unsigned short pos_denorm [] = { 0x0001, 0x0000 };
1144 return *_RWSTD_REINTERPRET_CAST (const long double*, pos_denorm);
1145#else
1146 // assume IEEE 754
1147
1148 static union {
1149 long double denorm_min;
1150 char denorm_min_bits [sizeof (long double)];
1151 } u;
1152
1153 if (big_endian)
1154 u.denorm_min_bits [sizeof (long double) - 1] = '\001';
1155 else
1156 u.denorm_min_bits [0] = '\001';
1157
1158 return u.denorm_min;
1159#endif
1160
1161 }
1162
1163
1164 static bool is_iec559 () {
1165#if defined (__osf__)
1166# ifdef _IEEE_FP
1167 return true;
1168# else
1169 return false;
1170# endif // _IEEE_FP
1171#else
1172 return true;
1173#endif
1174 }
1175
1176 static bool is_bounded () { return true; }
1177 static bool is_modulo () { return false; }
1178
1179 static bool traps () { return true; }
1180 static bool tinyness_before () { return false; }
1181
1182 static std::float_round_style round_style () {
1183#if defined (_AIX)
1184 return std::round_to_nearest;
1185#else
1186 return _RWSTD_STATIC_CAST (std::float_round_style, FLT_ROUNDS);
1187#endif
1188 }
1189};
1190
1191
1193template <class FloatT>
1194void test_limits (FloatT, const char *tname, const char *fmt)
1195{
1196 typedef std::numeric_limits<FloatT> FLim;
1197 typedef limits_values<FloatT> FVal;
1198
1199 // self-test: assert that endianness is correctly computed
1200#if defined (__alpha)
1201 rw_warn (!big_endian, 0, __LINE__, "alpha is typically little-endian");
1202#elif defined (_AIX)
1203 rw_warn (big_endian, 0, __LINE__, "AIX is big-endian");
1204#elif defined (__hpux) && defined (_BIG_ENDIAN)
1205 rw_warn (big_endian, 0, __LINE__, "HP-UX is big-endian");
1206#elif defined (__i386__)
1207 rw_warn (!big_endian, 0, __LINE__, "Intel x86 is little-endian");
1208#elif defined (__sparc)
1209 rw_warn (big_endian, 0, __LINE__, "SPARC is big-endian");
1210#elif defined (_WIN64)
1211 rw_warn (!big_endian, 0, __LINE__, "WIN64 is little-endian");
1212#elif defined (_WIN32)
1213 rw_warn (!big_endian, 0, __LINE__, "WIN32 is little-endian");
1214#endif
1215
1216#ifndef _RWSTD_NO_STATIC_CONST_MEMBER_INIT
1217
1218# if !defined (__EDG__) || __EDG_VERSION__ > 245
1219# define CHECK_CONST(const_int) \
1220 enum { e = const_int }; \
1221 (void)&const_int
1222# else // if EDG eccp < 3.0
1223 // working around an EDG eccp 2.4x ICE (not in 3.0)
1224# define CHECK_CONST(const_int) \
1225 switch (const_int) { case const_int: break; }; \
1226 (void)&const_int
1227# endif // __EDG__
1228#else
1229 // static const integral members must be usable
1230 // as constant integral expressions
1231# define CHECK_CONST(const_int) enum { e = const_int }
1232#endif // _RWSTD_NO_STATIC_CONST_MEMBER_INIT
1233
1234
1235// compare against a computed value
1236#define VERIFY_DATA(member) do { \
1237 /* verify that member is a constant integral expression */ \
1238 CHECK_CONST (FLim::member); \
1239 /* verify value */ \
1240 rw_assert (FLim::member == FVal::member (), 0, __LINE__, \
1241 "numeric_limits<%s>::" #member " == %i, got %i", \
1242 tname, FVal::member (), FLim::member); \
1243 } while (0)
1244
1245// compare against a constant
1246#define VERIFY_CONST(member, value) do { \
1247 /* verify that member if a constant integral expression */ \
1248 CHECK_CONST (FLim::member); \
1249 /* verify value */ \
1250 rw_assert (FLim::member == value, 0, __LINE__, \
1251 "numeric_limits<%s>::" #member " == %i, got %i", \
1252 tname, FVal::member (), value); \
1253 } while (0)
1254
1255// account for NaN != NaN
1256#define VERIFY_FUNCTION(member) do { \
1257 /* verify function signature */ \
1258 FloatT (*pf)() _PTR_THROWS(()) = &FLim::member; \
1259 _RWSTD_UNUSED (pf); \
1260 /* verify value */ \
1261 rw_assert ( FLim::member () == FVal::member () \
1262 || ( FLim::member () != FLim::member () \
1263 && FVal::member () != FVal::member ()), \
1264 0, __LINE__, \
1265 "numeric_limits<%s>::" #member "() == %{@}, got %{@}", \
1266 tname, fmt, FVal::member (), fmt, FLim::member ()); \
1267 } while (0)
1268
1269#define VERIFY_SIGNATURE(member) do { \
1270 /* verify function signature */ \
1271 FloatT (*pf)() _PTR_THROWS(()) = &FLim::member; \
1272 _RWSTD_UNUSED (pf); \
1273 } while (0)
1274
1275#undef min
1276#undef max
1277
1278 VERIFY_FUNCTION (min); // 18.2.1.2, p1
1279 VERIFY_FUNCTION (max); // p4
1280 VERIFY_DATA (digits); // p6
1281 VERIFY_DATA (digits10); // p9
1282 VERIFY_DATA (is_signed); // p11
1283 VERIFY_DATA (is_integer); // p13
1284 VERIFY_DATA (is_exact); // p15
1285 VERIFY_DATA (radix); // p17
1286
1287 VERIFY_FUNCTION (epsilon); // 18.2.1.2, p19
1288 VERIFY_FUNCTION (round_error); // p22
1289
1290 VERIFY_DATA (min_exponent); // 18.2.1.2, p23
1291 VERIFY_DATA (min_exponent10); // p25
1292 VERIFY_DATA (max_exponent); // p27
1293 VERIFY_DATA (max_exponent10); // p29
1294
1295 VERIFY_FUNCTION (infinity); // 18.2.1.2, p42
1296
1297 if (FLim::has_infinity)
1298 test_infinity (FLim::infinity (), FLim::max (), tname);
1299
1300 if (std::numeric_limits<FloatT>::traps) // p45
1301 VERIFY_SIGNATURE (quiet_NaN);
1302 else {
1303 VERIFY_FUNCTION (quiet_NaN);
1304
1305 if (FLim::has_quiet_NaN)
1306 test_quiet_NaN (FLim::quiet_NaN (),
1307 FLim::quiet_NaN (), tname);
1308 }
1309
1310 if (std::numeric_limits<FloatT>::traps) // p47
1311 VERIFY_SIGNATURE (signaling_NaN);
1312 else {
1313 VERIFY_FUNCTION (signaling_NaN);
1314
1315 if (FLim::has_signaling_NaN)
1316 test_signaling_NaN (FLim::signaling_NaN (),
1317 FLim::signaling_NaN (), tname);
1318 }
1319
1320 if (std::numeric_limits<FloatT>::traps) { // p49
1321 // denorm min may trap (e.g., Tru64 UNIX on Alpha
1322 // with Compaq C++ without the -ieee compiler flag)
1323 VERIFY_SIGNATURE (denorm_min);
1324 }
1325 else {
1326 VERIFY_FUNCTION (denorm_min);
1327 }
1328
1329#ifdef _MSC_VER
1330
1331 if (sizeof (FloatT) > sizeof (float)) {
1332 // for doubles and long doubles only, verify that denorm_min
1333 // is properly classified
1334
1335 const FloatT denorm_min = FLim::denorm_min ();
1336
1337 const int fpc = _fpclass (double (denorm_min));
1338
1339 rw_assert (_FPCLASS_PD == fpc, 0, __LINE__,
1340 "_fpclass(numeric_limits<%s>::denorm_min()) == "
1341 "%d (_FPCLASS_PD), got %d (%s)",
1342 tname, _FPCLASS_PD, fpc, fpclass_name (fpc));
1343 }
1344
1345#endif // _MSC_VER
1346
1347 VERIFY_DATA (is_iec559); // 18.2.1.2, p52
1348 VERIFY_DATA (is_bounded); // p54
1349 VERIFY_DATA (is_modulo); // p56
1350
1351 VERIFY_DATA (tinyness_before); // 18.2.1.2, p61
1352 VERIFY_DATA (round_style); // p63
1353
1354 if (!FLim::traps) { // 18.2.1.2, p59
1355 // invalid floating point operations must not trap
1356
1357 // IEEE 754 specifies that the following operations
1358 // return NaN unless they trap:
1359 // 1. sqrt (n); n < 0
1360 // 2. rem (x, 0.0), rem (inf, x)
1361 // 3. 0 * inf
1362 // 4. 0.0 / 0.0, inf / inf
1363 // 5. inf - inf (when both inf have the same sign)
1364
1365 // use a variable (not a literal) to prevent warnings
1366 volatile FloatT zero = 0;
1367
1368 // compute infinity (division may trap)
1369 const FloatT inf = FLim::infinity ();
1370
1371 FloatT nan = zero * inf; // #3
1372 nan = zero / zero; // #4a
1373 nan = inf / inf; // #4b
1374 nan = inf - inf; // #5
1375
1376 _RWSTD_UNUSED (inf);
1377 _RWSTD_UNUSED (nan);
1378 }
1379
1380 if (FLim::is_iec559) {
1381 // 18.2.1.2, p33
1382 VERIFY_CONST (has_infinity, true);
1383
1384 // 18.2.1.2, p36
1385 VERIFY_CONST (has_quiet_NaN, true);
1386
1387 // 18.2.1.2, p39
1388 VERIFY_CONST (has_signaling_NaN, true);
1389
1390 // 18.2.1.2, p40 - 42
1391 VERIFY_DATA (has_denorm);
1392 VERIFY_DATA (has_denorm_loss);
1393 }
1394 else {
1395 // 18.2.1.2, p34 - 42
1396 VERIFY_DATA (has_quiet_NaN);
1397 VERIFY_DATA (has_signaling_NaN);
1398 VERIFY_DATA (has_denorm);
1399 VERIFY_DATA (has_denorm_loss);
1400 }
1401}
1402
1403
1405static int
1406run_test (int, char**)
1407{
1408#undef VERIFY_CONST
1409#define VERIFY_CONST(x, value) do { \
1410 enum { e = x }; \
1411 rw_assert (value == x, 0, __LINE__, \
1412 #x " == %d, got %d", value, x); \
1413 } while (0)
1414
1415 // verify values of constants in 18.2.1.3
1416 VERIFY_CONST (std::round_indeterminate, -1);
1417 VERIFY_CONST (std::round_toward_zero, 0);
1418 VERIFY_CONST (std::round_to_nearest, 1);
1419 VERIFY_CONST (std::round_toward_infinity, 2);
1420 VERIFY_CONST (std::round_toward_neg_infinity, 3);
1421
1422 // verify values of constants in 18.2.1.4
1423 VERIFY_CONST (std::denorm_indeterminate, std::float_denorm_style (-1));
1424 VERIFY_CONST (std::denorm_absent, std::float_denorm_style (0));
1425 VERIFY_CONST (std::denorm_present, std::float_denorm_style (1));
1426
1427 test_limits (float (), "float", "%g");
1428 test_limits (double (), "double", "%g");
1429
1430#ifndef _RWSTD_NO_LONG_DOUBLE
1431
1432 // working around a SunPro 5.3 ICE (PR #25968)
1433# if !defined (__SUNPRO_CC) || __SUNPRO_CC > 0x530
1434
1435 const char fmt[] = "%" _RWSTD_LDBL_PRINTF_PREFIX "g";
1436 test_limits ((long double)0.0, "long double", fmt);
1437
1438# endif // SunPro > 5.3
1439
1440#endif //_RWSTD_NO_LONG_DOUBLE
1441
1442 return 0;
1443}
1444
1445
1447int main (int argc, char *argv[])
1448{
1449 // working around a bogus EDG eccp warning (see PR #25679)
1451
1452 return rw_test (argc, argv, __FILE__,
1453 "numeric.special",
1454 "floating specializations",
1455 run_test,
1456 "",
1457 (void*)0);
1458}
#define u
Definition 17.names.cpp:137
#define buf
Definition 17.names.cpp:452
#define val
Definition 17.names.cpp:570
volatile float flt_zero
#define VERIFY_SIGNATURE(member)
#define VERIFY_CONST(member, value)
volatile double dbl_zero
void test_infinity(FloatT inf, FloatT max, const char *tname)
void test_signaling_NaN(FloatT snan, FloatT snan2, const char *tname)
volatile long double ldbl_zero
void test_quiet_NaN(FloatT qnan, FloatT qnan2, const char *tname)
void test_limits(FloatT, const char *tname, const char *fmt)
#define VERIFY_DATA(member)
#define VERIFY_FUNCTION(member)
const bool big_endian
bool is_modulo(T _max)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
#define _RWSTD_SPECIALIZED_CLASS
@ big_endian
Definition INFINITY.cpp:70
volatile int zero
Definition LIMITS.cpp:60
#define LDBL_MIN
Definition _cfloat.h:67
#define DBL_MIN_EXP
Definition _cfloat.h:55
#define FLT_MANT_DIG
Definition _cfloat.h:40
#define LDBL_DIG
Definition _cfloat.h:60
#define FLT_DIG
Definition _cfloat.h:39
#define LDBL_MAX_EXP
Definition _cfloat.h:63
#define LDBL_MANT_DIG
Definition _cfloat.h:61
#define DBL_MAX_EXP
Definition _cfloat.h:53
#define FLT_RADIX
Definition _cfloat.h:45
#define DBL_MIN_10_EXP
Definition _cfloat.h:54
#define FLT_MIN_EXP
Definition _cfloat.h:44
#define LDBL_MAX_10_EXP
Definition _cfloat.h:62
#define FLT_ROUNDS
Definition _cfloat.h:37
#define DBL_MAX_10_EXP
Definition _cfloat.h:52
#define FLT_MAX
Definition _cfloat.h:46
#define LDBL_MIN_EXP
Definition _cfloat.h:65
#define FLT_MAX_10_EXP
Definition _cfloat.h:41
#define FLT_MIN
Definition _cfloat.h:47
#define FLT_MIN_10_EXP
Definition _cfloat.h:43
#define FLT_EPSILON
Definition _cfloat.h:48
#define DBL_DIG
Definition _cfloat.h:50
#define DBL_MIN
Definition _cfloat.h:57
#define DBL_EPSILON
Definition _cfloat.h:58
#define LDBL_MIN_10_EXP
Definition _cfloat.h:64
#define LDBL_EPSILON
Definition _cfloat.h:68
#define DBL_MANT_DIG
Definition _cfloat.h:51
#define LDBL_MAX
Definition _cfloat.h:66
#define DBL_MAX
Definition _cfloat.h:56
#define FLT_MAX_EXP
Definition _cfloat.h:42
#define _RWSTD_LDBL_PRINTF_PREFIX
Definition _config.h:381
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
constexpr bool is_integer
Metafunction for determining if a type is, or is a reference to, a int64_t or toml::value<int64_t>.
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647
static std::float_round_style round_style()
static std::float_denorm_style has_denorm()
static std::float_round_style round_style()
static std::float_denorm_style has_denorm()
static std::float_denorm_style has_denorm()
static std::float_round_style round_style()
#define min(a, b)
#define max(a, b)