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