12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013 |
- // 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.11.03
- #pragma once
- #include <Mathematics/BSNumber.h>
- // See the comments in BSNumber.h about the UInteger requirements. The
- // denominator of a BSRational is chosen to be positive, which allows some
- // simplification of comparisons. Also see the comments about exposing the
- // GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE conditional define.
- namespace WwiseGTE
- {
- template <typename UInteger>
- class BSRational
- {
- public:
- // Construction. The default constructor generates the zero
- // BSRational. The constructors that take only numerators set the
- // denominators to one.
- BSRational()
- :
- mNumerator(0),
- mDenominator(1)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(BSRational const& r)
- {
- *this = r;
- }
- BSRational(float numerator)
- :
- mNumerator(numerator),
- mDenominator(1.0f)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(double numerator)
- :
- mNumerator(numerator),
- mDenominator(1.0)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(int32_t numerator)
- :
- mNumerator(numerator),
- mDenominator(1)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(uint32_t numerator)
- :
- mNumerator(numerator),
- mDenominator(1)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(int64_t numerator)
- :
- mNumerator(numerator),
- mDenominator(1)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(uint64_t numerator)
- :
- mNumerator(numerator),
- mDenominator(1)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(BSNumber<UInteger> const& numerator)
- :
- mNumerator(numerator),
- mDenominator(1)
- {
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(float numerator, float denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(double numerator, double denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(int32_t numerator, int32_t denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(uint32_t numerator, uint32_t denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(int64_t numerator, int64_t denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(uint64_t numerator, uint64_t denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(BSNumber<UInteger> const& numerator, BSNumber<UInteger> const& denominator)
- :
- mNumerator(numerator),
- mDenominator(denominator)
- {
- LogAssert(mDenominator.mSign != 0, "Division by zero.");
- if (mDenominator.mSign < 0)
- {
- mNumerator.mSign = -mNumerator.mSign;
- mDenominator.mSign = 1;
- }
- // Set the exponent of the denominator to zero, but you can do so
- // only by modifying the biased exponent. Adjust the numerator
- // accordingly. This prevents large growth of the exponents in
- // both numerator and denominator simultaneously.
- mNumerator.mBiasedExponent -= mDenominator.GetExponent();
- mDenominator.mBiasedExponent = -(mDenominator.GetUInteger().GetNumBits() - 1);
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- }
- BSRational(std::string const& number)
- {
- LogAssert(number.size() > 0, "A number must be specified.");
- // Get the leading '+' or '-' if it exists.
- std::string fpNumber;
- int sign;
- if (number[0] == '+')
- {
- fpNumber = number.substr(1);
- sign = +1;
- LogAssert(fpNumber.size() > 1, "Invalid number format.");
- }
- else if (number[0] == '-')
- {
- fpNumber = number.substr(1);
- sign = -1;
- LogAssert(fpNumber.size() > 1, "Invalid number format.");
- }
- else
- {
- fpNumber = number;
- sign = +1;
- }
- size_t decimal = fpNumber.find('.');
- if (decimal != std::string::npos)
- {
- if (decimal > 0)
- {
- if (decimal < fpNumber.size())
- {
- // The number is "x.y".
- BSNumber<UInteger> intPart = BSNumber<UInteger>::ConvertToInteger(fpNumber.substr(0, decimal));
- BSRational frcPart = ConvertToFraction(fpNumber.substr(decimal + 1));
- mNumerator = intPart * frcPart.mDenominator + frcPart.mNumerator;
- mDenominator = frcPart.mDenominator;
- }
- else
- {
- // The number is "x.".
- mNumerator = BSNumber<UInteger>::ConvertToInteger(fpNumber.substr(0,fpNumber.size()-1));
- mDenominator = 1;
- }
- }
- else
- {
- // The number is ".y".
- BSRational frcPart = ConvertToFraction(fpNumber.substr(1));
- mNumerator = frcPart.mNumerator;
- mDenominator = frcPart.mDenominator;
- }
- }
- else
- {
- // The number is "x".
- mNumerator = BSNumber<UInteger>::ConvertToInteger(fpNumber);
- mDenominator = 1;
- }
- mNumerator.SetSign(sign);
- }
- BSRational(const char* number)
- :
- BSRational(std::string(number))
- {
- }
- // Implicit conversions. These always use the default rounding mode,
- // round-to-nearest-ties-to-even.
- operator float() const
- {
- float output;
- Convert(*this, FE_TONEAREST, output);
- return output;
- }
- operator double() const
- {
- double output;
- Convert(*this, FE_TONEAREST, output);
- return output;
- }
- // Assignment.
- BSRational& operator=(BSRational const& r)
- {
- mNumerator = r.mNumerator;
- mDenominator = r.mDenominator;
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- return *this;
- }
- // Support for move semantics.
- BSRational(BSRational&& r)
- {
- *this = std::move(r);
- }
- BSRational& operator=(BSRational&& r)
- {
- mNumerator = std::move(r.mNumerator);
- mDenominator = std::move(r.mDenominator);
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- mValue = (double)*this;
- #endif
- return *this;
- }
- // Member access.
- inline void SetSign(int sign)
- {
- mNumerator.SetSign(sign);
- mDenominator.SetSign(1);
- }
- inline int GetSign() const
- {
- return mNumerator.GetSign() * mDenominator.GetSign();
- }
- inline BSNumber<UInteger> const& GetNumerator() const
- {
- return mNumerator;
- }
- inline BSNumber<UInteger>& GetNumerator()
- {
- return mNumerator;
- }
- inline BSNumber<UInteger> const& GetDenominator() const
- {
- return mDenominator;
- }
- inline BSNumber<UInteger>& GetDenominator()
- {
- return mDenominator;
- }
- // Comparisons.
- bool operator==(BSRational const& r) const
- {
- // Do inexpensive sign tests first for optimum performance.
- if (mNumerator.mSign != r.mNumerator.mSign)
- {
- return false;
- }
- if (mNumerator.mSign == 0)
- {
- // The numbers are both zero.
- return true;
- }
- return mNumerator * r.mDenominator == mDenominator * r.mNumerator;
- }
- bool operator!=(BSRational const& r) const
- {
- return !operator==(r);
- }
- bool operator< (BSRational const& r) const
- {
- // Do inexpensive sign tests first for optimum performance.
- if (mNumerator.mSign > 0)
- {
- if (r.mNumerator.mSign <= 0)
- {
- return false;
- }
- }
- else if (mNumerator.mSign == 0)
- {
- return r.mNumerator.mSign > 0;
- }
- else if (mNumerator.mSign < 0)
- {
- if (r.mNumerator.mSign >= 0)
- {
- return true;
- }
- }
- return mNumerator * r.mDenominator < mDenominator * r.mNumerator;
- }
- bool operator<=(BSRational const& r) const
- {
- return !r.operator<(*this);
- }
- bool operator> (BSRational const& r) const
- {
- return r.operator<(*this);
- }
- bool operator>=(BSRational const& r) const
- {
- return !operator<(r);
- }
- // Unary operations.
- BSRational operator+() const
- {
- return *this;
- }
- BSRational operator-() const
- {
- return BSRational(-mNumerator, mDenominator);
- }
- // Arithmetic.
- BSRational operator+(BSRational const& r) const
- {
- BSNumber<UInteger> product0 = mNumerator * r.mDenominator;
- BSNumber<UInteger> product1 = mDenominator * r.mNumerator;
- BSNumber<UInteger> numerator = product0 + product1;
- // Complex expressions can lead to 0/denom, where denom is not 1.
- if (numerator.mSign != 0)
- {
- BSNumber<UInteger> denominator = mDenominator * r.mDenominator;
- return BSRational(numerator, denominator);
- }
- else
- {
- return BSRational(0);
- }
- }
- BSRational operator-(BSRational const& r) const
- {
- BSNumber<UInteger> product0 = mNumerator * r.mDenominator;
- BSNumber<UInteger> product1 = mDenominator * r.mNumerator;
- BSNumber<UInteger> numerator = product0 - product1;
- // Complex expressions can lead to 0/denom, where denom is not 1.
- if (numerator.mSign != 0)
- {
- BSNumber<UInteger> denominator = mDenominator * r.mDenominator;
- return BSRational(numerator, denominator);
- }
- else
- {
- return BSRational(0);
- }
- }
- BSRational operator*(BSRational const& r) const
- {
- BSNumber<UInteger> numerator = mNumerator * r.mNumerator;
- // Complex expressions can lead to 0/denom, where denom is not 1.
- if (numerator.mSign != 0)
- {
- BSNumber<UInteger> denominator = mDenominator * r.mDenominator;
- return BSRational(numerator, denominator);
- }
- else
- {
- return BSRational(0);
- }
- }
- BSRational operator/(BSRational const& r) const
- {
- LogAssert(r.mNumerator.mSign != 0, "Division by zero in BSRational::operator/.");
- BSNumber<UInteger> numerator = mNumerator * r.mDenominator;
- // Complex expressions can lead to 0/denom, where denom is not 1.
- if (numerator.mSign != 0)
- {
- BSNumber<UInteger> denominator = mDenominator * r.mNumerator;
- if (denominator.mSign < 0)
- {
- numerator.mSign = -numerator.mSign;
- denominator.mSign = 1;
- }
- return BSRational(numerator, denominator);
- }
- else
- {
- return BSRational(0);
- }
- }
- BSRational& operator+=(BSRational const& r)
- {
- *this = operator+(r);
- return *this;
- }
- BSRational& operator-=(BSRational const& r)
- {
- *this = operator-(r);
- return *this;
- }
- BSRational& operator*=(BSRational const& r)
- {
- *this = operator*(r);
- return *this;
- }
- BSRational& operator/=(BSRational const& r)
- {
- *this = operator/(r);
- return *this;
- }
- // Disk input/output. The fstream objects should be created using
- // std::ios::binary. The return value is 'true' iff the operation
- // was successful.
- bool Write(std::ostream& output) const
- {
- return mNumerator.Write(output) && mDenominator.Write(output);
- }
- bool Read(std::istream& input)
- {
- return mNumerator.Read(input) && mDenominator.Read(input);
- }
- private:
- // Helper for converting a string to a BSRational, where the string
- // is the fractional part "y" of the string "x.y".
- static BSRational ConvertToFraction(std::string const& number)
- {
- LogAssert(number.find_first_not_of("0123456789") == std::string::npos, "Invalid number format.");
- BSRational y(0), ten(10), pow10(10);
- for (size_t i = 0; i < number.size(); ++i)
- {
- int digit = static_cast<int>(number[i]) - static_cast<int>('0');
- if (digit > 0)
- {
- y += BSRational(digit) / pow10;
- }
- pow10 *= ten;
- }
- return y;
- }
- #if defined(GTE_BINARY_SCIENTIFIC_SHOW_DOUBLE)
- public:
- // List this first so that it shows up first in the debugger watch
- // window.
- double mValue;
- private:
- #endif
- BSNumber<UInteger> mNumerator, mDenominator;
- };
- // Explicit conversion to a user-specified precision. The rounding
- // mode is one of the flags provided in <cfenv>. The modes are
- // FE_TONEAREST: round to nearest ties to even
- // FE_DOWNWARD: round towards negative infinity
- // FE_TOWARDZERO: round towards zero
- // FE_UPWARD: round towards positive infinity
- template <typename UInteger>
- void Convert(BSRational<UInteger> const& input, int32_t precision,
- int32_t roundingMode, BSNumber<UInteger>& output)
- {
- if (precision <= 0)
- {
- LogError("Precision must be positive.");
- }
- int64_t const maxSize = static_cast<int64_t>(UInteger::GetMaxSize());
- int64_t const excess = 32LL * maxSize - static_cast<int64_t>(precision);
- if (excess <= 0)
- {
- LogError("The maximum precision has been exceeded.");
- }
- if (input.GetSign() == 0)
- {
- output = BSNumber<UInteger>(0);
- return;
- }
- BSNumber<UInteger> n = input.GetNumerator();
- BSNumber<UInteger> d = input.GetDenominator();
- // The ratio is abstractly of the form n/d = (1.u*2^p)/(1.v*2^q).
- // Convert to the form
- // (1.u/1.v)*2^{p-q}, if 1.u >= 1.v
- // 2*(1.u/1.v)*2^{p-q-1} if 1.u < 1.v
- // which are in the interval [1,2).
- int32_t sign = n.GetSign() * d.GetSign();
- n.SetSign(1);
- d.SetSign(1);
- int32_t pmq = n.GetExponent() - d.GetExponent();
- n.SetExponent(0);
- d.SetExponent(0);
- if (n < d)
- {
- n.SetExponent(n.GetExponent() + 1);
- --pmq;
- }
- // Let p = precision. At this time, n/d = 1.c in [1,2). Define the
- // sequence of bits w = 1c = w_{p-1} w_{p-2} ... w_0 r, where
- // w_{p-1} = 1. The bits r after w_0 are used for rounding based on
- // the user-specified rounding mode.
- // Compute p bits for w, the leading bit guaranteed to be 1 and
- // occurring at index (1 << (precision-1)).
- BSNumber<UInteger> one(1), two(2);
- UInteger& w = output.GetUInteger();
- w.SetNumBits(precision);
- w.SetAllBitsToZero();
- int32_t const size = w.GetSize();
- int32_t const precisionM1 = precision - 1;
- int32_t const leading = precisionM1 % 32;
- uint32_t mask = (1 << leading);
- auto& bits = w.GetBits();
- int32_t current = size - 1;
- int32_t lastBit = -1;
- for (int i = precisionM1; i >= 0; --i)
- {
- if (n < d)
- {
- n = two * n;
- lastBit = 0;
- }
- else
- {
- n = two * (n - d);
- bits[current] |= mask;
- lastBit = 1;
- }
- if (mask == 0x00000001u)
- {
- --current;
- mask = 0x80000000u;
- }
- else
- {
- mask >>= 1;
- }
- }
- // At this point as a sequence of bits, r = n/d = r0 r1 ...
- if (roundingMode == FE_TONEAREST)
- {
- n = n - d;
- if (n.GetSign() > 0 || (n.GetSign() == 0 && lastBit == 1))
- {
- // round up
- pmq += w.RoundUp();
- }
- // else round down, equivalent to truncating the r bits
- }
- else if (roundingMode == FE_UPWARD)
- {
- if (n.GetSign() > 0 && sign > 0)
- {
- // round up
- pmq += w.RoundUp();
- }
- // else round down, equivalent to truncating the r bits
- }
- else if (roundingMode == FE_DOWNWARD)
- {
- if (n.GetSign() > 0 && sign < 0)
- {
- // Round down. This is the round-up operation applied to
- // w, but the final sign is negative which amounts to
- // rounding down.
- pmq += w.RoundUp();
- }
- // else round down, equivalent to truncating the r bits
- }
- else if (roundingMode != FE_TOWARDZERO)
- {
- // Currently, no additional implementation-dependent modes
- // are supported for rounding.
- LogError("Implementation-dependent rounding mode not supported.");
- }
- // else roundingMode == FE_TOWARDZERO. Truncate the r bits, which
- // requires no additional work.
- // Do not use SetExponent(pmq) at this step. The number of
- // requested bits is 'precision' but w.GetNumBits() will be
- // different when round-up occurs, and SetExponent accesses
- // w.GetNumBits().
- output.SetSign(sign);
- output.SetBiasedExponent(pmq - precisionM1);
- }
- // This conversion is used to avoid having to expose BSNumber in the
- // APConversion class as well as other places where BSRational<UInteger>
- // is passed via a template parameter named Rational.
- template <typename UInteger>
- void Convert(BSRational<UInteger> const& input, int32_t precision,
- int32_t roundingMode, BSRational<UInteger>& output)
- {
- BSNumber<UInteger> numerator;
- Convert(input, precision, roundingMode, numerator);
- output = BSRational<UInteger>(numerator);
- }
- // Convert to 'float' or 'double' using the specified rounding mode.
- template <typename UInteger, typename FPType>
- void Convert(BSRational<UInteger> const& input, int32_t roundingMode, FPType& output)
- {
- static_assert(std::is_floating_point<FPType>::value, "Invalid floating-point type.");
- BSNumber<UInteger> number;
- Convert(input, std::numeric_limits<FPType>::digits, roundingMode, number);
- output = static_cast<FPType>(number);
- }
- }
- namespace std
- {
- // TODO: Allow for implementations of the math functions in which a
- // specified precision is used when computing the result.
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> acos(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::acos((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> acosh(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::acosh((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> asin(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::asin((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> asinh(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::asinh((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> atan(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::atan((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> atanh(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::atanh((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> atan2(WwiseGTE::BSRational<UInteger> const& y, WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::atan2((double)y, (double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> ceil(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::ceil((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> cos(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::cos((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> cosh(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::cosh((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> exp(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::exp((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> exp2(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::exp2((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> fabs(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (x.GetSign() >= 0 ? x : -x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> floor(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::floor((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> fmod(WwiseGTE::BSRational<UInteger> const& x, WwiseGTE::BSRational<UInteger> const& y)
- {
- return (WwiseGTE::BSRational<UInteger>)std::fmod((double)x, (double)y);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> frexp(WwiseGTE::BSRational<UInteger> const& x, int* exponent)
- {
- WwiseGTE::BSRational<UInteger> result = x;
- auto& numer = result.GetNumerator();
- auto& denom = result.GetDenominator();
- int32_t e = numer.GetExponent() - denom.GetExponent();
- numer.SetExponent(0);
- denom.SetExponent(0);
- int32_t saveSign = numer.GetSign();
- numer.SetSign(1);
- if (numer >= denom)
- {
- ++e;
- numer.SetExponent(-1);
- }
- numer.SetSign(saveSign);
- *exponent = e;
- return result;
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> ldexp(WwiseGTE::BSRational<UInteger> const& x, int exponent)
- {
- WwiseGTE::BSRational<UInteger> result = x;
- int biasedExponent = result.GetNumerator().GetBiasedExponent();
- biasedExponent += exponent;
- result.GetNumerator().SetBiasedExponent(biasedExponent);
- return result;
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> log(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::log((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> log2(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::log2((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> log10(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::log10((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> pow(WwiseGTE::BSRational<UInteger> const& x, WwiseGTE::BSRational<UInteger> const& y)
- {
- return (WwiseGTE::BSRational<UInteger>)std::pow((double)x, (double)y);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> sin(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::sin((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> sinh(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::sinh((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> sqrt(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::sqrt((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> tan(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::tan((double)x);
- }
- template <typename UInteger>
- inline WwiseGTE::BSRational<UInteger> tanh(WwiseGTE::BSRational<UInteger> const& x)
- {
- return (WwiseGTE::BSRational<UInteger>)std::tanh((double)x);
- }
- // Type trait that says BSRational is a signed type.
- template <typename UInteger>
- struct is_signed<WwiseGTE::BSRational<UInteger>> : true_type {};
- }
- namespace WwiseGTE
- {
- template <typename UInteger>
- inline BSRational<UInteger> atandivpi(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)atandivpi((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> atan2divpi(BSRational<UInteger> const& y, BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)atan2divpi((double)y, (double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> clamp(BSRational<UInteger> const& x, BSRational<UInteger> const& xmin, BSRational<UInteger> const& xmax)
- {
- return (BSRational<UInteger>)clamp((double)x, (double)xmin, (double)xmax);
- }
- template <typename UInteger>
- inline BSRational<UInteger> cospi(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)cospi((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> exp10(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)exp10((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> invsqrt(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)invsqrt((double)x);
- }
- template <typename UInteger>
- inline int isign(BSRational<UInteger> const& x)
- {
- return isign((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> saturate(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)saturate((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> sign(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)sign((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> sinpi(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)sinpi((double)x);
- }
- template <typename UInteger>
- inline BSRational<UInteger> sqr(BSRational<UInteger> const& x)
- {
- return (BSRational<UInteger>)sqr((double)x);
- }
- // See the comments in Math.h about traits is_arbitrary_precision
- // and has_division_operator.
- template <typename UInteger>
- struct is_arbitrary_precision_internal<BSRational<UInteger>> : std::true_type {};
- template <typename UInteger>
- struct has_division_operator_internal<BSRational<UInteger>> : std::true_type {};
- }
|