/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 | 51.6M | { |
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) |
332 | | // The direct intrinsic for this is __lznct, but that is not supported |
333 | | // on older x86_64 hardware or ARM. Instead uses the bsr instruction |
334 | | // and one additional subtraction. This assumes hexpmant != 0, for 0 |
335 | | // bsr and lznct would behave differently. |
336 | | unsigned long bsr; |
337 | | _BitScanReverse (&bsr, hexpmant); |
338 | | lc = (31 - bsr); |
339 | | # elif defined(__GNUC__) || defined(__clang__) |
340 | | lc = (uint32_t) __builtin_clz (hexpmant); |
341 | | # else |
342 | | lc = 0; |
343 | | while (0 == ((hexpmant << lc) & 0x80000000)) |
344 | | ++lc; |
345 | | # endif |
346 | 0 | lc -= 8; |
347 | | // so nominally we want to remove that extra bit we shifted |
348 | | // up, but we are going to add that bit back in, then subtract |
349 | | // from it with the 0x38800000 - (lc << 23).... |
350 | | // |
351 | | // by combining, this allows us to skip the & operation (and |
352 | | // remove a constant) |
353 | | // |
354 | | // hexpmant &= ~0x00800000; |
355 | 0 | v.i |= 0x38800000; |
356 | | // lc is now x, where the desired exponent is then |
357 | | // -14 - lc |
358 | | // + 127 -> new exponent |
359 | 0 | v.i |= (hexpmant << lc); |
360 | 0 | v.i -= (lc << 23); |
361 | 0 | } |
362 | | return v.f; |
363 | | #endif |
364 | 51.6M | } 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 | 5.05M | { | 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 | | 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) | 332 | | // The direct intrinsic for this is __lznct, but that is not supported | 333 | | // on older x86_64 hardware or ARM. Instead uses the bsr instruction | 334 | | // and one additional subtraction. This assumes hexpmant != 0, for 0 | 335 | | // bsr and lznct would behave differently. | 336 | | unsigned long bsr; | 337 | | _BitScanReverse (&bsr, hexpmant); | 338 | | lc = (31 - bsr); | 339 | | # elif defined(__GNUC__) || defined(__clang__) | 340 | | lc = (uint32_t) __builtin_clz (hexpmant); | 341 | | # else | 342 | | lc = 0; | 343 | | while (0 == ((hexpmant << lc) & 0x80000000)) | 344 | | ++lc; | 345 | | # endif | 346 | | lc -= 8; | 347 | | // so nominally we want to remove that extra bit we shifted | 348 | | // up, but we are going to add that bit back in, then subtract | 349 | | // from it with the 0x38800000 - (lc << 23).... | 350 | | // | 351 | | // by combining, this allows us to skip the & operation (and | 352 | | // remove a constant) | 353 | | // | 354 | | // hexpmant &= ~0x00800000; | 355 | | v.i |= 0x38800000; | 356 | | // lc is now x, where the desired exponent is then | 357 | | // -14 - lc | 358 | | // + 127 -> new exponent | 359 | | v.i |= (hexpmant << lc); | 360 | | v.i -= (lc << 23); | 361 | | } | 362 | | return v.f; | 363 | | #endif | 364 | 5.05M | } |
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 | 18.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 | | 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) | 332 | | // The direct intrinsic for this is __lznct, but that is not supported | 333 | | // on older x86_64 hardware or ARM. Instead uses the bsr instruction | 334 | | // and one additional subtraction. This assumes hexpmant != 0, for 0 | 335 | | // bsr and lznct would behave differently. | 336 | | unsigned long bsr; | 337 | | _BitScanReverse (&bsr, hexpmant); | 338 | | lc = (31 - bsr); | 339 | | # elif defined(__GNUC__) || defined(__clang__) | 340 | | lc = (uint32_t) __builtin_clz (hexpmant); | 341 | | # else | 342 | | lc = 0; | 343 | | while (0 == ((hexpmant << lc) & 0x80000000)) | 344 | | ++lc; | 345 | | # endif | 346 | | lc -= 8; | 347 | | // so nominally we want to remove that extra bit we shifted | 348 | | // up, but we are going to add that bit back in, then subtract | 349 | | // from it with the 0x38800000 - (lc << 23).... | 350 | | // | 351 | | // by combining, this allows us to skip the & operation (and | 352 | | // remove a constant) | 353 | | // | 354 | | // hexpmant &= ~0x00800000; | 355 | | v.i |= 0x38800000; | 356 | | // lc is now x, where the desired exponent is then | 357 | | // -14 - lc | 358 | | // + 127 -> new exponent | 359 | | v.i |= (hexpmant << lc); | 360 | | v.i -= (lc << 23); | 361 | | } | 362 | | return v.f; | 363 | | #endif | 364 | 18.0M | } |
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 | 28.6M | { | 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 | | 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) | 332 | | // The direct intrinsic for this is __lznct, but that is not supported | 333 | | // on older x86_64 hardware or ARM. Instead uses the bsr instruction | 334 | | // and one additional subtraction. This assumes hexpmant != 0, for 0 | 335 | | // bsr and lznct would behave differently. | 336 | | unsigned long bsr; | 337 | | _BitScanReverse (&bsr, hexpmant); | 338 | | lc = (31 - bsr); | 339 | | # elif defined(__GNUC__) || defined(__clang__) | 340 | | lc = (uint32_t) __builtin_clz (hexpmant); | 341 | | # else | 342 | | lc = 0; | 343 | | while (0 == ((hexpmant << lc) & 0x80000000)) | 344 | | ++lc; | 345 | | # endif | 346 | | lc -= 8; | 347 | | // so nominally we want to remove that extra bit we shifted | 348 | | // up, but we are going to add that bit back in, then subtract | 349 | | // from it with the 0x38800000 - (lc << 23).... | 350 | | // | 351 | | // by combining, this allows us to skip the & operation (and | 352 | | // remove a constant) | 353 | | // | 354 | | // hexpmant &= ~0x00800000; | 355 | | v.i |= 0x38800000; | 356 | | // lc is now x, where the desired exponent is then | 357 | | // -14 - lc | 358 | | // + 127 -> new exponent | 359 | | v.i |= (hexpmant << lc); | 360 | | v.i -= (lc << 23); | 361 | | } | 362 | | return v.f; | 363 | | #endif | 364 | 28.6M | } |
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: internal_dwa.c:imath_half_to_float Unexecuted instantiation: coding.c:imath_half_to_float Unexecuted instantiation: half.cpp:imath_half_to_float(unsigned short) |
365 | | |
366 | | /// |
367 | | /// Convert half to float |
368 | | /// |
369 | | /// Note: This only supports the "round to even" rounding mode, which |
370 | | /// was the only mode supported by the original OpenEXR library |
371 | | /// |
372 | | |
373 | | static inline imath_half_bits_t |
374 | | imath_float_to_half (float f) |
375 | 10.1M | { |
376 | | #if defined(__F16C__) |
377 | | # ifdef _MSC_VER |
378 | | // msvc does not seem to have cvtsh_ss :( |
379 | | return _mm_extract_epi16 ( |
380 | | _mm_cvtps_ph ( |
381 | | _mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), |
382 | | 0); |
383 | | # else |
384 | | // preserve the fixed rounding mode to nearest |
385 | | return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); |
386 | | # endif |
387 | | #else |
388 | 10.1M | imath_half_uif_t v; |
389 | 10.1M | imath_half_bits_t ret; |
390 | 10.1M | uint32_t e, m, ui, r, shift; |
391 | | |
392 | 10.1M | v.f = f; |
393 | | |
394 | 10.1M | ui = (v.i & ~0x80000000); |
395 | 10.1M | ret = ((v.i >> 16) & 0x8000); |
396 | | |
397 | | // exponent large enough to result in a normal number, round and return |
398 | 10.1M | if (ui >= 0x38800000) |
399 | 1.11M | { |
400 | | // inf or nan |
401 | 1.11M | if (IMATH_UNLIKELY (ui >= 0x7f800000)) |
402 | 423k | { |
403 | 423k | ret |= 0x7c00; |
404 | 423k | if (ui == 0x7f800000) return ret; |
405 | 204k | m = (ui & 0x7fffff) >> 13; |
406 | | // make sure we have at least one bit after shift to preserve nan-ness |
407 | 204k | return ret | (uint16_t) m | (uint16_t) (m == 0); |
408 | 423k | } |
409 | | |
410 | | // too large, round to infinity |
411 | 695k | if (IMATH_UNLIKELY (ui > 0x477fefff)) |
412 | 248 | { |
413 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS |
414 | | feraiseexcept (FE_OVERFLOW); |
415 | | # endif |
416 | 248 | return ret | 0x7c00; |
417 | 248 | } |
418 | | |
419 | 694k | ui -= 0x38000000; |
420 | 694k | ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); |
421 | 694k | return ret | (uint16_t) ui; |
422 | 695k | } |
423 | | |
424 | | // zero or flush to 0 |
425 | 9.05M | if (ui < 0x33000001) |
426 | 8.92M | { |
427 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS |
428 | | if (ui == 0) return ret; |
429 | | feraiseexcept (FE_UNDERFLOW); |
430 | | # endif |
431 | 8.92M | return ret; |
432 | 8.92M | } |
433 | | |
434 | | // produce a denormalized half |
435 | 124k | e = (ui >> 23); |
436 | 124k | shift = 0x7e - e; |
437 | 124k | m = 0x800000 | (ui & 0x7fffff); |
438 | 124k | r = m << (32 - shift); |
439 | 124k | ret |= (m >> shift); |
440 | 124k | if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; |
441 | 124k | return ret; |
442 | 9.05M | #endif |
443 | 9.05M | } Unexecuted instantiation: ImfCheckFile.cpp:imath_float_to_half(float) ImfCompositeDeepScanLine.cpp:imath_float_to_half(float) Line | Count | Source | 375 | 13.5k | { | 376 | | #if defined(__F16C__) | 377 | | # ifdef _MSC_VER | 378 | | // msvc does not seem to have cvtsh_ss :( | 379 | | return _mm_extract_epi16 ( | 380 | | _mm_cvtps_ph ( | 381 | | _mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), | 382 | | 0); | 383 | | # else | 384 | | // preserve the fixed rounding mode to nearest | 385 | | return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); | 386 | | # endif | 387 | | #else | 388 | 13.5k | imath_half_uif_t v; | 389 | 13.5k | imath_half_bits_t ret; | 390 | 13.5k | uint32_t e, m, ui, r, shift; | 391 | | | 392 | 13.5k | v.f = f; | 393 | | | 394 | 13.5k | ui = (v.i & ~0x80000000); | 395 | 13.5k | ret = ((v.i >> 16) & 0x8000); | 396 | | | 397 | | // exponent large enough to result in a normal number, round and return | 398 | 13.5k | if (ui >= 0x38800000) | 399 | 1.17k | { | 400 | | // inf or nan | 401 | 1.17k | if (IMATH_UNLIKELY (ui >= 0x7f800000)) | 402 | 274 | { | 403 | 274 | ret |= 0x7c00; | 404 | 274 | if (ui == 0x7f800000) return ret; | 405 | 230 | m = (ui & 0x7fffff) >> 13; | 406 | | // make sure we have at least one bit after shift to preserve nan-ness | 407 | 230 | return ret | (uint16_t) m | (uint16_t) (m == 0); | 408 | 274 | } | 409 | | | 410 | | // too large, round to infinity | 411 | 898 | if (IMATH_UNLIKELY (ui > 0x477fefff)) | 412 | 248 | { | 413 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 414 | | feraiseexcept (FE_OVERFLOW); | 415 | | # endif | 416 | 248 | return ret | 0x7c00; | 417 | 248 | } | 418 | | | 419 | 650 | ui -= 0x38000000; | 420 | 650 | ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); | 421 | 650 | return ret | (uint16_t) ui; | 422 | 898 | } | 423 | | | 424 | | // zero or flush to 0 | 425 | 12.3k | if (ui < 0x33000001) | 426 | 11.9k | { | 427 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 428 | | if (ui == 0) return ret; | 429 | | feraiseexcept (FE_UNDERFLOW); | 430 | | # endif | 431 | 11.9k | return ret; | 432 | 11.9k | } | 433 | | | 434 | | // produce a denormalized half | 435 | 386 | e = (ui >> 23); | 436 | 386 | shift = 0x7e - e; | 437 | 386 | m = 0x800000 | (ui & 0x7fffff); | 438 | 386 | r = m << (32 - shift); | 439 | 386 | ret |= (m >> shift); | 440 | 386 | if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; | 441 | 386 | return ret; | 442 | 12.3k | #endif | 443 | 12.3k | } |
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 | 375 | 10.1M | { | 376 | | #if defined(__F16C__) | 377 | | # ifdef _MSC_VER | 378 | | // msvc does not seem to have cvtsh_ss :( | 379 | | return _mm_extract_epi16 ( | 380 | | _mm_cvtps_ph ( | 381 | | _mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), | 382 | | 0); | 383 | | # else | 384 | | // preserve the fixed rounding mode to nearest | 385 | | return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); | 386 | | # endif | 387 | | #else | 388 | 10.1M | imath_half_uif_t v; | 389 | 10.1M | imath_half_bits_t ret; | 390 | 10.1M | uint32_t e, m, ui, r, shift; | 391 | | | 392 | 10.1M | v.f = f; | 393 | | | 394 | 10.1M | ui = (v.i & ~0x80000000); | 395 | 10.1M | ret = ((v.i >> 16) & 0x8000); | 396 | | | 397 | | // exponent large enough to result in a normal number, round and return | 398 | 10.1M | if (ui >= 0x38800000) | 399 | 1.11M | { | 400 | | // inf or nan | 401 | 1.11M | if (IMATH_UNLIKELY (ui >= 0x7f800000)) | 402 | 423k | { | 403 | 423k | ret |= 0x7c00; | 404 | 423k | if (ui == 0x7f800000) return ret; | 405 | 204k | m = (ui & 0x7fffff) >> 13; | 406 | | // make sure we have at least one bit after shift to preserve nan-ness | 407 | 204k | return ret | (uint16_t) m | (uint16_t) (m == 0); | 408 | 423k | } | 409 | | | 410 | | // too large, round to infinity | 411 | 694k | if (IMATH_UNLIKELY (ui > 0x477fefff)) | 412 | 0 | { | 413 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 414 | | feraiseexcept (FE_OVERFLOW); | 415 | | # endif | 416 | 0 | return ret | 0x7c00; | 417 | 0 | } | 418 | | | 419 | 694k | ui -= 0x38000000; | 420 | 694k | ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); | 421 | 694k | return ret | (uint16_t) ui; | 422 | 694k | } | 423 | | | 424 | | // zero or flush to 0 | 425 | 9.03M | if (ui < 0x33000001) | 426 | 8.91M | { | 427 | | # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS | 428 | | if (ui == 0) return ret; | 429 | | feraiseexcept (FE_UNDERFLOW); | 430 | | # endif | 431 | 8.91M | return ret; | 432 | 8.91M | } | 433 | | | 434 | | // produce a denormalized half | 435 | 124k | e = (ui >> 23); | 436 | 124k | shift = 0x7e - e; | 437 | 124k | m = 0x800000 | (ui & 0x7fffff); | 438 | 124k | r = m << (32 - shift); | 439 | 124k | ret |= (m >> shift); | 440 | 124k | if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; | 441 | 124k | return ret; | 442 | 9.03M | #endif | 443 | 9.03M | } |
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: internal_dwa.c:imath_float_to_half Unexecuted instantiation: coding.c:imath_float_to_half Unexecuted instantiation: half.cpp:imath_float_to_half(float) |
444 | | |
445 | | //////////////////////////////////////// |
446 | | |
447 | | #ifdef __cplusplus |
448 | | |
449 | | # include <iostream> |
450 | | |
451 | | IMATH_INTERNAL_NAMESPACE_HEADER_ENTER |
452 | | |
453 | | /// |
454 | | /// |
455 | | /// class half represents a 16-bit floating point number |
456 | | /// |
457 | | /// Type half can represent positive and negative numbers whose |
458 | | /// magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative |
459 | | /// error of 9.8e-4; numbers smaller than 6.1e-5 can be represented |
460 | | /// with an absolute error of 6.0e-8. All integers from -2048 to |
461 | | /// +2048 can be represented exactly. |
462 | | /// |
463 | | /// Type half behaves (almost) like the built-in C++ floating point |
464 | | /// types. In arithmetic expressions, half, float and double can be |
465 | | /// mixed freely. Here are a few examples: |
466 | | /// |
467 | | /// half a (3.5); |
468 | | /// float b (a + sqrt (a)); |
469 | | /// a += b; |
470 | | /// b += a; |
471 | | /// b = a + 7; |
472 | | /// |
473 | | /// Conversions from half to float are lossless; all half numbers |
474 | | /// are exactly representable as floats. |
475 | | /// |
476 | | /// Conversions from float to half may not preserve a float's value |
477 | | /// exactly. If a float is not representable as a half, then the |
478 | | /// float value is rounded to the nearest representable half. If a |
479 | | /// float value is exactly in the middle between the two closest |
480 | | /// representable half values, then the float value is rounded to |
481 | | /// the closest half whose least significant bit is zero. |
482 | | /// |
483 | | /// Overflows during float-to-half conversions cause arithmetic |
484 | | /// exceptions. An overflow occurs when the float value to be |
485 | | /// converted is too large to be represented as a half, or if the |
486 | | /// float value is an infinity or a NAN. |
487 | | /// |
488 | | /// The implementation of type half makes the following assumptions |
489 | | /// about the implementation of the built-in C++ types: |
490 | | /// |
491 | | /// * float is an IEEE 754 single-precision number |
492 | | /// * sizeof (float) == 4 |
493 | | /// * sizeof (unsigned int) == sizeof (float) |
494 | | /// * alignof (unsigned int) == alignof (float) |
495 | | /// * sizeof (uint16_t) == 2 |
496 | | /// |
497 | | |
498 | | class IMATH_EXPORT_TYPE half |
499 | | { |
500 | | public: |
501 | | /// A special tag that lets us initialize a half from the raw bits. |
502 | | enum IMATH_EXPORT_ENUM FromBitsTag |
503 | | { |
504 | | FromBits |
505 | | }; |
506 | | |
507 | | /// @{ |
508 | | /// @name Constructors |
509 | | |
510 | | /// Default construction provides no initialization (hence it is |
511 | | /// not constexpr). |
512 | | half () IMATH_NOEXCEPT = default; |
513 | | |
514 | | /// Construct from float |
515 | | half (float f) IMATH_NOEXCEPT; |
516 | | |
517 | | /// Construct from bit-vector |
518 | | constexpr half (FromBitsTag, uint16_t bits) IMATH_NOEXCEPT; |
519 | | |
520 | | /// Copy constructor |
521 | | constexpr half (const half&) IMATH_NOEXCEPT = default; |
522 | | |
523 | | /// Move constructor |
524 | | constexpr half (half&&) IMATH_NOEXCEPT = default; |
525 | | |
526 | | /// Destructor |
527 | | ~half () IMATH_NOEXCEPT = default; |
528 | | |
529 | | /// @} |
530 | | |
531 | | /// Conversion to float |
532 | | operator float () const IMATH_NOEXCEPT; |
533 | | |
534 | | /// @{ |
535 | | /// @name Basic Algebra |
536 | | |
537 | | /// Unary minus |
538 | | constexpr half operator- () const IMATH_NOEXCEPT; |
539 | | |
540 | | /// Assignment |
541 | | half& operator= (const half& h) IMATH_NOEXCEPT = default; |
542 | | |
543 | | /// Move assignment |
544 | | half& operator= (half&& h) IMATH_NOEXCEPT = default; |
545 | | |
546 | | /// Assignment from float |
547 | | half& operator= (float f) IMATH_NOEXCEPT; |
548 | | |
549 | | /// Addition assignment |
550 | | half& operator+= (half h) IMATH_NOEXCEPT; |
551 | | |
552 | | /// Addition assignment from float |
553 | | half& operator+= (float f) IMATH_NOEXCEPT; |
554 | | |
555 | | /// Subtraction assignment |
556 | | half& operator-= (half h) IMATH_NOEXCEPT; |
557 | | |
558 | | /// Subtraction assignment from float |
559 | | half& operator-= (float f) IMATH_NOEXCEPT; |
560 | | |
561 | | /// Multiplication assignment |
562 | | half& operator*= (half h) IMATH_NOEXCEPT; |
563 | | |
564 | | /// Multiplication assignment from float |
565 | | half& operator*= (float f) IMATH_NOEXCEPT; |
566 | | |
567 | | /// Division assignment |
568 | | half& operator/= (half h) IMATH_NOEXCEPT; |
569 | | |
570 | | /// Division assignment from float |
571 | | half& operator/= (float f) IMATH_NOEXCEPT; |
572 | | |
573 | | /// @} |
574 | | |
575 | | /// Round to n-bit precision (n should be between 0 and 10). |
576 | | /// After rounding, the significand's 10-n least significant |
577 | | /// bits will be zero. |
578 | | IMATH_CONSTEXPR14 half round (unsigned int n) const IMATH_NOEXCEPT; |
579 | | |
580 | | /// @{ |
581 | | /// @name Classification |
582 | | |
583 | | /// Return true if a normalized number, a denormalized number, or |
584 | | /// zero. |
585 | | constexpr bool isFinite () const IMATH_NOEXCEPT; |
586 | | |
587 | | /// Return true if a normalized number. |
588 | | constexpr bool isNormalized () const IMATH_NOEXCEPT; |
589 | | |
590 | | /// Return true if a denormalized number. |
591 | | constexpr bool isDenormalized () const IMATH_NOEXCEPT; |
592 | | |
593 | | /// Return true if zero. |
594 | | constexpr bool isZero () const IMATH_NOEXCEPT; |
595 | | |
596 | | /// Return true if NAN. |
597 | | constexpr bool isNan () const IMATH_NOEXCEPT; |
598 | | |
599 | | /// Return true if a positive or a negative infinity |
600 | | constexpr bool isInfinity () const IMATH_NOEXCEPT; |
601 | | |
602 | | /// Return true if the sign bit is set (negative) |
603 | | constexpr bool isNegative () const IMATH_NOEXCEPT; |
604 | | |
605 | | /// @} |
606 | | |
607 | | /// @{ |
608 | | /// @name Special values |
609 | | |
610 | | /// Return +infinity |
611 | | static constexpr half posInf () IMATH_NOEXCEPT; |
612 | | |
613 | | /// Return -infinity |
614 | | static constexpr half negInf () IMATH_NOEXCEPT; |
615 | | |
616 | | /// Returns a NAN with the bit pattern 0111111111111111 |
617 | | static constexpr half qNan () IMATH_NOEXCEPT; |
618 | | |
619 | | /// Return a NAN with the bit pattern 0111110111111111 |
620 | | static constexpr half sNan () IMATH_NOEXCEPT; |
621 | | |
622 | | /// @} |
623 | | |
624 | | /// @{ |
625 | | /// @name Access to the internal representation |
626 | | |
627 | | /// Return the bit pattern |
628 | | constexpr uint16_t bits () const IMATH_NOEXCEPT; |
629 | | |
630 | | /// Set the bit pattern |
631 | | IMATH_CONSTEXPR14 void setBits (uint16_t bits) IMATH_NOEXCEPT; |
632 | | |
633 | | /// @} |
634 | | |
635 | | public: |
636 | | static_assert ( |
637 | | sizeof (float) == sizeof (uint32_t), |
638 | | "Assumption about the size of floats correct"); |
639 | | using uif = imath_half_uif; |
640 | | |
641 | | private: |
642 | | constexpr uint16_t mantissa () const IMATH_NOEXCEPT; |
643 | | constexpr uint16_t exponent () const IMATH_NOEXCEPT; |
644 | | |
645 | | uint16_t _h; |
646 | | }; |
647 | | |
648 | | //---------------------------- |
649 | | // Half-from-float constructor |
650 | | //---------------------------- |
651 | | |
652 | | inline half::half (float f) IMATH_NOEXCEPT : _h (imath_float_to_half (f)) |
653 | 10.1M | {} |
654 | | |
655 | | //------------------------------------------ |
656 | | // Half from raw bits constructor |
657 | | //------------------------------------------ |
658 | | |
659 | | inline constexpr half::half (FromBitsTag, uint16_t bits) IMATH_NOEXCEPT |
660 | | : _h (bits) |
661 | 15.3M | {} |
662 | | |
663 | | //------------------------- |
664 | | // Half-to-float conversion |
665 | | //------------------------- |
666 | | |
667 | | inline half::operator float () const IMATH_NOEXCEPT |
668 | 51.6M | { |
669 | 51.6M | return imath_half_to_float (_h); |
670 | 51.6M | } |
671 | | |
672 | | //------------------------- |
673 | | // Round to n-bit precision |
674 | | //------------------------- |
675 | | |
676 | | inline IMATH_CONSTEXPR14 half |
677 | | half::round (unsigned int n) const IMATH_NOEXCEPT |
678 | 0 | { |
679 | | // |
680 | | // Parameter check. |
681 | | // |
682 | |
|
683 | 0 | if (n >= 10) return *this; |
684 | | |
685 | | // |
686 | | // Disassemble h into the sign, s, |
687 | | // and the combined exponent and significand, e. |
688 | | // |
689 | | |
690 | 0 | uint16_t s = _h & 0x8000; |
691 | 0 | uint16_t e = _h & 0x7fff; |
692 | | |
693 | | // |
694 | | // Round the exponent and significand to the nearest value |
695 | | // where ones occur only in the (10-n) most significant bits. |
696 | | // Note that the exponent adjusts automatically if rounding |
697 | | // up causes the significand to overflow. |
698 | | // |
699 | |
|
700 | 0 | e >>= 9 - n; |
701 | 0 | e += e & 1; |
702 | 0 | e <<= 9 - n; |
703 | | |
704 | | // |
705 | | // Check for exponent overflow. |
706 | | // |
707 | |
|
708 | 0 | if (e >= 0x7c00) |
709 | 0 | { |
710 | | // |
711 | | // Overflow occurred -- truncate instead of rounding. |
712 | | // |
713 | |
|
714 | 0 | e = _h; |
715 | 0 | e >>= 10 - n; |
716 | 0 | e <<= 10 - n; |
717 | 0 | } |
718 | | |
719 | | // |
720 | | // Put the original sign bit back. |
721 | | // |
722 | |
|
723 | 0 | half h (FromBits, s | e); |
724 | |
|
725 | 0 | return h; |
726 | 0 | } |
727 | | |
728 | | //----------------------- |
729 | | // Other inline functions |
730 | | //----------------------- |
731 | | |
732 | | inline constexpr half |
733 | | half::operator- () const IMATH_NOEXCEPT |
734 | 0 | { |
735 | 0 | return half (FromBits, bits () ^ 0x8000); |
736 | 0 | } |
737 | | |
738 | | inline half& |
739 | | half::operator= (float f) IMATH_NOEXCEPT |
740 | 390 | { |
741 | 390 | *this = half (f); |
742 | 390 | return *this; |
743 | 390 | } |
744 | | |
745 | | inline half& |
746 | | half::operator+= (half h) IMATH_NOEXCEPT |
747 | 0 | { |
748 | 0 | *this = half (float (*this) + float (h)); |
749 | 0 | return *this; |
750 | 0 | } |
751 | | |
752 | | inline half& |
753 | | half::operator+= (float f) IMATH_NOEXCEPT |
754 | 0 | { |
755 | 0 | *this = half (float (*this) + f); |
756 | 0 | return *this; |
757 | 0 | } |
758 | | |
759 | | inline half& |
760 | | half::operator-= (half h) IMATH_NOEXCEPT |
761 | 0 | { |
762 | 0 | *this = half (float (*this) - float (h)); |
763 | 0 | return *this; |
764 | 0 | } |
765 | | |
766 | | inline half& |
767 | | half::operator-= (float f) IMATH_NOEXCEPT |
768 | 0 | { |
769 | 0 | *this = half (float (*this) - f); |
770 | 0 | return *this; |
771 | 0 | } |
772 | | |
773 | | inline half& |
774 | | half::operator*= (half h) IMATH_NOEXCEPT |
775 | 0 | { |
776 | 0 | *this = half (float (*this) * float (h)); |
777 | 0 | return *this; |
778 | 0 | } |
779 | | |
780 | | inline half& |
781 | | half::operator*= (float f) IMATH_NOEXCEPT |
782 | 0 | { |
783 | 0 | *this = half (float (*this) * f); |
784 | 0 | return *this; |
785 | 0 | } |
786 | | |
787 | | inline half& |
788 | | half::operator/= (half h) IMATH_NOEXCEPT |
789 | 0 | { |
790 | 0 | *this = half (float (*this) / float (h)); |
791 | 0 | return *this; |
792 | 0 | } |
793 | | |
794 | | inline half& |
795 | | half::operator/= (float f) IMATH_NOEXCEPT |
796 | 0 | { |
797 | 0 | *this = half (float (*this) / f); |
798 | 0 | return *this; |
799 | 0 | } |
800 | | |
801 | | inline constexpr uint16_t |
802 | | half::mantissa () const IMATH_NOEXCEPT |
803 | 904k | { |
804 | 904k | return _h & 0x3ff; |
805 | 904k | } |
806 | | |
807 | | inline constexpr uint16_t |
808 | | half::exponent () const IMATH_NOEXCEPT |
809 | 28.2M | { |
810 | 28.2M | return (_h >> 10) & 0x001f; |
811 | 28.2M | } |
812 | | |
813 | | inline constexpr bool |
814 | | half::isFinite () const IMATH_NOEXCEPT |
815 | 0 | { |
816 | 0 | return exponent () < 31; |
817 | 0 | } |
818 | | |
819 | | inline constexpr bool |
820 | | half::isNormalized () const IMATH_NOEXCEPT |
821 | 0 | { |
822 | 0 | return exponent () > 0 && exponent () < 31; |
823 | 0 | } |
824 | | |
825 | | inline constexpr bool |
826 | | half::isDenormalized () const IMATH_NOEXCEPT |
827 | 0 | { |
828 | 0 | return exponent () == 0 && mantissa () != 0; |
829 | 0 | } |
830 | | |
831 | | inline constexpr bool |
832 | | half::isZero () const IMATH_NOEXCEPT |
833 | 0 | { |
834 | 0 | return (_h & 0x7fff) == 0; |
835 | 0 | } |
836 | | |
837 | | inline constexpr bool |
838 | | half::isNan () const IMATH_NOEXCEPT |
839 | 14.2M | { |
840 | 14.2M | return exponent () == 31 && mantissa () != 0; |
841 | 14.2M | } |
842 | | |
843 | | inline constexpr bool |
844 | | half::isInfinity () const IMATH_NOEXCEPT |
845 | 13.9M | { |
846 | 13.9M | return exponent () == 31 && mantissa () == 0; |
847 | 13.9M | } |
848 | | |
849 | | inline constexpr bool |
850 | | half::isNegative () const IMATH_NOEXCEPT |
851 | 15.3M | { |
852 | 15.3M | return (_h & 0x8000) != 0; |
853 | 15.3M | } |
854 | | |
855 | | inline constexpr half |
856 | | half::posInf () IMATH_NOEXCEPT |
857 | 416k | { |
858 | 416k | return half (FromBits, 0x7c00); |
859 | 416k | } |
860 | | |
861 | | inline constexpr half |
862 | | half::negInf () IMATH_NOEXCEPT |
863 | 30.0k | { |
864 | 30.0k | return half (FromBits, 0xfc00); |
865 | 30.0k | } |
866 | | |
867 | | inline constexpr half |
868 | | half::qNan () IMATH_NOEXCEPT |
869 | 0 | { |
870 | 0 | return half (FromBits, 0x7fff); |
871 | 0 | } |
872 | | |
873 | | inline constexpr half |
874 | | half::sNan () IMATH_NOEXCEPT |
875 | 0 | { |
876 | 0 | return half (FromBits, 0x7dff); |
877 | 0 | } |
878 | | |
879 | | inline constexpr uint16_t |
880 | | half::bits () const IMATH_NOEXCEPT |
881 | 22.2k | { |
882 | 22.2k | return _h; |
883 | 22.2k | } |
884 | | |
885 | | inline IMATH_CONSTEXPR14 void |
886 | | half::setBits (uint16_t bits) IMATH_NOEXCEPT |
887 | 25.3M | { |
888 | 25.3M | _h = bits; |
889 | 25.3M | } |
890 | | |
891 | | IMATH_INTERNAL_NAMESPACE_HEADER_EXIT |
892 | | |
893 | | /// Output h to os, formatted as a float |
894 | | IMATH_EXPORT std::ostream& |
895 | | operator<< (std::ostream& os, IMATH_INTERNAL_NAMESPACE::half h); |
896 | | |
897 | | /// Input h from is |
898 | | IMATH_EXPORT std::istream& |
899 | | operator>> (std::istream& is, IMATH_INTERNAL_NAMESPACE::half& h); |
900 | | |
901 | | #include <limits> |
902 | | |
903 | | namespace std |
904 | | { |
905 | | |
906 | | template <> class numeric_limits<IMATH_INTERNAL_NAMESPACE::half> |
907 | | { |
908 | | public: |
909 | | static const bool is_specialized = true; |
910 | | |
911 | | static constexpr IMATH_INTERNAL_NAMESPACE::half min () IMATH_NOEXCEPT |
912 | 0 | { |
913 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x0400); /*HALF_MIN*/ |
914 | 0 | } |
915 | | static constexpr IMATH_INTERNAL_NAMESPACE::half max () IMATH_NOEXCEPT |
916 | 10.1M | { |
917 | 10.1M | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7bff); /*HALF_MAX*/ |
918 | 10.1M | } |
919 | | static constexpr IMATH_INTERNAL_NAMESPACE::half lowest () |
920 | 4.77M | { |
921 | 4.77M | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0xfbff); /* -HALF_MAX */ |
922 | 4.77M | } |
923 | | |
924 | | static constexpr int digits = HALF_MANT_DIG; |
925 | | static constexpr int digits10 = HALF_DIG; |
926 | | static constexpr int max_digits10 = HALF_DECIMAL_DIG; |
927 | | static constexpr bool is_signed = true; |
928 | | static constexpr bool is_integer = false; |
929 | | static constexpr bool is_exact = false; |
930 | | static constexpr int radix = HALF_RADIX; |
931 | | static constexpr IMATH_INTERNAL_NAMESPACE::half epsilon () IMATH_NOEXCEPT |
932 | 0 | { |
933 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x1400); /*HALF_EPSILON*/ |
934 | 0 | } |
935 | | static constexpr IMATH_INTERNAL_NAMESPACE::half round_error () IMATH_NOEXCEPT |
936 | 0 | { |
937 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x3800); /*0.5*/ |
938 | 0 | } |
939 | | |
940 | | static constexpr int min_exponent = HALF_DENORM_MIN_EXP; |
941 | | static constexpr int min_exponent10 = HALF_DENORM_MIN_10_EXP; |
942 | | static constexpr int max_exponent = HALF_MAX_EXP; |
943 | | static constexpr int max_exponent10 = HALF_MAX_10_EXP; |
944 | | |
945 | | static constexpr bool has_infinity = true; |
946 | | static constexpr bool has_quiet_NaN = true; |
947 | | static constexpr bool has_signaling_NaN = true; |
948 | | static constexpr float_denorm_style has_denorm = denorm_present; |
949 | | static constexpr bool has_denorm_loss = false; |
950 | | static constexpr IMATH_INTERNAL_NAMESPACE::half infinity () IMATH_NOEXCEPT |
951 | 0 | { |
952 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7c00); /*half::posInf()*/ |
953 | 0 | } |
954 | | static constexpr IMATH_INTERNAL_NAMESPACE::half quiet_NaN () IMATH_NOEXCEPT |
955 | 0 | { |
956 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7fff); /*half::qNan()*/ |
957 | 0 | } |
958 | | static constexpr IMATH_INTERNAL_NAMESPACE::half signaling_NaN () IMATH_NOEXCEPT |
959 | 0 | { |
960 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x7dff); /*half::sNan()*/ |
961 | 0 | } |
962 | | static constexpr IMATH_INTERNAL_NAMESPACE::half denorm_min () IMATH_NOEXCEPT |
963 | 0 | { |
964 | 0 | return IMATH_INTERNAL_NAMESPACE::half (IMATH_INTERNAL_NAMESPACE::half::FromBits, 0x0001); /*HALF_DENORM_MIN*/ |
965 | 0 | } |
966 | | |
967 | | static constexpr bool is_iec559 = false; |
968 | | static constexpr bool is_bounded = false; |
969 | | static constexpr bool is_modulo = false; |
970 | | |
971 | | static constexpr bool traps = true; |
972 | | static constexpr bool tinyness_before = false; |
973 | | static constexpr float_round_style round_style = round_to_nearest; |
974 | | }; |
975 | | |
976 | | } // namespace std |
977 | | |
978 | | //---------- |
979 | | // Debugging |
980 | | //---------- |
981 | | |
982 | | IMATH_EXPORT void |
983 | | printBits (std::ostream& os, IMATH_INTERNAL_NAMESPACE::half h); |
984 | | IMATH_EXPORT void printBits (std::ostream& os, float f); |
985 | | IMATH_EXPORT void printBits (char c[19], IMATH_INTERNAL_NAMESPACE::half h); |
986 | | IMATH_EXPORT void printBits (char c[35], float f); |
987 | | |
988 | | # if !defined(__CUDACC__) && !defined(__CUDA_FP16_HPP__) |
989 | | using half = IMATH_INTERNAL_NAMESPACE::half; |
990 | | # else |
991 | | # include <cuda_fp16.h> |
992 | | # endif |
993 | | |
994 | | #endif // __cplusplus |
995 | | |
996 | | #endif // IMATH_HALF_H_ |