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