| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- enum class LikelyNumberType
- {
- Double,
- Int,
- BigInt,
- };
- namespace Js
- {
- class NumberConstants : public NumberConstantsBase
- {
- public:
- // Our float tagging scheme relies on NaNs to be of this value - changing the NaN value
- // will break float tagging for x64.
- static const uint64 k_PosInf = 0x7FF0000000000000ull;
- static const uint64 k_NegInf = 0xFFF0000000000000ull;
- static const uint64 k_PosMin = 0x0000000000000001ull;
- static const uint64 k_PosMax = 0x7FEFFFFFFFFFFFFFull;
- static const uint64 k_NegZero = 0x8000000000000000ull;
- static const uint64 k_Zero = 0x0000000000000000ull;
- static const uint64 k_PointFive = 0x3FE0000000000000ull;
- static const uint64 k_NegPointFive = 0xBFE0000000000000ull;
- static const uint64 k_NegOne = 0xBFF0000000000000ull;
- static const uint64 k_OnePointZero = 0x3FF0000000000000ull;
- // 2^52
- static const uint64 k_TwoToFraction = 0x4330000000000000ull;
- // -2^52
- static const uint64 k_NegTwoToFraction = 0xC330000000000000ull;
- static const uint64 k_TwoTo63 = 0x43e0000000000000ull;
- static const uint64 k_NegTwoTo63 = 0xc3e0000000000000ull;
- static const uint64 k_TwoTo64 = 0x43f0000000000000ull;
- static const uint64 k_TwoTo31 = 0x41dfffffffc00000ull;
- static const uint64 k_NegTwoTo31 = 0xc1e0000000000000ull;
- static const uint64 k_TwoTo32 = 0x41efffffffe00000ull;
- static const uint64 k_MinIntMinusOne = 0xc1e0000000200000ull;
- static const uint64 k_UintMaxPlusOne = 0x41f0000000000000ull;
- static const uint64 k_IntMaxPlusOne = 0x41e0000000000000ull;
- static const uint32 k_Float32Zero = 0x00000000ul;
- static const uint32 k_Float32PointFive = 0x3F000000ul;
- static const uint32 k_Float32NegPointFive = 0xBF000000ul;
- static const uint32 k_Float32NegZero = 0x80000000ul;
- // 2^23
- static const uint32 k_Float32TwoToFraction = 0x4B000000ul;
- // -2^23
- static const uint32 k_Float32NegTwoToFraction = 0xCB000000ul;
- static const uint32 k_Float32TwoTo63 = 0x5f000000u;
- static const uint32 k_Float32NegTwoTo63 = 0xdf000000u;
- static const uint32 k_Float32TwoTo64 = 0x5f800000u;
- static const uint32 k_Float32NegOne = 0xbf800000u;
- static const uint32 k_Float32TwoTo31 = 0x4f000000u;
- static const uint32 k_Float32NegTwoTo31 = 0xcf000000u;
- static const uint32 k_Float32TwoTo32 = 0x4f800000u;
- static const double MAX_VALUE;
- static const double MIN_VALUE;
- static const double NaN;
- static const double NegativeNaN;
- static const double NEGATIVE_INFINITY;
- static const double POSITIVE_INFINITY;
- static const double NEG_ZERO;
- static const double ONE_POINT_ZERO;
- static const double DOUBLE_INT_MIN;
- static const double DOUBLE_TWO_TO_31;
- static const BYTE AbsDoubleCst[];
- static const BYTE AbsFloatCst[];
- static const BYTE SgnFloatBitCst[];
- static const BYTE SgnDoubleBitCst[];
- static double const UIntConvertConst[];
- static double const MaskNegDouble[];
- static float const MaskNegFloat[];
- };
- class NumberUtilities : public NumberUtilitiesBase
- {
- public:
- static bool IsDigit(int ch);
- static BOOL FHexDigit(char16 ch, int *pw);
- static uint32 MulLu(uint32 lu1, uint32 lu2, uint32 *pluHi);
- static int AddLu(uint32 *plu1, uint32 lu2);
- static uint32 &LuHiDbl(double &dbl);
- static uint32 &LuLoDbl(double &dbl);
- static INT64 TryToInt64(double d);
- static bool IsValidTryToInt64(__int64 value); // Whether TryToInt64 resulted in a valid value.
- static int CbitZeroLeft(uint32 lu);
- static bool IsFinite(double value);
- static bool IsNan(double value);
- static bool IsNegative(double value);
- static bool IsFloat32NegZero(float value);
- static bool IsSpecial(double value, uint64 nSpecial);
- static uint64 ToSpecial(double value);
- static uint32 ToSpecial(float value);
- static float VECTORCALL ReinterpretBits(int value);
- static double VECTORCALL ReinterpretBits(int64 value);
- // Convert a given UINT16 into its corresponding string.
- // outBufferSize is in WCHAR elements (and used only for ASSERTs)
- // Returns the number of characters written to outBuffer (not including the \0)
- static charcount_t UInt16ToString(uint16 integer, __out __ecount(outBufferSize) WCHAR* outBuffer, charcount_t outBufferSize, char widthForPaddingZerosInsteadSpaces);
- // Try to parse an integer string to find out if the string contains an index property name.
- static BOOL TryConvertToUInt32(const char16* str, int length, uint32* intVal);
- static double Modulus(double dblLeft, double dblRight);
- enum FormatType
- {
- FormatFixed,
- FormatExponential,
- FormatPrecision
- };
- // Ref: Warren's Hacker's Delight, Chapter 10.
- // Calculates magic number (multiplier) and shift amounts (shiftAmt) to replace division by constants with multiplication and shifts
- struct DivMagicNumber
- {
- DivMagicNumber(int multiplier, uint shiftAmt) : multiplier(multiplier), shiftAmt(shiftAmt), addIndicator(0){}
- DivMagicNumber(int multiplier, uint shiftAmt, int addIndicator) : multiplier(multiplier), shiftAmt(shiftAmt), addIndicator(addIndicator) {}
- int multiplier;
- uint shiftAmt;
- int addIndicator; // Only used for unsigned
- };
- // Calculation for signed divisors
- DivMagicNumber static GenerateDivMagicNumber(const int divisor)
- {
- Assert((1 < divisor && divisor < INT32_MAX) || (-1 > divisor && divisor > INT32_MIN));
- int p;
- unsigned ad, anc, delta, q1, r1, q2, r2, t;
- const unsigned two31 = static_cast<unsigned>(1) << (sizeof(int) * 8 - 1); // 2^31
- ad = (divisor < 0) ? (0 - divisor) : divisor;
- t = two31 + ((unsigned)divisor >> 31);
- anc = t - 1 - t % ad; // abs(nc)
- p = 31; // init p
- q1 = two31 / anc; // init q1 = 2^p/|nc|
- r1 = two31 - q1 * anc;// init r1 = rem(2^p, |nc|)
- q2 = two31 / ad; // init q2 = 2^p / |d|
- r2 = two31 - q2 * ad; // init r2 = rem(2^p, |d|)
- do
- {
- p = p + 1;
- q1 = 2 * q1; // update q1 = 2 ^p / |nc|
- r1 = 2 * r1; // update r1 = rem(2^p, |nc|)
- if (r1 >= anc) // Must be an unsigned comparison here.
- {
- q1 = q1 + 1;
- r1 = r1 - anc;
- }
- q2 = 2 * q2; // update q2 = 2^p / |d|
- r2 = 2 * r2; // update r2 = rem(2^p, |d|)
- if (r2 >= ad) // Must be an unsigned comparison here.
- {
- q2 = q2 + 1;
- r2 = r2 - ad;
- }
- delta = ad - r2;
- } while (q1 < delta || (q1 == delta && r1 == 0));
- int magic_num = q2 + 1;
- if (divisor < 0)
- {
- magic_num = -magic_num;
- }
- return DivMagicNumber(magic_num, p - 32); // (Magic number, shift amount)
- }
- // Ref: Warren's Hacker's Delight, Chapter 10.
- // Calculation for unsigned divisors
- DivMagicNumber static GenerateDivMagicNumber(const uint divisor)
- {
- Assert(1 <= divisor && divisor <= UINT32_MAX - 1);
- auto p = 31;
- unsigned p32 = 0, q, r, delta;
- auto addIndicator = 0;
- const unsigned two31 = static_cast<unsigned>(1) << (sizeof(int) * 8 - 1); // 2^31
- q = (two31 - 1) / divisor; // (2^p -1)/d
- r = (two31 - 1) - q * divisor; // rem(2^p - 1, d);
- do
- {
- ++p;
- p32 = (p == 32) ? 1 : 2 * p32;// p32 = 2^(p-32)
- if (r + 1 >= divisor - r)
- {
- if (q >= (two31 - 1))
- {
- addIndicator = 1;
- }
- q = 2 * q + 1;
- r = 2 * r + 1 - divisor;
- }
- else
- {
- if (q > two31)
- {
- addIndicator = 1;
- }
- q = 2 * q;
- r = 2 * r + 1;
- }
- delta = divisor - 1 - r;
- } while (p < 64 && p32 < delta);
- return DivMagicNumber(q + 1, p - 32, addIndicator);
- }
- // Implemented in lib\parser\common. Should move to lib\common
- template<typename EncodedChar>
- static double StrToDbl(const EncodedChar *psz, const EncodedChar **ppchLim, LikelyNumberType& likelyType, bool isESBigIntEnabled = false, bool isNumericSeparatorEnabled = false);
- static BOOL FDblToStr(double dbl, __out_ecount(nDstBufSize) char16 *psz, int nDstBufSize);
- static int FDblToStr(double dbl, NumberUtilities::FormatType ft, int nDigits, __out_ecount(cchDst) char16 *pchDst, int cchDst);
- static BOOL FNonZeroFiniteDblToStr(double dbl, _Out_writes_(nDstBufSize) WCHAR* psz, int nDstBufSize);
- _Success_(return) static BOOL FNonZeroFiniteDblToStr(double dbl, _In_range_(2, 36) int radix, _Out_writes_(nDstBufSize) WCHAR* psz, int nDstBufSize);
- static double DblFromDecimal(DECIMAL * pdecIn);
- static void CodePointAsSurrogatePair(codepoint_t codePointValue, __out char16* first, __out char16* second);
- static codepoint_t SurrogatePairAsCodePoint(codepoint_t first, codepoint_t second);
- static bool IsSurrogateUpperPart(codepoint_t codePointValue);
- static bool IsSurrogateLowerPart(codepoint_t codePointValue);
- static bool IsInSupplementaryPlane(codepoint_t codePointValue);
- static int32 LwFromDblNearest(double dbl);
- static uint32 LuFromDblNearest(double dbl);
- static BOOL FDblIsInt32(double dbl, int32 *plw);
- template<typename EncodedChar>
- static double DblFromHex(const EncodedChar *psz, const EncodedChar **ppchLim, bool isNumericSeparatorEnabled = false);
- template <typename EncodedChar>
- static double DblFromBinary(const EncodedChar *psz, const EncodedChar **ppchLim, bool isNumericSeparatorEnabled = false);
- template<typename EncodedChar>
- static double DblFromOctal(const EncodedChar *psz, const EncodedChar **ppchLim, bool isNumericSeparatorEnabled = false);
- template<typename EncodedChar>
- static double StrToDbl(const EncodedChar *psz, const EncodedChar **ppchLim, Js::ScriptContext *const scriptContext);
- const NumberUtilitiesBase* GetNumberUtilitiesBase() const { return static_cast<const NumberUtilitiesBase*>(this); }
- };
- }
|