OpenVDB: openvdb/math/Half.h Source File

OpenVDB 13.0.0

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