GteBSNumber.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
13 #include <algorithm>
14 #include <fstream>
15 #include <limits>
16 
17 // The class BSNumber (binary scientific number) is designed to provide exact
18 // arithmetic for robust algorithms, typically those for which we need to know
19 // the exact sign of determinants. The template parameter UIntegerType must
20 // have support for at least the following public interface. The fstream
21 // objects for Write/Read must be created using std::ios::binary. The return
22 // value of Write/Read is 'true' iff the operation was successful.
23 //
24 // class UIntegerType
25 // {
26 // public:
27 // UIntegerType();
28 // UIntegerType(UIntegerType const& number);
29 // UIntegerType(uint32_t number);
30 // UIntegerType(uint64_t number);
31 // UIntegerType(int numBits);
32 // UIntegerType& operator=(UIntegerType const& number);
33 // UIntegerType(UIntegerType&& number);
34 // UIntegerType& operator=(UIntegerType&& number);
35 // int32_t GetNumBits() const;
36 // bool operator==(UIntegerType const& number) const;
37 // bool operator< (UIntegerType const& number) const;
38 // void Add(UIntegerType const& n0, UIntegerType const& n1);
39 // void Sub(UIntegerType const& n0, UIntegerType const& n1);
40 // void Mul(UIntegerType const& n0, UIntegerType const& n1);
41 // void ShiftLeft(UIntegerType const& number, int shift);
42 // int32_t ShiftRightToOdd(UIntegerType const& number);
43 // uint64_t GetPrefix(int numRequested) const;
44 // bool Write(std::ofstream& output) const;
45 // bool Read(std::ifstream& input);
46 // };
47 //
48 // GTEngine currently has 32-bits-per-word storage for UIntegerType. See the
49 // classes UIntegerAP32 (arbitrary precision), UIntegerFP32<N> (fixed
50 // precision), and UIntegerALU32 (arithmetic logic unit shared by the previous
51 // two classes). The document at the following link describes the design,
52 // implementation, and use of BSNumber and BSRational.
53 // http://www.geometrictools.com/Documentation/ArbitraryPrecision.pdf
54 //
55 // Support for debugging algorithms that use exact rational arithmetic. Each
56 // BSNumber and BSRational has a double-precision member that is exposed when
57 // the conditional define is enabled. Be aware that this can be very slow
58 // because of the conversion to double-precision whenever new objects are
59 // created by arithmetic operations. As a faster alternative, you can add
60 // temporary code in your algorithms that explicitly convert specific rational
61 // numbers to double precision.
62 //
63 //#define GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE
64 
65 namespace gte
66 {
67 
68 template <typename UIntegerType> class BSRational;
69 
70 template <typename UIntegerType>
71 class BSNumber
72 {
73 public:
74  // Construction. The default constructor generates the zero BSNumber.
75  BSNumber();
76  BSNumber(BSNumber const& number);
77  BSNumber(float number);
78  BSNumber(double number);
79  BSNumber(int32_t number);
80  BSNumber(uint32_t number);
81  BSNumber(int64_t number);
82  BSNumber(uint64_t number);
83 
84  // Implicit conversions.
85  inline operator float() const;
86  inline operator double() const;
87 
88  // Assignment.
89  BSNumber& operator=(BSNumber const& number);
90 
91  // Support for std::move.
92  BSNumber(BSNumber&& number);
93  BSNumber& operator=(BSNumber&& number);
94 
95  // Member access.
96  inline int32_t GetSign() const;
97  inline int32_t GetBiasedExponent() const;
98  inline int32_t GetExponent() const;
99  inline UIntegerType const& GetUInteger() const;
100 
101  // Comparisons.
102  bool operator==(BSNumber const& number) const;
103  bool operator!=(BSNumber const& number) const;
104  bool operator< (BSNumber const& number) const;
105  bool operator<=(BSNumber const& number) const;
106  bool operator> (BSNumber const& number) const;
107  bool operator>=(BSNumber const& number) const;
108 
109  // Unary operations.
110  BSNumber operator+() const;
111  BSNumber operator-() const;
112 
113  // Arithmetic.
114  BSNumber operator+(BSNumber const& number) const;
115  BSNumber operator-(BSNumber const& number) const;
116  BSNumber operator*(BSNumber const& number) const;
117  BSNumber& operator+=(BSNumber const& number);
118  BSNumber& operator-=(BSNumber const& number);
119  BSNumber& operator*=(BSNumber const& number);
120 
121  // Disk input/output. The fstream objects should be created using
122  // std::ios::binary. The return value is 'true' iff the operation
123  // was successful.
124  bool Write(std::ofstream& output) const;
125  bool Read(std::ifstream& input);
126 
127 private:
128  // Helpers for operator==, operator<, operator+, operator-.
129  static bool EqualIgnoreSign(BSNumber const& n0, BSNumber const& n1);
130  static bool LessThanIgnoreSign(BSNumber const& n0, BSNumber const& n1);
131 
132  // Add two positive numbers.
133  static BSNumber AddIgnoreSign(BSNumber const& n0, BSNumber const& n1,
134  int32_t resultSign);
135 
136  // Subtract two positive numbers where n0 > n1.
137  static BSNumber SubIgnoreSign(BSNumber const& n0, BSNumber const& n1,
138  int32_t resultSign);
139 
140  // Support for conversions from floating-point numbers to BSNumber.
141  template <typename IEEE>
142  void ConvertFrom(typename IEEE::FloatType number);
143 
144  // Support for conversions from BSNumber to floating-point numbers.
145  template <typename IEEE>
146  typename IEEE::FloatType ConvertTo() const;
147 
148  template <typename IEEE>
149  typename IEEE::UIntType GetTrailing(int32_t normal, int32_t sigma) const;
150 
151 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
152 public:
153  // List this first so that it shows up first in the debugger watch window.
154  double mValue;
155 private:
156 #endif
157 
158  // The number 0 is represented by: mSign = 0, mBiasedExponent = 0, and
159  // mUInteger = 0. For nonzero numbers, mSign != 0 and mUInteger > 0.
160  int32_t mSign;
162  UIntegerType mUInteger;
163 
164  // Access to members to avoid exposing them publically when they are
165  // needed only internally.
166  friend class BSRational<UIntegerType>;
167  friend class UnitTestBSNumber;
168 };
169 
170 
171 template <typename UIntegerType>
173  :
174  mSign(0),
175  mBiasedExponent(0)
176 {
177 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
178  mValue = (double)*this;
179 #endif
180 }
181 
182 template <typename UIntegerType>
184 {
185  *this = number;
186 }
187 
188 template <typename UIntegerType>
190 {
191  ConvertFrom<IEEEBinary32>(number);
192 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
193  mValue = (double)*this;
194 #endif
195 }
196 
197 template <typename UIntegerType>
199 {
200  ConvertFrom<IEEEBinary64>(number);
201 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
202  mValue = (double)*this;
203 #endif
204 }
205 
206 template <typename UIntegerType>
208 {
209  if (number == 0)
210  {
211  mSign = 0;
212  mBiasedExponent = 0;
213  }
214  else
215  {
216  if (number < 0)
217  {
218  mSign = -1;
219  number = -number;
220  }
221  else
222  {
223  mSign = 1;
224  }
225 
227  mUInteger = (uint32_t)number;
228  }
229 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
230  mValue = (double)*this;
231 #endif
232 }
233 
234 template <typename UIntegerType>
236 {
237  if (number == 0)
238  {
239  mSign = 0;
240  mBiasedExponent = 0;
241  }
242  else
243  {
244  mSign = 1;
246  mUInteger = number;
247  }
248 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
249  mValue = (double)*this;
250 #endif
251 }
252 
253 template <typename UIntegerType>
255 {
256  if (number == 0)
257  {
258  mSign = 0;
259  mBiasedExponent = 0;
260  }
261  else
262  {
263  if (number < 0)
264  {
265  mSign = -1;
266  number = -number;
267  }
268  else
269  {
270  mSign = 1;
271  }
272 
274  mUInteger = (uint64_t)number;
275  }
276 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
277  mValue = (double)*this;
278 #endif
279 }
280 
281 template <typename UIntegerType>
283 {
284  if (number == 0)
285  {
286  mSign = 0;
287  mBiasedExponent = 0;
288  }
289  else
290  {
291  mSign = 1;
293  mUInteger = number;
294  }
295 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
296  mValue = (double)*this;
297 #endif
298 }
299 
300 template <typename UIntegerType> inline
302 {
303  return ConvertTo<IEEEBinary32>();
304 }
305 
306 template <typename UIntegerType>
307 inline BSNumber<UIntegerType>::operator double() const
308 {
309  return ConvertTo<IEEEBinary64>();
310 }
311 
312 template <typename UIntegerType>
314  BSNumber const& number)
315 {
316  mSign = number.mSign;
318  mUInteger = number.mUInteger;
319 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
320  mValue = number.mValue;
321 #endif
322  return *this;
323 }
324 
325 template <typename UIntegerType>
327 {
328  *this = std::move(number);
329 }
330 
331 template <typename UIntegerType>
333 {
334  mSign = number.mSign;
335  mBiasedExponent = number.mBiasedExponent;
336  mUInteger = std::move(number.mUInteger);
337  number.mSign = 0;
338  number.mBiasedExponent = 0;
339 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
340  mValue = number.mValue;
341 #endif
342  return *this;
343 }
344 
345 template <typename UIntegerType> inline
347 {
348  return mSign;
349 }
350 
351 template <typename UIntegerType> inline
353 {
354  return mBiasedExponent;
355 }
356 
357 template <typename UIntegerType> inline
359 {
360  return mBiasedExponent + mUInteger.GetNumBits() - 1;
361 }
362 
363 template <typename UIntegerType> inline
364 UIntegerType const& BSNumber<UIntegerType>::GetUInteger() const
365 {
366  return mUInteger;
367 }
368 
369 template <typename UIntegerType>
371 {
372  return (mSign == number.mSign ? EqualIgnoreSign(*this, number) : false);
373 }
374 
375 template <typename UIntegerType>
377 {
378  return !operator==(number);
379 }
380 
381 template <typename UIntegerType>
383 {
384  if (mSign > 0)
385  {
386  if (number.mSign <= 0)
387  {
388  return false;
389  }
390 
391  // Both numbers are positive.
392  return LessThanIgnoreSign(*this, number);
393  }
394  else if (mSign < 0)
395  {
396  if (number.mSign >= 0)
397  {
398  return true;
399  }
400 
401  // Both numbers are negative.
402  return LessThanIgnoreSign(number, *this);
403  }
404  else
405  {
406  return number.mSign > 0;
407  }
408 }
409 
410 template <typename UIntegerType>
412 {
413  return operator<(number) || operator==(number);
414 }
415 
416 template <typename UIntegerType>
418 {
419  return !operator<=(number);
420 }
421 
422 template <typename UIntegerType>
424 {
425  return !operator<(number);
426 }
427 
428 template <typename UIntegerType>
430 {
431  return *this;
432 }
433 
434 template <typename UIntegerType>
436 {
437  BSNumber result = *this;
438  result.mSign = -result.mSign;
439 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
440  result.mValue = (double)result;
441 #endif
442  return result;
443 }
444 
445 template <typename UIntegerType>
447 const
448 {
449  BSNumber const& n0 = *this;
450 
451  if (n0.mSign == 0)
452  {
453  return n1;
454  }
455 
456  if (n1.mSign == 0)
457  {
458  return n0;
459  }
460 
461  if (n0.mSign > 0)
462  {
463  if (n1.mSign > 0)
464  {
465  // n0 + n1 = |n0| + |n1|
466  return AddIgnoreSign(n0, n1, +1);
467  }
468  else // n1.mSign < 0
469  {
470  if (!EqualIgnoreSign(n0, n1))
471  {
472  if (LessThanIgnoreSign(n1, n0))
473  {
474  // n0 + n1 = |n0| - |n1| > 0
475  return SubIgnoreSign(n0, n1, +1);
476  }
477  else
478  {
479  // n0 + n1 = -(|n1| - |n0|) < 0
480  return SubIgnoreSign(n1, n0, -1);
481  }
482  }
483  // else n0 + n1 = 0
484  }
485  }
486  else // n0.mSign < 0
487  {
488  if (n1.mSign < 0)
489  {
490  // n0 + n1 = -(|n0| + |n1|)
491  return AddIgnoreSign(n0, n1, -1);
492  }
493  else // n1.mSign > 0
494  {
495  if (!EqualIgnoreSign(n0, n1))
496  {
497  if (LessThanIgnoreSign(n1, n0))
498  {
499  // n0 + n1 = -(|n0| - |n1|) < 0
500  return SubIgnoreSign(n0, n1, -1);
501  }
502  else
503  {
504  // n0 + n1 = |n1| - |n0| > 0
505  return SubIgnoreSign(n1, n0, +1);
506  }
507  }
508  // else n0 + n1 = 0
509  }
510  }
511 
512  return BSNumber(); // = 0
513 }
514 
515 template <typename UIntegerType>
517 const
518 {
519  BSNumber const& n0 = *this;
520 
521  if (n0.mSign == 0)
522  {
523  return -n1;
524  }
525 
526  if (n1.mSign == 0)
527  {
528  return n0;
529  }
530 
531  if (n0.mSign > 0)
532  {
533  if (n1.mSign < 0)
534  {
535  // n0 - n1 = |n0| + |n1|
536  return AddIgnoreSign(n0, n1, +1);
537  }
538  else // n1.mSign > 0
539  {
540  if (!EqualIgnoreSign(n0, n1))
541  {
542  if (LessThanIgnoreSign(n1, n0))
543  {
544  // n0 - n1 = |n0| - |n1| > 0
545  return SubIgnoreSign(n0, n1, +1);
546  }
547  else
548  {
549  // n0 - n1 = -(|n1| - |n0|) < 0
550  return SubIgnoreSign(n1, n0, -1);
551  }
552  }
553  // else n0 - n1 = 0
554  }
555  }
556  else // n0.mSign < 0
557  {
558  if (n1.mSign > 0)
559  {
560  // n0 - n1 = -(|n0| + |n1|)
561  return AddIgnoreSign(n0, n1, -1);
562  }
563  else // n1.mSign < 0
564  {
565  if (!EqualIgnoreSign(n0, n1))
566  {
567  if (LessThanIgnoreSign(n1, n0))
568  {
569  // n0 - n1 = -(|n0| - |n1|) < 0
570  return SubIgnoreSign(n0, n1, -1);
571  }
572  else
573  {
574  // n0 - n1 = |n1| - |n0| > 0
575  return SubIgnoreSign(n1, n0, +1);
576  }
577  }
578  // else n0 - n1 = 0
579  }
580  }
581 
582  return BSNumber(); // = 0
583 }
584 
585 template <typename UIntegerType>
587  BSNumber const& number) const
588 {
589  BSNumber result; // = 0
590  int sign = mSign * number.mSign;
591  if (sign != 0)
592  {
593  result.mSign = sign;
595  result.mUInteger.Mul(mUInteger, number.mUInteger);
596  }
597 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
598  result.mValue = (double)result;
599 #endif
600  return result;
601 }
602 
603 template <typename UIntegerType>
605  BSNumber const& number)
606 {
607  *this = operator+(number);
608  return *this;
609 }
610 
611 template <typename UIntegerType>
613  BSNumber const& number)
614 {
615  *this = operator-(number);
616  return *this;
617 }
618 
619 template <typename UIntegerType>
621  BSNumber const& number)
622 {
623  *this = operator*(number);
624  return *this;
625 }
626 
627 template <typename UIntegerType>
628 bool BSNumber<UIntegerType>::Write(std::ofstream& output) const
629 {
630  if (output.write((char const*)&mSign, sizeof(mSign)).bad())
631  {
632  return false;
633  }
634 
635  if (output.write((char const*)&mBiasedExponent,
636  sizeof(mBiasedExponent)).bad())
637  {
638  return false;
639  }
640 
641  return mUInteger.Write(output);
642 }
643 
644 template <typename UIntegerType>
646 {
647  if (input.read((char*)&mSign, sizeof(mSign)).bad())
648  {
649  return false;
650  }
651 
652  if (input.read((char*)&mBiasedExponent, sizeof(mBiasedExponent)).bad())
653  {
654  return false;
655  }
656 
657  return mUInteger.Read(input);
658 }
659 
660 template <typename UIntegerType>
662  BSNumber const& n1)
663 {
664  return n0.mBiasedExponent == n1.mBiasedExponent
665  && n0.mUInteger == n1.mUInteger;
666 }
667 
668 template <typename UIntegerType>
670  BSNumber const& n1)
671 {
672  int32_t e0 = n0.GetExponent(), e1 = n1.GetExponent();
673  if (e0 < e1)
674  {
675  return true;
676  }
677  if (e0 > e1)
678  {
679  return false;
680  }
681  return n0.mUInteger < n1.mUInteger;
682 }
683 
684 template <typename UIntegerType>
686  BSNumber const& n0, BSNumber const& n1, int32_t resultSign)
687 {
688  BSNumber result, temp;
689 
690  int32_t diff = n0.mBiasedExponent - n1.mBiasedExponent;
691  if (diff > 0)
692  {
693  temp.mUInteger.ShiftLeft(n0.mUInteger, diff);
694  result.mUInteger.Add(temp.mUInteger, n1.mUInteger);
695  result.mBiasedExponent = n1.mBiasedExponent;
696  }
697  else if (diff < 0)
698  {
699  temp.mUInteger.ShiftLeft(n1.mUInteger, -diff);
700  result.mUInteger.Add(n0.mUInteger, temp.mUInteger);
701  result.mBiasedExponent = n0.mBiasedExponent;
702  }
703  else
704  {
705  temp.mUInteger.Add(n0.mUInteger, n1.mUInteger);
706  int32_t shift = result.mUInteger.ShiftRightToOdd(temp.mUInteger);
707  result.mBiasedExponent = n0.mBiasedExponent + shift;
708  }
709 
710  result.mSign = resultSign;
711 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
712  result.mValue = (double)result;
713 #endif
714  return result;
715 }
716 
717 template <typename UIntegerType>
719  BSNumber const& n0, BSNumber const& n1, int32_t resultSign)
720 {
721  BSNumber result, temp;
722 
723  int32_t diff = n0.mBiasedExponent - n1.mBiasedExponent;
724  if (diff > 0)
725  {
726  temp.mUInteger.ShiftLeft(n0.mUInteger, diff);
727  result.mUInteger.Sub(temp.mUInteger, n1.mUInteger);
728  result.mBiasedExponent = n1.mBiasedExponent;
729  }
730  else if (diff < 0)
731  {
732  temp.mUInteger.ShiftLeft(n1.mUInteger, -diff);
733  result.mUInteger.Sub(n0.mUInteger, temp.mUInteger);
734  result.mBiasedExponent = n0.mBiasedExponent;
735  }
736  else
737  {
738  temp.mUInteger.Sub(n0.mUInteger, n1.mUInteger);
739  int32_t shift = result.mUInteger.ShiftRightToOdd(temp.mUInteger);
740  result.mBiasedExponent = n0.mBiasedExponent + shift;
741  }
742 
743  result.mSign = resultSign;
744 #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
745  result.mValue = (double)result;
746 #endif
747  return result;
748 }
749 
750 template <typename UIntegerType>
751 template <typename IEEE>
752 void BSNumber<UIntegerType>::ConvertFrom(typename IEEE::FloatType number)
753 {
754  IEEE x(number);
755 
756  // Extract sign s, biased exponent e, and trailing significand t.
757  typename IEEE::UIntType s = x.GetSign();
758  typename IEEE::UIntType e = x.GetBiased();
759  typename IEEE::UIntType t = x.GetTrailing();
760 
761  if (e == 0)
762  {
763  if (t == 0) // zeros
764  {
765  // x = (-1)^s * 0
766  mSign = 0;
767  mBiasedExponent = 0;
768  }
769  else // subnormal numbers
770  {
771  // x = (-1)^s * 0.t * 2^{1-EXPONENT_BIAS}
772  int32_t last = GetTrailingBit(t);
773  int32_t diff = IEEE::NUM_TRAILING_BITS - last;
774  mSign = (s > 0 ? -1 : 1);
775  mBiasedExponent = IEEE::MIN_SUB_EXPONENT - diff;
776  mUInteger = (t >> last);
777  }
778  }
779  else if (e < IEEE::MAX_BIASED_EXPONENT) // normal numbers
780  {
781  // x = (-1)^s * 1.t * 2^{e-EXPONENT_BIAS}
782  if (t > 0)
783  {
784  int32_t last = GetTrailingBit(t);
785  int32_t diff = IEEE::NUM_TRAILING_BITS - last;
786  mSign = (s > 0 ? -1 : 1);
788  static_cast<int32_t>(e)-IEEE::EXPONENT_BIAS - diff;
789  mUInteger = ((t | IEEE::SUP_TRAILING) >> last);
790  }
791  else
792  {
793  mSign = (s > 0 ? -1 : 1);
794  mBiasedExponent = static_cast<int32_t>(e)-IEEE::EXPONENT_BIAS;
795  mUInteger = (typename IEEE::UIntType)1;
796  }
797  }
798  else // e == MAX_BIASED_EXPONENT, special numbers
799  {
800  if (t == 0) // infinities
801  {
802  // x = (-1)^s * infinity
803  LogWarning("Input is " + std::string(s > 0 ? "-" : "+") +
804  "infinity.");
805 
806  // Return (-1)^s * 2^{1+EXPONENT_BIAS} for a graceful exit.
807  mSign = (s > 0 ? -1 : 1);
808  mBiasedExponent = 1 + IEEE::EXPONENT_BIAS;
809  mUInteger = (typename IEEE::UIntType)1;
810  }
811  else // not-a-number (NaN)
812  {
813  LogError("Input is a " +
814  std::string(t & IEEE::NAN_QUIET_MASK ?
815  "quiet" : "signaling") + " NaN with payload " +
816  std::to_string(t & IEEE::NAN_PAYLOAD_MASK) + ".");
817 
818  // Return 0 for a graceful exit.
819  mSign = 0;
820  mBiasedExponent = 0;
821  }
822  }
823 }
824 
825 template <typename UIntegerType>
826 template <typename IEEE>
827 typename IEEE::FloatType BSNumber<UIntegerType>::ConvertTo() const
828 {
829  typename IEEE::UIntType s = (mSign < 0 ? 1 : 0);
830  typename IEEE::UIntType e, t;
831 
832  if (mSign != 0)
833  {
834  // The conversions use round-to-nearest-ties-to-even semantics.
835  int32_t exponent = GetExponent();
836  if (exponent < IEEE::MIN_EXPONENT)
837  {
838  if (exponent < IEEE::MIN_EXPONENT - 1
839  || mUInteger.GetNumBits() == 1) // x = 1.0*2^{MIN_EXPONENT-1}
840  {
841  // Round to zero.
842  e = 0;
843  t = 0;
844  }
845  else
846  {
847  // Round to min subnormal.
848  e = 0;
849  t = 1;
850  }
851  }
852  else if (exponent < IEEE::MIN_SUB_EXPONENT)
853  {
854  // The second input is in {0, ..., NUM_TRAILING_BITS-1}.
855  t = GetTrailing<IEEE>(0, IEEE::MIN_SUB_EXPONENT - exponent - 1);
856  if (t & IEEE::SUP_TRAILING)
857  {
858  // Leading NUM_SIGNIFICAND_BITS bits were all 1, so round to
859  // min normal.
860  e = 1;
861  t = 0;
862  }
863  else
864  {
865  e = 0;
866  }
867  }
868  else if (exponent <= IEEE::EXPONENT_BIAS)
869  {
870  e = static_cast<uint32_t>(exponent + IEEE::EXPONENT_BIAS);
871  t = GetTrailing<IEEE>(1, 0);
872  if (t & (IEEE::SUP_TRAILING << 1))
873  {
874  // Carry-out occurred, so increase exponent by 1 and
875  // shift right to compensate.
876  ++e;
877  t >>= 1;
878  }
879  // Eliminate the leading 1 (implied for normals).
880  t &= ~IEEE::SUP_TRAILING;
881  }
882  else
883  {
884  // Set to infinity.
885  e = IEEE::MAX_BIASED_EXPONENT;
886  t = 0;
887  }
888  }
889  else
890  {
891  // The input is zero.
892  e = 0;
893  t = 0;
894  }
895 
896  IEEE x(s, e, t);
897  return x.number;
898 }
899 
900 template <typename UIntegerType>
901 template <typename IEEE>
902 typename IEEE::UIntType BSNumber<UIntegerType>::GetTrailing(int32_t normal,
903  int32_t sigma) const
904 {
905  int32_t const numRequested = IEEE::NUM_SIGNIFICAND_BITS + normal;
906 
907  // We need numRequested bits to determine rounding direction. These are
908  // stored in the high-order bits of 'prefix'.
909  uint64_t prefix = mUInteger.GetPrefix(numRequested);
910 
911  // The first bit index after the implied binary point for rounding.
912  int32_t diff = numRequested - sigma;
913  int32_t roundBitIndex = 64 - diff;
914 
915  // Determine rounding value based on round-to-nearest-ties-to-even.
916  uint64_t mask = (GTE_U64(1) << roundBitIndex);
917  uint64_t round;
918  if (prefix & mask)
919  {
920  // The first bit of the remainder is 1.
921  if (mUInteger.GetNumBits() == diff)
922  {
923  // The first bit of the remainder is the lowest-order bit of
924  // mBits[0]. Apply the ties-to-even rule.
925  if (prefix & (mask << 1))
926  {
927  // The last bit of the trailing significand is odd, so
928  // round up.
929  round = 1;
930  }
931  else
932  {
933  // The last bit of the trailing significand is even, so
934  // round down.
935  round = 0;
936  }
937  }
938  else
939  {
940  // The first bit of the remainder is not the lowest-order bit of
941  // mBits[0]. The remainder as a fraction is larger than 1/2, so
942  // round up.
943  round = 1;
944  }
945  }
946  else
947  {
948  // The first bit of the remainder is 0, so round down.
949  round = 0;
950  }
951 
952  // Get the unrounded trailing significand.
953  uint64_t trailing = prefix >> (roundBitIndex + 1);
954 
955  // Apply the rounding.
956  trailing += round;
957  return static_cast<typename IEEE::UIntType>(trailing);
958 }
959 
960 
961 }
962 
963 namespace std
964 {
965  template <typename UIntegerType> inline
967  {
968  return (number.GetSign() >= 0 ? number : -number);
969  }
970 }
bool operator==(BSNumber const &number) const
Definition: GteBSNumber.h:370
static BSNumber AddIgnoreSign(BSNumber const &n0, BSNumber const &n1, int32_t resultSign)
Definition: GteBSNumber.h:685
bool operator>(BSNumber const &number) const
Definition: GteBSNumber.h:417
BSNumber operator+() const
Definition: GteBSNumber.h:429
GTE_IMPEXP int32_t GetTrailingBit(uint32_t value)
BSNumber & operator-=(BSNumber const &number)
Definition: GteBSNumber.h:612
void ConvertFrom(typename IEEE::FloatType number)
Definition: GteBSNumber.h:752
UIntegerType const & GetUInteger() const
Definition: GteBSNumber.h:364
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
bool operator!=(BSNumber const &number) const
Definition: GteBSNumber.h:376
static bool EqualIgnoreSign(BSNumber const &n0, BSNumber const &n1)
Definition: GteBSNumber.h:661
BSNumber operator-() const
Definition: GteBSNumber.h:435
friend class UnitTestBSNumber
Definition: GteBSNumber.h:167
UIntegerType mUInteger
Definition: GteBSNumber.h:162
int32_t GetSign() const
Definition: GteBSNumber.h:346
GLint GLenum GLint x
Definition: glcorearb.h:404
GLint GLuint mask
Definition: glcorearb.h:119
int32_t GetExponent() const
Definition: GteBSNumber.h:358
bool operator<(BSNumber const &number) const
Definition: GteBSNumber.h:382
bool operator<=(BSNumber const &number) const
Definition: GteBSNumber.h:411
GLsizei const GLchar *const * string
Definition: glcorearb.h:809
#define GTE_U64(v)
Definition: GteBitHacks.h:15
#define LogError(message)
Definition: GteLogger.h:92
bool Write(std::ofstream &output) const
Definition: GteBSNumber.h:628
bool operator>=(BSNumber const &number) const
Definition: GteBSNumber.h:423
#define LogWarning(message)
Definition: GteLogger.h:95
GLdouble GLdouble t
Definition: glext.h:239
int32_t mSign
Definition: GteBSNumber.h:160
BSNumber operator*(BSNumber const &number) const
Definition: GteBSNumber.h:586
IEEE::FloatType ConvertTo() const
Definition: GteBSNumber.h:827
int32_t GetBiasedExponent() const
Definition: GteBSNumber.h:352
BSNumber & operator=(BSNumber const &number)
Definition: GteBSNumber.h:313
GLdouble s
Definition: glext.h:231
GLenum GLenum GLenum input
Definition: glext.h:9913
bool Read(std::ifstream &input)
Definition: GteBSNumber.h:645
static bool LessThanIgnoreSign(BSNumber const &n0, BSNumber const &n1)
Definition: GteBSNumber.h:669
GLuint64EXT * result
Definition: glext.h:10003
GLint * exponent
Definition: glext.h:5080
static BSNumber SubIgnoreSign(BSNumber const &n0, BSNumber const &n1, int32_t resultSign)
Definition: GteBSNumber.h:718
BSNumber & operator+=(BSNumber const &number)
Definition: GteBSNumber.h:604
IEEE::UIntType GetTrailing(int32_t normal, int32_t sigma) const
Definition: GteBSNumber.h:902
int32_t mBiasedExponent
Definition: GteBSNumber.h:161
BSNumber & operator*=(BSNumber const &number)
Definition: GteBSNumber.h:620


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:59