You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2019/08/08 17:30:31 UTC

[commons-numbers] 08/18: NUMBERS-120: Don't calculate more bits than necessary in toFloatingPointBits(int, int)

This is an automated email from the ASF dual-hosted git repository.

erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-numbers.git

commit 167f004f167c5177c7944e4c1f5e9d72dcbd1843
Author: Schamschi <he...@gmx.at>
AuthorDate: Thu Jun 27 14:50:01 2019 +0200

    NUMBERS-120: Don't calculate more bits than necessary in toFloatingPointBits(int, int)
---
 .../commons/numbers/fraction/BigFraction.java      | 24 ++++++++++++++--------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
index 3a1a63d..c5410b0 100644
--- a/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
+++ b/commons-numbers-fraction/src/main/java/org/apache/commons/numbers/fraction/BigFraction.java
@@ -712,23 +712,29 @@ public class BigFraction extends Number implements Comparable<BigFraction>, Seri
          * significant bits of the fraction's value using integer division. To
          * guarantee that the quotient of the division has at least
          * (significandLength + 2) bits, the bit length of the dividend must
-         * exceed that of the divisor by at least that amount. If the numerator
-         * has powers of 2 beyond this limit, they can be removed as well.
+         * exceed that of the divisor by at least that amount.
+         *
+         * If the denominator has prime factors other than 2, i.e. if the
+         * divisor was not reduced to 1, an excess of exactly
+         * (significandLength + 2) bits is sufficient, because the knowledge
+         * that the fractional part of the precise quotient's binary
+         * representation does not terminate is enough information to resolve
+         * cases where the most significant (significandLength + 2) bits alone
+         * are not conclusive.
+         *
+         * Otherwise, the quotient must be calculated exactly and the bit length
+         * of the numerator can only be reduced as long as no precision is lost
+         * in the process (meaning it can have powers of 2 removed, like the
+         * denominator).
          */
         int numRightShift = positiveNumerator.bitLength() - divisor.bitLength() - (significandLength + 2);
-        if (numRightShift > 0) {
+        if (numRightShift > 0 && divisor.equals(BigInteger.ONE)) {
             numRightShift = Math.min(numRightShift, positiveNumerator.getLowestSetBit());
         }
         BigInteger dividend = positiveNumerator.shiftRight(numRightShift);
 
         BigInteger quotient = dividend.divide(divisor);
 
-        /*
-         * If the denominator was a power of two, then the divisor was reduced
-         * to 1, meaning the quotient was calculated exactly. Otherwise, the
-         * fractional part of the precise quotient's binary representation does
-         * not terminate.
-         */
         int quotRightShift = quotient.bitLength() - (significandLength + 1);
         long significand = roundAndRightShift(
                 quotient,