123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2019.09.25
- #pragma once
- #include <algorithm>
- #include <cstdint>
- #include <limits>
- // Support for determining the number of bits of precision required to compute
- // an expression using BSNumber or BSRational.
- namespace WwiseGTE
- {
- class BSPrecision
- {
- public:
- enum Type
- {
- IS_FLOAT,
- IS_DOUBLE,
- IS_INT32,
- IS_INT64,
- IS_UINT32,
- IS_UINT64
- };
- struct Parameters
- {
- Parameters()
- :
- minExponent(0),
- maxExponent(0),
- maxBits(0),
- maxWords(0)
- {
- }
- Parameters(int inMinExponent, int inMaxExponent, int inMaxBits)
- :
- minExponent(inMinExponent),
- maxExponent(inMaxExponent),
- maxBits(inMaxBits),
- maxWords(GetMaxWords())
- {
- }
- inline int GetMaxWords() const
- {
- return maxBits / 32 + ((maxBits % 32) > 0 ? 1 : 0);
- }
- int minExponent, maxExponent, maxBits, maxWords;
- };
- Parameters bsn, bsr;
- BSPrecision() = default;
- BSPrecision(Type type)
- {
- switch (type)
- {
- case IS_FLOAT:
- bsn = Parameters(-149, 127, 24);
- break;
- case IS_DOUBLE:
- bsn = Parameters(-1074, 1023, 53);
- break;
- case IS_INT32:
- bsn = Parameters(0, 30, 31);
- break;
- case IS_INT64:
- bsn = Parameters(0, 62, 63);
- break;
- case IS_UINT32:
- bsn = Parameters(0, 31, 32);
- break;
- case IS_UINT64:
- bsn = Parameters(0, 63, 64);
- break;
- }
- bsr = bsn;
- }
- BSPrecision(int minExponent, int maxExponent, int maxBits)
- :
- bsn(minExponent, maxExponent, maxBits),
- bsr(minExponent, maxExponent, maxBits)
- {
- }
- };
- inline BSPrecision operator+(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- BSPrecision result;
- result.bsn.minExponent = std::min(bsp0.bsn.minExponent, bsp1.bsn.minExponent);
- if (bsp0.bsn.maxExponent >= bsp1.bsn.maxExponent)
- {
- result.bsn.maxExponent = bsp0.bsn.maxExponent;
- if (bsp0.bsn.maxExponent - bsp0.bsn.maxBits + 1 <= bsp1.bsn.maxExponent)
- {
- ++result.bsn.maxExponent;
- }
- result.bsn.maxBits = bsp0.bsn.maxExponent - bsp1.bsn.minExponent + 1;
- if (result.bsn.maxBits <= bsp0.bsn.maxBits + bsp1.bsn.maxBits - 1)
- {
- ++result.bsn.maxBits;
- }
- }
- else
- {
- result.bsn.maxExponent = bsp1.bsn.maxExponent;
- if (bsp1.bsn.maxExponent - bsp1.bsn.maxBits + 1 <= bsp0.bsn.maxExponent)
- {
- ++result.bsn.maxExponent;
- }
- result.bsn.maxBits = bsp1.bsn.maxExponent - bsp0.bsn.minExponent + 1;
- if (result.bsn.maxBits <= bsp0.bsn.maxBits + bsp1.bsn.maxBits - 1)
- {
- ++result.bsn.maxBits;
- }
- }
- result.bsn.maxWords = result.bsn.GetMaxWords();
- // Addition is n0/d0 + n1/d1 = (n0*d1 + n1*d0)/(d0*d1). The numerator
- // and denominator of a number are assumed to have the same
- // parameters, so for the addition, the numerator is used for the
- // parameter computations.
- // Compute the parameters for the multiplication.
- int mulMinExponent = bsp0.bsr.minExponent + bsp1.bsr.minExponent;
- int mulMaxExponent = bsp0.bsr.maxExponent + bsp1.bsr.maxExponent + 1;
- int mulMaxBits = bsp0.bsr.maxBits + bsp1.bsr.maxBits;
- // Compute the parameters for the addition. The number n0*d1 and n1*d0
- // are in the same arbitrary-precision set.
- result.bsr.minExponent = mulMinExponent;
- result.bsr.maxExponent = mulMaxExponent + 1; // Always a carry-out.
- result.bsr.maxBits = mulMaxExponent - mulMinExponent + 1;
- if (result.bsr.maxBits <= 2 * mulMaxBits - 1)
- {
- ++result.bsr.maxBits;
- }
- result.bsr.maxWords = result.bsr.GetMaxWords();
- return result;
- }
- inline BSPrecision operator-(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- return bsp0 + bsp1;
- }
- inline BSPrecision operator*(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- BSPrecision result;
- result.bsn.minExponent = bsp0.bsn.minExponent + bsp1.bsn.minExponent;
- result.bsn.maxExponent = bsp0.bsn.maxExponent + bsp1.bsn.maxExponent + 1;
- result.bsn.maxBits = bsp0.bsn.maxBits + bsp1.bsn.maxBits;
- result.bsn.maxWords = result.bsn.GetMaxWords();
- // Multiplication is (n0/d0) * (n1/d1) = (n0 * n1) / (d0 * d1). The
- // parameters are the same as for bsn.
- result.bsr = result.bsn;
- return result;
- }
- inline BSPrecision operator/(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- BSPrecision result;
- // BSNumber does not support division, so result.bsr has all members
- // set to zero.
- // Division is (n0/d0) / (n1/d1) = (n0 * d1) / (n1 * d0). The
- // parameters are the same as for multiplication.
- result.bsr.minExponent = bsp0.bsr.minExponent + bsp1.bsr.minExponent;
- result.bsr.maxExponent = bsp0.bsr.maxExponent + bsp1.bsr.maxExponent + 1;
- result.bsr.maxBits = bsp0.bsr.maxBits + bsp1.bsr.maxBits;
- result.bsr.maxWords = result.bsr.GetMaxWords();
- return result;
- }
- // Comparisons for BSNumber do not involve dynamic allocations, so
- // the results are the extremes of the inputs. Comparisons for BSRational
- // involve multiplications of numerators and denominators.
- inline BSPrecision operator==(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- BSPrecision result;
- result.bsn.minExponent = std::min(bsp0.bsn.minExponent, bsp1.bsn.minExponent);
- result.bsn.maxExponent = std::max(bsp0.bsn.maxExponent, bsp1.bsn.maxExponent);
- result.bsn.maxBits = std::max(bsp0.bsn.maxBits, bsp1.bsn.maxBits);
- result.bsn.maxWords = result.bsn.GetMaxWords();
- result.bsr.minExponent = bsp0.bsr.minExponent + bsp1.bsr.minExponent;
- result.bsr.maxExponent = bsp0.bsr.maxExponent + bsp1.bsr.maxExponent + 1;
- result.bsr.maxBits = bsp0.bsr.maxBits + bsp1.bsr.maxBits;
- result.bsr.maxWords = result.bsr.GetMaxWords();
- return result;
- }
- inline BSPrecision operator!=(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- return operator==(bsp0, bsp1);
- }
- inline BSPrecision operator<(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- return operator==(bsp0, bsp1);
- }
- inline BSPrecision operator<=(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- return operator==(bsp0, bsp1);
- }
- inline BSPrecision operator>(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- return operator==(bsp0, bsp1);
- }
- inline BSPrecision operator>=(BSPrecision const& bsp0, BSPrecision const& bsp1)
- {
- return operator==(bsp0, bsp1);
- }
- }
|