mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8331907: BigInteger and BigDecimal should use optimized division
Reviewed-by: rgiulietti, bpb
This commit is contained in:
parent
440782e016
commit
beea5305b0
4 changed files with 89 additions and 186 deletions
|
@ -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<BigDecimal> {
|
|||
|
||||
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<BigDecimal> {
|
|||
|
||||
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<BigDecimal> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue