Coverage Report

Created: 2024-07-27 06:04

/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_