Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: dragon4 fractional output mode adds too many trailing zeros #10725

Merged
merged 1 commit into from
Mar 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 36 additions & 27 deletions numpy/core/src/multiarray/dragon4.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ BigInt_ShiftLeft(BigInt *result, npy_uint32 shift)
if (shiftBits == 0) {
npy_uint32 i;

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

/*
* if we are directly in the middle, round towards the even digit (i.e.
* IEEE rouding rules)
* IEEE rounding rules)
*/
if (compare == 0) {
roundDown = (outputDigit & 1) == 0;
Expand Down Expand Up @@ -1588,12 +1588,12 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
npy_int32 digits_right)
{
npy_int32 printExponent;
npy_int32 numDigits, numWholeDigits, has_sign=0;
npy_int32 numDigits, numWholeDigits=0, has_sign=0;

npy_int32 maxPrintLen = bufferSize - 1, pos = 0;
npy_int32 maxPrintLen = (npy_int32)bufferSize - 1, pos = 0;

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

DEBUG_ASSERT(bufferSize > 0);

Expand Down Expand Up @@ -1637,11 +1637,11 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
}
}
/* insert the decimal point prior to the fraction */
else if (numDigits > (npy_uint32)numWholeDigits) {
npy_uint32 maxFractionDigits;
else if (numDigits > numWholeDigits) {
npy_int32 maxFractionDigits;

numFractionDigits = numDigits - numWholeDigits;
maxFractionDigits = maxPrintLen - numWholeDigits -1-pos;
maxFractionDigits = maxPrintLen - numWholeDigits - 1 - pos;
if (numFractionDigits > maxFractionDigits) {
numFractionDigits = maxFractionDigits;
}
Expand All @@ -1656,19 +1656,20 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
}
else {
/* shift out the fraction to make room for the leading zeros */
npy_uint32 numFractionZeros = 0;
npy_int32 numFractionZeros = 0;
if (pos + 2 < maxPrintLen) {
npy_uint32 maxFractionZeros, digitsStartIdx, maxFractionDigits, i;
npy_int32 maxFractionZeros, digitsStartIdx, maxFractionDigits, i;

maxFractionZeros = maxPrintLen - 2 - pos;
numFractionZeros = (npy_uint32)-printExponent - 1;
numFractionZeros = -(printExponent + 1);
if (numFractionZeros > maxFractionZeros) {
numFractionZeros = maxFractionZeros;
}

digitsStartIdx = 2 + numFractionZeros;

/* shift the significant digits right such that there is room for
/*
* shift the significant digits right such that there is room for
* leading zeros
*/
numFractionDigits = numDigits;
Expand Down Expand Up @@ -1710,6 +1711,11 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
buffer[pos++] = '.';
}

desiredFractionalDigits = precision;
if (cutoff_mode == CutoffMode_TotalLength && precision >= 0) {
desiredFractionalDigits = precision - numWholeDigits;
}

if (trim_mode == TrimMode_LeaveOneZero) {
/* if we didn't print any fractional digits, add a trailing 0 */
if (numFractionDigits == 0 && pos < maxPrintLen) {
Expand All @@ -1718,11 +1724,12 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
}
}
else if (trim_mode == TrimMode_None &&
digit_mode != DigitMode_Unique &&
precision > (npy_int32)numFractionDigits && pos < maxPrintLen) {
digit_mode != DigitMode_Unique &&
desiredFractionalDigits > numFractionDigits &&
pos < maxPrintLen) {
/* add trailing zeros up to precision length */
/* compute the number of trailing zeros needed */
npy_uint32 count = precision - numFractionDigits;
npy_int32 count = desiredFractionalDigits - numFractionDigits;
if (pos + count > maxPrintLen) {
count = maxPrintLen - pos;
}
Expand Down Expand Up @@ -1751,7 +1758,7 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,

/* add any whitespace padding to right side */
if (digits_right >= numFractionDigits) {
npy_uint32 count = digits_right - numFractionDigits;
npy_int32 count = digits_right - numFractionDigits;

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

if (count + shift > maxPrintLen){
count = maxPrintLen - shift;
Expand All @@ -1781,7 +1788,7 @@ FormatPositional(char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
}
pos = shift + count;
for ( ; shift > 0; shift--) {
buffer[shift-1] = ' ';
buffer[shift - 1] = ' ';
}
}

Expand Down Expand Up @@ -1871,7 +1878,8 @@ FormatScientific (char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
/* insert the decimal point prior to the fractional number */
numFractionDigits = numDigits-1;
if (numFractionDigits > 0 && bufferSize > 1) {
npy_uint32 maxFractionDigits = bufferSize-2;
npy_int32 maxFractionDigits = (npy_int32)bufferSize - 2;

if (numFractionDigits > maxFractionDigits) {
numFractionDigits = maxFractionDigits;
}
Expand Down Expand Up @@ -1905,9 +1913,10 @@ FormatScientific (char *buffer, npy_uint32 bufferSize, npy_uint64 mantissa,
if (precision > (npy_int32)numFractionDigits) {
char *pEnd;
/* compute the number of trailing zeros needed */
npy_uint32 numZeros = (precision - numFractionDigits);
if (numZeros > bufferSize-1) {
numZeros = bufferSize-1;
npy_int32 numZeros = (precision - numFractionDigits);

if (numZeros > (npy_int32)bufferSize - 1) {
numZeros = (npy_int32)bufferSize - 1;
}

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

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

/* copy the exponent buffer into the output */
count = exp_size + 2;
if (count > bufferSize-1) {
count = bufferSize-1;
if (count > (npy_int32)bufferSize - 1) {
count = (npy_int32)bufferSize - 1;
}
memcpy(pCurOut, exponentBuffer, count);
pCurOut += count;
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/tests/test_scalarprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ def test_dragon4(self):
assert_equal(fpos64('1.5', unique=False, precision=3), "1.500")
assert_equal(fsci32('1.5', unique=False, precision=3), "1.500e+00")
assert_equal(fsci64('1.5', unique=False, precision=3), "1.500e+00")
# gh-10713
assert_equal(fpos64('324', unique=False, precision=5, fractional=False), "324.00")

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