-
Notifications
You must be signed in to change notification settings - Fork 104
Open
Description
When e2 < 0, current RyuFloat calculates dvIsTrailingZeros by the code below, which should be equivalent to mv%2^(q-1) == 0.
dvIsTrailingZeros = (q < FLOAT_MANTISSA_BITS) && (mv & ((1 << (q - 1)) - 1)) == 0;| dvIsTrailingZeros = (q < FLOAT_MANTISSA_BITS) && (mv & ((1 << (q - 1)) - 1)) == 0; |
If I understand correctly, (q < FLOAT_MANTISSA_BITS) is a cap for q that works as follows:
- The maximum value of
vis2^FLOAT_MANTISSA_BITS - 1 - Therefore, when
qis greater than or equal toFLOAT_MANTISSA_BITS,vis never divisible by2^q - So, if
(q < FLOAT_MANTISSA_BITS)is false, we can skip the(mv & ((1 << (q - 1)) - 1)) == 0check
However, I think it should be (q - 1 < FLOAT_MANTISSA_BITS + 2) because:
- We're checking if
mvis divisible by2^(q-1), not2^q. So the left-hand side should beq - 1 - The maximum value of
mvis larger than2^FLOAT_MANTISSA_BITS - 1:mvis4 * m, wheremis the 23-bit mantissa. This meansmv <= 4 * (2^23 - 1) = 2^25 - 4- To check if
mvis divisible by2^(q-1), the conditionq < 23is too restrictive, becausemvcan be divisible by up to2^24 - Therefore, the right-hand side should be
FLOAT_MANTISSA_BITS + 2
Actually, a test from f2s_test.cc's lotsOfTrailingZeros fails in the Java implementation:
Line 69 in 1264a94
| ASSERT_F2S("2.4414062E-3", 2.4414062E-3f); |
1) lotsOfTrailingZeros(info.adams.ryu.RyuFloatTest)
org.junit.ComparisonFailure: expected:<0.002441406[2]> but was:<0.002441406[3]>
This is because:
mv = 41943040,e2 = -34, andq = 23- Therefore,
dvIsTrailingZeros = falsebecauseq < 23is false (but it should be true) - By step 4,
dvis reduced from244140625to24414062(withlastRemovedDigit = 5) - The condition
(dvIsTrailingZeros && (lastRemovedDigit == 5) && (dv % 2 == 0))evaluates to false (but it should be true!), becausedvIsTrailingZeros = false
ryu/src/main/java/info/adams/ryu/RyuFloat.java
Lines 267 to 269 in 1264a94
if (dvIsTrailingZeros && (lastRemovedDigit == 5) && (dv % 2 == 0)) { // Round down not up if the number ends in X50000 and the number is even. lastRemovedDigit = 4;
As a result, it is rounded up to24414063, but it should be rounded to24414062.
Metadata
Metadata
Assignees
Labels
No labels