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