All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ilmbase_half.h
1 //
3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // * Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
34 
35 // Primary authors:
36 // Florian Kainz <kainz@ilm.com>
37 // Rod Bogart <rgb@ilm.com>
38 
39 //---------------------------------------------------------------------------
40 //
41 // half -- a 16-bit floating point number class:
42 //
43 // Type half can represent positive and negative numbers whose
44 // magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative
45 // error of 9.8e-4; numbers smaller than 6.1e-5 can be represented
46 // with an absolute error of 6.0e-8. All integers from -2048 to
47 // +2048 can be represented exactly.
48 //
49 // Type half behaves (almost) like the built-in C++ floating point
50 // types. In arithmetic expressions, half, float and double can be
51 // mixed freely. Here are a few examples:
52 //
53 // half a (3.5);
54 // float b (a + sqrt (a));
55 // a += b;
56 // b += a;
57 // b = a + 7;
58 //
59 // Conversions from half to float are lossless; all half numbers
60 // are exactly representable as floats.
61 //
62 // Conversions from float to half may not preserve a float's value
63 // exactly. If a float is not representable as a half, then the
64 // float value is rounded to the nearest representable half. If a
65 // float value is exactly in the middle between the two closest
66 // representable half values, then the float value is rounded to
67 // the closest half whose least significant bit is zero.
68 //
69 // Overflows during float-to-half conversions cause arithmetic
70 // exceptions. An overflow occurs when the float value to be
71 // converted is too large to be represented as a half, or if the
72 // float value is an infinity or a NAN.
73 //
74 // The implementation of type half makes the following assumptions
75 // about the implementation of the built-in C++ types:
76 //
77 // float is an IEEE 754 single-precision number
78 // sizeof (float) == 4
79 // sizeof (unsigned int) == sizeof (float)
80 // alignof (unsigned int) == alignof (float)
81 // sizeof (unsigned short) == 2
82 //
83 //---------------------------------------------------------------------------
84 
85 #ifndef PXR_HALF_H
86 #define PXR_HALF_H
87 
88 #include "pxr/pxr.h"
89 #include "pxr/base/gf/api.h"
90 
91 #include <iosfwd>
92 
93 PXR_NAMESPACE_OPEN_SCOPE
94 
95 namespace pxr_half {
96 
97 class half
98 {
99  public:
100 
101  //-------------
102  // Constructors
103  //-------------
104 
105  half () = default; // no initialization
106  half (float f);
107 
108  constexpr half (const half& h) = default;
109 
110 
111  //--------------------
112  // Conversion to float
113  //--------------------
114 
115  operator float () const;
116 
117 
118  //------------
119  // Unary minus
120  //------------
121 
122  half operator - () const;
123 
124 
125  //-----------
126  // Assignment
127  //-----------
128 
129  half & operator = (const half &) = default;
130  half & operator = (float f);
131 
132  half & operator += (half h);
133  half & operator += (float f);
134 
135  half & operator -= (half h);
136  half & operator -= (float f);
137 
138  half & operator *= (half h);
139  half & operator *= (float f);
140 
141  half & operator /= (half h);
142  half & operator /= (float f);
143 
144 
145  //---------------------------------------------------------
146  // Round to n-bit precision (n should be between 0 and 10).
147  // After rounding, the significand's 10-n least significant
148  // bits will be zero.
149  //---------------------------------------------------------
150 
151  half round (unsigned int n) const;
152 
153 
154  //--------------------------------------------------------------------
155  // Classification:
156  //
157  // h.isFinite() returns true if h is a normalized number,
158  // a denormalized number or zero
159  //
160  // h.isNormalized() returns true if h is a normalized number
161  //
162  // h.isDenormalized() returns true if h is a denormalized number
163  //
164  // h.isZero() returns true if h is zero
165  //
166  // h.isNan() returns true if h is a NAN
167  //
168  // h.isInfinity() returns true if h is a positive
169  // or a negative infinity
170  //
171  // h.isNegative() returns true if the sign bit of h
172  // is set (negative)
173  //--------------------------------------------------------------------
174 
175  bool isFinite () const;
176  bool isNormalized () const;
177  bool isDenormalized () const;
178  bool isZero () const;
179  bool isNan () const;
180  bool isInfinity () const;
181  bool isNegative () const;
182 
183 
184  //--------------------------------------------
185  // Special values
186  //
187  // posInf() returns +infinity
188  //
189  // negInf() returns -infinity
190  //
191  // qNan() returns a NAN with the bit
192  // pattern 0111111111111111
193  //
194  // sNan() returns a NAN with the bit
195  // pattern 0111110111111111
196  //--------------------------------------------
197 
198  static half posInf ();
199  static half negInf ();
200  static half qNan ();
201  static half sNan ();
202 
203 
204  //--------------------------------------
205  // Access to the internal representation
206  //--------------------------------------
207 
208  GF_API unsigned short bits () const;
209  GF_API void setBits (unsigned short bits);
210 
211 
212  public:
213 
214  union uif
215  {
216  unsigned int i;
217  float f;
218  };
219 
220  private:
221 
222  GF_API static short convert (int i);
223  GF_API static float overflow ();
224 
225  unsigned short _h;
226 
227  GF_API static const uif _toFloat[1 << 16];
228  GF_API static const unsigned short _eLut[1 << 9];
229 };
230 
231 
232 
233 //-----------
234 // Stream I/O
235 //-----------
236 
237 GF_API std::ostream & operator << (std::ostream &os, half h);
238 GF_API std::istream & operator >> (std::istream &is, half &h);
239 
240 
241 //----------
242 // Debugging
243 //----------
244 
245 GF_API void printBits (std::ostream &os, half h);
246 GF_API void printBits (std::ostream &os, float f);
247 GF_API void printBits (char c[19], half h);
248 GF_API void printBits (char c[35], float f);
249 
250 
251 //-------------------------------------------------------------------------
252 // Limits
253 //
254 // Visual C++ will complain if HALF_MIN, HALF_NRM_MIN etc. are not float
255 // constants, but at least one other compiler (gcc 2.96) produces incorrect
256 // results if they are.
257 //-------------------------------------------------------------------------
258 
259 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
260 
261  #define HALF_MIN 5.96046448e-08f // Smallest positive half
262 
263  #define HALF_NRM_MIN 6.10351562e-05f // Smallest positive normalized half
264 
265  #define HALF_MAX 65504.0f // Largest positive half
266 
267  #define HALF_EPSILON 0.00097656f // Smallest positive e for which
268  // half (1.0 + e) != half (1.0)
269 #else
270 
271  #define HALF_MIN 5.96046448e-08 // Smallest positive half
272 
273  #define HALF_NRM_MIN 6.10351562e-05 // Smallest positive normalized half
274 
275  #define HALF_MAX 65504.0 // Largest positive half
276 
277  #define HALF_EPSILON 0.00097656 // Smallest positive e for which
278  // half (1.0 + e) != half (1.0)
279 #endif
280 
281 
282 #define HALF_MANT_DIG 11 // Number of digits in mantissa
283  // (significand + hidden leading 1)
284 
285 #define HALF_DIG 2 // Number of base 10 digits that
286  // can be represented without change
287 
288 #define HALF_DECIMAL_DIG 5 // Number of base-10 digits that are
289  // necessary to uniquely represent all
290  // distinct values
291 
292 #define HALF_RADIX 2 // Base of the exponent
293 
294 #define HALF_MIN_EXP -13 // Minimum negative integer such that
295  // HALF_RADIX raised to the power of
296  // one less than that integer is a
297  // normalized half
298 
299 #define HALF_MAX_EXP 16 // Maximum positive integer such that
300  // HALF_RADIX raised to the power of
301  // one less than that integer is a
302  // normalized half
303 
304 #define HALF_MIN_10_EXP -4 // Minimum positive integer such
305  // that 10 raised to that power is
306  // a normalized half
307 
308 #define HALF_MAX_10_EXP 4 // Maximum positive integer such
309  // that 10 raised to that power is
310  // a normalized half
311 
312 
313 //---------------------------------------------------------------------------
314 //
315 // Implementation --
316 //
317 // Representation of a float:
318 //
319 // We assume that a float, f, is an IEEE 754 single-precision
320 // floating point number, whose bits are arranged as follows:
321 //
322 // 31 (msb)
323 // |
324 // | 30 23
325 // | | |
326 // | | | 22 0 (lsb)
327 // | | | | |
328 // X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
329 //
330 // s e m
331 //
332 // S is the sign-bit, e is the exponent and m is the significand.
333 //
334 // If e is between 1 and 254, f is a normalized number:
335 //
336 // s e-127
337 // f = (-1) * 2 * 1.m
338 //
339 // If e is 0, and m is not zero, f is a denormalized number:
340 //
341 // s -126
342 // f = (-1) * 2 * 0.m
343 //
344 // If e and m are both zero, f is zero:
345 //
346 // f = 0.0
347 //
348 // If e is 255, f is an "infinity" or "not a number" (NAN),
349 // depending on whether m is zero or not.
350 //
351 // Examples:
352 //
353 // 0 00000000 00000000000000000000000 = 0.0
354 // 0 01111110 00000000000000000000000 = 0.5
355 // 0 01111111 00000000000000000000000 = 1.0
356 // 0 10000000 00000000000000000000000 = 2.0
357 // 0 10000000 10000000000000000000000 = 3.0
358 // 1 10000101 11110000010000000000000 = -124.0625
359 // 0 11111111 00000000000000000000000 = +infinity
360 // 1 11111111 00000000000000000000000 = -infinity
361 // 0 11111111 10000000000000000000000 = NAN
362 // 1 11111111 11111111111111111111111 = NAN
363 //
364 // Representation of a half:
365 //
366 // Here is the bit-layout for a half number, h:
367 //
368 // 15 (msb)
369 // |
370 // | 14 10
371 // | | |
372 // | | | 9 0 (lsb)
373 // | | | | |
374 // X XXXXX XXXXXXXXXX
375 //
376 // s e m
377 //
378 // S is the sign-bit, e is the exponent and m is the significand.
379 //
380 // If e is between 1 and 30, h is a normalized number:
381 //
382 // s e-15
383 // h = (-1) * 2 * 1.m
384 //
385 // If e is 0, and m is not zero, h is a denormalized number:
386 //
387 // S -14
388 // h = (-1) * 2 * 0.m
389 //
390 // If e and m are both zero, h is zero:
391 //
392 // h = 0.0
393 //
394 // If e is 31, h is an "infinity" or "not a number" (NAN),
395 // depending on whether m is zero or not.
396 //
397 // Examples:
398 //
399 // 0 00000 0000000000 = 0.0
400 // 0 01110 0000000000 = 0.5
401 // 0 01111 0000000000 = 1.0
402 // 0 10000 0000000000 = 2.0
403 // 0 10000 1000000000 = 3.0
404 // 1 10101 1111000001 = -124.0625
405 // 0 11111 0000000000 = +infinity
406 // 1 11111 0000000000 = -infinity
407 // 0 11111 1000000000 = NAN
408 // 1 11111 1111111111 = NAN
409 //
410 // Conversion:
411 //
412 // Converting from a float to a half requires some non-trivial bit
413 // manipulations. In some cases, this makes conversion relatively
414 // slow, but the most common case is accelerated via table lookups.
415 //
416 // Converting back from a half to a float is easier because we don't
417 // have to do any rounding. In addition, there are only 65536
418 // different half numbers; we can convert each of those numbers once
419 // and store the results in a table. Later, all conversions can be
420 // done using only simple table lookups.
421 //
422 //---------------------------------------------------------------------------
423 
424 
425 //----------------------------
426 // Half-from-float constructor
427 //----------------------------
428 
429 inline
430 half::half (float f)
431 {
432  uif x;
433 
434  x.f = f;
435 
436  if (f == 0)
437  {
438  //
439  // Common special case - zero.
440  // Preserve the zero's sign bit.
441  //
442 
443  _h = (x.i >> 16);
444  }
445  else
446  {
447  //
448  // We extract the combined sign and exponent, e, from our
449  // floating-point number, f. Then we convert e to the sign
450  // and exponent of the half number via a table lookup.
451  //
452  // For the most common case, where a normalized half is produced,
453  // the table lookup returns a non-zero value; in this case, all
454  // we have to do is round f's significand to 10 bits and combine
455  // the result with e.
456  //
457  // For all other cases (overflow, zeroes, denormalized numbers
458  // resulting from underflow, infinities and NANs), the table
459  // lookup returns zero, and we call a longer, non-inline function
460  // to do the float-to-half conversion.
461  //
462 
463  int e = (x.i >> 23) & 0x000001ff;
464 
465  e = _eLut[e];
466 
467  if (e)
468  {
469  //
470  // Simple case - round the significand, m, to 10
471  // bits and combine it with the sign and exponent.
472  //
473 
474  int m = x.i & 0x007fffff;
475  _h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13);
476  }
477  else
478  {
479  //
480  // Difficult case - call a function.
481  //
482 
483  _h = convert (x.i);
484  }
485  }
486 }
487 
488 
489 //------------------------------------------
490 // Half-to-float conversion via table lookup
491 //------------------------------------------
492 
493 inline
494 half::operator float () const
495 {
496  return _toFloat[_h].f;
497 }
498 
499 
500 //-------------------------
501 // Round to n-bit precision
502 //-------------------------
503 
504 inline half
505 half::round (unsigned int n) const
506 {
507  //
508  // Parameter check.
509  //
510 
511  if (n >= 10)
512  return *this;
513 
514  //
515  // Disassemble h into the sign, s,
516  // and the combined exponent and significand, e.
517  //
518 
519  unsigned short s = _h & 0x8000;
520  unsigned short e = _h & 0x7fff;
521 
522  //
523  // Round the exponent and significand to the nearest value
524  // where ones occur only in the (10-n) most significant bits.
525  // Note that the exponent adjusts automatically if rounding
526  // up causes the significand to overflow.
527  //
528 
529  e >>= 9 - n;
530  e += e & 1;
531  e <<= 9 - n;
532 
533  //
534  // Check for exponent overflow.
535  //
536 
537  if (e >= 0x7c00)
538  {
539  //
540  // Overflow occurred -- truncate instead of rounding.
541  //
542 
543  e = _h;
544  e >>= 10 - n;
545  e <<= 10 - n;
546  }
547 
548  //
549  // Put the original sign bit back.
550  //
551 
552  half h;
553  h._h = s | e;
554 
555  return h;
556 }
557 
558 
559 //-----------------------
560 // Other inline functions
561 //-----------------------
562 
563 inline half
564 half::operator - () const
565 {
566  half h;
567  h._h = _h ^ 0x8000;
568  return h;
569 }
570 
571 
572 inline half &
573 half::operator = (float f)
574 {
575  *this = half (f);
576  return *this;
577 }
578 
579 
580 inline half &
581 half::operator += (half h)
582 {
583  *this = half (float (*this) + float (h));
584  return *this;
585 }
586 
587 
588 inline half &
589 half::operator += (float f)
590 {
591  *this = half (float (*this) + f);
592  return *this;
593 }
594 
595 
596 inline half &
597 half::operator -= (half h)
598 {
599  *this = half (float (*this) - float (h));
600  return *this;
601 }
602 
603 
604 inline half &
605 half::operator -= (float f)
606 {
607  *this = half (float (*this) - f);
608  return *this;
609 }
610 
611 
612 inline half &
613 half::operator *= (half h)
614 {
615  *this = half (float (*this) * float (h));
616  return *this;
617 }
618 
619 
620 inline half &
621 half::operator *= (float f)
622 {
623  *this = half (float (*this) * f);
624  return *this;
625 }
626 
627 
628 inline half &
629 half::operator /= (half h)
630 {
631  *this = half (float (*this) / float (h));
632  return *this;
633 }
634 
635 
636 inline half &
637 half::operator /= (float f)
638 {
639  *this = half (float (*this) / f);
640  return *this;
641 }
642 
643 
644 inline bool
645 half::isFinite () const
646 {
647  unsigned short e = (_h >> 10) & 0x001f;
648  return e < 31;
649 }
650 
651 
652 inline bool
653 half::isNormalized () const
654 {
655  unsigned short e = (_h >> 10) & 0x001f;
656  return e > 0 && e < 31;
657 }
658 
659 
660 inline bool
661 half::isDenormalized () const
662 {
663  unsigned short e = (_h >> 10) & 0x001f;
664  unsigned short m = _h & 0x3ff;
665  return e == 0 && m != 0;
666 }
667 
668 
669 inline bool
670 half::isZero () const
671 {
672  return (_h & 0x7fff) == 0;
673 }
674 
675 
676 inline bool
677 half::isNan () const
678 {
679  unsigned short e = (_h >> 10) & 0x001f;
680  unsigned short m = _h & 0x3ff;
681  return e == 31 && m != 0;
682 }
683 
684 
685 inline bool
686 half::isInfinity () const
687 {
688  unsigned short e = (_h >> 10) & 0x001f;
689  unsigned short m = _h & 0x3ff;
690  return e == 31 && m == 0;
691 }
692 
693 
694 inline bool
695 half::isNegative () const
696 {
697  return (_h & 0x8000) != 0;
698 }
699 
700 
701 inline half
702 half::posInf ()
703 {
704  half h;
705  h._h = 0x7c00;
706  return h;
707 }
708 
709 
710 inline half
711 half::negInf ()
712 {
713  half h;
714  h._h = 0xfc00;
715  return h;
716 }
717 
718 
719 inline half
720 half::qNan ()
721 {
722  half h;
723  h._h = 0x7fff;
724  return h;
725 }
726 
727 
728 inline half
729 half::sNan ()
730 {
731  half h;
732  h._h = 0x7dff;
733  return h;
734 }
735 
736 
737 inline unsigned short
738 half::bits () const
739 {
740  return _h;
741 }
742 
743 
744 inline void
745 half::setBits (unsigned short bits)
746 {
747  _h = bits;
748 }
749 
750 } // namespace pxr_half
751 
752 PXR_NAMESPACE_CLOSE_SCOPE
753 
754 #endif
USDUTILS_API std::istream & operator>>(std::istream &is, UsdUtilsTimeCodeRange &timeCodeRange)
Stream extraction operator.
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].