|
|
@@ -1263,7 +1263,7 @@ template double Js::NumberUtilities::StrToDbl<utf8char_t>(const utf8char_t * psz
|
|
|
Uses big integer arithmetic to get the sequence of digits.
|
|
|
***************************************************************************/
|
|
|
_Success_(return)
|
|
|
-static BOOL FDblToRgbPrecise(double dbl, __out_ecount(kcbMaxRgb) byte *prgb, int *pwExp10, byte **ppbLim)
|
|
|
+static BOOL FDblToRgbPrecise(double dbl, __out_ecount(kcbMaxRgb) byte *prgb, int *pwExp10, byte **ppbLim, int normalizeHBound = 1)
|
|
|
{
|
|
|
byte bT;
|
|
|
BOOL fPow2;
|
|
|
@@ -1516,7 +1516,9 @@ static BOOL FDblToRgbPrecise(double dbl, __out_ecount(kcbMaxRgb) byte *prgb, int
|
|
|
if (bT != 9)
|
|
|
{
|
|
|
Assert(ib < kcbMaxRgb);
|
|
|
- prgb[ib++] = bT + 1;
|
|
|
+ // Do not always push to higherBound
|
|
|
+ // See Js::NumberUtilities::FDblToStr for the exception
|
|
|
+ prgb[ib++] = bT + (byte)normalizeHBound;
|
|
|
break;
|
|
|
}
|
|
|
LRoundUp9:
|
|
|
@@ -1562,7 +1564,8 @@ LFail:
|
|
|
Get mantissa bytes (BCD).
|
|
|
***************************************************************************/
|
|
|
_Success_(return)
|
|
|
-static BOOL FDblToRgbFast(double dbl, _Out_writes_to_(kcbMaxRgb, (*ppbLim - prgb)) byte *prgb, int *pwExp10, byte **ppbLim)
|
|
|
+static BOOL FDblToRgbFast(double dbl, _Out_writes_to_(kcbMaxRgb, (*ppbLim - prgb)) byte *prgb,
|
|
|
+ int *pwExp10, byte **ppbLim, const int highBound = 1)
|
|
|
{
|
|
|
int ib;
|
|
|
int iT;
|
|
|
@@ -1808,7 +1811,16 @@ static BOOL FDblToRgbFast(double dbl, _Out_writes_to_(kcbMaxRgb, (*ppbLim - prgb
|
|
|
// the difference.
|
|
|
prgb[ib++] = (bHL + bLH + 1) / 2;
|
|
|
}
|
|
|
- else if (0 != luHL || !numHL.FZero() || 0 == (Js::NumberUtilities::LuLoDbl(dbl) & 1))
|
|
|
+ // We don't know whether BHL or BLH is the correct one
|
|
|
+ // When highBound is set, that means the consumer is not
|
|
|
+ // interested with the entire value. On the other hand, we may not
|
|
|
+ // just roundup to the higher bound. That breaks IEEE754
|
|
|
+ // Imagine LowerBound is 4999... while the UpperBoud is 50001..
|
|
|
+ // We need to know where actually the number is instead of picking
|
|
|
+ // either Lower or UpperBoud
|
|
|
+ // at this point, we should skip and fail
|
|
|
+ // let FDblToRgbPrecise do the math.
|
|
|
+ else if (highBound == 1 && (0 != luHL || !numHL.FZero() || 0 == (Js::NumberUtilities::LuLoDbl(dbl) & 1)))
|
|
|
{
|
|
|
Assert(ib < kcbMaxRgb);
|
|
|
if(!(ib < kcbMaxRgb))
|
|
|
@@ -2199,7 +2211,7 @@ static int RoundTo(byte *pbSrc, byte *pbLim, int nDigits, __out_bcount(nDigits+1
|
|
|
{
|
|
|
int i = nDigits;
|
|
|
|
|
|
- if( pbSrc[i] > 5 )
|
|
|
+ if( pbSrc[i] >= 5 )
|
|
|
{
|
|
|
// Add 1 to the BCD representation.
|
|
|
for( i = nDigits - 1; i >= 0; i-- )
|
|
|
@@ -2241,6 +2253,7 @@ static int RoundTo(byte *pbSrc, byte *pbLim, int nDigits, __out_bcount(nDigits+1
|
|
|
* Returns the number of chars. in the result. If 'nDstBufSize'
|
|
|
* is less than this number, no data is written to the buffer 'pchDst'.
|
|
|
*/
|
|
|
+
|
|
|
int Js::NumberUtilities::FDblToStr(double dbl, Js::NumberUtilities::FormatType ft, int nDigits, __out_ecount(cchDst) char16 *pchDst, int cchDst)
|
|
|
{
|
|
|
int n = 0; // the no. of chars in the result.
|
|
|
@@ -2286,7 +2299,7 @@ int Js::NumberUtilities::FDblToStr(double dbl, Js::NumberUtilities::FormatType f
|
|
|
if (Js::NumberUtilities::LuHiDbl(dbl) & 0x80000000)
|
|
|
{
|
|
|
n++;
|
|
|
- if( cchDst >= n)
|
|
|
+ if(cchDst >= n)
|
|
|
{
|
|
|
*pchDst++ = '-';
|
|
|
cchDst--;
|
|
|
@@ -2294,13 +2307,14 @@ int Js::NumberUtilities::FDblToStr(double dbl, Js::NumberUtilities::FormatType f
|
|
|
Js::NumberUtilities::LuHiDbl(dbl) &= 0x7FFFFFFF;
|
|
|
}
|
|
|
|
|
|
- if (!FDblToRgbFast(dbl, rgb, &wExp10, &pbLim) &&
|
|
|
- !FDblToRgbPrecise(dbl, rgb, &wExp10, &pbLim))
|
|
|
+ const int hBound = nDigits == -1 ? 1 : 0;
|
|
|
+ // in case we restrict the number of digits, do not push for a higher bound
|
|
|
+ if (!FDblToRgbFast(dbl, rgb, &wExp10, &pbLim, hBound) &&
|
|
|
+ !FDblToRgbPrecise(dbl, rgb, &wExp10, &pbLim, hBound))
|
|
|
{
|
|
|
AssertMsg(FALSE, "Failure in FDblToRgbPrecise");
|
|
|
return FALSE;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
// We have to round up and truncate the BCD representation of the mantissa
|
|
|
@@ -2322,7 +2336,7 @@ int Js::NumberUtilities::FDblToStr(double dbl, Js::NumberUtilities::FormatType f
|
|
|
else
|
|
|
{
|
|
|
//Special case: When negative power of 10 is more than most significant digit.
|
|
|
- if( rgb[0] > 5 )
|
|
|
+ if( rgb[0] >= 5 )
|
|
|
{
|
|
|
rgbAdj[0] = 1;
|
|
|
wExp10 += 1;
|