diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index 207ff9bdf54..d915568a502 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5680,18 +5680,8 @@ public class BigDecimal extends Number implements Comparable { tmp = (dividendHi << shift) | (dividendLo >>> 64 - shift); long u2 = tmp & LONG_MASK; - long q1, r_tmp; - if (v1 == 1) { - q1 = tmp; - r_tmp = 0; - } else if (tmp >= 0) { - q1 = tmp / v1; - r_tmp = tmp - q1 * v1; - } else { - long[] rq = divRemNegativeLong(tmp, v1); - q1 = rq[1]; - r_tmp = rq[0]; - } + long q1 = Long.divideUnsigned(tmp, v1); + long r_tmp = Long.remainderUnsigned(tmp, v1); while(q1 >= DIV_NUM_BASE || unsignedLongCompare(q1*v0, make64(r_tmp, u1))) { q1--; @@ -5702,18 +5692,8 @@ public class BigDecimal extends Number implements Comparable { tmp = mulsub(u2,u1,v1,v0,q1); u1 = tmp & LONG_MASK; - long q0; - if (v1 == 1) { - q0 = tmp; - r_tmp = 0; - } else if (tmp >= 0) { - q0 = tmp / v1; - r_tmp = tmp - q0 * v1; - } else { - long[] rq = divRemNegativeLong(tmp, v1); - q0 = rq[1]; - r_tmp = rq[0]; - } + long q0 = Long.divideUnsigned(tmp, v1); + r_tmp = Long.remainderUnsigned(tmp, v1); while(q0 >= DIV_NUM_BASE || unsignedLongCompare(q0*v0,make64(r_tmp,u0))) { q0--; @@ -5793,37 +5773,6 @@ public class BigDecimal extends Number implements Comparable { } } - /** - * Calculate the quotient and remainder of dividing a negative long by - * another long. - * - * @param n the numerator; must be negative - * @param d the denominator; must not be unity - * @return a two-element {@code long} array with the remainder and quotient in - * the initial and final elements, respectively - */ - private static long[] divRemNegativeLong(long n, long d) { - assert n < 0 : "Non-negative numerator " + n; - assert d != 1 : "Unity denominator"; - - // Approximate the quotient and remainder - long q = (n >>> 1) / (d >>> 1); - long r = n - q * d; - - // Correct the approximation - while (r < 0) { - r += d; - q--; - } - while (r >= d) { - r -= d; - q++; - } - - // n - q*d == r && 0 <= r < d, hence we're done. - return new long[] {r, q}; - } - private static long make64(long hi, long lo) { return hi<<32 | lo; } diff --git a/src/java.base/share/classes/java/math/MutableBigInteger.java b/src/java.base/share/classes/java/math/MutableBigInteger.java index eca42ee25b1..30ea8e130fc 100644 --- a/src/java.base/share/classes/java/math/MutableBigInteger.java +++ b/src/java.base/share/classes/java/math/MutableBigInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1092,9 +1092,9 @@ class MutableBigInteger { // Special case of one word dividend if (intLen == 1) { - long dividendValue = value[offset] & LONG_MASK; - int q = (int) (dividendValue / divisorLong); - int r = (int) (dividendValue - q * divisorLong); + int dividendValue = value[offset]; + int q = Integer.divideUnsigned(dividendValue, divisor); + int r = Integer.remainderUnsigned(dividendValue, divisor); quotient.value[0] = q; quotient.intLen = (q == 0) ? 0 : 1; quotient.offset = 0; @@ -1106,41 +1106,17 @@ class MutableBigInteger { quotient.offset = 0; quotient.intLen = intLen; - // Normalize the divisor - int shift = Integer.numberOfLeadingZeros(divisor); - - int rem = value[offset]; - long remLong = rem & LONG_MASK; - if (remLong < divisorLong) { - quotient.value[0] = 0; - } else { - quotient.value[0] = (int)(remLong / divisorLong); - rem = (int) (remLong - (quotient.value[0] * divisorLong)); - remLong = rem & LONG_MASK; - } - int xlen = intLen; - while (--xlen > 0) { - long dividendEstimate = (remLong << 32) | + long rem = 0; + for (int xlen = intLen; xlen > 0; xlen--) { + long dividendEstimate = (rem << 32) | (value[offset + intLen - xlen] & LONG_MASK); - int q; - if (dividendEstimate >= 0) { - q = (int) (dividendEstimate / divisorLong); - rem = (int) (dividendEstimate - q * divisorLong); - } else { - long tmp = divWord(dividendEstimate, divisor); - q = (int) (tmp & LONG_MASK); - rem = (int) (tmp >>> 32); - } + int q = (int) Long.divideUnsigned(dividendEstimate, divisorLong); + rem = Long.remainderUnsigned(dividendEstimate, divisorLong); quotient.value[intLen - xlen] = q; - remLong = rem & LONG_MASK; } quotient.normalize(); - // Unnormalize - if (shift > 0) - return rem % divisor; - else - return rem; + return (int)rem; } /** @@ -1557,14 +1533,8 @@ class MutableBigInteger { skipCorrection = qrem + 0x80000000 < nh2; } else { long nChunk = (((long)nh) << 32) | (nm & LONG_MASK); - if (nChunk >= 0) { - qhat = (int) (nChunk / dhLong); - qrem = (int) (nChunk - (qhat * dhLong)); - } else { - long tmp = divWord(nChunk, dh); - qhat = (int) (tmp & LONG_MASK); - qrem = (int) (tmp >>> 32); - } + qhat = (int) Long.divideUnsigned(nChunk, dhLong); + qrem = (int) Long.remainderUnsigned(nChunk, dhLong); } if (qhat == 0) @@ -1616,14 +1586,8 @@ class MutableBigInteger { skipCorrection = qrem + 0x80000000 < nh2; } else { long nChunk = (((long) nh) << 32) | (nm & LONG_MASK); - if (nChunk >= 0) { - qhat = (int) (nChunk / dhLong); - qrem = (int) (nChunk - (qhat * dhLong)); - } else { - long tmp = divWord(nChunk, dh); - qhat = (int) (tmp & LONG_MASK); - qrem = (int) (tmp >>> 32); - } + qhat = (int) Long.divideUnsigned(nChunk, dhLong); + qrem = (int) Long.remainderUnsigned(nChunk, dhLong); } if (qhat != 0) { if (!skipCorrection) { // Correct qhat @@ -1732,14 +1696,8 @@ class MutableBigInteger { skipCorrection = qrem + 0x80000000 < nh2; } else { long nChunk = (((long) nh) << 32) | (nm & LONG_MASK); - if (nChunk >= 0) { - qhat = (int) (nChunk / dhLong); - qrem = (int) (nChunk - (qhat * dhLong)); - } else { - long tmp = divWord(nChunk, dh); - qhat =(int)(tmp & LONG_MASK); - qrem = (int)(tmp>>>32); - } + qhat = (int) Long.divideUnsigned(nChunk, dhLong); + qrem = (int) Long.remainderUnsigned(nChunk, dhLong); } if (qhat == 0) @@ -1834,40 +1792,6 @@ class MutableBigInteger { return (one+Long.MIN_VALUE) > (two+Long.MIN_VALUE); } - /** - * This method divides a long quantity by an int to estimate - * qhat for two multi precision numbers. It is used when - * the signed value of n is less than zero. - * Returns long value where high 32 bits contain remainder value and - * low 32 bits contain quotient value. - */ - static long divWord(long n, int d) { - long dLong = d & LONG_MASK; - long r; - long q; - if (dLong == 1) { - q = (int)n; - r = 0; - return (r << 32) | (q & LONG_MASK); - } - - // Approximate the quotient and remainder - q = (n >>> 1) / (dLong >>> 1); - r = n - q*dLong; - - // Correct the approximation - while (r < 0) { - r += dLong; - q--; - } - while (r >= dLong) { - r -= dLong; - q++; - } - // n - q*dlong == r && 0 <= r