OpenVDB: openvdb/math/Half.h Source File

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