/work/_deps/imath-src/src/Imath/half.h
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // SPDX-License-Identifier: BSD-3-Clause |
3 | | // Copyright Contributors to the OpenEXR Project. |
4 | | // |
5 | | |
6 | | // |
7 | | // Primary original authors: |
8 | | // Florian Kainz <kainz@ilm.com> |
9 | | // Rod Bogart <rgb@ilm.com> |
10 | | // |
11 | | |
12 | | #ifndef IMATH_HALF_H_ |
13 | | #define IMATH_HALF_H_ |
14 | | |
15 | | #include "ImathExport.h" |
16 | | #include "ImathNamespace.h" |
17 | | #include "ImathPlatform.h" |
18 | | |
19 | | /// @file half.h |
20 | | /// The half type is a 16-bit floating number, compatible with the |
21 | | /// IEEE 754-2008 binary16 type. |
22 | | /// |
23 | | /// **Representation of a 32-bit float:** |
24 | | /// |
25 | | /// We assume that a float, f, is an IEEE 754 single-precision |
26 | | /// floating point number, whose bits are arranged as follows: |
27 | | /// |
28 | | /// 31 (msb) |
29 | | /// | |
30 | | /// | 30 23 |
31 | | /// | | | |
32 | | /// | | | 22 0 (lsb) |
33 | | /// | | | | | |
34 | | /// X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX |
35 | | /// |
36 | | /// s e m |
37 | | /// |
38 | | /// S is the sign-bit, e is the exponent and m is the significand. |
39 | | /// |
40 | | /// If e is between 1 and 254, f is a normalized number: |
41 | | /// |
42 | | /// s e-127 |
43 | | /// f = (-1) * 2 * 1.m |
44 | | /// |
45 | | /// If e is 0, and m is not zero, f is a denormalized number: |
46 | | /// |
47 | | /// s -126 |
48 | | /// f = (-1) * 2 * 0.m |
49 | | /// |
50 | | /// If e and m are both zero, f is zero: |
51 | | /// |
52 | | /// f = 0.0 |
53 | | /// |
54 | | /// If e is 255, f is an "infinity" or "not a number" (NAN), |
55 | | /// depending on whether m is zero or not. |
56 | | /// |
57 | | /// Examples: |
58 | | /// |
59 | | /// 0 00000000 00000000000000000000000 = 0.0 |
60 | | /// 0 01111110 00000000000000000000000 = 0.5 |
61 | | /// 0 01111111 00000000000000000000000 = 1.0 |
62 | | /// 0 10000000 00000000000000000000000 = 2.0 |
63 | | /// 0 10000000 10000000000000000000000 = 3.0 |
64 | | /// 1 10000101 11110000010000000000000 = -124.0625 |
65 | | /// 0 11111111 00000000000000000000000 = +infinity |
66 | | /// 1 11111111 00000000000000000000000 = -infinity |
67 | | /// 0 11111111 10000000000000000000000 = NAN |
68 | | /// 1 11111111 11111111111111111111111 = NAN |
69 | | /// |
70 | | /// **Representation of a 16-bit half:** |
71 | | /// |
72 | | /// Here is the bit-layout for a half number, h: |
73 | | /// |
74 | | /// 15 (msb) |
75 | | /// | |
76 | | /// | 14 10 |
77 | | /// | | | |
78 | | /// | | | 9 0 (lsb) |
79 | | /// | | | | | |
80 | | /// X XXXXX XXXXXXXXXX |
81 | | /// |
82 | | /// s e m |
83 | | /// |
84 | | /// S is the sign-bit, e is the exponent and m is the significand. |
85 | | /// |
86 | | /// If e is between 1 and 30, h is a normalized number: |
87 | | /// |
88 | | /// s e-15 |
89 | | /// h = (-1) * 2 * 1.m |
90 | | /// |
91 | | /// If e is 0, and m is not zero, h is a denormalized number: |
92 | | /// |
93 | | /// S -14 |
94 | | /// h = (-1) * 2 * 0.m |
95 | | /// |
96 | | /// If e and m are both zero, h is zero: |
97 | | /// |
98 | | /// h = 0.0 |
99 | | /// |
100 | | /// If e is 31, h is an "infinity" or "not a number" (NAN), |
101 | | /// depending on whether m is zero or not. |
102 | | /// |
103 | | /// Examples: |
104 | | /// |
105 | | /// 0 00000 0000000000 = 0.0 |
106 | | /// 0 01110 0000000000 = 0.5 |
107 | | /// 0 01111 0000000000 = 1.0 |
108 | | /// 0 10000 0000000000 = 2.0 |
109 | | /// 0 10000 1000000000 = 3.0 |
110 | | /// 1 10101 1111000001 = -124.0625 |
111 | | /// 0 11111 0000000000 = +infinity |
112 | | /// 1 11111 0000000000 = -infinity |
113 | | /// 0 11111 1000000000 = NAN |
114 | | /// 1 11111 1111111111 = NAN |
115 | | /// |
116 | | /// **Conversion via Lookup Table:** |
117 | | /// |
118 | | /// Converting from half to float is performed by default using a |
119 | | /// lookup table. There are only 65,536 different half numbers; each |
120 | | /// of these numbers has been converted and stored in a table pointed |
121 | | /// to by the ``imath_half_to_float_table`` pointer. |
122 | | /// |
123 | | /// Prior to Imath v3.1, conversion from float to half was |
124 | | /// accomplished with the help of an exponent look table, but this is |
125 | | /// now replaced with explicit bit shifting. |
126 | | /// |
127 | | /// **Conversion via Hardware:** |
128 | | /// |
129 | | /// For Imath v3.1, the conversion routines have been extended to use |
130 | | /// F16C SSE instructions whenever present and enabled by compiler |
131 | | /// flags. |
132 | | /// |
133 | | /// **Conversion via Bit-Shifting** |
134 | | /// |
135 | | /// If F16C SSE instructions are not available, conversion can be |
136 | | /// accomplished by a bit-shifting algorithm. For half-to-float |
137 | | /// conversion, this is generally slower than the lookup table, but it |
138 | | /// may be preferable when memory limits preclude storing of the |
139 | | /// 65,536-entry lookup table. |
140 | | /// |
141 | | /// The lookup table symbol is included in the compilation even if |
142 | | /// ``IMATH_HALF_USE_LOOKUP_TABLE`` is false, because application code |
143 | | /// using the exported ``half.h`` may choose to enable the use of the table. |
144 | | /// |
145 | | /// An implementation can eliminate the table from compilation by |
146 | | /// defining the ``IMATH_HALF_NO_LOOKUP_TABLE`` preprocessor symbol. |
147 | | /// Simply add: |
148 | | /// |
149 | | /// #define IMATH_HALF_NO_LOOKUP_TABLE |
150 | | /// |
151 | | /// before including ``half.h``, or define the symbol on the compile |
152 | | /// command line. |
153 | | /// |
154 | | /// Furthermore, an implementation wishing to receive ``FE_OVERFLOW`` |
155 | | /// and ``FE_UNDERFLOW`` floating point exceptions when converting |
156 | | /// float to half by the bit-shift algorithm can define the |
157 | | /// preprocessor symbol ``IMATH_HALF_ENABLE_FP_EXCEPTIONS`` prior to |
158 | | /// including ``half.h``: |
159 | | /// |
160 | | /// #define IMATH_HALF_ENABLE_FP_EXCEPTIONS |
161 | | /// |
162 | | /// **Conversion Performance Comparison:** |
163 | | /// |
164 | | /// Testing on a Core i9, the timings are approximately: |
165 | | /// |
166 | | /// half to float |
167 | | /// - table: 0.71 ns / call |
168 | | /// - no table: 1.06 ns / call |
169 | | /// - f16c: 0.45 ns / call |
170 | | /// |
171 | | /// float-to-half: |
172 | | /// - original: 5.2 ns / call |
173 | | /// - no exp table + opt: 1.27 ns / call |
174 | | /// - f16c: 0.45 ns / call |
175 | | /// |
176 | | /// **Note:** the timing above depends on the distribution of the |
177 | | /// floats in question. |
178 | | /// |
179 | | |
180 | | #ifdef __CUDA_ARCH__ |
181 | | // do not include intrinsics headers on Cuda |
182 | | #elif defined(_WIN32) |
183 | | # include <intrin.h> |
184 | | #elif defined(__x86_64__) |
185 | | # include <x86intrin.h> |
186 | | #elif defined(__F16C__) |
187 | | # include <immintrin.h> |
188 | | #endif |
189 | | |
190 | | #include <stdint.h> |
191 | | #include <stdio.h> |
192 | | |
193 | | #ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS |
194 | | # include <fenv.h> |
195 | | #endif |
196 | | |
197 | | //------------------------------------------------------------------------- |
198 | | // Limits |
199 | | // |
200 | | // Visual C++ will complain if HALF_DENORM_MIN, HALF_NRM_MIN etc. are not float |
201 | | // constants, but at least one other compiler (gcc 2.96) produces incorrect |
202 | | // results if they are. |
203 | | //------------------------------------------------------------------------- |
204 | | |
205 | | #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER |
206 | | |
207 | | /// Smallest positive denormalized half |
208 | | # define HALF_DENORM_MIN 5.96046448e-08f |
209 | | /// Smallest positive normalized half |
210 | | # define HALF_NRM_MIN 6.10351562e-05f |
211 | | /// Smallest positive normalized half |
212 | | # define HALF_MIN 6.10351562e-05f |
213 | | /// Largest positive half |
214 | | # define HALF_MAX 65504.0f |
215 | | /// Smallest positive e for which ``half(1.0 + e) != half(1.0)`` |
216 | | # define HALF_EPSILON 0.00097656f |
217 | | #else |
218 | | /// Smallest positive denormalized half |
219 | | # define HALF_DENORM_MIN 5.96046448e-08 |
220 | | /// Smallest positive normalized half |
221 | | # define HALF_NRM_MIN 6.10351562e-05 |
222 | | /// Smallest positive normalized half |
223 | | # define HALF_MIN 6.10351562e-05f |
224 | | /// Largest positive half |
225 | 0 | # define HALF_MAX 65504.0 |
226 | | /// Smallest positive e for which ``half(1.0 + e) != half(1.0)`` |
227 | | # define HALF_EPSILON 0.00097656 |
228 | | #endif |
229 | | |
230 | | /// Number of digits in mantissa (significand + hidden leading 1) |
231 | | #define HALF_MANT_DIG 11 |
232 | | /// Number of base 10 digits that can be represented without change: |
233 | | /// |
234 | | /// ``floor( (HALF_MANT_DIG - 1) * log10(2) ) => 3.01... -> 3`` |
235 | | #define HALF_DIG 3 |
236 | | /// Number of base-10 digits that are necessary to uniquely represent |
237 | | /// all distinct values: |
238 | | /// |
239 | | /// ``ceil(HALF_MANT_DIG * log10(2) + 1) => 4.31... -> 5`` |
240 | | #define HALF_DECIMAL_DIG 5 |
241 | | /// Base of the exponent |
242 | | #define HALF_RADIX 2 |
243 | | /// Minimum negative integer such that ``HALF_RADIX`` raised to the power |
244 | | /// of one less than that integer is a normalized half |
245 | | #define HALF_DENORM_MIN_EXP -13 |
246 | | /// Maximum positive integer such that ``HALF_RADIX`` raised to the power |
247 | | /// of one less than that integer is a normalized half |
248 | | #define HALF_MAX_EXP 16 |
249 | | /// Minimum positive integer such that 10 raised to that power is a |
250 | | /// normalized half |
251 | | #define HALF_DENORM_MIN_10_EXP -4 |
252 | | /// Maximum positive integer such that 10 raised to that power is a |
253 | | /// normalized half |
254 | | #define HALF_MAX_10_EXP 4 |
255 | | |
256 | | /// a type for both C-only programs and C++ to use the same utilities |
257 | | typedef union imath_half_uif |
258 | | { |
259 | | uint32_t i; |
260 | | float f; |
261 | | } imath_half_uif_t; |
262 | | |
263 | | /// a type for both C-only programs and C++ to use the same utilities |
264 | | typedef uint16_t imath_half_bits_t; |
265 | | |
266 | | #if !defined(__cplusplus) && !defined(__CUDACC__) |
267 | | /// if we're in a C-only context, alias the half bits type to half |
268 | | typedef imath_half_bits_t half; |
269 | | #endif |
270 | | |
271 | | #if !defined(IMATH_HALF_NO_LOOKUP_TABLE) |
272 | | # if defined(__cplusplus) |
273 | | extern "C" |
274 | | # else |
275 | | extern |
276 | | # endif |
277 | | IMATH_EXPORT const imath_half_uif_t* imath_half_to_float_table; |
278 | | #endif |
279 | | |
280 | | /// |
281 | | /// Convert half to float |
282 | | /// |
283 | | |
284 | | static inline float |
285 | | imath_half_to_float (imath_half_bits_t h) |
286 | 66.0M | { |
287 | | #if defined(__F16C__) |
288 | | // NB: The intel implementation does seem to treat NaN slightly |
289 | | // different than the original toFloat table does (i.e. where the |
290 | | // 1 bits are, meaning the signalling or not bits). This seems |
291 | | // benign, given that the original library didn't really deal with |
292 | | // signalling vs non-signalling NaNs |
293 | | # ifdef _MSC_VER |
294 | | /* msvc does not seem to have cvtsh_ss :( */ |
295 | | return _mm_cvtss_f32 (_mm_cvtph_ps (_mm_set1_epi16 (h))); |
296 | | # else |
297 | | return _cvtsh_ss (h); |
298 | | # endif |
299 | | #elif defined(IMATH_HALF_USE_LOOKUP_TABLE) && \ |
300 | | !defined(IMATH_HALF_NO_LOOKUP_TABLE) |
301 | | return imath_half_to_float_table[h].f; |
302 | | #else |
303 | | imath_half_uif_t v; |
304 | | // this code would be clearer, although it does appear to be faster |
305 | | // (1.06 vs 1.08 ns/call) to avoid the constants and just do 4 |
306 | | // shifts. |
307 | | // |
308 | | uint32_t hexpmant = ((uint32_t) (h) << 17) >> 4; |
309 | | v.i = ((uint32_t) (h >> 15)) << 31; |
310 | | |
311 | | // the likely really does help if most of your numbers are "normal" half numbers |
312 | 0 | if (IMATH_LIKELY ((hexpmant >= 0x00800000))) |
313 | 0 | { |
314 | 0 | v.i |= hexpmant; |
315 | | // either we are a normal number, in which case add in the bias difference |
316 | | // otherwise make sure all exponent bits are set |
317 | 0 | if (IMATH_LIKELY ((hexpmant < 0x0f800000))) |
318 | 0 | v.i += 0x38000000; |
319 | 0 | else |
320 | 0 | v.i |= 0x7f800000; |
321 | 0 | } |
322 | 0 | else if (hexpmant != 0) |
323 | 0 | { |
324 | | // exponent is 0 because we're denormal, don't have to extract |
325 | | // the mantissa, can just use as is |
326 | | // |
327 | | // |
328 | | // other compilers may provide count-leading-zeros primitives, |
329 | | // but we need the community to inform us of the variants |
330 | 0 | uint32_t lc; |
331 | | # if defined(_MSC_VER) && (_M_IX86 || _M_X64) |
332 | | lc = __lzcnt (hexpmant); |
333 | | # elif defined(__GNUC__) || defined(__clang__) |
334 | 0 | lc = (uint32_t) __builtin_clz (hexpmant); |
335 | | # else |
336 | | lc = 0; |
337 | | while (0 == ((hexpmant << lc) & 0x80000000)) |
338 | | ++lc; |
339 | | # endif |
340 | 0 | lc -= 8; |
341 | | // so nominally we want to remove that extra bit we shifted |
342 | | // up, but we are going to add that bit back in, then subtract |
343 | | // from it with the 0x38800000 - (lc << 23).... |
344 | | // |
345 | | // by combining, this allows us to skip the & operation (and |
346 | | // remove a constant) |
347 | | // |
348 | | // hexpmant &= ~0x00800000; |
349 | 0 | v.i |= 0x38800000; |
350 | | // lc is now x, where the desired exponent is then |
351 | | // -14 - lc |
352 | | // + 127 -> new exponent |
353 | 0 | v.i |= (hexpmant << lc); |
354 | 0 | v.i -= (lc << 23); |
355 | 0 | } |
356 | | return v.f; |
357 | | #endif |
358 | 66.0M | } Unexecuted instantiation: ImfCheckFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfCompositeDeepScanLine.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfCompressor.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfDeepScanLineInputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfDeepScanLineInputPart.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfDeepTiledInputFile.cpp:imath_half_to_float(unsigned short) ImfDwaCompressor.cpp:imath_half_to_float(unsigned short) Line | Count | Source | 286 | 6.33M | { | 287 | | #if defined(__F16C__) | 288 | | // NB: The intel implementation does seem to treat NaN slightly | 289 | | // different than the original toFloat table does (i.e. where the | 290 | | // 1 bits are, meaning the signalling or not bits). This seems | 291 | | // benign, given that the original library didn't really deal with | 292 | | // signalling vs non-signalling NaNs | 293 | | # ifdef _MSC_VER | 294 | | /* msvc does not seem to have cvtsh_ss :( */ | 295 | | return _mm_cvtss_f32 (_mm_cvtph_ps (_mm_set1_epi16 (h))); | 296 | | # else | 297 | | return _cvtsh_ss (h); | 298 | | # endif | 299 | | #elif defined(IMATH_HALF_USE_LOOKUP_TABLE) && \ | 300 | | !defined(IMATH_HALF_NO_LOOKUP_TABLE) | 301 | 6.33M | return imath_half_to_float_table[h].f; | 302 | | #else | 303 | | imath_half_uif_t v; | 304 | | // this code would be clearer, although it does appear to be faster | 305 | | // (1.06 vs 1.08 ns/call) to avoid the constants and just do 4 | 306 | | // shifts. | 307 | | // | 308 | | uint32_t hexpmant = ((uint32_t) (h) << 17) >> 4; | 309 | | v.i = ((uint32_t) (h >> 15)) << 31; | 310 | | | 311 | | // the likely really does help if most of your numbers are "normal" half numbers | 312 | | if (IMATH_LIKELY ((hexpmant >= 0x00800000))) | 313 | | { | 314 | | v.i |= hexpmant; | 315 | | // either we are a normal number, in which case add in the bias difference | 316 | | // otherwise make sure all exponent bits are set | 317 | | if (IMATH_LIKELY ((hexpmant < 0x0f800000))) | 318 | | v.i += 0x38000000; | 319 | | else | 320 | | v.i |= 0x7f800000; | 321 | | } | 322 | | else if (hexpmant != 0) | 323 | | { | 324 | | // exponent is 0 because we're denormal, don't have to extract | 325 | | // the mantissa, can just use as is | 326 | | // | 327 | | // | 328 | | // other compilers may provide count-leading-zeros primitives, | 329 | | // but we need the community to inform us of the variants | 330 | | uint32_t lc; | 331 | | # if defined(_MSC_VER) && (_M_IX86 || _M_X64) | 332 | | lc = __lzcnt (hexpmant); | 333 | | # elif defined(__GNUC__) || defined(__clang__) | 334 | | lc = (uint32_t) __builtin_clz (hexpmant); | 335 | | # else | 336 | | lc = 0; | 337 | | while (0 == ((hexpmant << lc) & 0x80000000)) | 338 | | ++lc; | 339 | | # endif | 340 | | lc -= 8; | 341 | | // so nominally we want to remove that extra bit we shifted | 342 | | // up, but we are going to add that bit back in, then subtract | 343 | | // from it with the 0x38800000 - (lc << 23).... | 344 | | // | 345 | | // by combining, this allows us to skip the & operation (and | 346 | | // remove a constant) | 347 | | // | 348 | | // hexpmant &= ~0x00800000; | 349 | | v.i |= 0x38800000; | 350 | | // lc is now x, where the desired exponent is then | 351 | | // -14 - lc | 352 | | // + 127 -> new exponent | 353 | | v.i |= (hexpmant << lc); | 354 | | v.i -= (lc << 23); | 355 | | } | 356 | | return v.f; | 357 | | #endif | 358 | 6.33M | } |
Unexecuted instantiation: ImfGenericInputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfHeader.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfIDManifestAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfInputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfIntAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfKeyCodeAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfLineOrderAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfMatrixAttribute.cpp:imath_half_to_float(unsigned short) ImfMisc.cpp:imath_half_to_float(unsigned short) Line | Count | Source | 286 | 14.7M | { | 287 | | #if defined(__F16C__) | 288 | | // NB: The intel implementation does seem to treat NaN slightly | 289 | | // different than the original toFloat table does (i.e. where the | 290 | | // 1 bits are, meaning the signalling or not bits). This seems | 291 | | // benign, given that the original library didn't really deal with | 292 | | // signalling vs non-signalling NaNs | 293 | | # ifdef _MSC_VER | 294 | | /* msvc does not seem to have cvtsh_ss :( */ | 295 | | return _mm_cvtss_f32 (_mm_cvtph_ps (_mm_set1_epi16 (h))); | 296 | | # else | 297 | | return _cvtsh_ss (h); | 298 | | # endif | 299 | | #elif defined(IMATH_HALF_USE_LOOKUP_TABLE) && \ | 300 | | !defined(IMATH_HALF_NO_LOOKUP_TABLE) | 301 | 14.7M | return imath_half_to_float_table[h].f; | 302 | | #else | 303 | | imath_half_uif_t v; | 304 | | // this code would be clearer, although it does appear to be faster | 305 | | // (1.06 vs 1.08 ns/call) to avoid the constants and just do 4 | 306 | | // shifts. | 307 | | // | 308 | | uint32_t hexpmant = ((uint32_t) (h) << 17) >> 4; | 309 | | v.i = ((uint32_t) (h >> 15)) << 31; | 310 | | | 311 | | // the likely really does help if most of your numbers are "normal" half numbers | 312 | | if (IMATH_LIKELY ((hexpmant >= 0x00800000))) | 313 | | { | 314 | | v.i |= hexpmant; | 315 | | // either we are a normal number, in which case add in the bias difference | 316 | | // otherwise make sure all exponent bits are set | 317 | | if (IMATH_LIKELY ((hexpmant < 0x0f800000))) | 318 | | v.i += 0x38000000; | 319 | | else | 320 | | v.i |= 0x7f800000; | 321 | | } | 322 | | else if (hexpmant != 0) | 323 | | { | 324 | | // exponent is 0 because we're denormal, don't have to extract | 325 | | // the mantissa, can just use as is | 326 | | // | 327 | | // | 328 | | // other compilers may provide count-leading-zeros primitives, | 329 | | // but we need the community to inform us of the variants | 330 | | uint32_t lc; | 331 | | # if defined(_MSC_VER) && (_M_IX86 || _M_X64) | 332 | | lc = __lzcnt (hexpmant); | 333 | | # elif defined(__GNUC__) || defined(__clang__) | 334 | | lc = (uint32_t) __builtin_clz (hexpmant); | 335 | | # else | 336 | | lc = 0; | 337 | | while (0 == ((hexpmant << lc) & 0x80000000)) | 338 | | ++lc; | 339 | | # endif | 340 | | lc -= 8; | 341 | | // so nominally we want to remove that extra bit we shifted | 342 | | // up, but we are going to add that bit back in, then subtract | 343 | | // from it with the 0x38800000 - (lc << 23).... | 344 | | // | 345 | | // by combining, this allows us to skip the & operation (and | 346 | | // remove a constant) | 347 | | // | 348 | | // hexpmant &= ~0x00800000; | 349 | | v.i |= 0x38800000; | 350 | | // lc is now x, where the desired exponent is then | 351 | | // -14 - lc | 352 | | // + 127 -> new exponent | 353 | | v.i |= (hexpmant << lc); | 354 | | v.i -= (lc << 23); | 355 | | } | 356 | | return v.f; | 357 | | #endif | 358 | 14.7M | } |
Unexecuted instantiation: ImfMultiPartInputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfOpaqueAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfPizCompressor.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfPreviewImageAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfPxr24Compressor.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfRationalAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfRgbaFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfRgbaYca.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfScanLineInputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfStandardAttributes.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfStringAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfStringVectorAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfTileDescriptionAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfTiledInputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfTiledMisc.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfTileOffsets.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfTimeCodeAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfVecAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfZipCompressor.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfB44Compressor.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfBoxAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfChannelListAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfChromaticitiesAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfCompressionAttribute.cpp:imath_half_to_float(unsigned short) ImfConvert.cpp:imath_half_to_float(unsigned short) Line | Count | Source | 286 | 45.0M | { | 287 | | #if defined(__F16C__) | 288 | | // NB: The intel implementation does seem to treat NaN slightly | 289 | | // different than the original toFloat table does (i.e. where the | 290 | | // 1 bits are, meaning the signalling or not bits). This seems | 291 | | // benign, given that the original library didn't really deal with | 292 | | // signalling vs non-signalling NaNs | 293 | | # ifdef _MSC_VER | 294 | | /* msvc does not seem to have cvtsh_ss :( */ | 295 | | return _mm_cvtss_f32 (_mm_cvtph_ps (_mm_set1_epi16 (h))); | 296 | | # else | 297 | | return _cvtsh_ss (h); | 298 | | # endif | 299 | | #elif defined(IMATH_HALF_USE_LOOKUP_TABLE) && \ | 300 | | !defined(IMATH_HALF_NO_LOOKUP_TABLE) | 301 | 45.0M | return imath_half_to_float_table[h].f; | 302 | | #else | 303 | | imath_half_uif_t v; | 304 | | // this code would be clearer, although it does appear to be faster | 305 | | // (1.06 vs 1.08 ns/call) to avoid the constants and just do 4 | 306 | | // shifts. | 307 | | // | 308 | | uint32_t hexpmant = ((uint32_t) (h) << 17) >> 4; | 309 | | v.i = ((uint32_t) (h >> 15)) << 31; | 310 | | | 311 | | // the likely really does help if most of your numbers are "normal" half numbers | 312 | | if (IMATH_LIKELY ((hexpmant >= 0x00800000))) | 313 | | { | 314 | | v.i |= hexpmant; | 315 | | // either we are a normal number, in which case add in the bias difference | 316 | | // otherwise make sure all exponent bits are set | 317 | | if (IMATH_LIKELY ((hexpmant < 0x0f800000))) | 318 | | v.i += 0x38000000; | 319 | | else | 320 | | v.i |= 0x7f800000; | 321 | | } | 322 | | else if (hexpmant != 0) | 323 | | { | 324 | | // exponent is 0 because we're denormal, don't have to extract | 325 | | // the mantissa, can just use as is | 326 | | // | 327 | | // | 328 | | // other compilers may provide count-leading-zeros primitives, | 329 | | // but we need the community to inform us of the variants | 330 | | uint32_t lc; | 331 | | # if defined(_MSC_VER) && (_M_IX86 || _M_X64) | 332 | | lc = __lzcnt (hexpmant); | 333 | | # elif defined(__GNUC__) || defined(__clang__) | 334 | | lc = (uint32_t) __builtin_clz (hexpmant); | 335 | | # else | 336 | | lc = 0; | 337 | | while (0 == ((hexpmant << lc) & 0x80000000)) | 338 | | ++lc; | 339 | | # endif | 340 | | lc -= 8; | 341 | | // so nominally we want to remove that extra bit we shifted | 342 | | // up, but we are going to add that bit back in, then subtract | 343 | | // from it with the 0x38800000 - (lc << 23).... | 344 | | // | 345 | | // by combining, this allows us to skip the & operation (and | 346 | | // remove a constant) | 347 | | // | 348 | | // hexpmant &= ~0x00800000; | 349 | | v.i |= 0x38800000; | 350 | | // lc is now x, where the desired exponent is then | 351 | | // -14 - lc | 352 | | // + 127 -> new exponent | 353 | | v.i |= (hexpmant << lc); | 354 | | v.i -= (lc << 23); | 355 | | } | 356 | | return v.f; | 357 | | #endif | 358 | 45.0M | } |
Unexecuted instantiation: ImfDeepImageStateAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfDoubleAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfEnvmapAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfFloatAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfFloatVectorAttribute.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfIDManifest.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfInputPartData.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfOutputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: ImfGenericOutputFile.cpp:imath_half_to_float(unsigned short) Unexecuted instantiation: chunk.c:imath_half_to_float Unexecuted instantiation: decoding.c:imath_half_to_float Unexecuted instantiation: unpack.c:imath_half_to_float Unexecuted instantiation: internal_rle.c:imath_half_to_float Unexecuted instantiation: internal_zip.c:imath_half_to_float Unexecuted instantiation: internal_pxr24.c:imath_half_to_float Unexecuted instantiation: internal_b44.c:imath_half_to_float Unexecuted instantiation: internal_piz.c:imath_half_to_float Unexecuted instantiation: coding.c:imath_half_to_float Unexecuted instantiation: half.cpp:imath_half_to_float(unsigned short) |
359 | | |
360 | | /// |
361 | | /// Convert half to float |
362 | | /// |
363 | | /// Note: This only supports the "round to even" rounding mode, which |
364 | | /// was the only mode supported by the original OpenEXR library |
365 | | /// |
366 | | |
367 | | static inline imath_half_bits_t |
368 | | imath_float_to_half (float f) |
369 | 13.6M | { |
370 | | #if defined(__F16C__) |
371 | | # ifdef _MSC_VER |
372 | | // msvc does not seem to have cvtsh_ss :( |
373 | | return _mm_extract_epi16 ( |
374 | | _mm_cvtps_ph ( |
375 | | _mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), |
376 | | 0); |
377 | | # else |
378 | | // preserve the fixed rounding mode to nearest |
379 | | return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); |
380 | | # endif |
381 | | #else |
382 | 13.6M | imath_half_uif_t v; |
383 | 13.6M | imath_half_bits_t ret; |
384 | 13.6M | uint32_t e, m, ui, r, shift; |
385 | | |
386 | 13.6M | v.f = f; |
387 | | |
388 | 13.6M | ui = (v.i & ~0x80000000); |
389 | 13.6M | ret = ((v.i >> 16) & 0x8000); |
390 | | |
391 | | // exponent large enough to result in a normal number, round and return |
392 | 13.6M | if (ui >= 0x38800000) |
393 | 591k | { |
394 | | // inf or nan |
395 | 591k | if (IMATH_UNLIKELY (ui >= 0x7f800000)) |
396 | 225k | { |
397 | 225k | ret |= 0x7c00; |
398 | 225k | if (ui == 0x7f800000) return ret; |
399 | 42.8k | m = (ui & 0x7fffff) >> 13; |
400 | | // make sure we have at least one bit after shift to preserve nan-ness |
401 | 42.8k | return ret | (uint16_t) m | (uint16_t) (m == 0); |
402 | 225k | } |
403 | | |
404 | | // too large, round to infinity |
405 | 366k | if (IMATH_UNLIKELY (ui > 0x477fefff)) |
406 | 286 | { |
407 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS |
408 | | feraiseexcept (FE_OVERFLOW); |
409 | | # endif |
410 | 286 | return ret | 0x7c00; |
411 | 286 | } |
412 | | |
413 | 366k | ui -= 0x38000000; |
414 | 366k | ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); |
415 | 366k | return ret | (uint16_t) ui; |
416 | 366k | } |
417 | | |
418 | | // zero or flush to 0 |
419 | 13.0M | if (ui < 0x33000001) |
420 | 12.9M | { |
421 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS |
422 | | if (ui == 0) return ret; |
423 | | feraiseexcept (FE_UNDERFLOW); |
424 | | # endif |
425 | 12.9M | return ret; |
426 | 12.9M | } |
427 | | |
428 | | // produce a denormalized half |
429 | 117k | e = (ui >> 23); |
430 | 117k | shift = 0x7e - e; |
431 | 117k | m = 0x800000 | (ui & 0x7fffff); |
432 | 117k | r = m << (32 - shift); |
433 | 117k | ret |= (m >> shift); |
434 | 117k | if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; |
435 | 117k | return ret; |
436 | 13.0M | #endif |
437 | 13.0M | } Unexecuted instantiation: ImfCheckFile.cpp:imath_float_to_half(float) ImfCompositeDeepScanLine.cpp:imath_float_to_half(float) Line | Count | Source | 369 | 12.9k | { | 370 | | #if defined(__F16C__) | 371 | | # ifdef _MSC_VER | 372 | | // msvc does not seem to have cvtsh_ss :( | 373 | | return _mm_extract_epi16 ( | 374 | | _mm_cvtps_ph ( | 375 | | _mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), | 376 | | 0); | 377 | | # else | 378 | | // preserve the fixed rounding mode to nearest | 379 | | return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); | 380 | | # endif | 381 | | #else | 382 | 12.9k | imath_half_uif_t v; | 383 | 12.9k | imath_half_bits_t ret; | 384 | 12.9k | uint32_t e, m, ui, r, shift; | 385 | | | 386 | 12.9k | v.f = f; | 387 | | | 388 | 12.9k | ui = (v.i & ~0x80000000); | 389 | 12.9k | ret = ((v.i >> 16) & 0x8000); | 390 | | | 391 | | // exponent large enough to result in a normal number, round and return | 392 | 12.9k | if (ui >= 0x38800000) | 393 | 1.16k | { | 394 | | // inf or nan | 395 | 1.16k | if (IMATH_UNLIKELY (ui >= 0x7f800000)) | 396 | 452 | { | 397 | 452 | ret |= 0x7c00; | 398 | 452 | if (ui == 0x7f800000) return ret; | 399 | 426 | m = (ui & 0x7fffff) >> 13; | 400 | | // make sure we have at least one bit after shift to preserve nan-ness | 401 | 426 | return ret | (uint16_t) m | (uint16_t) (m == 0); | 402 | 452 | } | 403 | | | 404 | | // too large, round to infinity | 405 | 708 | if (IMATH_UNLIKELY (ui > 0x477fefff)) | 406 | 286 | { | 407 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 408 | | feraiseexcept (FE_OVERFLOW); | 409 | | # endif | 410 | 286 | return ret | 0x7c00; | 411 | 286 | } | 412 | | | 413 | 422 | ui -= 0x38000000; | 414 | 422 | ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); | 415 | 422 | return ret | (uint16_t) ui; | 416 | 708 | } | 417 | | | 418 | | // zero or flush to 0 | 419 | 11.8k | if (ui < 0x33000001) | 420 | 11.5k | { | 421 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 422 | | if (ui == 0) return ret; | 423 | | feraiseexcept (FE_UNDERFLOW); | 424 | | # endif | 425 | 11.5k | return ret; | 426 | 11.5k | } | 427 | | | 428 | | // produce a denormalized half | 429 | 271 | e = (ui >> 23); | 430 | 271 | shift = 0x7e - e; | 431 | 271 | m = 0x800000 | (ui & 0x7fffff); | 432 | 271 | r = m << (32 - shift); | 433 | 271 | ret |= (m >> shift); | 434 | 271 | if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; | 435 | 271 | return ret; | 436 | 11.8k | #endif | 437 | 11.8k | } |
Unexecuted instantiation: ImfCompressor.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfDeepScanLineInputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfDeepScanLineInputPart.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfDeepTiledInputFile.cpp:imath_float_to_half(float) ImfDwaCompressor.cpp:imath_float_to_half(float) Line | Count | Source | 369 | 13.6M | { | 370 | | #if defined(__F16C__) | 371 | | # ifdef _MSC_VER | 372 | | // msvc does not seem to have cvtsh_ss :( | 373 | | return _mm_extract_epi16 ( | 374 | | _mm_cvtps_ph ( | 375 | | _mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), | 376 | | 0); | 377 | | # else | 378 | | // preserve the fixed rounding mode to nearest | 379 | | return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); | 380 | | # endif | 381 | | #else | 382 | 13.6M | imath_half_uif_t v; | 383 | 13.6M | imath_half_bits_t ret; | 384 | 13.6M | uint32_t e, m, ui, r, shift; | 385 | | | 386 | 13.6M | v.f = f; | 387 | | | 388 | 13.6M | ui = (v.i & ~0x80000000); | 389 | 13.6M | ret = ((v.i >> 16) & 0x8000); | 390 | | | 391 | | // exponent large enough to result in a normal number, round and return | 392 | 13.6M | if (ui >= 0x38800000) | 393 | 590k | { | 394 | | // inf or nan | 395 | 590k | if (IMATH_UNLIKELY (ui >= 0x7f800000)) | 396 | 225k | { | 397 | 225k | ret |= 0x7c00; | 398 | 225k | if (ui == 0x7f800000) return ret; | 399 | 42.3k | m = (ui & 0x7fffff) >> 13; | 400 | | // make sure we have at least one bit after shift to preserve nan-ness | 401 | 42.3k | return ret | (uint16_t) m | (uint16_t) (m == 0); | 402 | 225k | } | 403 | | | 404 | | // too large, round to infinity | 405 | 365k | if (IMATH_UNLIKELY (ui > 0x477fefff)) | 406 | 0 | { | 407 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 408 | | feraiseexcept (FE_OVERFLOW); | 409 | | # endif | 410 | 0 | return ret | 0x7c00; | 411 | 0 | } | 412 | | | 413 | 365k | ui -= 0x38000000; | 414 | 365k | ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); | 415 | 365k | return ret | (uint16_t) ui; | 416 | 365k | } | 417 | | | 418 | | // zero or flush to 0 | 419 | 13.0M | if (ui < 0x33000001) | 420 | 12.8M | { | 421 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 422 | | if (ui == 0) return ret; | 423 | | feraiseexcept (FE_UNDERFLOW); | 424 | | # endif | 425 | 12.8M | return ret; | 426 | 12.8M | } | 427 | | | 428 | | // produce a denormalized half | 429 | 117k | e = (ui >> 23); | 430 | 117k | shift = 0x7e - e; | 431 | 117k | m = 0x800000 | (ui & 0x7fffff); | 432 | 117k | r = m << (32 - shift); | 433 | 117k | ret |= (m >> shift); | 434 | 117k | if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; | 435 | 117k | return ret; | 436 | 13.0M | #endif | 437 | 13.0M | } |
Unexecuted instantiation: ImfGenericInputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfHeader.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfIDManifestAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfInputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfIntAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfKeyCodeAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfLineOrderAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfMatrixAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfMisc.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfMultiPartInputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfOpaqueAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfPizCompressor.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfPreviewImageAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfPxr24Compressor.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfRationalAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfRgbaFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfRgbaYca.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfScanLineInputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfStandardAttributes.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfStringAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfStringVectorAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfTileDescriptionAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfTiledInputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfTiledMisc.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfTileOffsets.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfTimeCodeAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfVecAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfZipCompressor.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfB44Compressor.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfBoxAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfChannelListAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfChromaticitiesAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfCompressionAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfConvert.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfDeepImageStateAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfDoubleAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfEnvmapAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfFloatAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfFloatVectorAttribute.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfIDManifest.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfInputPartData.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfOutputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: ImfGenericOutputFile.cpp:imath_float_to_half(float) Unexecuted instantiation: chunk.c:imath_float_to_half Unexecuted instantiation: decoding.c:imath_float_to_half Unexecuted instantiation: unpack.c:imath_float_to_half Unexecuted instantiation: internal_rle.c:imath_float_to_half Unexecuted instantiation: internal_zip.c:imath_float_to_half Unexecuted instantiation: internal_pxr24.c:imath_float_to_half Unexecuted instantiation: internal_b44.c:imath_float_to_half Unexecuted instantiation: internal_piz.c:imath_float_to_half Unexecuted instantiation: coding.c:imath_float_to_half Unexecuted instantiation: half.cpp:imath_float_to_half(float) |
438 | | |
439 | | //////////////////////////////////////// |
440 | | |
441 | | #ifdef __cplusplus |
442 | | |
443 | | # include <iostream> |
444 | | |
445 | | IMATH_INTERNAL_NAMESPACE_HEADER_ENTER |
446 | | |
447 | | /// |
448 | | /// |
449 | | /// class half -- 16-bit floating point number |
450 | | /// |
451 | | /// Type half can represent positive and negative numbers whose |
452 | | /// magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative |
453 | | /// error of 9.8e-4; numbers smaller than 6.1e-5 can be represented |
454 | | /// with an absolute error of 6.0e-8. All integers from -2048 to |
455 | | /// +2048 can be represented exactly. |
456 | | /// |
457 | | /// Type half behaves (almost) like the built-in C++ floating point |
458 | | /// types. In arithmetic expressions, half, float and double can be |
459 | | /// mixed freely. Here are a few examples: |
460 | | /// |
461 | | /// half a (3.5); |
462 | | /// float b (a + sqrt (a)); |
463 | | /// a += b; |
464 | | /// b += a; |
465 | | /// b = a + 7; |
466 | | /// |
467 | | /// Conversions from half to float are lossless; all half numbers |
468 | | /// are exactly representable as floats. |
469 | | /// |
470 | | /// Conversions from float to half may not preserve a float's value |
471 | | /// exactly. If a float is not representable as a half, then the |
472 | | /// float value is rounded to the nearest representable half. If a |
473 | | /// float value is exactly in the middle between the two closest |
474 | | /// representable half values, then the float value is rounded to |
475 | | /// the closest half whose least significant bit is zero. |
476 | | /// |
477 | | /// Overflows during float-to-half conversions cause arithmetic |
478 | | /// exceptions. An overflow occurs when the float value to be |
479 | | /// converted is too large to be represented as a half, or if the |
480 | | /// float value is an infinity or a NAN. |
481 | | /// |
482 | | /// The implementation of type half makes the following assumptions |
483 | | /// about the implementation of the built-in C++ types: |
484 | | /// |
485 | | /// * float is an IEEE 754 single-precision number |
486 | | /// * sizeof (float) == 4 |
487 | | /// * sizeof (unsigned int) == sizeof (float) |
488 | | /// * alignof (unsigned int) == alignof (float) |
489 | | /// * sizeof (uint16_t) == 2 |
490 | | /// |
491 | | |
492 | | class IMATH_EXPORT_TYPE half |
493 | | { |
494 | | public: |
495 | | /// A special tag that lets us initialize a half from the raw bits. |
496 | | enum IMATH_EXPORT_ENUM FromBitsTag |
497 | | { |
498 | | FromBits |
499 | | }; |
500 | | |
501 | | /// @{ |
502 | | /// @name Constructors |
503 | | |
504 | | /// Default construction provides no initialization (hence it is |
505 | | /// not constexpr). |
506 | | half () IMATH_NOEXCEPT = default; |
507 | | |
508 | | /// Construct from float |
509 | | half (float f) IMATH_NOEXCEPT; |
510 | | |
511 | | /// Construct from bit-vector |
512 | | constexpr half (FromBitsTag, uint16_t bits) IMATH_NOEXCEPT; |
513 | | |
514 | | /// Copy constructor |
515 | | constexpr half (const half&) IMATH_NOEXCEPT = default; |
516 | | |
517 | | /// Move constructor |
518 | | constexpr half (half&&) IMATH_NOEXCEPT = default; |
519 | | |
520 | | /// Destructor |
521 | | ~half () IMATH_NOEXCEPT = default; |
522 | | |
523 | | /// @} |
524 | | |
525 | | /// Conversion to float |
526 | | operator float () const IMATH_NOEXCEPT; |
527 | | |
528 | | /// @{ |
529 | | /// @name Basic Algebra |
530 | | |
531 | | /// Unary minus |
532 | | constexpr half operator- () const IMATH_NOEXCEPT; |
533 | | |
534 | | /// Assignment |
535 | | half& operator= (const half& h) IMATH_NOEXCEPT = default; |
536 | | |
537 | | /// Move assignment |
538 | | half& operator= (half&& h) IMATH_NOEXCEPT = default; |
539 | | |
540 | | /// Assignment from float |
541 | | half& operator= (float f) IMATH_NOEXCEPT; |
542 | | |
543 | | /// Addition assignment |
544 | | half& operator+= (half h) IMATH_NOEXCEPT; |
545 | | |
546 | | /// Addition assignment from float |
547 | | half& operator+= (float f) IMATH_NOEXCEPT; |
548 | | |
549 | | /// Subtraction assignment |
550 | | half& operator-= (half h) IMATH_NOEXCEPT; |
551 | | |
552 | | /// Subtraction assignment from float |
553 | | half& operator-= (float f) IMATH_NOEXCEPT; |
554 | | |
555 | | /// Multiplication assignment |
556 | | half& operator*= (half h) IMATH_NOEXCEPT; |
557 | | |
558 | | /// Multiplication assignment from float |
559 | | half& operator*= (float f) IMATH_NOEXCEPT; |
560 | | |
561 | | /// Division assignment |
562 | | half& operator/= (half h) IMATH_NOEXCEPT; |
563 | | |
564 | | /// Division assignment from float |
565 | | half& operator/= (float f) IMATH_NOEXCEPT; |
566 | | |
567 | | /// @} |
568 | | |
569 | | /// Round to n-bit precision (n should be between 0 and 10). |
570 | | /// After rounding, the significand's 10-n least significant |
571 | | /// bits will be zero. |
572 | | IMATH_CONSTEXPR14 half round (unsigned int n) const IMATH_NOEXCEPT; |
573 | | |
574 | | /// @{ |
575 | | /// @name Classification |
576 | | |
577 | | /// Return true if a normalized number, a denormalized number, or |
578 | | /// zero. |
579 | | constexpr bool isFinite () const IMATH_NOEXCEPT; |
580 | | |
581 | | /// Return true if a normalized number. |
582 | | constexpr bool isNormalized () const IMATH_NOEXCEPT; |
583 | | |
584 | | /// Return true if a denormalized number. |
585 | | constexpr bool isDenormalized () const IMATH_NOEXCEPT; |
586 | | |
587 | | /// Return true if zero. |
588 | | constexpr bool isZero () const IMATH_NOEXCEPT; |
589 | | |
590 | | /// Return true if NAN. |
591 | | constexpr bool isNan () const IMATH_NOEXCEPT; |
592 | | |
593 | | /// Return true if a positive or a negative infinity |
594 | | constexpr bool isInfinity () const IMATH_NOEXCEPT; |
595 | | |
596 | | /// Return true if the sign bit is set (negative) |
597 | | constexpr bool isNegative () const IMATH_NOEXCEPT; |
598 | | |
599 | | /// @} |
600 | | |
601 | | /// @{ |
602 | | /// @name Special values |
603 | | |
604 | | /// Return +infinity |
605 | | static constexpr half posInf () IMATH_NOEXCEPT; |
606 | | |
607 | | /// Return -infinity |
608 | | static constexpr half negInf () IMATH_NOEXCEPT; |
609 | | |
610 | | /// Returns a NAN with the bit pattern 0111111111111111 |
611 | | static constexpr half qNan () IMATH_NOEXCEPT; |
612 | | |
613 | | /// Return a NAN with the bit pattern 0111110111111111 |
614 | | static constexpr half sNan () IMATH_NOEXCEPT; |
615 | | |
616 | | /// @} |
617 | | |
618 | | /// @{ |
619 | | /// @name Access to the internal representation |
620 | | |
621 | | /// Return the bit pattern |
622 | | IMATH_EXPORT constexpr uint16_t bits () const IMATH_NOEXCEPT; |
623 | | |
624 | | /// Set the bit pattern |
625 | | IMATH_EXPORT IMATH_CONSTEXPR14 void setBits (uint16_t bits) IMATH_NOEXCEPT; |
626 | | |
627 | | /// @} |
628 | | |
629 | | public: |
630 | | static_assert ( |
631 | | sizeof (float) == sizeof (uint32_t), |
632 | | "Assumption about the size of floats correct"); |
633 | | using uif = imath_half_uif; |
634 | | |
635 | | private: |
636 | | constexpr uint16_t mantissa () const IMATH_NOEXCEPT; |
637 | | constexpr uint16_t exponent () const IMATH_NOEXCEPT; |
638 | | |
639 | | uint16_t _h; |
640 | | }; |
641 | | |
642 | | //---------------------------- |
643 | | // Half-from-float constructor |
644 | | //---------------------------- |
645 | | |
646 | | inline half::half (float f) IMATH_NOEXCEPT : _h (imath_float_to_half (f)) |
647 | 13.6M | {} |
648 | | |
649 | | //------------------------------------------ |
650 | | // Half from raw bits constructor |
651 | | //------------------------------------------ |
652 | | |
653 | | inline constexpr half::half (FromBitsTag, uint16_t bits) IMATH_NOEXCEPT |
654 | | : _h (bits) |
655 | 21.1M | {} |
656 | | |
657 | | //------------------------- |
658 | | // Half-to-float conversion |
659 | | //------------------------- |
660 | | |
661 | | inline half::operator float () const IMATH_NOEXCEPT |
662 | 66.0M | { |
663 | 66.0M | return imath_half_to_float (_h); |
664 | 66.0M | } |
665 | | |
666 | | //------------------------- |
667 | | // Round to n-bit precision |
668 | | //------------------------- |
669 | | |
670 | | inline IMATH_CONSTEXPR14 half |
671 | | half::round (unsigned int n) const IMATH_NOEXCEPT |
672 | 0 | { |
673 | | // |
674 | | // Parameter check. |
675 | | // |
676 | |
|
677 | 0 | if (n >= 10) return *this; |
678 | | |
679 | | // |
680 | | // Disassemble h into the sign, s, |
681 | | // and the combined exponent and significand, e. |
682 | | // |
683 | | |
684 | 0 | uint16_t s = _h & 0x8000; |
685 | 0 | uint16_t e = _h & 0x7fff; |
686 | | |
687 | | // |
688 | | // Round the exponent and significand to the nearest value |
689 | | // where ones occur only in the (10-n) most significant bits. |
690 | | // Note that the exponent adjusts automatically if rounding |
691 | | // up causes the significand to overflow. |
692 | | // |
693 | |
|
694 | 0 | e >>= 9 - n; |
695 | 0 | e += e & 1; |
696 | 0 | e <<= 9 - n; |
697 | | |
698 | | // |
699 | | // Check for exponent overflow. |
700 | | // |
701 | |
|
702 | 0 | if (e >= 0x7c00) |
703 | 0 | { |
704 | | // |
705 | | // Overflow occurred -- truncate instead of rounding. |
706 | | // |
707 | |
|
708 | 0 | e = _h; |
709 | 0 | e >>= 10 - n; |
710 | 0 | e <<= 10 - n; |
711 | 0 | } |
712 | | |
713 | | // |
714 | | // Put the original sign bit back. |
715 | | // |
716 | |
|
717 | 0 | half h (FromBits, s | e); |
718 | |
|
719 | 0 | return h; |
720 | 0 | } |
721 | | |
722 | | //----------------------- |
723 | | // Other inline functions |
724 | | //----------------------- |
725 | | |
726 | | inline constexpr half |
727 | | half::operator- () const IMATH_NOEXCEPT |
728 | 0 | { |
729 | 0 | return half (FromBits, bits () ^ 0x8000); |
730 | 0 | } |
731 | | |
732 | | inline half& |
733 | | half::operator= (float f) IMATH_NOEXCEPT |
734 | 2.85k | { |
735 | 2.85k | *this = half (f); |
736 | 2.85k | return *this; |
737 | 2.85k | } |
738 | | |
739 | | inline half& |
740 | | half::operator+= (half h) IMATH_NOEXCEPT |
741 | 0 | { |
742 | 0 | *this = half (float (*this) + float (h)); |
743 | 0 | return *this; |
744 | 0 | } |
745 | | |
746 | | inline half& |
747 | | half::operator+= (float f) IMATH_NOEXCEPT |
748 | 0 | { |
749 | 0 | *this = half (float (*this) + f); |
750 | 0 | return *this; |
751 | 0 | } |
752 | | |
753 | | inline half& |
754 | | half::operator-= (half h) IMATH_NOEXCEPT |
755 | 0 | { |
756 | 0 | *this = half (float (*this) - float (h)); |
757 | 0 | return *this; |
758 | 0 | } |
759 | | |
760 | | inline half& |
761 | | half::operator-= (float f) IMATH_NOEXCEPT |
762 | 0 | { |
763 | 0 | *this = half (float (*this) - f); |
764 | 0 | return *this; |
765 | 0 | } |
766 | | |
767 | | inline half& |
768 | | half::operator*= (half h) IMATH_NOEXCEPT |
769 | 0 | { |
770 | 0 | *this = half (float (*this) * float (h)); |
771 | 0 | return *this; |
772 | 0 | } |
773 | | |
774 | | inline half& |
775 | | half::operator*= (float f) IMATH_NOEXCEPT |
776 | 0 | { |
777 | 0 | *this = half (float (*this) * f); |
778 | 0 | return *this; |
779 | 0 | } |
780 | | |
781 | | inline half& |
782 | | half::operator/= (half h) IMATH_NOEXCEPT |
783 | 0 | { |
784 | 0 | *this = half (float (*this) / float (h)); |
785 | 0 | return *this; |
786 | 0 | } |
787 | | |
788 | | inline half& |
789 | | half::operator/= (float f) IMATH_NOEXCEPT |
790 | 0 | { |
791 | 0 | *this = half (float (*this) / f); |
792 | 0 | return *this; |
793 | 0 | } |
794 | | |
795 | | inline constexpr uint16_t |
796 | | half::mantissa () const IMATH_NOEXCEPT |
797 | 1.35M | { |
798 | 1.35M | return _h & 0x3ff; |
799 | 1.35M | } |
800 | | |
801 | | inline constexpr uint16_t |
802 | | half::exponent () const IMATH_NOEXCEPT |
803 | 51.6M | { |
804 | 51.6M | return (_h >> 10) & 0x001f; |
805 | 51.6M | } |
806 | | |
807 | | inline constexpr bool |
808 | | half::isFinite () const IMATH_NOEXCEPT |
809 | 0 | { |
810 | 0 | return exponent () < 31; |
811 | 0 | } |
812 | | |
813 | | inline constexpr bool |
814 | | half::isNormalized () const IMATH_NOEXCEPT |
815 | 0 | { |
816 | 0 | return exponent () > 0 && exponent () < 31; |
817 | 0 | } |
818 | | |
819 | | inline constexpr bool |
820 | | half::isDenormalized () const IMATH_NOEXCEPT |
821 | 0 | { |
822 | 0 | return exponent () == 0 && mantissa () != 0; |
823 | 0 | } |
824 | | |
825 | | inline constexpr bool |
826 | | half::isZero () const IMATH_NOEXCEPT |
827 | 0 | { |
828 | 0 | return (_h & 0x7fff) == 0; |
829 | 0 | } |
830 | | |
831 | | inline constexpr bool |
832 | | half::isNan () const IMATH_NOEXCEPT |
833 | 26.0M | { |
834 | 26.0M | return exponent () == 31 && mantissa () != 0; |
835 | 26.0M | } |
836 | | |
837 | | inline constexpr bool |
838 | | half::isInfinity () const IMATH_NOEXCEPT |
839 | 25.6M | { |
840 | 25.6M | return exponent () == 31 && mantissa () == 0; |
841 | 25.6M | } |
842 | | |
843 | | inline constexpr bool |
844 | | half::isNegative () const IMATH_NOEXCEPT |
845 | 28.1M | { |
846 | 28.1M | return (_h & 0x8000) != 0; |
847 | 28.1M | } |
848 | | |
849 | | inline constexpr half |
850 | | half::posInf () IMATH_NOEXCEPT |
851 | 1.22M | { |
852 | 1.22M | return half (FromBits, 0x7c00); |
853 | 1.22M | } |
854 | | |
855 | | inline constexpr half |
856 | | half::negInf () IMATH_NOEXCEPT |
857 | 110k | { |
858 | 110k | return half (FromBits, 0xfc00); |
859 | 110k | } |
860 | | |
861 | | inline constexpr half |
862 | | half::qNan () IMATH_NOEXCEPT |
863 | 0 | { |
864 | 0 | return half (FromBits, 0x7fff); |
865 | 0 | } |
866 | | |
867 | | inline constexpr half |
868 | | half::sNan () IMATH_NOEXCEPT |
869 | 0 | { |
870 | 0 | return half (FromBits, 0x7dff); |
871 | 0 | } |
872 | | |
873 | | inline constexpr uint16_t |
874 | | half::bits () const IMATH_NOEXCEPT |
875 | 35.2k | { |
876 | 35.2k | return _h; |
877 | 35.2k | } |
878 | | |
879 | | inline IMATH_CONSTEXPR14 void |
880 | | half::setBits (uint16_t bits) IMATH_NOEXCEPT |
881 | 26.8M | { |
882 | 26.8M | _h = bits; |
883 | 26.8M | } |
884 | | |
885 | | IMATH_INTERNAL_NAMESPACE_HEADER_EXIT |
886 | | |
887 | | /// Output h to os, formatted as a float |
888 | | IMATH_EXPORT std::ostream& |
889 | | operator<< (std::ostream& os, IMATH_INTERNAL_NAMESPACE::half h); |
890 | | |
891 | | /// Input h from is |
892 | | IMATH_EXPORT std::istream& |
893 | | operator>> (std::istream& is, IMATH_INTERNAL_NAMESPACE::half& h); |
894 | | |
895 | | #include <limits> |
896 | | |
897 | | namespace std |
898 | | { |
899 | | |
900 | | template <> class numeric_limits<IMATH_INTERNAL_NAMESPACE::half> |
901 | | { |
902 | | public: |
903 | | static const bool is_specialized = true; |
904 | | |
905 | | static constexpr IMATH_INTERNAL_NAMESPACE::half min () IMATH_NOEXCEPT |
906 | 0 | { |
907 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x0400); /*HALF_MIN*/ |
908 | 0 | } |
909 | | static constexpr IMATH_INTERNAL_NAMESPACE::half max () IMATH_NOEXCEPT |
910 | 14.6M | { |
911 | 14.6M | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7bff); /*HALF_MAX*/ |
912 | 14.6M | } |
913 | | static constexpr IMATH_INTERNAL_NAMESPACE::half lowest () |
914 | 5.17M | { |
915 | 5.17M | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0xfbff); /* -HALF_MAX */ |
916 | 5.17M | } |
917 | | |
918 | | static constexpr int digits = HALF_MANT_DIG; |
919 | | static constexpr int digits10 = HALF_DIG; |
920 | | static constexpr int max_digits10 = HALF_DECIMAL_DIG; |
921 | | static constexpr bool is_signed = true; |
922 | | static constexpr bool is_integer = false; |
923 | | static constexpr bool is_exact = false; |
924 | | static constexpr int radix = HALF_RADIX; |
925 | | static constexpr IMATH_INTERNAL_NAMESPACE::half epsilon () IMATH_NOEXCEPT |
926 | 0 | { |
927 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x1400); /*HALF_EPSILON*/ |
928 | 0 | } |
929 | | static constexpr IMATH_INTERNAL_NAMESPACE::half round_error () IMATH_NOEXCEPT |
930 | 0 | { |
931 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x3800); /*0.5*/ |
932 | 0 | } |
933 | | |
934 | | static constexpr int min_exponent = HALF_DENORM_MIN_EXP; |
935 | | static constexpr int min_exponent10 = HALF_DENORM_MIN_10_EXP; |
936 | | static constexpr int max_exponent = HALF_MAX_EXP; |
937 | | static constexpr int max_exponent10 = HALF_MAX_10_EXP; |
938 | | |
939 | | static constexpr bool has_infinity = true; |
940 | | static constexpr bool has_quiet_NaN = true; |
941 | | static constexpr bool has_signaling_NaN = true; |
942 | | static constexpr float_denorm_style has_denorm = denorm_present; |
943 | | static constexpr bool has_denorm_loss = false; |
944 | | static constexpr IMATH_INTERNAL_NAMESPACE::half infinity () IMATH_NOEXCEPT |
945 | 0 | { |
946 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7c00); /*half::posInf()*/ |
947 | 0 | } |
948 | | static constexpr IMATH_INTERNAL_NAMESPACE::half quiet_NaN () IMATH_NOEXCEPT |
949 | 0 | { |
950 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7fff); /*half::qNan()*/ |
951 | 0 | } |
952 | | static constexpr IMATH_INTERNAL_NAMESPACE::half signaling_NaN () IMATH_NOEXCEPT |
953 | 0 | { |
954 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7dff); /*half::sNan()*/ |
955 | 0 | } |
956 | | static constexpr IMATH_INTERNAL_NAMESPACE::half denorm_min () IMATH_NOEXCEPT |
957 | 0 | { |
958 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x0001); /*HALF_DENORM_MIN*/ |
959 | 0 | } |
960 | | |
961 | | static constexpr bool is_iec559 = false; |
962 | | static constexpr bool is_bounded = false; |
963 | | static constexpr bool is_modulo = false; |
964 | | |
965 | | static constexpr bool traps = true; |
966 | | static constexpr bool tinyness_before = false; |
967 | | static constexpr float_round_style round_style = round_to_nearest; |
968 | | }; |
969 | | |
970 | | } // namespace std |
971 | | |
972 | | //---------- |
973 | | // Debugging |
974 | | //---------- |
975 | | |
976 | | IMATH_EXPORT void |
977 | | printBits (std::ostream& os, IMATH_INTERNAL_NAMESPACE::half h); |
978 | | IMATH_EXPORT void printBits (std::ostream& os, float f); |
979 | | IMATH_EXPORT void printBits (char c[19], IMATH_INTERNAL_NAMESPACE::half h); |
980 | | IMATH_EXPORT void printBits (char c[35], float f); |
981 | | |
982 | | # ifndef __CUDACC__ |
983 | | using half = IMATH_INTERNAL_NAMESPACE::half; |
984 | | # else |
985 | | # include <cuda_fp16.h> |
986 | | # endif |
987 | | |
988 | | #endif // __cplusplus |
989 | | |
990 | | #endif // IMATH_HALF_H_ |