123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- #pragma once
- #include <cstdint>
- namespace WwiseGTE
- {
- template <typename Float, typename UInt, int NumBits, int Precision>
- class IEEEBinary
- {
- public:
-
- using FloatType = Float;
- using UIntType = UInt;
-
-
-
- ~IEEEBinary() = default;
- IEEEBinary() = default;
- IEEEBinary(IEEEBinary const& object)
- :
- encoding(object.encoding)
- {
- }
- IEEEBinary(UInt inEncoding)
- :
- encoding(inEncoding)
- {
- }
- IEEEBinary(UInt inSign, UInt inBiased, UInt inTrailing)
- {
- SetEncoding(inSign, inBiased, inTrailing);
- }
- IEEEBinary(Float inNumber)
- :
- number(inNumber)
- {
- }
-
- inline operator UInt () const
- {
- return encoding;
- }
- inline operator Float () const
- {
- return number;
- }
-
- IEEEBinary& operator= (IEEEBinary const& object)
- {
- encoding = object.encoding;
- return *this;
- }
-
- static int const NUM_ENCODING_BITS = NumBits;
- static int const NUM_EXPONENT_BITS = NumBits - Precision;
- static int const NUM_SIGNIFICAND_BITS = Precision;
- static int const NUM_TRAILING_BITS = Precision - 1;
- static int const EXPONENT_BIAS = (1 << (NUM_EXPONENT_BITS - 1)) - 1;
- static int const MAX_BIASED_EXPONENT = (1 << NUM_EXPONENT_BITS) - 1;
- static int const MIN_SUB_EXPONENT = 1 - EXPONENT_BIAS;
- static int const MIN_EXPONENT = MIN_SUB_EXPONENT - NUM_TRAILING_BITS;
- static int const SIGN_SHIFT = NumBits - 1;
- static UInt const SIGN_MASK = (UInt(1) << (NumBits - 1));
- static UInt const NOT_SIGN_MASK = UInt(~SIGN_MASK);
- static UInt const TRAILING_MASK = (UInt(1) << NUM_TRAILING_BITS) - 1;
- static UInt const EXPONENT_MASK = NOT_SIGN_MASK & ~TRAILING_MASK;
- static UInt const NAN_QUIET_MASK = (UInt(1) << (NUM_TRAILING_BITS - 1));
- static UInt const NAN_PAYLOAD_MASK = (TRAILING_MASK >> 1);
- static UInt const MAX_TRAILING = TRAILING_MASK;
- static UInt const SUP_TRAILING = (UInt(1) << NUM_TRAILING_BITS);
- static UInt const POS_ZERO = UInt(0);
- static UInt const NEG_ZERO = SIGN_MASK;
- static UInt const MIN_SUBNORMAL = UInt(1);
- static UInt const MAX_SUBNORMAL = TRAILING_MASK;
- static UInt const MIN_NORMAL = SUP_TRAILING;
- static UInt const MAX_NORMAL = NOT_SIGN_MASK & ~SUP_TRAILING;
- static UInt const POS_INFINITY = EXPONENT_MASK;
- static UInt const NEG_INFINITY = SIGN_MASK | EXPONENT_MASK;
-
- enum Classification
- {
- CLASS_NEG_INFINITY,
- CLASS_NEG_SUBNORMAL,
- CLASS_NEG_NORMAL,
- CLASS_NEG_ZERO,
- CLASS_POS_ZERO,
- CLASS_POS_SUBNORMAL,
- CLASS_POS_NORMAL,
- CLASS_POS_INFINITY,
- CLASS_QUIET_NAN,
- CLASS_SIGNALING_NAN
- };
- Classification GetClassification() const
- {
- UInt sign, biased, trailing;
- GetEncoding(sign, biased, trailing);
- if (biased == 0)
- {
- if (trailing == 0)
- {
- return (sign != 0 ? CLASS_NEG_ZERO : CLASS_POS_ZERO);
- }
- else
- {
- return (sign != 0 ? CLASS_NEG_SUBNORMAL : CLASS_POS_SUBNORMAL);
- }
- }
- else if (biased < MAX_BIASED_EXPONENT)
- {
- return (sign != 0 ? CLASS_NEG_NORMAL : CLASS_POS_NORMAL);
- }
- else if (trailing == 0)
- {
- return (sign != 0 ? CLASS_NEG_INFINITY : CLASS_POS_INFINITY);
- }
- else if (trailing & NAN_QUIET_MASK)
- {
- return CLASS_QUIET_NAN;
- }
- else
- {
- return CLASS_SIGNALING_NAN;
- }
- }
- bool IsZero() const
- {
- return encoding == POS_ZERO || encoding == NEG_ZERO;
- }
- bool IsSignMinus() const
- {
- return (encoding & SIGN_MASK) != 0;
- }
- bool IsSubnormal() const
- {
- return GetBiased() == 0 && GetTrailing() > 0;
- }
- bool IsNormal() const
- {
- UInt biased = GetBiased();
- return 0 < biased&& biased < MAX_BIASED_EXPONENT;
- }
- bool IsFinite() const
- {
- return GetBiased() < MAX_BIASED_EXPONENT;
- }
- bool IsInfinite() const
- {
- return GetBiased() == MAX_BIASED_EXPONENT && GetTrailing() == 0;
- }
- bool IsNaN() const
- {
- return GetBiased() == MAX_BIASED_EXPONENT && GetTrailing() != 0;
- }
- bool IsSignalingNaN() const
- {
- UInt trailing = GetTrailing();
- return GetBiased() == MAX_BIASED_EXPONENT
- && (trailing & NAN_QUIET_MASK) == 0
- && (trailing & NAN_PAYLOAD_MASK) != 0;
- }
-
- UInt GetNextUp() const
- {
- UInt sign, biased, trailing;
- GetEncoding(sign, biased, trailing);
- if (biased == 0)
- {
- if (trailing == 0)
- {
-
- return MIN_SUBNORMAL;
- }
- else
- {
- if (sign != 0)
- {
-
-
- --trailing;
- return SIGN_MASK | trailing;
- }
- else
- {
-
-
- ++trailing;
- return trailing;
- }
- }
- }
- else if (biased < MAX_BIASED_EXPONENT)
- {
- UInt nonnegative = (encoding & NOT_SIGN_MASK);
- if (sign != 0)
- {
- --nonnegative;
- return SIGN_MASK | nonnegative;
- }
- else
- {
- ++nonnegative;
- return nonnegative;
- }
- }
- else if (trailing == 0)
- {
- if (sign != 0)
- {
-
- return SIGN_MASK | MAX_NORMAL;
- }
- else
- {
-
- return POS_INFINITY;
- }
- }
- else if (trailing & NAN_QUIET_MASK)
- {
-
-
- return 0;
- }
- else
- {
-
-
- return 0;
- }
- }
- UInt GetNextDown() const
- {
- UInt sign, biased, trailing;
- GetEncoding(sign, biased, trailing);
- if (biased == 0)
- {
- if (trailing == 0)
- {
-
- return SIGN_MASK | MIN_SUBNORMAL;
- }
- else
- {
- if (sign == 0)
- {
-
-
- --trailing;
- return trailing;
- }
- else
- {
-
-
- ++trailing;
- return SIGN_MASK | trailing;
- }
- }
- }
- else if (biased < MAX_BIASED_EXPONENT)
- {
- UInt nonnegative = (encoding & NOT_SIGN_MASK);
- if (sign == 0)
- {
- --nonnegative;
- return nonnegative;
- }
- else
- {
- ++nonnegative;
- return SIGN_MASK | nonnegative;
- }
- }
- else if (trailing == 0)
- {
- if (sign == 0)
- {
-
- return MAX_NORMAL;
- }
- else
- {
-
- return NEG_INFINITY;
- }
- }
- else if (trailing & NAN_QUIET_MASK)
- {
-
-
- return 0;
- }
- else
- {
-
-
- return 0;
- }
- }
-
-
-
-
- UInt GetSign() const
- {
- return (encoding & SIGN_MASK) >> SIGN_SHIFT;
- }
- UInt GetBiased() const
- {
- return (encoding & EXPONENT_MASK) >> NUM_TRAILING_BITS;
- }
- UInt GetTrailing() const
- {
- return encoding & TRAILING_MASK;
- }
- void SetEncoding(UInt sign, UInt biased, UInt trailing)
- {
- encoding = (sign << SIGN_SHIFT) | (biased << NUM_TRAILING_BITS) | trailing;
- }
- void GetEncoding(UInt& sign, UInt& biased, UInt& trailing) const
- {
- sign = GetSign();
- biased = GetBiased();
- trailing = GetTrailing();
- }
-
- union
- {
- UInt encoding;
- Float number;
- };
- };
- using IEEEBinary32 = IEEEBinary<float, uint32_t, 32, 24>;
- using IEEEBinary64 = IEEEBinary<double, uint64_t, 64, 53>;
- }
|