1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 #ifdef NDEBUG
7 #    undef NDEBUG
8 #endif
9 
10 #include "halfLimits.h"
11 #include <assert.h>
12 #include <cmath>
13 #include <iostream>
14 #include "testLimits.h"
15 
16 using namespace std;
17 
18 namespace
19 {
20 
21 float
mypow(int x,int y)22 mypow (int x, int y)
23 {
24     bool negative = false;
25 
26     if (y < 0)
27     {
28         negative = true;
29         y        = -y;
30     }
31 
32     float z = 1;
33 
34     while (y > 0)
35     {
36         z *= x;
37         y -= 1;
38     }
39 
40     if (negative)
41         z = 1 / z;
42 
43     return z;
44 }
45 
46 } // namespace
47 
48 void
testLimits()49 testLimits()
50 {
51     cout << "values in std::numeric_limits<half>\n";
52 
53     cout << "min_exponent\n";
54 
55     {
56         half h (mypow (2, numeric_limits<half>::min_exponent - 1));
57         assert (h.isNormalized());
58     }
59 
60     {
61         half h (mypow (2, numeric_limits<half>::min_exponent - 2));
62         assert (h.isDenormalized());
63     }
64 
65     cout << "max_exponent\n";
66 
67     {
68         half h (mypow (2, numeric_limits<half>::max_exponent - 1));
69         assert (h.isNormalized());
70     }
71 
72     {
73         half h (mypow (2, numeric_limits<half>::max_exponent));
74         assert (h.isInfinity());
75     }
76 
77     cout << "min_exponent10\n";
78 
79     {
80         half h (mypow (10, numeric_limits<half>::min_exponent10));
81         assert (h.isNormalized());
82     }
83 
84     {
85         half h (mypow (10, numeric_limits<half>::min_exponent10 - 1));
86         assert (h.isDenormalized());
87     }
88 
89     cout << "max_exponent10\n";
90 
91     {
92         half h (mypow (10, numeric_limits<half>::max_exponent10));
93         assert (h.isNormalized());
94     }
95 
96     {
97         half h (mypow (10, numeric_limits<half>::max_exponent10 + 1));
98         assert (h.isInfinity());
99     }
100 
101 #if __cplusplus >= 201103L
102 
103     cout << "max_digits10\n";
104     assert (numeric_limits<half>::max_digits10 ==
105             std::ceil (numeric_limits<half>::digits * std::log10 (2) + 1));
106 
107     cout << "lowest\n";
108     assert (numeric_limits<half>::lowest() == -HALF_MAX);
109 
110 #endif
111 
112     cout << "ok\n\n" << flush;
113 }
114 
115 void
testHalfLimits()116 testHalfLimits()
117 {
118     cout << "values in std::numeric_limits<half>\n";
119 
120     // For reference:
121     printf("HALF_DENORM_MIN %g -> 0x%04x\n", (float)HALF_DENORM_MIN, half(HALF_DENORM_MIN).bits());
122     printf("HALF_NRM_MIN %g -> 0x%04x\n", (float)HALF_NRM_MIN, half(HALF_NRM_MIN).bits());
123     printf("HALF_MIN %g -> 0x%04x\n", (float)HALF_MIN, half(HALF_MIN).bits());
124     printf("HALF_MAX %g -> 0x%04x\n", (float)HALF_MAX, half(HALF_MAX).bits());
125     printf("HALF_LOWEST %g -> 0x%04x\n", (float)-HALF_MAX, half(-HALF_MAX).bits());
126     printf("HALF_EPSILON %g -> 0x%04x\n", (float)HALF_EPSILON, half(HALF_EPSILON).bits());
127     printf("half posInf %g -> 0x%04x\n", (float)half::posInf(), half::posInf().bits());
128     printf("half negInf %g -> 0x%04x\n", (float)half::negInf(), half::negInf().bits());
129     printf("half qNan %g -> 0x%04x\n", (float)half::qNan(), half::qNan().bits());
130     printf("half sNan %g -> 0x%04x\n", (float)half::sNan(), half::sNan().bits());
131     printf("numeric_limits<half> min %g -> 0x%04x\n", (float)std::numeric_limits<half>::min(), std::numeric_limits<half>::min().bits());
132     printf("numeric_limits<half> max %g -> 0x%04x\n", (float)std::numeric_limits<half>::max(), std::numeric_limits<half>::max().bits());
133     printf("numeric_limits<half> lowest %g -> 0x%04x\n", (float)std::numeric_limits<half>::lowest(), std::numeric_limits<half>::lowest().bits());
134     printf("numeric_limits<half> epsilon %g -> 0x%04x\n", (float)std::numeric_limits<half>::epsilon(), std::numeric_limits<half>::epsilon().bits());
135     printf("numeric_limits<half> round_error %g -> 0x%04x\n", (float)std::numeric_limits<half>::round_error(), std::numeric_limits<half>::round_error().bits());
136     printf("numeric_limits<half> infinity %g -> 0x%04x\n", (float)std::numeric_limits<half>::infinity(), std::numeric_limits<half>::infinity().bits());
137     printf("numeric_limits<half> quiet_NaN %g -> 0x%04x\n", (float)std::numeric_limits<half>::quiet_NaN(), std::numeric_limits<half>::quiet_NaN().bits());
138     printf("numeric_limits<half> signaling_NaN %g -> 0x%04x\n", (float)std::numeric_limits<half>::signaling_NaN(), std::numeric_limits<half>::signaling_NaN().bits());
139     printf("numeric_limits<half> denorm_min %g -> 0x%04x\n", (float)std::numeric_limits<half>::denorm_min(), std::numeric_limits<half>::denorm_min().bits());
140 
141     assert (std::numeric_limits<half>::max() == half(HALF_MAX));
142     assert (std::numeric_limits<half>::min() == half(HALF_NRM_MIN));
143     assert (std::numeric_limits<half>::denorm_min() == half(HALF_DENORM_MIN));
144     assert (std::numeric_limits<half>::lowest() == half(-HALF_MAX));
145     assert (std::numeric_limits<half>::epsilon() == half(HALF_EPSILON));
146     assert (std::numeric_limits<half>::infinity() == half::posInf());
147     assert (std::numeric_limits<half>::quiet_NaN().bits() == half::qNan().bits());
148     assert (std::numeric_limits<half>::signaling_NaN().bits() == half::sNan().bits());
149     assert (std::numeric_limits<half>::infinity() == half::posInf());
150 
151     cout << "ok\n\n" << flush;
152 }
153