HDK
Half.h
Go to the documentation of this file.
1 //
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.
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
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
197 namespace openvdb {
199 namespace OPENVDB_VERSION_NAME {
200 namespace 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
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;
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
284 #endif
285
286 #if !defined(IMATH_HALF_NO_LOOKUP_TABLE)
287 #if defined(__cplusplus)
288 extern "C"
289 #else
290 extern
291 #endif
293 #endif
294
295 ///
296 /// Convert half to float
297 ///
298
299 static inline float
300 imath_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
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
381 static inline imath_half_bits_t
382 imath_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
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
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
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  /// @{
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");
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
656 inline 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
681 inline constexpr half
682 half::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
738 inline constexpr half
740 {
741  return half (FromBits, bits() ^ 0x8000);
742 }
743
744 inline half&
745 half::operator= (float f) noexcept
746 {
747  *this = half (f);
748  return *this;
749 }
750
751 inline half&
753 {
754  *this = half (float (*this) + float (h));
755  return *this;
756 }
757
758 inline half&
759 half::operator+= (float f) noexcept
760 {
761  *this = half (float (*this) + f);
762  return *this;
763 }
764
765 inline half&
767 {
768  *this = half (float (*this) - float (h));
769  return *this;
770 }
771
772 inline half&
773 half::operator-= (float f) noexcept
774 {
775  *this = half (float (*this) - f);
776  return *this;
777 }
778
779 inline half&
781 {
782  *this = half (float (*this) * float (h));
783  return *this;
784 }
785
786 inline half&
787 half::operator*= (float f) noexcept
788 {
789  *this = half (float (*this) * f);
790  return *this;
791 }
792
793 inline half&
795 {
796  *this = half (float (*this) / float (h));
797  return *this;
798 }
799
800 inline half&
801 half::operator/= (float f) noexcept
802 {
803  *this = half (float (*this) / f);
804  return *this;
805 }
806
807 inline constexpr uint16_t
808 half::mantissa() const noexcept
809 {
810  return _h & 0x3ff;
811 }
812
813 inline constexpr uint16_t
814 half::exponent() const noexcept
815 {
816  return (_h >> 10) & 0x001f;
817 }
818
819 inline constexpr bool
821 {
822  return exponent() < 31;
823 }
824
825 inline constexpr bool
827 {
828  return exponent() > 0 && exponent() < 31;
829 }
830
831 inline constexpr bool
833 {
834  return exponent() == 0 && mantissa() != 0;
835 }
836
837 inline constexpr bool
838 half::isZero() const noexcept
839 {
840  return (_h & 0x7fff) == 0;
841 }
842
843 inline constexpr bool
844 half::isNan() const noexcept
845 {
846  return exponent() == 31 && mantissa() != 0;
847 }
848
849 inline constexpr bool
851 {
852  return exponent() == 31 && mantissa() == 0;
853 }
854
855 inline constexpr bool
857 {
858  return (_h & 0x8000) != 0;
859 }
860
861 inline constexpr half
862 half::posInf() noexcept
863 {
864  return half (FromBits, 0x7c00);
865 }
866
867 inline constexpr half
868 half::negInf() noexcept
869 {
870  return half (FromBits, 0xfc00);
871 }
872
873 inline constexpr half
874 half::qNan() noexcept
875 {
876  return half (FromBits, 0x7fff);
877 }
878
879 inline constexpr half
880 half::sNan() noexcept
881 {
882  return half (FromBits, 0x7dff);
883 }
884
885 inline constexpr uint16_t
886 half::bits() const noexcept
887 {
888  return _h;
889 }
890
891 inline constexpr void
892 half::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
919 namespace std
920 {
921
922 template <> class numeric_limits<openvdb::math::internal::half>
923 {
924 public:
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  }
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;
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
995
996 #endif // OPENVDB_MATH_HALF_HAS_BEEN_INCLUDED
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition: Platform.h:234
half & operator*=(half h) noexcept
Multiplication assignment.
Definition: Half.h:780
constexpr auto digits10() FMT_NOEXCEPT-> int
Definition: format.h:988
static constexpr half sNan() noexcept
Return a NAN with the bit pattern 0111110111111111.
Definition: Half.h:880
OIIO_FORCEINLINE const vint4 & operator/=(vint4 &a, const vint4 &b)
Definition: simd.h:4438
#define OPENVDB_UNLIKELY(x)
Definition: Platform.h:98
constexpr bool isNormalized() const noexcept
Return true if a normalized number.
Definition: Half.h:826
imath_half_bits_t half
if we're in a C-only context, alias the half bits type to half
Definition: half.h:266
static constexpr openvdb::math::internal::half lowest()
Definition: Half.h:935
half & operator=(const half &h) noexcept=default
Assignment.
const GLdouble * v
Definition: glcorearb.h:837
OPENVDB_API void printBits(std::ostream &os, half h)
IMATH_EXPORT const imath_half_uif_t * imath_half_to_float_table
a type for both C-only programs and C++ to use the same utilities
Definition: Half.h:272
Vec3< typename promote< T, Coord::ValueType >::type > operator-(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be subtracted from a Vec3.
Definition: Coord.h:553
OPENVDB_API std::istream & operator>>(std::istream &is, half &h)
Input h from is.
bool_constant< is_integral< T >::value &&!std::is_same< T, bool >::value &&!std::is_same< T, char >::value &&!std::is_same< T, wchar_t >::value > is_integer
Definition: format.h:2010
half & operator/=(half h) noexcept
Division assignment.
Definition: Half.h:794
a type for both C-only programs and C++ to use the same utilities
Definition: half.h:255
static constexpr openvdb::math::internal::half infinity() noexcept
Definition: Half.h:966
half & operator+=(half h) noexcept
Definition: Half.h:752
GLdouble s
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:239
static constexpr openvdb::math::internal::half round_error() noexcept
Definition: Half.h:951
uint16_t imath_half_bits_t
a type for both C-only programs and C++ to use the same utilities
Definition: half.h:262
float f
Definition: half.h:258
imath_half_bits_t half
if we're in a C-only context, alias the half bits type to half
Definition: Half.h:283
#define VDB_HALF_MAX_EXP
Definition: Half.h:263
std::integral_constant< bool, std::numeric_limits< T >::is_signed||std::is_same< T, int128_t >::value > is_signed
Definition: format.h:821
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition: Math.h:367
half & operator-=(half h) noexcept
Subtraction assignment.
Definition: Half.h:766
uint32_t i
Definition: half.h:257
constexpr bool isInfinity() const noexcept
Return true if a positive or a negative infinity.
Definition: Half.h:850
GLdouble n
Definition: glcorearb.h:2008
GLfloat f
Definition: glcorearb.h:1926
static constexpr half negInf() noexcept
Return -infinity.
Definition: Half.h:868
#define OPENVDB_API
Definition: Platform.h:280
#define VDBB_HALF_DENORM_MIN_10_EXP
Definition: Half.h:266
#define VDB_HALF_MAX_10_EXP
Definition: Half.h:269
constexpr bool isNegative() const noexcept
Return true if the sign bit is set (negative)
Definition: Half.h:856
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4369
#define VDB_HALF_DECIMAL_DIG
Definition: Half.h:255
static constexpr openvdb::math::internal::half quiet_NaN() noexcept
Definition: Half.h:970
Base of the exponent.
Definition: Half.h:257
static constexpr openvdb::math::internal::half epsilon() noexcept
Definition: Half.h:947
constexpr bool isZero() const noexcept
Return true if zero.
Definition: Half.h:838
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
Definition: Math.h:395
#define VDB_HALF_DIG
Definition: Half.h:250
static constexpr openvdb::math::internal::half denorm_min() noexcept
Definition: Half.h:978
vfloat4 round(const vfloat4 &a)
Definition: simd.h:7436
static constexpr half qNan() noexcept
Returns a NAN with the bit pattern 0111111111111111.
Definition: Half.h:874
union openvdb::OPENVDB_VERSION_NAME::math::internal::imath_half_uif imath_half_uif_t
a type for both C-only programs and C++ to use the same utilities
IMATH_HOSTDEVICE const Vec2< S > & operator*=(Vec2< S > &v, const Matrix22< T > &m) IMATH_NOEXCEPT
Vector-matrix multiplication: v *= m.
Definition: ImathMatrix.h:4660
#define VDBB_HALF_DENORM_MIN_EXP
Definition: Half.h:260
constexpr void setBits(uint16_t bits) noexcept
Set the bit pattern.
Definition: Half.h:892
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
Library and file format version numbers.
constexpr uint16_t bits() const noexcept
Return the bit pattern.
Definition: Half.h:886
#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
static constexpr half posInf() noexcept
Return +infinity.
Definition: Half.h:862
#define VDB_HALF_MANT_DIG
Number of digits in mantissa (significand + hidden leading 1)
Definition: Half.h:246
constexpr bool isNan() const noexcept
Return true if NAN.
Definition: Half.h:844
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4392
constexpr half operator-() const noexcept
Unary minus.
Definition: Half.h:739
static constexpr openvdb::math::internal::half min() noexcept
Definition: Half.h:927
GLboolean r
Definition: glcorearb.h:1222
#define const
Definition: zconf.h:214
static constexpr openvdb::math::internal::half signaling_NaN() noexcept
Definition: Half.h:974
#define OPENVDB_LIKELY(x)
Definition: Platform.h:97
constexpr bool isFinite() const noexcept
Definition: Half.h:820
constexpr half round(unsigned int n) const noexcept
Definition: Half.h:682
uint16_t imath_half_bits_t
a type for both C-only programs and C++ to use the same utilities
Definition: Half.h:279
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:119
OPENVDB_API std::ostream & operator<<(std::ostream &os, half h)
Output h to os, formatted as a float.
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:337
static constexpr openvdb::math::internal::half max() noexcept
Definition: Half.h:931
bool isFinite(const float x)
Return true if x is finite.
Definition: Math.h:375
constexpr bool isDenormalized() const noexcept
Return true if a denormalized number.
Definition: Half.h:832