8000 BUG: dragon4 fractional output mode adds too many trailing zeros · numpy/numpy@f44d6fb · GitHub
[go: up one dir, main page]

Skip to content

Commit f44d6fb

Browse files
ahaldanecharris
authored andcommitted
BUG: dragon4 fractional output mode adds too many trailing zeros
Fixes #10713
1 parent c0f864c commit f44d6fb

File tree

2 files changed

+38
-27
lines changed

2 files changed

+38
-27
lines changed

numpy/core/src/multiarray/dragon4.c

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ BigInt_ShiftLeft(BigInt *result, npy_uint32 shift)
896896
if (shiftBits == 0) {
897897
npy_uint32 i;
898898

899-
/* copy blcoks from high to low */
899+
/* copy blocks from high to low */
900900
for (pInCur = result->blocks + result->length,
901901
pOutCur = pInCur + shiftBlocks;
902902
pInCur >= pInBlocks;
@@ -1002,7 +1002,7 @@ BigInt_ShiftLeft(BigInt *result, npy_uint32 shift)
10021002
* * exponent - value exponent in base 2
10031003
* * mantissaBit - index of the highest set mantissa bit
10041004
* * hasUnequalMargins - is the high margin twice as large as the low margin
1005-
* * cutoffMode - how to intepret cutoffNumber: fractional or total digits?
1005+
* * cutoffMode - how to interpret cutoffNumber: fractional or total digits?
10061006
* * cutoffNumber - cut off printing after this many digits. -1 for no cutoff
10071007
* * pOutBuffer - buffer to output into
10081008
* * bufferSize - maximum characters that can be printed to pOutBuffer
@@ -1381,7 +1381,7 @@ Dragon4(const npy_uint64 mantissa, const npy_int32 exponent,
13811381

13821382
/*
13831383
* if we are directly in the middle, round towards the even digit (i.e.
1384-
* IEEE rouding rules)
1384+
* IEEE rounding rules)
13851385
*/
13861386
if (compare == 0) {
13871387
roundDown = (outputDigit & 1) == 0;
@@ -1588,12 +1588,12 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
15881588
npy_int32 digits_right)
15891589
{
15901590
npy_int32 printExponent;
1591-
npy_int32 numDigits, numWholeDigits, has_sign=0;
1591+
npy_int32 numDigits, numWholeDigits=0, has_sign=0;
15921592

1593-
npy_int32 maxPrintLen = bufferSize - 1, pos = 0;
1593+
npy_int32 maxPrintLen = (npy_int32)bufferSize - < 8000 span class="pl-c1">1, pos = 0;
15941594

15951595
/* track the # of digits past the decimal point that have been printed */
1596-
npy_int32 numFractionDigits = 0;
1596+
npy_int32 numFractionDigits = 0, desiredFractionalDigits;
15971597

15981598
DEBUG_ASSERT(bufferSize > 0);
15991599

@@ -1637,11 +1637,11 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
16371637
}
16381638
}
16391639
/* insert the decimal point prior to the fraction */
1640-
else if (numDigits > (npy_uint32)numWholeDigits) {
1641-
npy_uint32 maxFractionDigits;
1640+
else if (numDigits > numWholeDigits) {
1641+
npy_int32 maxFractionDigits;
16421642

16431643
numFractionDigits = numDigits - numWholeDigits;
1644-
maxFractionDigits = maxPrintLen - numWholeDigits -1-pos;
1644+
maxFractionDigits = maxPrintLen - numWholeDigits - 1 - pos;
16451645
if (numFractionDigits > maxFractionDigits) {
16461646
numFractionDigits = maxFractionDigits;
16471647
}
@@ -1656,19 +1656,20 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
16561656
}
16571657
else {
16581658
/* shift out the fraction to make room for the leading zeros */
1659-
npy_uint32 numFractionZeros = 0;
1659+
npy_int32 numFractionZeros = 0;
16601660
if (pos + 2 < maxPrintLen) {
1661-
npy_uint32 maxFractionZeros, digitsStartIdx, maxFractionDigits, i;
1661+
npy_int32 maxFractionZeros, digitsStartIdx, maxFractionDigits, i;
16621662

16631663
maxFractionZeros = maxPrintLen - 2 - pos;
1664-
numFractionZeros = (npy_uint32)-printExponent - 1;
1664+
numFractionZeros = -(printExponent + 1);
16651665
if (numFractionZeros > maxFractionZeros) {
16661666
numFractionZeros = maxFractionZeros;
16671667
}
16681668

16691669
digitsStartIdx = 2 + numFractionZeros;
16701670

1671-
/* shift the significant digits right such that there is room for
1671+
/*
1672+
* shift the significant digits right such that there is room for
16721673
* leading zeros
16731674
*/
16741675
numFractionDigits = numDigits;
@@ -1710,6 +1711,11 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
17101711
buffer[pos++] = '.';
17111712
}
17121713

1714+
desiredFractionalDigits = precision;
1715+
if (cutoff_mode == CutoffMode_TotalLength && precision >= 0) {
1716+
desiredFractionalDigits = precision - numWholeDigits;
1717+
}
1718+
17131719
if (trim_mode == TrimMode_LeaveOneZero) {
17141720
/* if we didn't print any fractional digits, add a trailing 0 */
17151721
if (numFractionDigits == 0 && pos < maxPrintLen) {
@@ -1718,11 +1724,12 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
17181724
}
17191725
}
17201726
else if (trim_mode == TrimMode_None &&
1721-
digit_mode != DigitMode_Unique &&
1722-
precision > (npy_int32)numFractionDigits && pos < maxPrintLen) {
1727+
digit_mode != DigitMode_Unique &&
1728+
desiredFractionalDigits > numFractionDigits &&
1729+
pos < maxPrintLen) {
17231730
/* add trailing zeros up to precision length */
17241731
/* compute the number of trailing zeros needed */
1725-
npy_uint32 count = precision - numFractionDigits;
1732+
npy_int32 count = desiredFractionalDigits - numFractionDigits;
17261733
if (pos + count > maxPrintLen) {
17271734
count = maxPrintLen - pos;
17281735
}
@@ -1751,7 +1758,7 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
17511758

17521759
/* add any whitespace padding to right side */
17531760
if (digits_right >= numFractionDigits) {
1754-
npy_uint32 count = digits_right - numFractionDigits;
1761+
npy_int32 count = digits_right - numFractionDigits;
17551762

17561763
/* in trim_mode DptZeros, if right padding, add a space for the . */
17571764
if (trim_mode == TrimMode_DptZeros && numFractionDigits == 0
@@ -1769,8 +1776,8 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
17691776
}
17701777
/* add any whitespace padding to left side */
17711778
if (digits_left > numWholeDigits + has_sign) {
1772-
npy_uint32 shift = digits_left - (numWholeDigits + has_sign);
1773-
npy_uint32 count = pos;
1779+
npy_int32 shift = digits_left - (numWholeDigits + has_sign);
1780+
npy_int32 count = pos;
17741781

17751782
if (count + shift > maxPrintLen){
17761783
count = maxPrintLen - shift;
@@ -1781,7 +1788,7 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
17811788
}
17821789
pos = shift + count;
17831790
for ( ; shift > 0; shift--) {
1784-
buffer[shift-1] = ' ';
1791+
buffer[shift - 1] = ' ';
17851792
}
17861793
}
17871794

@@ -1871,7 +1878,8 @@ FormatScientific (char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
18711878
/* insert the decimal point prior to the fractional number */
18721879
numFractionDigits = numDigits-1;
18731880
if (numFractionDigits > 0 && bufferSize > 1) {
1874-
npy_uint32 maxFractionDigits = bufferSize-2;
1881+
npy_int32 maxFractionDigits = (npy_int32)bufferSize - 2;
1882+
18751883
if (numFractionDigits > maxFractionDigits) {
18761884
numFractionDigits = maxFractionDigits;
18771885
}
@@ -1905,9 +1913,10 @@ FormatScientific (char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
19051913
if (precision > (npy_int32)numFractionDigits) {
19061914
char *pEnd;
19071915
/* compute the number of trailing zeros needed */
1908-
npy_uint32 numZeros = (precision - numFractionDigits);
1909-
if (numZeros > bufferSize-1) {
1910-
numZeros = bufferSize-1;
1916+
npy_int32 numZeros = (precision - numFractionDigits);
1917+
1918+
if (numZeros > (npy_int32)bufferSize - 1) {
1919+
numZeros = (npy_int32)bufferSize - 1;
19111920
}
19121921

19131922
for (pEnd = pCurOut + numZeros; pCurOut < pEnd; ++pCurOut) {
@@ -1941,7 +1950,7 @@ FormatScientific (char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
19411950
/* print the exponent into a local buffer and copy into output buffer */
19421951
if (bufferSize > 1) {
19431952
char exponentBuffer[7];
1944-
npy_uint32 digits[5];
1953+
npy_int32 digits[5];
19451954
npy_int32 i, exp_size, count;
19461955

19471956
if (exp_digits > 5) {
@@ -1978,8 +1987,8 @@ FormatScientific (char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
19781987

19791988
/* copy the exponent buffer into the output */
19801989
count = exp_size + 2;
1981-
if (count > bufferSize-1) {
1982-
count = bufferSize-1;
1990+
if (count > (npy_int32)bufferSize - 1) {
1991+
count = (npy_int32)bufferSize - 1;
19831992
}
19841993
memcpy(pCurOut, exponentBuffer, count);
19851994
pCurOut += count;

numpy/core/tests/test_scalarprint.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ def test_dragon4(self):
152152
assert_equal(fpos64('1.5', unique=False, precision=3), "1.500")
153153
assert_equal(fsci32('1.5', unique=False, precision=3), "1.500e+00")
154154
assert_equal(fsci64('1.5', unique=False, precision=3), "1.500e+00")
155+
# gh-10713
156+
assert_equal(fpos64('324', unique=False, precision=5, fractional=False), "324.00")
155157

156158
def test_dragon4_interface(self):
157159
tps = [np.float16, np.float32, np.float64]

0 commit comments

Comments
 (0)
0