Math-Ryu
view release on metacpan or search on metacpan
Ryu_Library/ryu/f2s.c view on Meta::CPAN
} else if (q < 31) { // TODO(ulfjack): Use a tighter bound here.
vrIsTrailingZeros = multipleOfPowerOf2_32(mv, q - 1);
#ifdef RYU_DEBUG
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
#endif
}
}
#ifdef RYU_DEBUG
printf("e10=%d\n", e10);
printf("V+=%u\nV =%u\nV-=%u\n", vp, vr, vm);
printf("vm is trailing zeros=%s\n", vmIsTrailingZeros ? "true" : "false");
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
#endif
// Step 4: Find the shortest decimal representation in the interval of valid representations.
int32_t removed = 0;
uint32_t output;
if (vmIsTrailingZeros || vrIsTrailingZeros) {
// General case, which happens rarely (~4.0%).
while (vp / 10 > vm / 10) {
#ifdef __clang__ // https://bugs.llvm.org/show_bug.cgi?id=23106
// The compiler does not realize that vm % 10 can be computed from vm / 10
// as vm - (vm / 10) * 10.
vmIsTrailingZeros &= vm - (vm / 10) * 10 == 0;
#else
vmIsTrailingZeros &= vm % 10 == 0;
#endif
vrIsTrailingZeros &= lastRemovedDigit == 0;
lastRemovedDigit = (uint8_t) (vr % 10);
vr /= 10;
vp /= 10;
vm /= 10;
++removed;
}
#ifdef RYU_DEBUG
printf("V+=%u\nV =%u\nV-=%u\n", vp, vr, vm);
printf("d-10=%s\n", vmIsTrailingZeros ? "true" : "false");
#endif
if (vmIsTrailingZeros) {
while (vm % 10 == 0) {
vrIsTrailingZeros &= lastRemovedDigit == 0;
lastRemovedDigit = (uint8_t) (vr % 10);
vr /= 10;
vp /= 10;
vm /= 10;
++removed;
}
}
#ifdef RYU_DEBUG
printf("%u %d\n", vr, lastRemovedDigit);
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
#endif
if (vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0) {
// Round even if the exact number is .....50..0.
lastRemovedDigit = 4;
}
// We need to take vr + 1 if vr is outside bounds or we need to round up.
output = vr + ((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || lastRemovedDigit >= 5);
} else {
// Specialized for the common case (~96.0%). Percentages below are relative to this.
// Loop iterations below (approximately):
// 0: 13.6%, 1: 70.7%, 2: 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
while (vp / 10 > vm / 10) {
lastRemovedDigit = (uint8_t) (vr % 10);
vr /= 10;
vp /= 10;
vm /= 10;
++removed;
}
#ifdef RYU_DEBUG
printf("%u %d\n", vr, lastRemovedDigit);
printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
#endif
// We need to take vr + 1 if vr is outside bounds or we need to round up.
output = vr + (vr == vm || lastRemovedDigit >= 5);
}
const int32_t exp = e10 + removed;
#ifdef RYU_DEBUG
printf("V+=%u\nV =%u\nV-=%u\n", vp, vr, vm);
printf("O=%u\n", output);
printf("EXP=%d\n", exp);
#endif
floating_decimal_32 fd;
fd.exponent = exp;
fd.mantissa = output;
return fd;
}
static inline int to_chars(const floating_decimal_32 v, const bool sign, char* const result) {
// Step 5: Print the decimal representation.
int index = 0;
if (sign) {
result[index++] = '-';
}
uint32_t output = v.mantissa;
const uint32_t olength = decimalLength9(output);
#ifdef RYU_DEBUG
printf("DIGITS=%u\n", v.mantissa);
printf("OLEN=%u\n", olength);
printf("EXP=%u\n", v.exponent + olength);
#endif
// Print the decimal digits.
// The following code is equivalent to:
// for (uint32_t i = 0; i < olength - 1; ++i) {
// const uint32_t c = output % 10; output /= 10;
// result[index + olength - i] = (char) ('0' + c);
// }
// result[index] = '0' + output % 10;
uint32_t i = 0;
while (output >= 10000) {
#ifdef __clang__ // https://bugs.llvm.org/show_bug.cgi?id=38217
const uint32_t c = output - 10000 * (output / 10000);
#else
const uint32_t c = output % 10000;
#endif
output /= 10000;
( run in 0.869 second using v1.01-cache-2.11-cpan-71847e10f99 )