Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
60839a4f
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
60839a4f
编写于
9月 01, 2011
作者:
D
darcy
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7082971: More performance tuning of BigDecimal and other java.math classes
Reviewed-by: darcy Contributed-by: sergey.kuksenko@oracle.com
上级
509f241d
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
2620 addition
and
772 deletion
+2620
-772
src/share/classes/java/math/BigDecimal.java
src/share/classes/java/math/BigDecimal.java
+2031
-675
src/share/classes/java/math/BigInteger.java
src/share/classes/java/math/BigInteger.java
+230
-31
src/share/classes/java/math/MutableBigInteger.java
src/share/classes/java/math/MutableBigInteger.java
+352
-60
test/java/math/BigDecimal/DivideMcTests.java
test/java/math/BigDecimal/DivideMcTests.java
+1
-1
test/java/math/BigDecimal/FloatDoubleValueTests.java
test/java/math/BigDecimal/FloatDoubleValueTests.java
+3
-2
test/java/math/BigDecimal/RangeTests.java
test/java/math/BigDecimal/RangeTests.java
+1
-1
test/java/math/BigDecimal/StrippingZerosTest.java
test/java/math/BigDecimal/StrippingZerosTest.java
+1
-1
test/java/math/BigDecimal/ToPlainStringTests.java
test/java/math/BigDecimal/ToPlainStringTests.java
+1
-1
未找到文件。
src/share/classes/java/math/BigDecimal.java
浏览文件 @
60839a4f
...
@@ -215,6 +215,7 @@ import static java.math.BigInteger.LONG_MASK;
...
@@ -215,6 +215,7 @@ import static java.math.BigInteger.LONG_MASK;
* @author Josh Bloch
* @author Josh Bloch
* @author Mike Cowlishaw
* @author Mike Cowlishaw
* @author Joseph D. Darcy
* @author Joseph D. Darcy
* @author Sergey V. Kuksenko
*/
*/
public
class
BigDecimal
extends
Number
implements
Comparable
<
BigDecimal
>
{
public
class
BigDecimal
extends
Number
implements
Comparable
<
BigDecimal
>
{
/**
/**
...
@@ -224,7 +225,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -224,7 +225,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @serial
* @serial
* @see #unscaledValue
* @see #unscaledValue
*/
*/
private
volatile
BigInteger
intVal
;
private
final
BigInteger
intVal
;
/**
/**
* The scale of this BigDecimal, as returned by {@link #scale}.
* The scale of this BigDecimal, as returned by {@link #scale}.
...
@@ -232,8 +233,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -232,8 +233,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @serial
* @serial
* @see #scale
* @see #scale
*/
*/
private
int
scale
;
// Note: this may have any value, so
private
final
int
scale
;
// Note: this may have any value, so
// calculations must be done in longs
// calculations must be done in longs
/**
/**
* The number of decimal digits in this BigDecimal, or 0 if the
* The number of decimal digits in this BigDecimal, or 0 if the
* number of digits are not known (lookaside information). If
* number of digits are not known (lookaside information). If
...
@@ -256,19 +258,19 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -256,19 +258,19 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
static
final
long
INFLATED
=
Long
.
MIN_VALUE
;
static
final
long
INFLATED
=
Long
.
MIN_VALUE
;
private
static
final
BigInteger
INFLATED_BIGINT
=
BigInteger
.
valueOf
(
INFLATED
);
/**
/**
* If the absolute value of the significand of this BigDecimal is
* If the absolute value of the significand of this BigDecimal is
* less than or equal to {@code Long.MAX_VALUE}, the value can be
* less than or equal to {@code Long.MAX_VALUE}, the value can be
* compactly stored in this field and used in computations.
* compactly stored in this field and used in computations.
*/
*/
private
transient
long
intCompact
;
private
final
transient
long
intCompact
;
// All 18-digit base ten strings fit into a long; not all 19-digit
// All 18-digit base ten strings fit into a long; not all 19-digit
// strings will
// strings will
private
static
final
int
MAX_COMPACT_DIGITS
=
18
;
private
static
final
int
MAX_COMPACT_DIGITS
=
18
;
private
static
final
int
MAX_BIGINT_BITS
=
62
;
/* Appease the serialization gods */
/* Appease the serialization gods */
private
static
final
long
serialVersionUID
=
6108874887143696463L
;
private
static
final
long
serialVersionUID
=
6108874887143696463L
;
...
@@ -282,17 +284,17 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -282,17 +284,17 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// Cache of common small BigDecimal values.
// Cache of common small BigDecimal values.
private
static
final
BigDecimal
zeroThroughTen
[]
=
{
private
static
final
BigDecimal
zeroThroughTen
[]
=
{
new
BigDecimal
(
BigInteger
.
ZERO
,
0
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
ZERO
,
0
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
ONE
,
1
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
ONE
,
1
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
2
),
2
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
2
),
2
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
3
),
3
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
3
),
3
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
4
),
4
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
4
),
4
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
5
),
5
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
5
),
5
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
6
),
6
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
6
),
6
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
7
),
7
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
7
),
7
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
8
),
8
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
8
),
8
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
9
),
9
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
valueOf
(
9
),
9
,
0
,
1
),
new
BigDecimal
(
BigInteger
.
TEN
,
10
,
0
,
2
),
new
BigDecimal
(
BigInteger
.
TEN
,
10
,
0
,
2
),
};
};
// Cache of zero scaled by 0 - 15
// Cache of zero scaled by 0 - 15
...
@@ -378,9 +380,36 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -378,9 +380,36 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
char
[]
in
,
int
offset
,
int
len
)
{
public
BigDecimal
(
char
[]
in
,
int
offset
,
int
len
)
{
this
(
in
,
offset
,
len
,
MathContext
.
UNLIMITED
);
}
/**
* Translates a character array representation of a
* {@code BigDecimal} into a {@code BigDecimal}, accepting the
* same sequence of characters as the {@link #BigDecimal(String)}
* constructor, while allowing a sub-array to be specified and
* with rounding according to the context settings.
*
* <p>Note that if the sequence of characters is already available
* within a character array, using this constructor is faster than
* converting the {@code char} array to string and using the
* {@code BigDecimal(String)} constructor .
*
* @param in {@code char} array that is the source of characters.
* @param offset first character in the array to inspect.
* @param len number of characters to consider..
* @param mc the context to use.
* @throws ArithmeticException if the result is inexact but the
* rounding mode is {@code UNNECESSARY}.
* @throws NumberFormatException if {@code in} is not a valid
* representation of a {@code BigDecimal} or the defined subarray
* is not wholly within {@code in}.
* @since 1.5
*/
public
BigDecimal
(
char
[]
in
,
int
offset
,
int
len
,
MathContext
mc
)
{
// protect against huge length.
// protect against huge length.
if
(
offset
+
len
>
in
.
length
||
offset
<
0
)
if
(
offset
+
len
>
in
.
length
||
offset
<
0
)
throw
new
NumberFormatException
();
throw
new
NumberFormatException
(
"Bad offset or len arguments for char[] input."
);
// This is the primary string to BigDecimal constructor; all
// This is the primary string to BigDecimal constructor; all
// incoming strings end up here; it uses explicit (inline)
// incoming strings end up here; it uses explicit (inline)
// parsing for speed and generates at most one intermediate
// parsing for speed and generates at most one intermediate
...
@@ -391,7 +420,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -391,7 +420,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
int
scl
=
0
;
// record scale value
int
scl
=
0
;
// record scale value
long
rs
=
0
;
// the compact value in long
long
rs
=
0
;
// the compact value in long
BigInteger
rb
=
null
;
// the inflated value in BigInteger
BigInteger
rb
=
null
;
// the inflated value in BigInteger
// use array bounds checking to handle too-long, len == 0,
// use array bounds checking to handle too-long, len == 0,
// bad offset, etc.
// bad offset, etc.
try
{
try
{
...
@@ -408,23 +436,39 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -408,23 +436,39 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// should now be at numeric part of the significand
// should now be at numeric part of the significand
boolean
dot
=
false
;
// true when there is a '.'
boolean
dot
=
false
;
// true when there is a '.'
int
cfirst
=
offset
;
// record start of integer
long
exp
=
0
;
// exponent
long
exp
=
0
;
// exponent
char
c
;
// current character
char
c
;
// current character
boolean
isCompact
=
(
len
<=
MAX_COMPACT_DIGITS
);
boolean
isCompact
=
(
len
<=
MAX_COMPACT_DIGITS
);
// integer significand array & idx is the index to it. The array
// integer significand array & idx is the index to it. The array
// is ONLY used when we can't use a compact representation.
// is ONLY used when we can't use a compact representation.
char
coeff
[]
=
isCompact
?
null
:
new
char
[
len
];
int
idx
=
0
;
int
idx
=
0
;
if
(
isCompact
)
{
for
(;
len
>
0
;
offset
++,
len
--)
{
// First compact case, we need not to preserve the character
c
=
in
[
offset
];
// and we can just compute the value in place.
// have digit
for
(;
len
>
0
;
offset
++,
len
--)
{
if
((
c
>=
'0'
&&
c
<=
'9'
)
||
Character
.
isDigit
(
c
))
{
c
=
in
[
offset
];
// First compact case, we need not to preserve the character
if
((
c
==
'0'
))
{
// have zero
// and we can just compute the value in place.
if
(
prec
==
0
)
if
(
isCompact
)
{
prec
=
1
;
else
if
(
rs
!=
0
)
{
rs
*=
10
;
++
prec
;
}
// else digit is a redundant leading zero
if
(
dot
)
++
scl
;
}
else
if
((
c
>=
'1'
&&
c
<=
'9'
))
{
// have digit
int
digit
=
c
-
'0'
;
if
(
prec
!=
1
||
rs
!=
0
)
++
prec
;
// prec unchanged if preceded by 0s
rs
=
rs
*
10
+
digit
;
if
(
dot
)
++
scl
;
}
else
if
(
c
==
'.'
)
{
// have dot
// have dot
if
(
dot
)
// two dots
throw
new
NumberFormatException
();
dot
=
true
;
}
else
if
(
Character
.
isDigit
(
c
))
{
// slow path
int
digit
=
Character
.
digit
(
c
,
10
);
int
digit
=
Character
.
digit
(
c
,
10
);
if
(
digit
==
0
)
{
if
(
digit
==
0
)
{
if
(
prec
==
0
)
if
(
prec
==
0
)
...
@@ -438,7 +482,44 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -438,7 +482,44 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
++
prec
;
// prec unchanged if preceded by 0s
++
prec
;
// prec unchanged if preceded by 0s
rs
=
rs
*
10
+
digit
;
rs
=
rs
*
10
+
digit
;
}
}
}
else
{
// the unscaled value is likely a BigInteger object.
if
(
dot
)
++
scl
;
}
else
if
((
c
==
'e'
)
||
(
c
==
'E'
))
{
exp
=
parseExp
(
in
,
offset
,
len
);
// Next test is required for backwards compatibility
if
((
int
)
exp
!=
exp
)
// overflow
throw
new
NumberFormatException
();
break
;
// [saves a test]
}
else
{
throw
new
NumberFormatException
();
}
}
if
(
prec
==
0
)
// no digits found
throw
new
NumberFormatException
();
// Adjust scale if exp is not zero.
if
(
exp
!=
0
)
{
// had significant exponent
scl
=
adjustScale
(
scl
,
exp
);
}
rs
=
isneg
?
-
rs
:
rs
;
int
mcp
=
mc
.
precision
;
int
drop
=
prec
-
mcp
;
// prec has range [1, MAX_INT], mcp has range [0, MAX_INT];
// therefore, this subtract cannot overflow
if
(
mcp
>
0
&&
drop
>
0
)
{
// do rounding
while
(
drop
>
0
)
{
scl
=
checkScaleNonZero
((
long
)
scl
-
drop
);
rs
=
divideAndRound
(
rs
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
rs
);
drop
=
prec
-
mcp
;
}
}
}
else
{
char
coeff
[]
=
new
char
[
len
];
for
(;
len
>
0
;
offset
++,
len
--)
{
c
=
in
[
offset
];
// have digit
if
((
c
>=
'0'
&&
c
<=
'9'
)
||
Character
.
isDigit
(
c
))
{
// First compact case, we need not to preserve the character
// and we can just compute the value in place.
if
(
c
==
'0'
||
Character
.
digit
(
c
,
10
)
==
0
)
{
if
(
c
==
'0'
||
Character
.
digit
(
c
,
10
)
==
0
)
{
if
(
prec
==
0
)
{
if
(
prec
==
0
)
{
coeff
[
idx
]
=
c
;
coeff
[
idx
]
=
c
;
...
@@ -452,94 +533,64 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -452,94 +533,64 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
++
prec
;
// prec unchanged if preceded by 0s
++
prec
;
// prec unchanged if preceded by 0s
coeff
[
idx
++]
=
c
;
coeff
[
idx
++]
=
c
;
}
}
if
(
dot
)
++
scl
;
continue
;
}
}
if
(
dot
)
++
scl
;
continue
;
}
// have dot
if
(
c
==
'.'
)
{
// have dot
// have dot
if
(
dot
)
// two dots
if
(
c
==
'.'
)
{
throw
new
NumberFormatException
();
// have dot
dot
=
true
;
if
(
dot
)
// two dots
continue
;
}
// exponent expected
if
((
c
!=
'e'
)
&&
(
c
!=
'E'
))
throw
new
NumberFormatException
();
offset
++;
c
=
in
[
offset
];
len
--;
boolean
negexp
=
(
c
==
'-'
);
// optional sign
if
(
negexp
||
c
==
'+'
)
{
offset
++;
c
=
in
[
offset
];
len
--;
}
if
(
len
<=
0
)
// no exponent digits
throw
new
NumberFormatException
();
// skip leading zeros in the exponent
while
(
len
>
10
&&
Character
.
digit
(
c
,
10
)
==
0
)
{
offset
++;
c
=
in
[
offset
];
len
--;
}
if
(
len
>
10
)
// too many nonzero exponent digits
throw
new
NumberFormatException
();
// c now holds first digit of exponent
for
(;;
len
--)
{
int
v
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
v
=
c
-
'0'
;
}
else
{
v
=
Character
.
digit
(
c
,
10
);
if
(
v
<
0
)
// not a digit
throw
new
NumberFormatException
();
throw
new
NumberFormatException
();
dot
=
true
;
continue
;
}
}
exp
=
exp
*
10
+
v
;
// exponent expected
if
(
len
==
1
)
if
((
c
!=
'e'
)
&&
(
c
!=
'E'
))
break
;
// that was final character
throw
new
NumberFormatException
();
offset
++;
exp
=
parseExp
(
in
,
offset
,
len
);
c
=
in
[
offset
];
// Next test is required for backwards compatibility
if
((
int
)
exp
!=
exp
)
// overflow
throw
new
NumberFormatException
();
break
;
// [saves a test]
}
}
if
(
negexp
)
// apply sign
// here when no characters left
exp
=
-
exp
;
if
(
prec
==
0
)
// no digits found
// Next test is required for backwards compatibility
if
((
int
)
exp
!=
exp
)
// overflow
throw
new
NumberFormatException
();
throw
new
NumberFormatException
();
break
;
// [saves a test]
// Adjust scale if exp is not zero.
}
if
(
exp
!=
0
)
{
// had significant exponent
// here when no characters left
scl
=
adjustScale
(
scl
,
exp
);
if
(
prec
==
0
)
// no digits found
throw
new
NumberFormatException
();
// Adjust scale if exp is not zero.
if
(
exp
!=
0
)
{
// had significant exponent
// Can't call checkScale which relies on proper fields value
long
adjustedScale
=
scl
-
exp
;
if
(
adjustedScale
>
Integer
.
MAX_VALUE
||
adjustedScale
<
Integer
.
MIN_VALUE
)
throw
new
NumberFormatException
(
"Scale out of range."
);
scl
=
(
int
)
adjustedScale
;
}
// Remove leading zeros from precision (digits count)
if
(
isCompact
)
{
rs
=
isneg
?
-
rs
:
rs
;
}
else
{
char
quick
[];
if
(!
isneg
)
{
quick
=
(
coeff
.
length
!=
prec
)
?
Arrays
.
copyOf
(
coeff
,
prec
)
:
coeff
;
}
else
{
quick
=
new
char
[
prec
+
1
];
quick
[
0
]
=
'-'
;
System
.
arraycopy
(
coeff
,
0
,
quick
,
1
,
prec
);
}
}
rb
=
new
BigInteger
(
quick
);
// Remove leading zeros from precision (digits count)
rb
=
new
BigInteger
(
coeff
,
isneg
?
-
1
:
1
,
prec
);
rs
=
compactValFor
(
rb
);
rs
=
compactValFor
(
rb
);
int
mcp
=
mc
.
precision
;
if
(
mcp
>
0
&&
(
prec
>
mcp
))
{
if
(
rs
==
INFLATED
)
{
int
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scl
=
checkScaleNonZero
((
long
)
scl
-
drop
);
rb
=
divideAndRoundByTenPow
(
rb
,
drop
,
mc
.
roundingMode
.
oldMode
);
rs
=
compactValFor
(
rb
);
if
(
rs
!=
INFLATED
)
{
prec
=
longDigitLength
(
rs
);
break
;
}
prec
=
bigDigitLength
(
rb
);
drop
=
prec
-
mcp
;
}
}
if
(
rs
!=
INFLATED
)
{
int
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scl
=
checkScaleNonZero
((
long
)
scl
-
drop
);
rs
=
divideAndRound
(
rs
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
rs
);
drop
=
prec
-
mcp
;
}
rb
=
null
;
}
}
}
}
}
catch
(
ArrayIndexOutOfBoundsException
e
)
{
}
catch
(
ArrayIndexOutOfBoundsException
e
)
{
throw
new
NumberFormatException
();
throw
new
NumberFormatException
();
...
@@ -549,36 +600,61 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -549,36 +600,61 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
this
.
scale
=
scl
;
this
.
scale
=
scl
;
this
.
precision
=
prec
;
this
.
precision
=
prec
;
this
.
intCompact
=
rs
;
this
.
intCompact
=
rs
;
this
.
intVal
=
(
rs
!=
INFLATED
)
?
null
:
rb
;
this
.
intVal
=
rb
;
}
}
/**
private
int
adjustScale
(
int
scl
,
long
exp
)
{
* Translates a character array representation of a
long
adjustedScale
=
scl
-
exp
;
* {@code BigDecimal} into a {@code BigDecimal}, accepting the
if
(
adjustedScale
>
Integer
.
MAX_VALUE
||
adjustedScale
<
Integer
.
MIN_VALUE
)
* same sequence of characters as the {@link #BigDecimal(String)}
throw
new
NumberFormatException
(
"Scale out of range."
);
* constructor, while allowing a sub-array to be specified and
scl
=
(
int
)
adjustedScale
;
* with rounding according to the context settings.
return
scl
;
*
}
* <p>Note that if the sequence of characters is already available
* within a character array, using this constructor is faster than
/*
* converting the {@code char} array to string and using the
* parse exponent
* {@code BigDecimal(String)} constructor .
*
* @param in {@code char} array that is the source of characters.
* @param offset first character in the array to inspect.
* @param len number of characters to consider..
* @param mc the context to use.
* @throws ArithmeticException if the result is inexact but the
* rounding mode is {@code UNNECESSARY}.
* @throws NumberFormatException if {@code in} is not a valid
* representation of a {@code BigDecimal} or the defined subarray
* is not wholly within {@code in}.
* @since 1.5
*/
*/
public
BigDecimal
(
char
[]
in
,
int
offset
,
int
len
,
MathContext
mc
)
{
private
static
long
parseExp
(
char
[]
in
,
int
offset
,
int
len
){
this
(
in
,
offset
,
len
);
long
exp
=
0
;
if
(
mc
.
precision
>
0
)
offset
++;
roundThis
(
mc
);
char
c
=
in
[
offset
];
len
--;
boolean
negexp
=
(
c
==
'-'
);
// optional sign
if
(
negexp
||
c
==
'+'
)
{
offset
++;
c
=
in
[
offset
];
len
--;
}
if
(
len
<=
0
)
// no exponent digits
throw
new
NumberFormatException
();
// skip leading zeros in the exponent
while
(
len
>
10
&&
(
c
==
'0'
||
(
Character
.
digit
(
c
,
10
)
==
0
)))
{
offset
++;
c
=
in
[
offset
];
len
--;
}
if
(
len
>
10
)
// too many nonzero exponent digits
throw
new
NumberFormatException
();
// c now holds first digit of exponent
for
(;;
len
--)
{
int
v
;
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
v
=
c
-
'0'
;
}
else
{
v
=
Character
.
digit
(
c
,
10
);
if
(
v
<
0
)
// not a digit
throw
new
NumberFormatException
();
}
exp
=
exp
*
10
+
v
;
if
(
len
==
1
)
break
;
// that was final character
offset
++;
c
=
in
[
offset
];
}
if
(
negexp
)
// apply sign
exp
=
-
exp
;
return
exp
;
}
}
/**
/**
...
@@ -754,9 +830,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -754,9 +830,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
String
val
,
MathContext
mc
)
{
public
BigDecimal
(
String
val
,
MathContext
mc
)
{
this
(
val
.
toCharArray
(),
0
,
val
.
length
());
this
(
val
.
toCharArray
(),
0
,
val
.
length
(),
mc
);
if
(
mc
.
precision
>
0
)
roundThis
(
mc
);
}
}
/**
/**
...
@@ -804,49 +878,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -804,49 +878,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @throws NumberFormatException if {@code val} is infinite or NaN.
* @throws NumberFormatException if {@code val} is infinite or NaN.
*/
*/
public
BigDecimal
(
double
val
)
{
public
BigDecimal
(
double
val
)
{
if
(
Double
.
isInfinite
(
val
)
||
Double
.
isNaN
(
val
))
this
(
val
,
MathContext
.
UNLIMITED
);
throw
new
NumberFormatException
(
"Infinite or NaN"
);
// Translate the double into sign, exponent and significand, according
// to the formulae in JLS, Section 20.10.22.
long
valBits
=
Double
.
doubleToLongBits
(
val
);
int
sign
=
((
valBits
>>
63
)==
0
?
1
:
-
1
);
int
exponent
=
(
int
)
((
valBits
>>
52
)
&
0x7ff
L
);
long
significand
=
(
exponent
==
0
?
(
valBits
&
((
1L
<<
52
)
-
1
))
<<
1
:
(
valBits
&
((
1L
<<
52
)
-
1
))
|
(
1L
<<
52
));
exponent
-=
1075
;
// At this point, val == sign * significand * 2**exponent.
/*
* Special case zero to supress nonterminating normalization
* and bogus scale calculation.
*/
if
(
significand
==
0
)
{
intVal
=
BigInteger
.
ZERO
;
intCompact
=
0
;
precision
=
1
;
return
;
}
// Normalize
while
((
significand
&
1
)
==
0
)
{
// i.e., significand is even
significand
>>=
1
;
exponent
++;
}
// Calculate intVal and scale
long
s
=
sign
*
significand
;
BigInteger
b
;
if
(
exponent
<
0
)
{
b
=
BigInteger
.
valueOf
(
5
).
pow
(-
exponent
).
multiply
(
s
);
scale
=
-
exponent
;
}
else
if
(
exponent
>
0
)
{
b
=
BigInteger
.
valueOf
(
2
).
pow
(
exponent
).
multiply
(
s
);
}
else
{
b
=
BigInteger
.
valueOf
(
s
);
}
intCompact
=
compactValFor
(
b
);
intVal
=
(
intCompact
!=
INFLATED
)
?
null
:
b
;
}
}
/**
/**
...
@@ -868,9 +900,86 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -868,9 +900,86 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
double
val
,
MathContext
mc
)
{
public
BigDecimal
(
double
val
,
MathContext
mc
)
{
this
(
val
);
if
(
Double
.
isInfinite
(
val
)
||
Double
.
isNaN
(
val
))
if
(
mc
.
precision
>
0
)
throw
new
NumberFormatException
(
"Infinite or NaN"
);
roundThis
(
mc
);
// Translate the double into sign, exponent and significand, according
// to the formulae in JLS, Section 20.10.22.
int
sign
=
(
val
>=
0.0
?
1
:
-
1
);
// Preserving sign of zero doesn't matter
int
exponent
=
Math
.
getExponent
(
val
);
long
valBits
=
Double
.
doubleToLongBits
(
val
);
long
significand
=
(
exponent
==
(
Double
.
MIN_EXPONENT
-
1
)
?
(
valBits
&
((
1L
<<
52
)
-
1
))
<<
1
:
(
valBits
&
((
1L
<<
52
)
-
1
))
|
(
1L
<<
52
));
// At this point, val == sign * significand * 2**exponent.
/*
* Special case zero to supress nonterminating normalization and bogus
* scale calculation.
*/
if
(
significand
==
0
)
{
this
.
intVal
=
BigInteger
.
ZERO
;
this
.
scale
=
0
;
this
.
intCompact
=
0
;
this
.
precision
=
1
;
return
;
}
// Normalize
while
((
significand
&
1
)
==
0
)
{
// i.e., significand is even
significand
>>=
1
;
exponent
++;
}
int
scale
=
0
;
// Calculate intVal and scale
BigInteger
intVal
;
long
compactVal
=
sign
*
significand
;
if
(
exponent
==
0
)
{
// If the exponent is zero, the significant fits in a long
assert
compactVal
!=
INFLATED
;
intVal
=
null
;
}
else
{
if
(
exponent
<
0
)
{
intVal
=
BigInteger
.
valueOf
(
5
).
pow
(-
exponent
).
multiply
(
compactVal
);
scale
=
-
exponent
;
}
else
{
// (exponent > 0)
intVal
=
BigInteger
.
valueOf
(
2
).
pow
(
exponent
).
multiply
(
compactVal
);
}
compactVal
=
compactValFor
(
intVal
);
}
int
prec
=
0
;
int
mcp
=
mc
.
precision
;
if
(
mcp
>
0
)
{
// do rounding
int
mode
=
mc
.
roundingMode
.
oldMode
;
int
drop
;
if
(
compactVal
==
INFLATED
)
{
prec
=
bigDigitLength
(
intVal
);
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
intVal
=
divideAndRoundByTenPow
(
intVal
,
drop
,
mode
);
compactVal
=
compactValFor
(
intVal
);
if
(
compactVal
!=
INFLATED
)
{
break
;
}
prec
=
bigDigitLength
(
intVal
);
drop
=
prec
-
mcp
;
}
}
if
(
compactVal
!=
INFLATED
)
{
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
compactVal
=
divideAndRound
(
compactVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
}
intVal
=
null
;
}
}
this
.
intVal
=
intVal
;
this
.
intCompact
=
compactVal
;
this
.
scale
=
scale
;
this
.
precision
=
prec
;
}
}
/**
/**
...
@@ -881,8 +990,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -881,8 +990,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* {@code BigDecimal}.
* {@code BigDecimal}.
*/
*/
public
BigDecimal
(
BigInteger
val
)
{
public
BigDecimal
(
BigInteger
val
)
{
scale
=
0
;
intVal
=
val
;
intCompact
=
compactValFor
(
val
);
intCompact
=
compactValFor
(
val
);
intVal
=
(
intCompact
!=
INFLATED
)
?
null
:
val
;
}
}
/**
/**
...
@@ -898,9 +1008,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -898,9 +1008,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
BigInteger
val
,
MathContext
mc
)
{
public
BigDecimal
(
BigInteger
val
,
MathContext
mc
)
{
this
(
val
);
this
(
val
,
0
,
mc
);
if
(
mc
.
precision
>
0
)
roundThis
(
mc
);
}
}
/**
/**
...
@@ -914,7 +1022,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -914,7 +1022,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
public
BigDecimal
(
BigInteger
unscaledVal
,
int
scale
)
{
public
BigDecimal
(
BigInteger
unscaledVal
,
int
scale
)
{
// Negative scales are now allowed
// Negative scales are now allowed
this
(
unscaledVal
);
this
.
intVal
=
unscaledVal
;
this
.
intCompact
=
compactValFor
(
unscaledVal
);
this
.
scale
=
scale
;
this
.
scale
=
scale
;
}
}
...
@@ -934,10 +1043,41 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -934,10 +1043,41 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
BigInteger
unscaledVal
,
int
scale
,
MathContext
mc
)
{
public
BigDecimal
(
BigInteger
unscaledVal
,
int
scale
,
MathContext
mc
)
{
this
(
unscaledVal
);
long
compactVal
=
compactValFor
(
unscaledVal
);
int
mcp
=
mc
.
precision
;
int
prec
=
0
;
if
(
mcp
>
0
)
{
// do rounding
int
mode
=
mc
.
roundingMode
.
oldMode
;
if
(
compactVal
==
INFLATED
)
{
prec
=
bigDigitLength
(
unscaledVal
);
int
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
unscaledVal
=
divideAndRoundByTenPow
(
unscaledVal
,
drop
,
mode
);
compactVal
=
compactValFor
(
unscaledVal
);
if
(
compactVal
!=
INFLATED
)
{
break
;
}
prec
=
bigDigitLength
(
unscaledVal
);
drop
=
prec
-
mcp
;
}
}
if
(
compactVal
!=
INFLATED
)
{
prec
=
longDigitLength
(
compactVal
);
int
drop
=
prec
-
mcp
;
// drop can't be more than 18
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
compactVal
=
divideAndRound
(
compactVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
mode
);
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
}
unscaledVal
=
null
;
}
}
this
.
intVal
=
unscaledVal
;
this
.
intCompact
=
compactVal
;
this
.
scale
=
scale
;
this
.
scale
=
scale
;
if
(
mc
.
precision
>
0
)
this
.
precision
=
prec
;
roundThis
(
mc
);
}
}
/**
/**
...
@@ -949,7 +1089,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -949,7 +1089,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
int
val
)
{
public
BigDecimal
(
int
val
)
{
intCompact
=
val
;
this
.
intCompact
=
val
;
this
.
scale
=
0
;
this
.
intVal
=
null
;
}
}
/**
/**
...
@@ -964,9 +1106,24 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -964,9 +1106,24 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
int
val
,
MathContext
mc
)
{
public
BigDecimal
(
int
val
,
MathContext
mc
)
{
intCompact
=
val
;
int
mcp
=
mc
.
precision
;
if
(
mc
.
precision
>
0
)
long
compactVal
=
val
;
roundThis
(
mc
);
int
scale
=
0
;
int
prec
=
0
;
if
(
mcp
>
0
)
{
// do rounding
prec
=
longDigitLength
(
compactVal
);
int
drop
=
prec
-
mcp
;
// drop can't be more than 18
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
compactVal
=
divideAndRound
(
compactVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
}
}
this
.
intVal
=
null
;
this
.
intCompact
=
compactVal
;
this
.
scale
=
scale
;
this
.
precision
=
prec
;
}
}
/**
/**
...
@@ -978,7 +1135,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -978,7 +1135,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
public
BigDecimal
(
long
val
)
{
public
BigDecimal
(
long
val
)
{
this
.
intCompact
=
val
;
this
.
intCompact
=
val
;
this
.
intVal
=
(
val
==
INFLATED
)
?
BigInteger
.
valueOf
(
val
)
:
null
;
this
.
intVal
=
(
val
==
INFLATED
)
?
INFLATED_BIGINT
:
null
;
this
.
scale
=
0
;
}
}
/**
/**
...
@@ -993,9 +1151,42 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -993,9 +1151,42 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
(
long
val
,
MathContext
mc
)
{
public
BigDecimal
(
long
val
,
MathContext
mc
)
{
this
(
val
);
int
mcp
=
mc
.
precision
;
if
(
mc
.
precision
>
0
)
int
mode
=
mc
.
roundingMode
.
oldMode
;
roundThis
(
mc
);
int
prec
=
0
;
int
scale
=
0
;
BigInteger
intVal
=
(
val
==
INFLATED
)
?
INFLATED_BIGINT
:
null
;
if
(
mcp
>
0
)
{
// do rounding
if
(
val
==
INFLATED
)
{
prec
=
19
;
int
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
intVal
=
divideAndRoundByTenPow
(
intVal
,
drop
,
mode
);
val
=
compactValFor
(
intVal
);
if
(
val
!=
INFLATED
)
{
break
;
}
prec
=
bigDigitLength
(
intVal
);
drop
=
prec
-
mcp
;
}
}
if
(
val
!=
INFLATED
)
{
prec
=
longDigitLength
(
val
);
int
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
val
=
divideAndRound
(
val
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
val
);
drop
=
prec
-
mcp
;
}
intVal
=
null
;
}
}
this
.
intVal
=
intVal
;
this
.
intCompact
=
val
;
this
.
scale
=
scale
;
this
.
precision
=
prec
;
}
}
// Static Factory Methods
// Static Factory Methods
...
@@ -1016,13 +1207,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1016,13 +1207,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if
(
scale
==
0
)
if
(
scale
==
0
)
return
valueOf
(
unscaledVal
);
return
valueOf
(
unscaledVal
);
else
if
(
unscaledVal
==
0
)
{
else
if
(
unscaledVal
==
0
)
{
if
(
scale
>
0
&&
scale
<
ZERO_SCALED_BY
.
length
)
return
zeroValueOf
(
scale
);
return
ZERO_SCALED_BY
[
scale
];
else
return
new
BigDecimal
(
BigInteger
.
ZERO
,
0
,
scale
,
1
);
}
}
return
new
BigDecimal
(
unscaledVal
==
INFLATED
?
return
new
BigDecimal
(
unscaledVal
==
INFLATED
?
BigInteger
.
valueOf
(
unscaledVal
)
:
null
,
INFLATED_BIGINT
:
null
,
unscaledVal
,
scale
,
0
);
unscaledVal
,
scale
,
0
);
}
}
...
@@ -1041,7 +1229,34 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1041,7 +1229,34 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return
zeroThroughTen
[(
int
)
val
];
return
zeroThroughTen
[(
int
)
val
];
else
if
(
val
!=
INFLATED
)
else
if
(
val
!=
INFLATED
)
return
new
BigDecimal
(
null
,
val
,
0
,
0
);
return
new
BigDecimal
(
null
,
val
,
0
,
0
);
return
new
BigDecimal
(
BigInteger
.
valueOf
(
val
),
val
,
0
,
0
);
return
new
BigDecimal
(
INFLATED_BIGINT
,
val
,
0
,
0
);
}
static
BigDecimal
valueOf
(
long
unscaledVal
,
int
scale
,
int
prec
)
{
if
(
scale
==
0
&&
unscaledVal
>=
0
&&
unscaledVal
<
zeroThroughTen
.
length
)
{
return
zeroThroughTen
[(
int
)
unscaledVal
];
}
else
if
(
unscaledVal
==
0
)
{
return
zeroValueOf
(
scale
);
}
return
new
BigDecimal
(
unscaledVal
==
INFLATED
?
INFLATED_BIGINT
:
null
,
unscaledVal
,
scale
,
prec
);
}
static
BigDecimal
valueOf
(
BigInteger
intVal
,
int
scale
,
int
prec
)
{
long
val
=
compactValFor
(
intVal
);
if
(
val
==
0
)
{
return
zeroValueOf
(
scale
);
}
else
if
(
scale
==
0
&&
val
>=
0
&&
val
<
zeroThroughTen
.
length
)
{
return
zeroThroughTen
[(
int
)
val
];
}
return
new
BigDecimal
(
intVal
,
val
,
scale
,
prec
);
}
static
BigDecimal
zeroValueOf
(
int
scale
)
{
if
(
scale
>=
0
&&
scale
<
ZERO_SCALED_BY
.
length
)
return
ZERO_SCALED_BY
[
scale
];
else
return
new
BigDecimal
(
BigInteger
.
ZERO
,
0
,
scale
,
1
);
}
}
/**
/**
...
@@ -1079,42 +1294,19 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1079,42 +1294,19 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return {@code this + augend}
* @return {@code this + augend}
*/
*/
public
BigDecimal
add
(
BigDecimal
augend
)
{
public
BigDecimal
add
(
BigDecimal
augend
)
{
long
xs
=
this
.
intCompact
;
if
(
this
.
intCompact
!=
INFLATED
)
{
long
ys
=
augend
.
intCompact
;
if
((
augend
.
intCompact
!=
INFLATED
))
{
BigInteger
fst
=
(
xs
!=
INFLATED
)
?
null
:
this
.
intVal
;
return
add
(
this
.
intCompact
,
this
.
scale
,
augend
.
intCompact
,
augend
.
scale
);
BigInteger
snd
=
(
ys
!=
INFLATED
)
?
null
:
augend
.
intVal
;
int
rscale
=
this
.
scale
;
long
sdiff
=
(
long
)
rscale
-
augend
.
scale
;
if
(
sdiff
!=
0
)
{
if
(
sdiff
<
0
)
{
int
raise
=
checkScale
(-
sdiff
);
rscale
=
augend
.
scale
;
if
(
xs
==
INFLATED
||
(
xs
=
longMultiplyPowerTen
(
xs
,
raise
))
==
INFLATED
)
fst
=
bigMultiplyPowerTen
(
raise
);
}
else
{
}
else
{
int
raise
=
augend
.
checkScale
(
sdiff
);
return
add
(
this
.
intCompact
,
this
.
scale
,
augend
.
intVal
,
augend
.
scale
);
if
(
ys
==
INFLATED
||
}
(
ys
=
longMultiplyPowerTen
(
ys
,
raise
))
==
INFLATED
)
}
else
{
snd
=
augend
.
bigMultiplyPowerTen
(
raise
);
if
((
augend
.
intCompact
!=
INFLATED
))
{
}
return
add
(
augend
.
intCompact
,
augend
.
scale
,
this
.
intVal
,
this
.
scale
);
}
}
else
{
if
(
xs
!=
INFLATED
&&
ys
!=
INFLATED
)
{
return
add
(
this
.
intVal
,
this
.
scale
,
augend
.
intVal
,
augend
.
scale
);
long
sum
=
xs
+
ys
;
}
// See "Hacker's Delight" section 2-12 for explanation of
}
// the overflow test.
if
(
(((
sum
^
xs
)
&
(
sum
^
ys
)))
>=
0L
)
// not overflowed
return
BigDecimal
.
valueOf
(
sum
,
rscale
);
}
if
(
fst
==
null
)
fst
=
BigInteger
.
valueOf
(
xs
);
if
(
snd
==
null
)
snd
=
BigInteger
.
valueOf
(
ys
);
BigInteger
sum
=
fst
.
add
(
snd
);
return
(
fst
.
signum
==
snd
.
signum
)
?
new
BigDecimal
(
sum
,
INFLATED
,
rscale
,
0
)
:
new
BigDecimal
(
sum
,
rscale
);
}
}
/**
/**
...
@@ -1136,10 +1328,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1136,10 +1328,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return
add
(
augend
);
return
add
(
augend
);
BigDecimal
lhs
=
this
;
BigDecimal
lhs
=
this
;
// Could optimize if values are compact
this
.
inflate
();
augend
.
inflate
();
// If either number is zero then the other number, rounded and
// If either number is zero then the other number, rounded and
// scaled if necessary, is used as the result.
// scaled if necessary, is used as the result.
{
{
...
@@ -1150,20 +1338,14 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1150,20 +1338,14 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
int
preferredScale
=
Math
.
max
(
lhs
.
scale
(),
augend
.
scale
());
int
preferredScale
=
Math
.
max
(
lhs
.
scale
(),
augend
.
scale
());
BigDecimal
result
;
BigDecimal
result
;
// Could use a factory for zero instead of a new object
if
(
lhsIsZero
&&
augendIsZero
)
if
(
lhsIsZero
&&
augendIsZero
)
return
new
BigDecimal
(
BigInteger
.
ZERO
,
0
,
preferredScale
,
0
);
return
zeroValueOf
(
preferredScale
);
result
=
lhsIsZero
?
doRound
(
augend
,
mc
)
:
doRound
(
lhs
,
mc
);
result
=
lhsIsZero
?
doRound
(
augend
,
mc
)
:
doRound
(
lhs
,
mc
);
if
(
result
.
scale
()
==
preferredScale
)
if
(
result
.
scale
()
==
preferredScale
)
return
result
;
return
result
;
else
if
(
result
.
scale
()
>
preferredScale
)
{
else
if
(
result
.
scale
()
>
preferredScale
)
{
BigDecimal
scaledResult
=
return
stripZerosToMatchScale
(
result
.
intVal
,
result
.
intCompact
,
result
.
scale
,
preferredScale
);
new
BigDecimal
(
result
.
intVal
,
result
.
intCompact
,
result
.
scale
,
0
);
scaledResult
.
stripZerosToMatchScale
(
preferredScale
);
return
scaledResult
;
}
else
{
// result.scale < preferredScale
}
else
{
// result.scale < preferredScale
int
precisionDiff
=
mc
.
precision
-
result
.
precision
();
int
precisionDiff
=
mc
.
precision
-
result
.
precision
();
int
scaleDiff
=
preferredScale
-
result
.
scale
();
int
scaleDiff
=
preferredScale
-
result
.
scale
();
...
@@ -1176,17 +1358,14 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1176,17 +1358,14 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
}
}
}
long
padding
=
(
long
)
lhs
.
scale
-
augend
.
scale
;
long
padding
=
(
long
)
lhs
.
scale
-
augend
.
scale
;
if
(
padding
!=
0
)
{
// scales differ; alignment needed
if
(
padding
!=
0
)
{
// scales differ; alignment needed
BigDecimal
arg
[]
=
preAlign
(
lhs
,
augend
,
padding
,
mc
);
BigDecimal
arg
[]
=
preAlign
(
lhs
,
augend
,
padding
,
mc
);
matchScale
(
arg
);
matchScale
(
arg
);
lhs
=
arg
[
0
];
lhs
=
arg
[
0
];
augend
=
arg
[
1
];
augend
=
arg
[
1
];
}
}
return
doRound
(
lhs
.
inflated
().
add
(
augend
.
inflated
()),
lhs
.
scale
,
mc
);
BigDecimal
d
=
new
BigDecimal
(
lhs
.
inflate
().
add
(
augend
.
inflate
()),
lhs
.
scale
);
return
doRound
(
d
,
mc
);
}
}
/**
/**
...
@@ -1211,27 +1390,26 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1211,27 +1390,26 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* that the number of digits of the smaller operand could be
* that the number of digits of the smaller operand could be
* reduced even though the significands partially overlapped.
* reduced even though the significands partially overlapped.
*/
*/
private
BigDecimal
[]
preAlign
(
BigDecimal
lhs
,
BigDecimal
augend
,
private
BigDecimal
[]
preAlign
(
BigDecimal
lhs
,
BigDecimal
augend
,
long
padding
,
MathContext
mc
)
{
long
padding
,
MathContext
mc
)
{
assert
padding
!=
0
;
assert
padding
!=
0
;
BigDecimal
big
;
BigDecimal
big
;
BigDecimal
small
;
BigDecimal
small
;
if
(
padding
<
0
)
{
// lhs is big;
augend is small
if
(
padding
<
0
)
{
// lhs is big;
augend is small
big
=
lhs
;
big
=
lhs
;
small
=
augend
;
small
=
augend
;
}
else
{
// lhs is small; augend is big
}
else
{
// lhs is small; augend is big
big
=
augend
;
big
=
augend
;
small
=
lhs
;
small
=
lhs
;
}
}
/*
/*
* This is the estimated scale of an ulp of the result; it
* This is the estimated scale of an ulp of the result; it
assumes that
*
assumes that the result doesn't have a carry-out on a true
*
the result doesn't have a carry-out on a true add (e.g. 999 + 1 =>
*
add (e.g. 999 + 1 => 1000) or any subtractive cancellation
*
1000) or any subtractive cancellation on borrowing (e.g. 100 - 1.2 =>
*
on borrowing (e.g. 100 - 1.2 =>
98.8)
* 98.8)
*/
*/
long
estResultUlpScale
=
(
long
)
big
.
scale
-
big
.
precision
()
+
mc
.
precision
;
long
estResultUlpScale
=
(
long
)
big
.
scale
-
big
.
precision
()
+
mc
.
precision
;
/*
/*
* The low-order digit position of big is big.scale(). This
* The low-order digit position of big is big.scale(). This
...
@@ -1242,11 +1420,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1242,11 +1420,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* disjoint *and* the digit positions of small should not be
* disjoint *and* the digit positions of small should not be
* directly visible in the result.
* directly visible in the result.
*/
*/
long
smallHighDigitPos
=
(
long
)
small
.
scale
-
small
.
precision
()
+
1
;
long
smallHighDigitPos
=
(
long
)
small
.
scale
-
small
.
precision
()
+
1
;
if
(
smallHighDigitPos
>
big
.
scale
+
2
&&
// big and small disjoint
if
(
smallHighDigitPos
>
big
.
scale
+
2
&&
// big and small disjoint
smallHighDigitPos
>
estResultUlpScale
+
2
)
{
// small digits not visible
smallHighDigitPos
>
estResultUlpScale
+
2
)
{
// small digits not visible
small
=
BigDecimal
.
valueOf
(
small
.
signum
(),
small
=
BigDecimal
.
valueOf
(
small
.
signum
(),
this
.
checkScale
(
Math
.
max
(
big
.
scale
,
estResultUlpScale
)
+
3
));
this
.
checkScale
(
Math
.
max
(
big
.
scale
,
estResultUlpScale
)
+
3
));
}
}
// Since addition is symmetric, preserving input order in
// Since addition is symmetric, preserving input order in
...
@@ -1264,7 +1441,22 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1264,7 +1441,22 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return {@code this - subtrahend}
* @return {@code this - subtrahend}
*/
*/
public
BigDecimal
subtract
(
BigDecimal
subtrahend
)
{
public
BigDecimal
subtract
(
BigDecimal
subtrahend
)
{
return
add
(
subtrahend
.
negate
());
if
(
this
.
intCompact
!=
INFLATED
)
{
if
((
subtrahend
.
intCompact
!=
INFLATED
))
{
return
add
(
this
.
intCompact
,
this
.
scale
,
-
subtrahend
.
intCompact
,
subtrahend
.
scale
);
}
else
{
return
add
(
this
.
intCompact
,
this
.
scale
,
subtrahend
.
intVal
.
negate
(),
subtrahend
.
scale
);
}
}
else
{
if
((
subtrahend
.
intCompact
!=
INFLATED
))
{
// Pair of subtrahend values given before pair of
// values from this BigDecimal to avoid need for
// method overloading on the specialized add method
return
add
(-
subtrahend
.
intCompact
,
subtrahend
.
scale
,
this
.
intVal
,
this
.
scale
);
}
else
{
return
add
(
this
.
intVal
,
this
.
scale
,
subtrahend
.
intVal
.
negate
(),
subtrahend
.
scale
);
}
}
}
}
/**
/**
...
@@ -1282,11 +1474,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1282,11 +1474,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
subtract
(
BigDecimal
subtrahend
,
MathContext
mc
)
{
public
BigDecimal
subtract
(
BigDecimal
subtrahend
,
MathContext
mc
)
{
BigDecimal
nsubtrahend
=
subtrahend
.
negate
();
if
(
mc
.
precision
==
0
)
if
(
mc
.
precision
==
0
)
return
add
(
n
subtrahend
);
return
subtract
(
subtrahend
);
// share the special rounding code in add()
// share the special rounding code in add()
return
add
(
nsubtrahend
,
mc
);
return
add
(
subtrahend
.
negate
()
,
mc
);
}
}
/**
/**
...
@@ -1298,37 +1489,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1298,37 +1489,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return {@code this * multiplicand}
* @return {@code this * multiplicand}
*/
*/
public
BigDecimal
multiply
(
BigDecimal
multiplicand
)
{
public
BigDecimal
multiply
(
BigDecimal
multiplicand
)
{
long
x
=
this
.
intCompact
;
int
productScale
=
checkScale
((
long
)
scale
+
multiplicand
.
scale
);
long
y
=
multiplicand
.
intCompact
;
if
(
this
.
intCompact
!=
INFLATED
)
{
int
productScale
=
checkScale
((
long
)
scale
+
multiplicand
.
scale
);
if
((
multiplicand
.
intCompact
!=
INFLATED
))
{
return
multiply
(
this
.
intCompact
,
multiplicand
.
intCompact
,
productScale
);
// Might be able to do a more clever check incorporating the
}
else
{
// inflated check into the overflow computation.
return
multiply
(
this
.
intCompact
,
multiplicand
.
intVal
,
productScale
);
if
(
x
!=
INFLATED
&&
y
!=
INFLATED
)
{
}
/*
}
else
{
* If the product is not an overflowed value, continue
if
((
multiplicand
.
intCompact
!=
INFLATED
))
{
* to use the compact representation. if either of x or y
return
multiply
(
multiplicand
.
intCompact
,
this
.
intVal
,
productScale
);
* is INFLATED, the product should also be regarded as
}
else
{
* an overflow. Before using the overflow test suggested in
return
multiply
(
this
.
intVal
,
multiplicand
.
intVal
,
productScale
);
* "Hacker's Delight" section 2-12, we perform quick checks
}
* using the precision information to see whether the overflow
}
* would occur since division is expensive on most CPUs.
*/
long
product
=
x
*
y
;
long
prec
=
this
.
precision
()
+
multiplicand
.
precision
();
if
(
prec
<
19
||
(
prec
<
21
&&
(
y
==
0
||
product
/
y
==
x
)))
return
BigDecimal
.
valueOf
(
product
,
productScale
);
return
new
BigDecimal
(
BigInteger
.
valueOf
(
x
).
multiply
(
y
),
INFLATED
,
productScale
,
0
);
}
BigInteger
rb
;
if
(
x
==
INFLATED
&&
y
==
INFLATED
)
rb
=
this
.
intVal
.
multiply
(
multiplicand
.
intVal
);
else
if
(
x
!=
INFLATED
)
rb
=
multiplicand
.
intVal
.
multiply
(
x
);
else
rb
=
this
.
intVal
.
multiply
(
y
);
return
new
BigDecimal
(
rb
,
INFLATED
,
productScale
,
0
);
}
}
/**
/**
...
@@ -1345,7 +1519,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1345,7 +1519,20 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
public
BigDecimal
multiply
(
BigDecimal
multiplicand
,
MathContext
mc
)
{
public
BigDecimal
multiply
(
BigDecimal
multiplicand
,
MathContext
mc
)
{
if
(
mc
.
precision
==
0
)
if
(
mc
.
precision
==
0
)
return
multiply
(
multiplicand
);
return
multiply
(
multiplicand
);
return
doRound
(
this
.
multiply
(
multiplicand
),
mc
);
int
productScale
=
checkScale
((
long
)
scale
+
multiplicand
.
scale
);
if
(
this
.
intCompact
!=
INFLATED
)
{
if
((
multiplicand
.
intCompact
!=
INFLATED
))
{
return
multiplyAndRound
(
this
.
intCompact
,
multiplicand
.
intCompact
,
productScale
,
mc
);
}
else
{
return
multiplyAndRound
(
this
.
intCompact
,
multiplicand
.
intVal
,
productScale
,
mc
);
}
}
else
{
if
((
multiplicand
.
intCompact
!=
INFLATED
))
{
return
multiplyAndRound
(
multiplicand
.
intCompact
,
this
.
intVal
,
productScale
,
mc
);
}
else
{
return
multiplyAndRound
(
this
.
intVal
,
multiplicand
.
intVal
,
productScale
,
mc
);
}
}
}
}
/**
/**
...
@@ -1377,120 +1564,21 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1377,120 +1564,21 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @see #ROUND_UNNECESSARY
* @see #ROUND_UNNECESSARY
*/
*/
public
BigDecimal
divide
(
BigDecimal
divisor
,
int
scale
,
int
roundingMode
)
{
public
BigDecimal
divide
(
BigDecimal
divisor
,
int
scale
,
int
roundingMode
)
{
/*
* IMPLEMENTATION NOTE: This method *must* return a new object
* since divideAndRound uses divide to generate a value whose
* scale is then modified.
*/
if
(
roundingMode
<
ROUND_UP
||
roundingMode
>
ROUND_UNNECESSARY
)
if
(
roundingMode
<
ROUND_UP
||
roundingMode
>
ROUND_UNNECESSARY
)
throw
new
IllegalArgumentException
(
"Invalid rounding mode"
);
throw
new
IllegalArgumentException
(
"Invalid rounding mode"
);
/*
if
(
this
.
intCompact
!=
INFLATED
)
{
* Rescale dividend or divisor (whichever can be "upscaled" to
if
((
divisor
.
intCompact
!=
INFLATED
))
{
* produce correctly scaled quotient).
return
divide
(
this
.
intCompact
,
this
.
scale
,
divisor
.
intCompact
,
divisor
.
scale
,
scale
,
roundingMode
);
* Take care to detect out-of-range scales
}
else
{
*/
return
divide
(
this
.
intCompact
,
this
.
scale
,
divisor
.
intVal
,
divisor
.
scale
,
scale
,
roundingMode
);
BigDecimal
dividend
=
this
;
}
if
(
checkScale
((
long
)
scale
+
divisor
.
scale
)
>
this
.
scale
)
}
else
{
dividend
=
this
.
setScale
(
scale
+
divisor
.
scale
,
ROUND_UNNECESSARY
);
if
((
divisor
.
intCompact
!=
INFLATED
))
{
else
return
divide
(
this
.
intVal
,
this
.
scale
,
divisor
.
intCompact
,
divisor
.
scale
,
scale
,
roundingMode
);
divisor
=
divisor
.
setScale
(
checkScale
((
long
)
this
.
scale
-
scale
),
}
else
{
ROUND_UNNECESSARY
);
return
divide
(
this
.
intVal
,
this
.
scale
,
divisor
.
intVal
,
divisor
.
scale
,
scale
,
roundingMode
);
return
divideAndRound
(
dividend
.
intCompact
,
dividend
.
intVal
,
}
divisor
.
intCompact
,
divisor
.
intVal
,
}
scale
,
roundingMode
,
scale
);
}
/**
* Internally used for division operation. The dividend and divisor are
* passed both in {@code long} format and {@code BigInteger} format. The
* returned {@code BigDecimal} object is the quotient whose scale is set to
* the passed in scale. If the remainder is not zero, it will be rounded
* based on the passed in roundingMode. Also, if the remainder is zero and
* the last parameter, i.e. preferredScale is NOT equal to scale, the
* trailing zeros of the result is stripped to match the preferredScale.
*/
private
static
BigDecimal
divideAndRound
(
long
ldividend
,
BigInteger
bdividend
,
long
ldivisor
,
BigInteger
bdivisor
,
int
scale
,
int
roundingMode
,
int
preferredScale
)
{
boolean
isRemainderZero
;
// record remainder is zero or not
int
qsign
;
// quotient sign
long
q
=
0
,
r
=
0
;
// store quotient & remainder in long
MutableBigInteger
mq
=
null
;
// store quotient
MutableBigInteger
mr
=
null
;
// store remainder
MutableBigInteger
mdivisor
=
null
;
boolean
isLongDivision
=
(
ldividend
!=
INFLATED
&&
ldivisor
!=
INFLATED
);
if
(
isLongDivision
)
{
q
=
ldividend
/
ldivisor
;
if
(
roundingMode
==
ROUND_DOWN
&&
scale
==
preferredScale
)
return
new
BigDecimal
(
null
,
q
,
scale
,
0
);
r
=
ldividend
%
ldivisor
;
isRemainderZero
=
(
r
==
0
);
qsign
=
((
ldividend
<
0
)
==
(
ldivisor
<
0
))
?
1
:
-
1
;
}
else
{
if
(
bdividend
==
null
)
bdividend
=
BigInteger
.
valueOf
(
ldividend
);
// Descend into mutables for faster remainder checks
MutableBigInteger
mdividend
=
new
MutableBigInteger
(
bdividend
.
mag
);
mq
=
new
MutableBigInteger
();
if
(
ldivisor
!=
INFLATED
)
{
r
=
mdividend
.
divide
(
ldivisor
,
mq
);
isRemainderZero
=
(
r
==
0
);
qsign
=
(
ldivisor
<
0
)
?
-
bdividend
.
signum
:
bdividend
.
signum
;
}
else
{
mdivisor
=
new
MutableBigInteger
(
bdivisor
.
mag
);
mr
=
mdividend
.
divide
(
mdivisor
,
mq
);
isRemainderZero
=
mr
.
isZero
();
qsign
=
(
bdividend
.
signum
!=
bdivisor
.
signum
)
?
-
1
:
1
;
}
}
boolean
increment
=
false
;
if
(!
isRemainderZero
)
{
int
cmpFracHalf
;
/* Round as appropriate */
if
(
roundingMode
==
ROUND_UNNECESSARY
)
{
// Rounding prohibited
throw
new
ArithmeticException
(
"Rounding necessary"
);
}
else
if
(
roundingMode
==
ROUND_UP
)
{
// Away from zero
increment
=
true
;
}
else
if
(
roundingMode
==
ROUND_DOWN
)
{
// Towards zero
increment
=
false
;
}
else
if
(
roundingMode
==
ROUND_CEILING
)
{
// Towards +infinity
increment
=
(
qsign
>
0
);
}
else
if
(
roundingMode
==
ROUND_FLOOR
)
{
// Towards -infinity
increment
=
(
qsign
<
0
);
}
else
{
if
(
isLongDivision
||
ldivisor
!=
INFLATED
)
{
if
(
r
<=
HALF_LONG_MIN_VALUE
||
r
>
HALF_LONG_MAX_VALUE
)
{
cmpFracHalf
=
1
;
// 2 * r can't fit into long
}
else
{
cmpFracHalf
=
longCompareMagnitude
(
2
*
r
,
ldivisor
);
}
}
else
{
cmpFracHalf
=
mr
.
compareHalf
(
mdivisor
);
}
if
(
cmpFracHalf
<
0
)
increment
=
false
;
// We're closer to higher digit
else
if
(
cmpFracHalf
>
0
)
// We're closer to lower digit
increment
=
true
;
else
if
(
roundingMode
==
ROUND_HALF_UP
)
increment
=
true
;
else
if
(
roundingMode
==
ROUND_HALF_DOWN
)
increment
=
false
;
else
// roundingMode == ROUND_HALF_EVEN, true iff quotient is odd
increment
=
isLongDivision
?
(
q
&
1L
)
!=
0L
:
mq
.
isOdd
();
}
}
BigDecimal
res
;
if
(
isLongDivision
)
res
=
new
BigDecimal
(
null
,
(
increment
?
q
+
qsign
:
q
),
scale
,
0
);
else
{
if
(
increment
)
mq
.
add
(
MutableBigInteger
.
ONE
);
res
=
mq
.
toBigDecimal
(
qsign
,
scale
);
}
if
(
isRemainderZero
&&
preferredScale
!=
scale
)
res
.
stripZerosToMatchScale
(
preferredScale
);
return
res
;
}
}
/**
/**
...
@@ -1541,7 +1629,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1541,7 +1629,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @see #ROUND_UNNECESSARY
* @see #ROUND_UNNECESSARY
*/
*/
public
BigDecimal
divide
(
BigDecimal
divisor
,
int
roundingMode
)
{
public
BigDecimal
divide
(
BigDecimal
divisor
,
int
roundingMode
)
{
return
this
.
divide
(
divisor
,
scale
,
roundingMode
);
return
this
.
divide
(
divisor
,
scale
,
roundingMode
);
}
}
/**
/**
...
@@ -1588,15 +1676,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1588,15 +1676,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
}
// Calculate preferred scale
// Calculate preferred scale
int
preferredScale
=
saturateLong
((
long
)
this
.
scale
-
divisor
.
scale
);
int
preferredScale
=
saturateLong
((
long
)
this
.
scale
-
divisor
.
scale
);
if
(
this
.
signum
()
==
0
)
// 0/y
return
(
preferredScale
>=
0
&&
if
(
this
.
signum
()
==
0
)
// 0/y
preferredScale
<
ZERO_SCALED_BY
.
length
)
?
return
zeroValueOf
(
preferredScale
);
ZERO_SCALED_BY
[
preferredScale
]
:
BigDecimal
.
valueOf
(
0
,
preferredScale
);
else
{
else
{
this
.
inflate
();
divisor
.
inflate
();
/*
/*
* If the quotient this/divisor has a terminating decimal
* If the quotient this/divisor has a terminating decimal
* expansion, the expansion can have no more than
* expansion, the expansion can have no more than
...
@@ -1623,7 +1707,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1623,7 +1707,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// the desired one by removing trailing zeros; since the
// the desired one by removing trailing zeros; since the
// exact divide method does not have an explicit digit
// exact divide method does not have an explicit digit
// limit, we can add zeros too.
// limit, we can add zeros too.
if
(
preferredScale
>
quotientScale
)
if
(
preferredScale
>
quotientScale
)
return
quotient
.
setScale
(
preferredScale
,
ROUND_UNNECESSARY
);
return
quotient
.
setScale
(
preferredScale
,
ROUND_UNNECESSARY
);
...
@@ -1668,38 +1751,23 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1668,38 +1751,23 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
throw
new
ArithmeticException
(
"Division undefined"
);
// NaN
throw
new
ArithmeticException
(
"Division undefined"
);
// NaN
throw
new
ArithmeticException
(
"Division by zero"
);
throw
new
ArithmeticException
(
"Division by zero"
);
}
}
if
(
dividend
.
signum
()
==
0
)
// 0/y
if
(
dividend
.
signum
()
==
0
)
// 0/y
return
new
BigDecimal
(
BigInteger
.
ZERO
,
0
,
return
zeroValueOf
(
saturateLong
(
preferredScale
));
saturateLong
(
preferredScale
),
1
);
// Normalize dividend & divisor so that both fall into [0.1, 0.999...]
int
xscale
=
dividend
.
precision
();
int
xscale
=
dividend
.
precision
();
int
yscale
=
divisor
.
precision
();
int
yscale
=
divisor
.
precision
();
dividend
=
new
BigDecimal
(
dividend
.
intVal
,
dividend
.
intCompact
,
if
(
dividend
.
intCompact
!=
INFLATED
)
{
xscale
,
xscale
);
if
(
divisor
.
intCompact
!=
INFLATED
)
{
divisor
=
new
BigDecimal
(
divisor
.
intVal
,
divisor
.
intCompact
,
return
divide
(
dividend
.
intCompact
,
xscale
,
divisor
.
intCompact
,
yscale
,
preferredScale
,
mc
);
yscale
,
yscale
);
}
else
{
if
(
dividend
.
compareMagnitude
(
divisor
)
>
0
)
// satisfy constraint (b)
return
divide
(
dividend
.
intCompact
,
xscale
,
divisor
.
intVal
,
yscale
,
preferredScale
,
mc
);
yscale
=
divisor
.
scale
-=
1
;
// [that is, divisor *= 10]
}
}
else
{
// In order to find out whether the divide generates the exact result,
if
(
divisor
.
intCompact
!=
INFLATED
)
{
// we avoid calling the above divide method. 'quotient' holds the
return
divide
(
dividend
.
intVal
,
xscale
,
divisor
.
intCompact
,
yscale
,
preferredScale
,
mc
);
// return BigDecimal object whose scale will be set to 'scl'.
}
else
{
BigDecimal
quotient
;
return
divide
(
dividend
.
intVal
,
xscale
,
divisor
.
intVal
,
yscale
,
preferredScale
,
mc
);
int
scl
=
checkScale
(
preferredScale
+
yscale
-
xscale
+
mcp
);
}
if
(
checkScale
((
long
)
mcp
+
yscale
)
>
xscale
)
}
dividend
=
dividend
.
setScale
(
mcp
+
yscale
,
ROUND_UNNECESSARY
);
else
divisor
=
divisor
.
setScale
(
checkScale
((
long
)
xscale
-
mcp
),
ROUND_UNNECESSARY
);
quotient
=
divideAndRound
(
dividend
.
intCompact
,
dividend
.
intVal
,
divisor
.
intCompact
,
divisor
.
intVal
,
scl
,
mc
.
roundingMode
.
oldMode
,
checkScale
(
preferredScale
));
// doRound, here, only affects 1000000000 case.
quotient
=
doRound
(
quotient
,
mc
);
return
quotient
;
}
}
/**
/**
...
@@ -1715,13 +1783,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1715,13 +1783,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
public
BigDecimal
divideToIntegralValue
(
BigDecimal
divisor
)
{
public
BigDecimal
divideToIntegralValue
(
BigDecimal
divisor
)
{
// Calculate preferred scale
// Calculate preferred scale
int
preferredScale
=
saturateLong
((
long
)
this
.
scale
-
divisor
.
scale
);
int
preferredScale
=
saturateLong
((
long
)
this
.
scale
-
divisor
.
scale
);
if
(
this
.
compareMagnitude
(
divisor
)
<
0
)
{
if
(
this
.
compareMagnitude
(
divisor
)
<
0
)
{
// much faster when this << divisor
// much faster when this << divisor
return
BigDecimal
.
valueOf
(
0
,
preferredScale
);
return
zeroValueOf
(
preferredScale
);
}
}
if
(
this
.
signum
()
==
0
&&
divisor
.
signum
()
!=
0
)
if
(
this
.
signum
()
==
0
&&
divisor
.
signum
()
!=
0
)
return
this
.
setScale
(
preferredScale
,
ROUND_UNNECESSARY
);
return
this
.
setScale
(
preferredScale
,
ROUND_UNNECESSARY
);
// Perform a divide with enough digits to round to a correct
// Perform a divide with enough digits to round to a correct
...
@@ -1735,13 +1803,14 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1735,13 +1803,14 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
RoundingMode
.
DOWN
));
RoundingMode
.
DOWN
));
if
(
quotient
.
scale
>
0
)
{
if
(
quotient
.
scale
>
0
)
{
quotient
=
quotient
.
setScale
(
0
,
RoundingMode
.
DOWN
);
quotient
=
quotient
.
setScale
(
0
,
RoundingMode
.
DOWN
);
quotient
.
stripZerosToMatchScale
(
preferredScale
);
quotient
=
stripZerosToMatchScale
(
quotient
.
intVal
,
quotient
.
intCompact
,
quotient
.
scale
,
preferredScale
);
}
}
if
(
quotient
.
scale
<
preferredScale
)
{
if
(
quotient
.
scale
<
preferredScale
)
{
// pad with zeros if necessary
// pad with zeros if necessary
quotient
=
quotient
.
setScale
(
preferredScale
,
ROUND_UNNECESSARY
);
quotient
=
quotient
.
setScale
(
preferredScale
,
ROUND_UNNECESSARY
);
}
}
return
quotient
;
return
quotient
;
}
}
...
@@ -1766,8 +1835,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1766,8 +1835,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @author Joseph D. Darcy
* @author Joseph D. Darcy
*/
*/
public
BigDecimal
divideToIntegralValue
(
BigDecimal
divisor
,
MathContext
mc
)
{
public
BigDecimal
divideToIntegralValue
(
BigDecimal
divisor
,
MathContext
mc
)
{
if
(
mc
.
precision
==
0
||
// exact result
if
(
mc
.
precision
==
0
||
// exact result
(
this
.
compareMagnitude
(
divisor
)
<
0
)
)
// zero result
(
this
.
compareMagnitude
(
divisor
)
<
0
)
)
// zero result
return
divideToIntegralValue
(
divisor
);
return
divideToIntegralValue
(
divisor
);
// Calculate preferred scale
// Calculate preferred scale
...
@@ -1780,8 +1849,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1780,8 +1849,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* digits. Next, remove any fractional digits from the
* digits. Next, remove any fractional digits from the
* quotient and adjust the scale to the preferred value.
* quotient and adjust the scale to the preferred value.
*/
*/
BigDecimal
result
=
this
.
BigDecimal
result
=
this
.
divide
(
divisor
,
new
MathContext
(
mc
.
precision
,
RoundingMode
.
DOWN
));
divide
(
divisor
,
new
MathContext
(
mc
.
precision
,
RoundingMode
.
DOWN
));
if
(
result
.
scale
()
<
0
)
{
if
(
result
.
scale
()
<
0
)
{
/*
/*
...
@@ -1811,8 +1879,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1811,8 +1879,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return
result
.
setScale
(
result
.
scale
()
+
return
result
.
setScale
(
result
.
scale
()
+
Math
.
min
(
precisionDiff
,
preferredScale
-
result
.
scale
)
);
Math
.
min
(
precisionDiff
,
preferredScale
-
result
.
scale
)
);
}
else
{
}
else
{
result
.
stripZerosToMatchScale
(
preferredScale
);
return
stripZerosToMatchScale
(
result
.
intVal
,
result
.
intCompact
,
result
.
scale
,
preferredScale
);
return
result
;
}
}
}
}
...
@@ -1954,8 +2021,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -1954,8 +2021,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// No need to calculate pow(n) if result will over/underflow.
// No need to calculate pow(n) if result will over/underflow.
// Don't attempt to support "supernormal" numbers.
// Don't attempt to support "supernormal" numbers.
int
newScale
=
checkScale
((
long
)
scale
*
n
);
int
newScale
=
checkScale
((
long
)
scale
*
n
);
this
.
inflate
();
return
new
BigDecimal
(
this
.
inflated
().
pow
(
n
),
newScale
);
return
new
BigDecimal
(
intVal
.
pow
(
n
),
newScale
);
}
}
...
@@ -2016,12 +2082,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2016,12 +2082,10 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
throw
new
ArithmeticException
(
"Invalid operation"
);
throw
new
ArithmeticException
(
"Invalid operation"
);
if
(
n
==
0
)
if
(
n
==
0
)
return
ONE
;
// x**0 == 1 in X3.274
return
ONE
;
// x**0 == 1 in X3.274
this
.
inflate
();
BigDecimal
lhs
=
this
;
BigDecimal
lhs
=
this
;
MathContext
workmc
=
mc
;
// working settings
MathContext
workmc
=
mc
;
// working settings
int
mag
=
Math
.
abs
(
n
);
// magnitude of n
int
mag
=
Math
.
abs
(
n
);
// magnitude of n
if
(
mc
.
precision
>
0
)
{
if
(
mc
.
precision
>
0
)
{
int
elength
=
longDigitLength
(
mag
);
// length of n in digits
int
elength
=
longDigitLength
(
mag
);
// length of n in digits
if
(
elength
>
mc
.
precision
)
// X3.274 rule
if
(
elength
>
mc
.
precision
)
// X3.274 rule
throw
new
ArithmeticException
(
"Invalid operation"
);
throw
new
ArithmeticException
(
"Invalid operation"
);
...
@@ -2044,7 +2108,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2044,7 +2108,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// else (!seenbit) no point in squaring ONE
// else (!seenbit) no point in squaring ONE
}
}
// if negative n, calculate the reciprocal using working precision
// if negative n, calculate the reciprocal using working precision
if
(
n
<
0
)
// [hence mc.precision>0]
if
(
n
<
0
)
// [hence mc.precision>0]
acc
=
ONE
.
divide
(
acc
,
workmc
);
acc
=
ONE
.
divide
(
acc
,
workmc
);
// round to final precision and strip zeros
// round to final precision and strip zeros
return
doRound
(
acc
,
mc
);
return
doRound
(
acc
,
mc
);
...
@@ -2083,14 +2147,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2083,14 +2147,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return {@code -this}.
* @return {@code -this}.
*/
*/
public
BigDecimal
negate
()
{
public
BigDecimal
negate
()
{
BigDecimal
result
;
if
(
intCompact
==
INFLATED
)
{
if
(
intCompact
!=
INFLATED
)
return
new
BigDecimal
(
intVal
.
negate
(),
INFLATED
,
scale
,
precision
);
result
=
BigDecimal
.
valueOf
(-
intCompact
,
scale
);
}
else
{
else
{
return
valueOf
(-
intCompact
,
scale
,
precision
);
result
=
new
BigDecimal
(
intVal
.
negate
(),
scale
);
result
.
precision
=
precision
;
}
}
return
result
;
}
}
/**
/**
...
@@ -2186,7 +2247,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2186,7 +2247,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if
(
s
!=
INFLATED
)
if
(
s
!=
INFLATED
)
result
=
longDigitLength
(
s
);
result
=
longDigitLength
(
s
);
else
else
result
=
bigDigitLength
(
in
flate
()
);
result
=
bigDigitLength
(
in
tVal
);
precision
=
result
;
precision
=
result
;
}
}
return
result
;
return
result
;
...
@@ -2202,7 +2263,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2202,7 +2263,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.2
* @since 1.2
*/
*/
public
BigInteger
unscaledValue
()
{
public
BigInteger
unscaledValue
()
{
return
this
.
inflate
();
return
this
.
inflate
d
();
}
}
// Rounding Modes
// Rounding Modes
...
@@ -2383,29 +2444,41 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2383,29 +2444,41 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if
(
newScale
==
oldScale
)
// easy case
if
(
newScale
==
oldScale
)
// easy case
return
this
;
return
this
;
if
(
this
.
signum
()
==
0
)
// zero can have any scale
if
(
this
.
signum
()
==
0
)
// zero can have any scale
return
BigDecimal
.
valueOf
(
0
,
newScale
);
return
zeroValueOf
(
newScale
);
if
(
this
.
intCompact
!=
INFLATED
)
{
long
rs
=
this
.
intCompact
;
long
rs
=
this
.
intCompact
;
if
(
newScale
>
oldScale
)
{
if
(
newScale
>
oldScale
)
{
int
raise
=
checkScale
((
long
)
newScale
-
oldScale
);
int
raise
=
checkScale
((
long
)
newScale
-
oldScale
);
BigInteger
rb
=
null
;
if
((
rs
=
longMultiplyPowerTen
(
rs
,
raise
))
!=
INFLATED
)
{
if
(
rs
==
INFLATED
||
return
valueOf
(
rs
,
newScale
);
(
rs
=
longMultiplyPowerTen
(
rs
,
raise
))
==
INFLATED
)
}
rb
=
bigMultiplyPowerTen
(
raise
);
BigInteger
rb
=
bigMultiplyPowerTen
(
raise
);
return
new
BigDecimal
(
rb
,
rs
,
newScale
,
return
new
BigDecimal
(
rb
,
INFLATED
,
newScale
,
(
precision
>
0
)
?
precision
+
raise
:
0
);
(
precision
>
0
)
?
precision
+
raise
:
0
);
}
else
{
// newScale < oldScale -- drop some digits
// Can't predict the precision due to the effect of rounding.
int
drop
=
checkScale
((
long
)
oldScale
-
newScale
);
if
(
drop
<
LONG_TEN_POWERS_TABLE
.
length
)
{
return
divideAndRound
(
rs
,
LONG_TEN_POWERS_TABLE
[
drop
],
newScale
,
roundingMode
,
newScale
);
}
else
{
return
divideAndRound
(
this
.
inflated
(),
bigTenToThe
(
drop
),
newScale
,
roundingMode
,
newScale
);
}
}
}
else
{
}
else
{
// newScale < oldScale -- drop some digits
if
(
newScale
>
oldScale
)
{
// Can't predict the precision due to the effect of rounding.
int
raise
=
checkScale
((
long
)
newScale
-
oldScale
);
int
drop
=
checkScale
((
long
)
oldScale
-
newScale
);
BigInteger
rb
=
bigMultiplyPowerTen
(
this
.
intVal
,
raise
);
if
(
drop
<
LONG_TEN_POWERS_TABLE
.
length
)
return
new
BigDecimal
(
rb
,
INFLATED
,
newScale
,
(
precision
>
0
)
?
precision
+
raise
:
0
);
return
divideAndRound
(
rs
,
this
.
intVal
,
}
else
{
LONG_TEN_POWERS_TABLE
[
drop
],
null
,
// newScale < oldScale -- drop some digits
newScale
,
roundingMode
,
newScale
);
// Can't predict the precision due to the effect of rounding.
else
int
drop
=
checkScale
((
long
)
oldScale
-
newScale
);
return
divideAndRound
(
rs
,
this
.
intVal
,
if
(
drop
<
LONG_TEN_POWERS_TABLE
.
length
)
INFLATED
,
bigTenToThe
(
drop
),
return
divideAndRound
(
this
.
intVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
newScale
,
roundingMode
,
newScale
,
roundingMode
,
newScale
);
newScale
);
else
return
divideAndRound
(
this
.
intVal
,
bigTenToThe
(
drop
),
newScale
,
roundingMode
,
newScale
);
}
}
}
}
}
...
@@ -2524,10 +2597,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2524,10 +2597,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
stripTrailingZeros
()
{
public
BigDecimal
stripTrailingZeros
()
{
this
.
inflate
();
if
(
intCompact
!=
INFLATED
)
{
BigDecimal
result
=
new
BigDecimal
(
intVal
,
scale
);
return
createAndStripZerosToMatchScale
(
intCompact
,
scale
,
Long
.
MIN_VALUE
);
result
.
stripZerosToMatchScale
(
Long
.
MIN_VALUE
);
}
else
{
return
result
;
return
createAndStripZerosToMatchScale
(
intVal
,
scale
,
Long
.
MIN_VALUE
);
}
}
}
// Comparison Operations
// Comparison Operations
...
@@ -2647,7 +2721,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2647,7 +2721,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
else
if
(
xs
!=
INFLATED
)
}
else
if
(
xs
!=
INFLATED
)
return
xs
==
compactValFor
(
this
.
intVal
);
return
xs
==
compactValFor
(
this
.
intVal
);
return
this
.
inflate
().
equals
(
xDec
.
inflate
());
return
this
.
inflate
d
().
equals
(
xDec
.
inflated
());
}
}
/**
/**
...
@@ -2872,13 +2946,38 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2872,13 +2946,38 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @see #toEngineeringString()
* @see #toEngineeringString()
*/
*/
public
String
toPlainString
()
{
public
String
toPlainString
()
{
BigDecimal
bd
=
this
;
if
(
scale
==
0
)
{
if
(
bd
.
scale
<
0
)
if
(
intCompact
!=
INFLATED
)
{
bd
=
bd
.
setScale
(
0
);
return
Long
.
toString
(
intCompact
);
bd
.
inflate
();
}
else
{
if
(
bd
.
scale
==
0
)
// No decimal point
return
intVal
.
toString
();
return
bd
.
intVal
.
toString
();
}
return
bd
.
getValueString
(
bd
.
signum
(),
bd
.
intVal
.
abs
().
toString
(),
bd
.
scale
);
}
if
(
this
.
scale
<
0
)
{
// No decimal point
if
(
signum
()==
0
)
{
return
"0"
;
}
int
tailingZeros
=
checkScaleNonZero
((-(
long
)
scale
));
StringBuilder
buf
;
if
(
intCompact
!=
INFLATED
)
{
buf
=
new
StringBuilder
(
20
+
tailingZeros
);
buf
.
append
(
intCompact
);
}
else
{
String
str
=
intVal
.
toString
();
buf
=
new
StringBuilder
(
str
.
length
()+
tailingZeros
);
buf
.
append
(
str
);
}
for
(
int
i
=
0
;
i
<
tailingZeros
;
i
++)
buf
.
append
(
'0'
);
return
buf
.
toString
();
}
String
str
;
if
(
intCompact
!=
INFLATED
)
{
str
=
Long
.
toString
(
Math
.
abs
(
intCompact
));
}
else
{
str
=
intVal
.
abs
().
toString
();
}
return
getValueString
(
signum
(),
str
,
scale
);
}
}
/* Returns a digit.digit string */
/* Returns a digit.digit string */
...
@@ -2922,7 +3021,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2922,7 +3021,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
public
BigInteger
toBigInteger
()
{
public
BigInteger
toBigInteger
()
{
// force to an integer, quietly
// force to an integer, quietly
return
this
.
setScale
(
0
,
ROUND_DOWN
).
inflate
();
return
this
.
setScale
(
0
,
ROUND_DOWN
).
inflate
d
();
}
}
/**
/**
...
@@ -2937,7 +3036,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2937,7 +3036,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
public
BigInteger
toBigIntegerExact
()
{
public
BigInteger
toBigIntegerExact
()
{
// round to an integer, with Exception if decimal part non-0
// round to an integer, with Exception if decimal part non-0
return
this
.
setScale
(
0
,
ROUND_UNNECESSARY
).
inflate
();
return
this
.
setScale
(
0
,
ROUND_UNNECESSARY
).
inflate
d
();
}
}
/**
/**
...
@@ -2990,7 +3089,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -2990,7 +3089,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
BigDecimal
num
=
this
.
setScale
(
0
,
ROUND_UNNECESSARY
);
BigDecimal
num
=
this
.
setScale
(
0
,
ROUND_UNNECESSARY
);
if
(
num
.
precision
()
>=
19
)
// need to check carefully
if
(
num
.
precision
()
>=
19
)
// need to check carefully
LongOverflow
.
check
(
num
);
LongOverflow
.
check
(
num
);
return
num
.
inflate
().
longValue
();
return
num
.
inflate
d
().
longValue
();
}
}
private
static
class
LongOverflow
{
private
static
class
LongOverflow
{
...
@@ -3001,9 +3100,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3001,9 +3100,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
private
static
final
BigInteger
LONGMAX
=
BigInteger
.
valueOf
(
Long
.
MAX_VALUE
);
private
static
final
BigInteger
LONGMAX
=
BigInteger
.
valueOf
(
Long
.
MAX_VALUE
);
public
static
void
check
(
BigDecimal
num
)
{
public
static
void
check
(
BigDecimal
num
)
{
num
.
inflate
();
BigInteger
intVal
=
num
.
inflated
();
if
(
(
num
.
intVal
.
compareTo
(
LONGMIN
)
<
0
)
||
if
(
intVal
.
compareTo
(
LONGMIN
)
<
0
||
(
num
.
intVal
.
compareTo
(
LONGMAX
)
>
0
)
)
intVal
.
compareTo
(
LONGMAX
)
>
0
)
throw
new
java
.
lang
.
ArithmeticException
(
"Overflow"
);
throw
new
java
.
lang
.
ArithmeticException
(
"Overflow"
);
}
}
}
}
...
@@ -3107,8 +3206,28 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3107,8 +3206,28 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return this {@code BigDecimal} converted to a {@code float}.
* @return this {@code BigDecimal} converted to a {@code float}.
*/
*/
public
float
floatValue
(){
public
float
floatValue
(){
if
(
scale
==
0
&&
intCompact
!=
INFLATED
)
if
(
intCompact
!=
INFLATED
)
{
if
(
scale
==
0
)
{
return
(
float
)
intCompact
;
return
(
float
)
intCompact
;
}
else
{
/*
* If both intCompact and the scale can be exactly
* represented as float values, perform a single float
* multiply or divide to compute the (properly
* rounded) result.
*/
if
(
Math
.
abs
(
intCompact
)
<
1L
<<
22
)
{
// Don't have too guard against
// Math.abs(MIN_VALUE) because of outer check
// against INFLATED.
if
(
scale
>
0
&&
scale
<
float10pow
.
length
)
{
return
(
float
)
intCompact
/
float10pow
[
scale
];
}
else
if
(
scale
<
0
&&
scale
>
-
float10pow
.
length
)
{
return
(
float
)
intCompact
*
float10pow
[-
scale
];
}
}
}
}
// Somewhat inefficient, but guaranteed to work.
// Somewhat inefficient, but guaranteed to work.
return
Float
.
parseFloat
(
this
.
toString
());
return
Float
.
parseFloat
(
this
.
toString
());
}
}
...
@@ -3130,12 +3249,52 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3130,12 +3249,52 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @return this {@code BigDecimal} converted to a {@code double}.
* @return this {@code BigDecimal} converted to a {@code double}.
*/
*/
public
double
doubleValue
(){
public
double
doubleValue
(){
if
(
scale
==
0
&&
intCompact
!=
INFLATED
)
if
(
intCompact
!=
INFLATED
)
{
return
(
double
)
intCompact
;
if
(
scale
==
0
)
{
return
(
double
)
intCompact
;
}
else
{
/*
* If both intCompact and the scale can be exactly
* represented as double values, perform a single
* double multiply or divide to compute the (properly
* rounded) result.
*/
if
(
Math
.
abs
(
intCompact
)
<
1L
<<
52
)
{
// Don't have too guard against
// Math.abs(MIN_VALUE) because of outer check
// against INFLATED.
if
(
scale
>
0
&&
scale
<
double10pow
.
length
)
{
return
(
double
)
intCompact
/
double10pow
[
scale
];
}
else
if
(
scale
<
0
&&
scale
>
-
double10pow
.
length
)
{
return
(
double
)
intCompact
*
double10pow
[-
scale
];
}
}
}
}
// Somewhat inefficient, but guaranteed to work.
// Somewhat inefficient, but guaranteed to work.
return
Double
.
parseDouble
(
this
.
toString
());
return
Double
.
parseDouble
(
this
.
toString
());
}
}
/**
* Powers of 10 which can be represented exactly in {@code
* double}.
*/
private
static
final
double
double10pow
[]
=
{
1.0e0
,
1.0e1
,
1.0e2
,
1.0e3
,
1.0e4
,
1.0e5
,
1.0e6
,
1.0e7
,
1.0e8
,
1.0e9
,
1.0e10
,
1.0e11
,
1.0e12
,
1.0e13
,
1.0e14
,
1.0e15
,
1.0e16
,
1.0e17
,
1.0e18
,
1.0e19
,
1.0e20
,
1.0e21
,
1.0e22
};
/**
* Powers of 10 which can be represented exactly in {@code
* float}.
*/
private
static
final
float
float10pow
[]
=
{
1.0e0f
,
1.0e1f
,
1.0e2f
,
1.0e3f
,
1.0e4f
,
1.0e5f
,
1.0e6f
,
1.0e7f
,
1.0e8f
,
1.0e9f
,
1.0e10f
};
/**
/**
* Returns the size of an ulp, a unit in the last place, of this
* Returns the size of an ulp, a unit in the last place, of this
* {@code BigDecimal}. An ulp of a nonzero {@code BigDecimal}
* {@code BigDecimal}. An ulp of a nonzero {@code BigDecimal}
...
@@ -3151,10 +3310,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3151,10 +3310,9 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @since 1.5
* @since 1.5
*/
*/
public
BigDecimal
ulp
()
{
public
BigDecimal
ulp
()
{
return
BigDecimal
.
valueOf
(
1
,
this
.
scale
());
return
BigDecimal
.
valueOf
(
1
,
this
.
scale
()
,
1
);
}
}
// Private class to build a string representation for BigDecimal object.
// Private class to build a string representation for BigDecimal object.
// "StringBuilderHelper" is constructed as a thread local variable so it is
// "StringBuilderHelper" is constructed as a thread local variable so it is
// thread safe. The StringBuilder field acts as a buffer to hold the temporary
// thread safe. The StringBuilder field acts as a buffer to hold the temporary
...
@@ -3268,6 +3426,15 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3268,6 +3426,15 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return
(
intCompact
!=
INFLATED
)
?
return
(
intCompact
!=
INFLATED
)
?
Long
.
toString
(
intCompact
):
Long
.
toString
(
intCompact
):
intVal
.
toString
();
intVal
.
toString
();
if
(
scale
==
2
&&
intCompact
>=
0
&&
intCompact
<
Integer
.
MAX_VALUE
)
{
// currency fast path
int
lowInt
=
(
int
)
intCompact
%
100
;
int
highInt
=
(
int
)
intCompact
/
100
;
return
(
Integer
.
toString
(
highInt
)
+
'.'
+
StringBuilderHelper
.
DIGIT_TENS
[
lowInt
]
+
StringBuilderHelper
.
DIGIT_ONES
[
lowInt
])
;
}
StringBuilderHelper
sbHelper
=
threadLocalStringBuilderHelper
.
get
();
StringBuilderHelper
sbHelper
=
threadLocalStringBuilderHelper
.
get
();
char
[]
coeff
;
char
[]
coeff
;
...
@@ -3377,7 +3544,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3377,7 +3544,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
tenpow
[
0
]
=
'1'
;
tenpow
[
0
]
=
'1'
;
for
(
int
i
=
1
;
i
<=
n
;
i
++)
for
(
int
i
=
1
;
i
<=
n
;
i
++)
tenpow
[
i
]
=
'0'
;
tenpow
[
i
]
=
'0'
;
return
new
BigInteger
(
tenpow
);
return
new
BigInteger
(
tenpow
,
1
,
tenpow
.
length
);
}
}
/**
/**
...
@@ -3433,11 +3600,16 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3433,11 +3600,16 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
1000000000000000000L
// 18 / 10^18
1000000000000000000L
// 18 / 10^18
};
};
private
static
volatile
BigInteger
BIG_TEN_POWERS_TABLE
[]
=
{
BigInteger
.
ONE
,
private
static
volatile
BigInteger
BIG_TEN_POWERS_TABLE
[]
=
{
BigInteger
.
valueOf
(
10
),
BigInteger
.
valueOf
(
100
),
BigInteger
.
ONE
,
BigInteger
.
valueOf
(
1000
),
BigInteger
.
valueOf
(
10000
),
BigInteger
.
valueOf
(
10
),
BigInteger
.
valueOf
(
100000
),
BigInteger
.
valueOf
(
1000000
),
BigInteger
.
valueOf
(
100
),
BigInteger
.
valueOf
(
10000000
),
BigInteger
.
valueOf
(
100000000
),
BigInteger
.
valueOf
(
1000
),
BigInteger
.
valueOf
(
10000
),
BigInteger
.
valueOf
(
100000
),
BigInteger
.
valueOf
(
1000000
),
BigInteger
.
valueOf
(
10000000
),
BigInteger
.
valueOf
(
100000000
),
BigInteger
.
valueOf
(
1000000000
),
BigInteger
.
valueOf
(
1000000000
),
BigInteger
.
valueOf
(
10000000000L
),
BigInteger
.
valueOf
(
10000000000L
),
BigInteger
.
valueOf
(
100000000000L
),
BigInteger
.
valueOf
(
100000000000L
),
...
@@ -3502,7 +3674,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3502,7 +3674,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
*/
private
BigInteger
bigMultiplyPowerTen
(
int
n
)
{
private
BigInteger
bigMultiplyPowerTen
(
int
n
)
{
if
(
n
<=
0
)
if
(
n
<=
0
)
return
this
.
inflate
();
return
this
.
inflate
d
();
if
(
intCompact
!=
INFLATED
)
if
(
intCompact
!=
INFLATED
)
return
bigTenToThe
(
n
).
multiply
(
intCompact
);
return
bigTenToThe
(
n
).
multiply
(
intCompact
);
...
@@ -3511,12 +3683,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3511,12 +3683,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
}
/**
/**
*
Assign appropriate BigInteger to
intVal field if intVal is
*
Returns appropriate BigInteger from
intVal field if intVal is
* null, i.e. the compact representation is in use.
* null, i.e. the compact representation is in use.
*/
*/
private
BigInteger
inflate
()
{
private
BigInteger
inflated
()
{
if
(
intVal
==
null
)
if
(
intVal
==
null
)
{
intVal
=
BigInteger
.
valueOf
(
intCompact
);
return
BigInteger
.
valueOf
(
intCompact
);
}
return
intVal
;
return
intVal
;
}
}
...
@@ -3543,6 +3716,28 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3543,6 +3716,28 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
}
}
}
private
static
final
sun
.
misc
.
Unsafe
unsafe
=
sun
.
misc
.
Unsafe
.
getUnsafe
();
private
static
final
long
intCompactOffset
;
private
static
final
long
intValOffset
;
static
{
try
{
intCompactOffset
=
unsafe
.
objectFieldOffset
(
BigDecimal
.
class
.
getDeclaredField
(
"intCompact"
));
intValOffset
=
unsafe
.
objectFieldOffset
(
BigDecimal
.
class
.
getDeclaredField
(
"intVal"
));
}
catch
(
Exception
ex
)
{
throw
new
Error
(
ex
);
}
}
private
void
setIntCompactVolatile
(
long
val
)
{
unsafe
.
putLongVolatile
(
this
,
intCompactOffset
,
val
);
}
private
void
setIntValVolatile
(
BigInteger
val
)
{
unsafe
.
putObjectVolatile
(
this
,
intValOffset
,
val
);
}
/**
/**
* Reconstitute the {@code BigDecimal} instance from a stream (that is,
* Reconstitute the {@code BigDecimal} instance from a stream (that is,
* deserialize it).
* deserialize it).
...
@@ -3559,7 +3754,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3559,7 +3754,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
throw
new
java
.
io
.
StreamCorruptedException
(
message
);
throw
new
java
.
io
.
StreamCorruptedException
(
message
);
// [all values of scale are now allowed]
// [all values of scale are now allowed]
}
}
intCompact
=
compactValFor
(
intVal
);
setIntCompactVolatile
(
compactValFor
(
intVal
)
);
}
}
/**
/**
...
@@ -3570,13 +3765,12 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3570,13 +3765,12 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
private
void
writeObject
(
java
.
io
.
ObjectOutputStream
s
)
private
void
writeObject
(
java
.
io
.
ObjectOutputStream
s
)
throws
java
.
io
.
IOException
{
throws
java
.
io
.
IOException
{
// Must inflate to maintain compatible serial form.
// Must inflate to maintain compatible serial form.
this
.
inflate
();
if
(
this
.
intVal
==
null
)
this
.
setIntValVolatile
(
BigInteger
.
valueOf
(
this
.
intCompact
));
//
Write proper fields
//
Could reset intVal back to null if it has to be set.
s
.
defaultWriteObject
();
s
.
defaultWriteObject
();
}
}
/**
/**
* Returns the length of the absolute value of a {@code long}, in decimal
* Returns the length of the absolute value of a {@code long}, in decimal
* digits.
* digits.
...
@@ -3584,36 +3778,29 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3584,36 +3778,29 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
* @param x the {@code long}
* @param x the {@code long}
* @return the length of the unscaled value, in deciaml digits.
* @return the length of the unscaled value, in deciaml digits.
*/
*/
private
static
int
longDigitLength
(
long
x
)
{
static
int
longDigitLength
(
long
x
)
{
/*
/*
* As described in "Bit Twiddling Hacks" by Sean Anderson,
* As described in "Bit Twiddling Hacks" by Sean Anderson,
* (http://graphics.stanford.edu/~seander/bithacks.html)
* (http://graphics.stanford.edu/~seander/bithacks.html)
* integer log 10 of x is within 1 of
* integer log 10 of x is within 1 of
(1233/4096)* (1 +
*
(1233/4096)* (1 + integer log 2 of x).
*
integer log 2 of x). The fraction 1233/4096 approximates
*
The fraction 1233/4096 approximates log10(2). So we first
*
log10(2). So we first do a version of log2 (a variant of
*
do a version of log2 (a variant of Long class with
*
Long class with pre-checks and opposite directionality) and
*
pre-checks and opposite directionality) and then scale and
*
then scale and check against powers table. This is a little
*
check against powers table. This is a little simpler in
*
simpler in present context than the version in Hacker's
*
present context than the version in Hacker's Delight sec
*
Delight sec 11-4. Adding one to bit length allows comparing
*
11-4. Adding one to bit length allows comparing downwar
d
*
downward from the LONG_TEN_POWERS_TABLE that we nee
d
*
from the LONG_TEN_POWERS_TABLE that we need
anyway.
* anyway.
*/
*/
assert
x
!=
INFLATED
;
assert
x
!=
BigDecimal
.
INFLATED
;
if
(
x
<
0
)
if
(
x
<
0
)
x
=
-
x
;
x
=
-
x
;
if
(
x
<
10
)
// must screen for 0, might as well 10
if
(
x
<
10
)
// must screen for 0, might as well 10
return
1
;
return
1
;
int
n
=
64
;
// not 63, to avoid needing to add 1 later
int
r
=
((
64
-
Long
.
numberOfLeadingZeros
(
x
)
+
1
)
*
1233
)
>>>
12
;
int
y
=
(
int
)(
x
>>>
32
);
if
(
y
==
0
)
{
n
-=
32
;
y
=
(
int
)
x
;
}
if
(
y
>>>
16
==
0
)
{
n
-=
16
;
y
<<=
16
;
}
if
(
y
>>>
24
==
0
)
{
n
-=
8
;
y
<<=
8
;
}
if
(
y
>>>
28
==
0
)
{
n
-=
4
;
y
<<=
4
;
}
if
(
y
>>>
30
==
0
)
{
n
-=
2
;
y
<<=
2
;
}
int
r
=
(((
y
>>>
31
)
+
n
)
*
1233
)
>>>
12
;
long
[]
tab
=
LONG_TEN_POWERS_TABLE
;
long
[]
tab
=
LONG_TEN_POWERS_TABLE
;
// if r >= length, must have max possible digits for long
// if r >= length, must have max possible digits for long
return
(
r
>=
tab
.
length
||
x
<
tab
[
r
])
?
r
:
r
+
1
;
return
(
r
>=
tab
.
length
||
x
<
tab
[
r
])
?
r
:
r
+
1
;
}
}
/**
/**
...
@@ -3635,41 +3822,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3635,41 +3822,6 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return
b
.
compareMagnitude
(
bigTenToThe
(
r
))
<
0
?
r
:
r
+
1
;
return
b
.
compareMagnitude
(
bigTenToThe
(
r
))
<
0
?
r
:
r
+
1
;
}
}
/**
* Remove insignificant trailing zeros from this
* {@code BigDecimal} until the preferred scale is reached or no
* more zeros can be removed. If the preferred scale is less than
* Integer.MIN_VALUE, all the trailing zeros will be removed.
*
* {@code BigInteger} assistance could help, here?
*
* <p>WARNING: This method should only be called on new objects as
* it mutates the value fields.
*
* @return this {@code BigDecimal} with a scale possibly reduced
* to be closed to the preferred scale.
*/
private
BigDecimal
stripZerosToMatchScale
(
long
preferredScale
)
{
this
.
inflate
();
BigInteger
qr
[];
// quotient-remainder pair
while
(
intVal
.
compareMagnitude
(
BigInteger
.
TEN
)
>=
0
&&
scale
>
preferredScale
)
{
if
(
intVal
.
testBit
(
0
))
break
;
// odd number cannot end in 0
qr
=
intVal
.
divideAndRemainder
(
BigInteger
.
TEN
);
if
(
qr
[
1
].
signum
()
!=
0
)
break
;
// non-0 remainder
intVal
=
qr
[
0
];
scale
=
checkScale
((
long
)
scale
-
1
);
// could Overflow
if
(
precision
>
0
)
// adjust precision if known
precision
--;
}
if
(
intVal
!=
null
)
intCompact
=
compactValFor
(
intVal
);
return
this
;
}
/**
/**
* Check a scale for Underflow or Overflow. If this BigDecimal is
* Check a scale for Underflow or Overflow. If this BigDecimal is
* nonzero, throw an exception if the scale is outof range. If this
* nonzero, throw an exception if the scale is outof range. If this
...
@@ -3693,74 +3845,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3693,74 +3845,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return
asInt
;
return
asInt
;
}
}
/**
/**
* Round an operand; used only if digits > 0. Does not change
* {@code this}; if rounding is needed a new {@code BigDecimal}
* is created and returned.
*
* @param mc the context to use.
* @throws ArithmeticException if the result is inexact but the
* rounding mode is {@code UNNECESSARY}.
*/
private
BigDecimal
roundOp
(
MathContext
mc
)
{
BigDecimal
rounded
=
doRound
(
this
,
mc
);
return
rounded
;
}
/** Round this BigDecimal according to the MathContext settings;
* used only if precision {@literal >} 0.
*
* <p>WARNING: This method should only be called on new objects as
* it mutates the value fields.
*
* @param mc the context to use.
* @throws ArithmeticException if the rounding mode is
* {@code RoundingMode.UNNECESSARY} and the
* {@code BigDecimal} operation would require rounding.
*/
private
void
roundThis
(
MathContext
mc
)
{
BigDecimal
rounded
=
doRound
(
this
,
mc
);
if
(
rounded
==
this
)
// wasn't rounded
return
;
this
.
intVal
=
rounded
.
intVal
;
this
.
intCompact
=
rounded
.
intCompact
;
this
.
scale
=
rounded
.
scale
;
this
.
precision
=
rounded
.
precision
;
}
/**
* Returns a {@code BigDecimal} rounded according to the
* MathContext settings; used only if {@code mc.precision > 0}.
* Does not change {@code this}; if rounding is needed a new
* {@code BigDecimal} is created and returned.
*
* @param mc the context to use.
* @return a {@code BigDecimal} rounded according to the MathContext
* settings. May return this, if no rounding needed.
* @throws ArithmeticException if the rounding mode is
* {@code RoundingMode.UNNECESSARY} and the
* result is inexact.
*/
private
static
BigDecimal
doRound
(
BigDecimal
d
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
int
drop
;
// This might (rarely) iterate to cover the 999=>1000 case
while
((
drop
=
d
.
precision
()
-
mcp
)
>
0
)
{
int
newScale
=
d
.
checkScale
((
long
)
d
.
scale
-
drop
);
int
mode
=
mc
.
roundingMode
.
oldMode
;
if
(
drop
<
LONG_TEN_POWERS_TABLE
.
length
)
d
=
divideAndRound
(
d
.
intCompact
,
d
.
intVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
null
,
newScale
,
mode
,
newScale
);
else
d
=
divideAndRound
(
d
.
intCompact
,
d
.
intVal
,
INFLATED
,
bigTenToThe
(
drop
),
newScale
,
mode
,
newScale
);
}
return
d
;
}
/**
* Returns the compact value for given {@code BigInteger}, or
* Returns the compact value for given {@code BigInteger}, or
* INFLATED if too big. Relies on internal representation of
* INFLATED if too big. Relies on internal representation of
* {@code BigInteger}.
* {@code BigInteger}.
...
@@ -3852,4 +3937,1275 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
...
@@ -3852,4 +3937,1275 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
}
return
this
;
return
this
;
}
}
/* the same as checkScale where value!=0 */
private
static
int
checkScaleNonZero
(
long
val
)
{
int
asInt
=
(
int
)
val
;
if
(
asInt
!=
val
)
{
throw
new
ArithmeticException
(
asInt
>
0
?
"Underflow"
:
"Overflow"
);
}
return
asInt
;
}
private
static
int
checkScale
(
long
intCompact
,
long
val
)
{
int
asInt
=
(
int
)
val
;
if
(
asInt
!=
val
)
{
asInt
=
val
>
Integer
.
MAX_VALUE
?
Integer
.
MAX_VALUE
:
Integer
.
MIN_VALUE
;
if
(
intCompact
!=
0
)
throw
new
ArithmeticException
(
asInt
>
0
?
"Underflow"
:
"Overflow"
);
}
return
asInt
;
}
private
static
int
checkScale
(
BigInteger
intVal
,
long
val
)
{
int
asInt
=
(
int
)
val
;
if
(
asInt
!=
val
)
{
asInt
=
val
>
Integer
.
MAX_VALUE
?
Integer
.
MAX_VALUE
:
Integer
.
MIN_VALUE
;
if
(
intVal
.
signum
()
!=
0
)
throw
new
ArithmeticException
(
asInt
>
0
?
"Underflow"
:
"Overflow"
);
}
return
asInt
;
}
/**
* Returns a {@code BigDecimal} rounded according to the MathContext
* settings;
* If rounding is needed a new {@code BigDecimal} is created and returned.
*
* @param val the value to be rounded
* @param mc the context to use.
* @return a {@code BigDecimal} rounded according to the MathContext
* settings. May return {@code value}, if no rounding needed.
* @throws ArithmeticException if the rounding mode is
* {@code RoundingMode.UNNECESSARY} and the
* result is inexact.
*/
private
static
BigDecimal
doRound
(
BigDecimal
val
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
boolean
wasDivided
=
false
;
if
(
mcp
>
0
)
{
BigInteger
intVal
=
val
.
intVal
;
long
compactVal
=
val
.
intCompact
;
int
scale
=
val
.
scale
;
int
prec
=
val
.
precision
();
int
mode
=
mc
.
roundingMode
.
oldMode
;
int
drop
;
if
(
compactVal
==
INFLATED
)
{
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
intVal
=
divideAndRoundByTenPow
(
intVal
,
drop
,
mode
);
wasDivided
=
true
;
compactVal
=
compactValFor
(
intVal
);
if
(
compactVal
!=
INFLATED
)
{
prec
=
longDigitLength
(
compactVal
);
break
;
}
prec
=
bigDigitLength
(
intVal
);
drop
=
prec
-
mcp
;
}
}
if
(
compactVal
!=
INFLATED
)
{
drop
=
prec
-
mcp
;
// drop can't be more than 18
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
compactVal
=
divideAndRound
(
compactVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
wasDivided
=
true
;
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
intVal
=
null
;
}
}
return
wasDivided
?
new
BigDecimal
(
intVal
,
compactVal
,
scale
,
prec
)
:
val
;
}
return
val
;
}
/*
* Returns a {@code BigDecimal} created from {@code long} value with
* given scale rounded according to the MathContext settings
*/
private
static
BigDecimal
doRound
(
long
compactVal
,
int
scale
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
if
(
mcp
>
0
&&
mcp
<
19
)
{
int
prec
=
longDigitLength
(
compactVal
);
int
drop
=
prec
-
mcp
;
// drop can't be more than 18
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
compactVal
=
divideAndRound
(
compactVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
}
return
valueOf
(
compactVal
,
scale
,
prec
);
}
return
valueOf
(
compactVal
,
scale
);
}
/*
* Returns a {@code BigDecimal} created from {@code BigInteger} value with
* given scale rounded according to the MathContext settings
*/
private
static
BigDecimal
doRound
(
BigInteger
intVal
,
int
scale
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
int
prec
=
0
;
if
(
mcp
>
0
)
{
long
compactVal
=
compactValFor
(
intVal
);
int
mode
=
mc
.
roundingMode
.
oldMode
;
int
drop
;
if
(
compactVal
==
INFLATED
)
{
prec
=
bigDigitLength
(
intVal
);
drop
=
prec
-
mcp
;
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
intVal
=
divideAndRoundByTenPow
(
intVal
,
drop
,
mode
);
compactVal
=
compactValFor
(
intVal
);
if
(
compactVal
!=
INFLATED
)
{
break
;
}
prec
=
bigDigitLength
(
intVal
);
drop
=
prec
-
mcp
;
}
}
if
(
compactVal
!=
INFLATED
)
{
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
// drop can't be more than 18
while
(
drop
>
0
)
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
compactVal
=
divideAndRound
(
compactVal
,
LONG_TEN_POWERS_TABLE
[
drop
],
mc
.
roundingMode
.
oldMode
);
prec
=
longDigitLength
(
compactVal
);
drop
=
prec
-
mcp
;
}
return
valueOf
(
compactVal
,
scale
,
prec
);
}
}
return
new
BigDecimal
(
intVal
,
INFLATED
,
scale
,
prec
);
}
/*
* Divides {@code BigInteger} value by ten power.
*/
private
static
BigInteger
divideAndRoundByTenPow
(
BigInteger
intVal
,
int
tenPow
,
int
roundingMode
)
{
if
(
tenPow
<
LONG_TEN_POWERS_TABLE
.
length
)
intVal
=
divideAndRound
(
intVal
,
LONG_TEN_POWERS_TABLE
[
tenPow
],
roundingMode
);
else
intVal
=
divideAndRound
(
intVal
,
bigTenToThe
(
tenPow
),
roundingMode
);
return
intVal
;
}
/**
* Internally used for division operation for division {@code long} by
* {@code long}.
* The returned {@code BigDecimal} object is the quotient whose scale is set
* to the passed in scale. If the remainder is not zero, it will be rounded
* based on the passed in roundingMode. Also, if the remainder is zero and
* the last parameter, i.e. preferredScale is NOT equal to scale, the
* trailing zeros of the result is stripped to match the preferredScale.
*/
private
static
BigDecimal
divideAndRound
(
long
ldividend
,
long
ldivisor
,
int
scale
,
int
roundingMode
,
int
preferredScale
)
{
int
qsign
;
// quotient sign
long
q
=
ldividend
/
ldivisor
;
// store quotient in long
if
(
roundingMode
==
ROUND_DOWN
&&
scale
==
preferredScale
)
return
valueOf
(
q
,
scale
);
long
r
=
ldividend
%
ldivisor
;
// store remainder in long
qsign
=
((
ldividend
<
0
)
==
(
ldivisor
<
0
))
?
1
:
-
1
;
if
(
r
!=
0
)
{
boolean
increment
=
needIncrement
(
ldivisor
,
roundingMode
,
qsign
,
q
,
r
);
return
valueOf
((
increment
?
q
+
qsign
:
q
),
scale
);
}
else
{
if
(
preferredScale
!=
scale
)
return
createAndStripZerosToMatchScale
(
q
,
scale
,
preferredScale
);
else
return
valueOf
(
q
,
scale
);
}
}
/**
* Divides {@code long} by {@code long} and do rounding based on the
* passed in roundingMode.
*/
private
static
long
divideAndRound
(
long
ldividend
,
long
ldivisor
,
int
roundingMode
)
{
int
qsign
;
// quotient sign
long
q
=
ldividend
/
ldivisor
;
// store quotient in long
if
(
roundingMode
==
ROUND_DOWN
)
return
q
;
long
r
=
ldividend
%
ldivisor
;
// store remainder in long
qsign
=
((
ldividend
<
0
)
==
(
ldivisor
<
0
))
?
1
:
-
1
;
if
(
r
!=
0
)
{
boolean
increment
=
needIncrement
(
ldivisor
,
roundingMode
,
qsign
,
q
,
r
);
return
increment
?
q
+
qsign
:
q
;
}
else
{
return
q
;
}
}
/**
* Shared logic of need increment computation.
*/
private
static
boolean
commonNeedIncrement
(
int
roundingMode
,
int
qsign
,
int
cmpFracHalf
,
boolean
oddQuot
)
{
switch
(
roundingMode
)
{
case
ROUND_UNNECESSARY:
throw
new
ArithmeticException
(
"Rounding necessary"
);
case
ROUND_UP:
// Away from zero
return
true
;
case
ROUND_DOWN:
// Towards zero
return
false
;
case
ROUND_CEILING:
// Towards +infinity
return
qsign
>
0
;
case
ROUND_FLOOR:
// Towards -infinity
return
qsign
<
0
;
default
:
// Some kind of half-way rounding
if
(
roundingMode
==
ROUND_HALF_DOWN
||
cmpFracHalf
<
0
)
// We're closer to higher digit
return
false
;
else
if
(
roundingMode
==
ROUND_HALF_UP
||
cmpFracHalf
>
0
)
// We're closer to lower digit
return
true
;
else
// roundingMode == ROUND_HALF_EVEN, true iff quotient is odd
return
oddQuot
;
}
}
/**
* Tests if quotient has to be incremented according the roundingMode
*/
private
static
boolean
needIncrement
(
long
ldivisor
,
int
roundingMode
,
int
qsign
,
long
q
,
long
r
)
{
assert
r
!=
0L
;
int
cmpFracHalf
;
if
(
r
<=
HALF_LONG_MIN_VALUE
||
r
>
HALF_LONG_MAX_VALUE
)
{
cmpFracHalf
=
1
;
// 2 * r can't fit into long
}
else
{
cmpFracHalf
=
longCompareMagnitude
(
2
*
r
,
ldivisor
);
}
return
commonNeedIncrement
(
roundingMode
,
qsign
,
cmpFracHalf
,
(
q
&
1L
)
!=
0L
);
}
/**
* Divides {@code BigInteger} value by {@code long} value and
* do rounding based on the passed in roundingMode.
*/
private
static
BigInteger
divideAndRound
(
BigInteger
bdividend
,
long
ldivisor
,
int
roundingMode
)
{
boolean
isRemainderZero
;
// record remainder is zero or not
int
qsign
;
// quotient sign
long
r
=
0
;
// store quotient & remainder in long
MutableBigInteger
mq
=
null
;
// store quotient
// Descend into mutables for faster remainder checks
MutableBigInteger
mdividend
=
new
MutableBigInteger
(
bdividend
.
mag
);
mq
=
new
MutableBigInteger
();
r
=
mdividend
.
divide
(
ldivisor
,
mq
);
isRemainderZero
=
(
r
==
0
);
qsign
=
(
ldivisor
<
0
)
?
-
bdividend
.
signum
:
bdividend
.
signum
;
if
(!
isRemainderZero
)
{
if
(
needIncrement
(
ldivisor
,
roundingMode
,
qsign
,
mq
,
r
))
{
mq
.
add
(
MutableBigInteger
.
ONE
);
}
}
return
mq
.
toBigInteger
(
qsign
);
}
/**
* Internally used for division operation for division {@code BigInteger}
* by {@code long}.
* The returned {@code BigDecimal} object is the quotient whose scale is set
* to the passed in scale. If the remainder is not zero, it will be rounded
* based on the passed in roundingMode. Also, if the remainder is zero and
* the last parameter, i.e. preferredScale is NOT equal to scale, the
* trailing zeros of the result is stripped to match the preferredScale.
*/
private
static
BigDecimal
divideAndRound
(
BigInteger
bdividend
,
long
ldivisor
,
int
scale
,
int
roundingMode
,
int
preferredScale
)
{
boolean
isRemainderZero
;
// record remainder is zero or not
int
qsign
;
// quotient sign
long
r
=
0
;
// store quotient & remainder in long
MutableBigInteger
mq
=
null
;
// store quotient
// Descend into mutables for faster remainder checks
MutableBigInteger
mdividend
=
new
MutableBigInteger
(
bdividend
.
mag
);
mq
=
new
MutableBigInteger
();
r
=
mdividend
.
divide
(
ldivisor
,
mq
);
isRemainderZero
=
(
r
==
0
);
qsign
=
(
ldivisor
<
0
)
?
-
bdividend
.
signum
:
bdividend
.
signum
;
if
(!
isRemainderZero
)
{
if
(
needIncrement
(
ldivisor
,
roundingMode
,
qsign
,
mq
,
r
))
{
mq
.
add
(
MutableBigInteger
.
ONE
);
}
return
mq
.
toBigDecimal
(
qsign
,
scale
);
}
else
{
if
(
preferredScale
!=
scale
)
{
long
compactVal
=
mq
.
toCompactValue
(
qsign
);
if
(
compactVal
!=
INFLATED
)
{
return
createAndStripZerosToMatchScale
(
compactVal
,
scale
,
preferredScale
);
}
BigInteger
intVal
=
mq
.
toBigInteger
(
qsign
);
return
createAndStripZerosToMatchScale
(
intVal
,
scale
,
preferredScale
);
}
else
{
return
mq
.
toBigDecimal
(
qsign
,
scale
);
}
}
}
/**
* Tests if quotient has to be incremented according the roundingMode
*/
private
static
boolean
needIncrement
(
long
ldivisor
,
int
roundingMode
,
int
qsign
,
MutableBigInteger
mq
,
long
r
)
{
assert
r
!=
0L
;
int
cmpFracHalf
;
if
(
r
<=
HALF_LONG_MIN_VALUE
||
r
>
HALF_LONG_MAX_VALUE
)
{
cmpFracHalf
=
1
;
// 2 * r can't fit into long
}
else
{
cmpFracHalf
=
longCompareMagnitude
(
2
*
r
,
ldivisor
);
}
return
commonNeedIncrement
(
roundingMode
,
qsign
,
cmpFracHalf
,
mq
.
isOdd
());
}
/**
* Divides {@code BigInteger} value by {@code BigInteger} value and
* do rounding based on the passed in roundingMode.
*/
private
static
BigInteger
divideAndRound
(
BigInteger
bdividend
,
BigInteger
bdivisor
,
int
roundingMode
)
{
boolean
isRemainderZero
;
// record remainder is zero or not
int
qsign
;
// quotient sign
// Descend into mutables for faster remainder checks
MutableBigInteger
mdividend
=
new
MutableBigInteger
(
bdividend
.
mag
);
MutableBigInteger
mq
=
new
MutableBigInteger
();
MutableBigInteger
mdivisor
=
new
MutableBigInteger
(
bdivisor
.
mag
);
MutableBigInteger
mr
=
mdividend
.
divide
(
mdivisor
,
mq
);
isRemainderZero
=
mr
.
isZero
();
qsign
=
(
bdividend
.
signum
!=
bdivisor
.
signum
)
?
-
1
:
1
;
if
(!
isRemainderZero
)
{
if
(
needIncrement
(
mdivisor
,
roundingMode
,
qsign
,
mq
,
mr
))
{
mq
.
add
(
MutableBigInteger
.
ONE
);
}
}
return
mq
.
toBigInteger
(
qsign
);
}
/**
* Internally used for division operation for division {@code BigInteger}
* by {@code BigInteger}.
* The returned {@code BigDecimal} object is the quotient whose scale is set
* to the passed in scale. If the remainder is not zero, it will be rounded
* based on the passed in roundingMode. Also, if the remainder is zero and
* the last parameter, i.e. preferredScale is NOT equal to scale, the
* trailing zeros of the result is stripped to match the preferredScale.
*/
private
static
BigDecimal
divideAndRound
(
BigInteger
bdividend
,
BigInteger
bdivisor
,
int
scale
,
int
roundingMode
,
int
preferredScale
)
{
boolean
isRemainderZero
;
// record remainder is zero or not
int
qsign
;
// quotient sign
// Descend into mutables for faster remainder checks
MutableBigInteger
mdividend
=
new
MutableBigInteger
(
bdividend
.
mag
);
MutableBigInteger
mq
=
new
MutableBigInteger
();
MutableBigInteger
mdivisor
=
new
MutableBigInteger
(
bdivisor
.
mag
);
MutableBigInteger
mr
=
mdividend
.
divide
(
mdivisor
,
mq
);
isRemainderZero
=
mr
.
isZero
();
qsign
=
(
bdividend
.
signum
!=
bdivisor
.
signum
)
?
-
1
:
1
;
if
(!
isRemainderZero
)
{
if
(
needIncrement
(
mdivisor
,
roundingMode
,
qsign
,
mq
,
mr
))
{
mq
.
add
(
MutableBigInteger
.
ONE
);
}
return
mq
.
toBigDecimal
(
qsign
,
scale
);
}
else
{
if
(
preferredScale
!=
scale
)
{
long
compactVal
=
mq
.
toCompactValue
(
qsign
);
if
(
compactVal
!=
INFLATED
)
{
return
createAndStripZerosToMatchScale
(
compactVal
,
scale
,
preferredScale
);
}
BigInteger
intVal
=
mq
.
toBigInteger
(
qsign
);
return
createAndStripZerosToMatchScale
(
intVal
,
scale
,
preferredScale
);
}
else
{
return
mq
.
toBigDecimal
(
qsign
,
scale
);
}
}
}
/**
* Tests if quotient has to be incremented according the roundingMode
*/
private
static
boolean
needIncrement
(
MutableBigInteger
mdivisor
,
int
roundingMode
,
int
qsign
,
MutableBigInteger
mq
,
MutableBigInteger
mr
)
{
assert
!
mr
.
isZero
();
int
cmpFracHalf
=
mr
.
compareHalf
(
mdivisor
);
return
commonNeedIncrement
(
roundingMode
,
qsign
,
cmpFracHalf
,
mq
.
isOdd
());
}
/**
* Remove insignificant trailing zeros from this
* {@code BigInteger} value until the preferred scale is reached or no
* more zeros can be removed. If the preferred scale is less than
* Integer.MIN_VALUE, all the trailing zeros will be removed.
*
* @return new {@code BigDecimal} with a scale possibly reduced
* to be closed to the preferred scale.
*/
private
static
BigDecimal
createAndStripZerosToMatchScale
(
BigInteger
intVal
,
int
scale
,
long
preferredScale
)
{
BigInteger
qr
[];
// quotient-remainder pair
while
(
intVal
.
compareMagnitude
(
BigInteger
.
TEN
)
>=
0
&&
scale
>
preferredScale
)
{
if
(
intVal
.
testBit
(
0
))
break
;
// odd number cannot end in 0
qr
=
intVal
.
divideAndRemainder
(
BigInteger
.
TEN
);
if
(
qr
[
1
].
signum
()
!=
0
)
break
;
// non-0 remainder
intVal
=
qr
[
0
];
scale
=
checkScale
(
intVal
,(
long
)
scale
-
1
);
// could Overflow
}
return
valueOf
(
intVal
,
scale
,
0
);
}
/**
* Remove insignificant trailing zeros from this
* {@code long} value until the preferred scale is reached or no
* more zeros can be removed. If the preferred scale is less than
* Integer.MIN_VALUE, all the trailing zeros will be removed.
*
* @return new {@code BigDecimal} with a scale possibly reduced
* to be closed to the preferred scale.
*/
private
static
BigDecimal
createAndStripZerosToMatchScale
(
long
compactVal
,
int
scale
,
long
preferredScale
)
{
while
(
Math
.
abs
(
compactVal
)
>=
10L
&&
scale
>
preferredScale
)
{
if
((
compactVal
&
1L
)
!=
0L
)
break
;
// odd number cannot end in 0
long
r
=
compactVal
%
10L
;
if
(
r
!=
0L
)
break
;
// non-0 remainder
compactVal
/=
10
;
scale
=
checkScale
(
compactVal
,
(
long
)
scale
-
1
);
// could Overflow
}
return
valueOf
(
compactVal
,
scale
);
}
private
static
BigDecimal
stripZerosToMatchScale
(
BigInteger
intVal
,
long
intCompact
,
int
scale
,
int
preferredScale
)
{
if
(
intCompact
!=
INFLATED
)
{
return
createAndStripZerosToMatchScale
(
intCompact
,
scale
,
preferredScale
);
}
else
{
return
createAndStripZerosToMatchScale
(
intVal
==
null
?
INFLATED_BIGINT
:
intVal
,
scale
,
preferredScale
);
}
}
/*
* returns INFLATED if oveflow
*/
private
static
long
add
(
long
xs
,
long
ys
){
long
sum
=
xs
+
ys
;
// See "Hacker's Delight" section 2-12 for explanation of
// the overflow test.
if
(
(((
sum
^
xs
)
&
(
sum
^
ys
)))
>=
0L
)
{
// not overflowed
return
sum
;
}
return
INFLATED
;
}
private
static
BigDecimal
add
(
long
xs
,
long
ys
,
int
scale
){
long
sum
=
add
(
xs
,
ys
);
if
(
sum
!=
INFLATED
)
return
BigDecimal
.
valueOf
(
sum
,
scale
);
return
new
BigDecimal
(
BigInteger
.
valueOf
(
xs
).
add
(
ys
),
scale
);
}
private
static
BigDecimal
add
(
final
long
xs
,
int
scale1
,
final
long
ys
,
int
scale2
)
{
long
sdiff
=
(
long
)
scale1
-
scale2
;
if
(
sdiff
==
0
)
{
return
add
(
xs
,
ys
,
scale1
);
}
else
if
(
sdiff
<
0
)
{
int
raise
=
checkScale
(
xs
,-
sdiff
);
long
scaledX
=
longMultiplyPowerTen
(
xs
,
raise
);
if
(
scaledX
!=
INFLATED
)
{
return
add
(
scaledX
,
ys
,
scale2
);
}
else
{
BigInteger
bigsum
=
bigMultiplyPowerTen
(
xs
,
raise
).
add
(
ys
);
return
((
xs
^
ys
)>=
0
)
?
// same sign test
new
BigDecimal
(
bigsum
,
INFLATED
,
scale2
,
0
)
:
valueOf
(
bigsum
,
scale2
,
0
);
}
}
else
{
int
raise
=
checkScale
(
ys
,
sdiff
);
long
scaledY
=
longMultiplyPowerTen
(
ys
,
raise
);
if
(
scaledY
!=
INFLATED
)
{
return
add
(
xs
,
scaledY
,
scale1
);
}
else
{
BigInteger
bigsum
=
bigMultiplyPowerTen
(
ys
,
raise
).
add
(
xs
);
return
((
xs
^
ys
)>=
0
)
?
new
BigDecimal
(
bigsum
,
INFLATED
,
scale1
,
0
)
:
valueOf
(
bigsum
,
scale1
,
0
);
}
}
}
private
static
BigDecimal
add
(
final
long
xs
,
int
scale1
,
BigInteger
snd
,
int
scale2
)
{
int
rscale
=
scale1
;
long
sdiff
=
(
long
)
rscale
-
scale2
;
boolean
sameSigns
=
(
Long
.
signum
(
xs
)
==
snd
.
signum
);
BigInteger
sum
;
if
(
sdiff
<
0
)
{
int
raise
=
checkScale
(
xs
,-
sdiff
);
rscale
=
scale2
;
long
scaledX
=
longMultiplyPowerTen
(
xs
,
raise
);
if
(
scaledX
==
INFLATED
)
{
sum
=
snd
.
add
(
bigMultiplyPowerTen
(
xs
,
raise
));
}
else
{
sum
=
snd
.
add
(
scaledX
);
}
}
else
{
//if (sdiff > 0) {
int
raise
=
checkScale
(
snd
,
sdiff
);
snd
=
bigMultiplyPowerTen
(
snd
,
raise
);
sum
=
snd
.
add
(
xs
);
}
return
(
sameSigns
)
?
new
BigDecimal
(
sum
,
INFLATED
,
rscale
,
0
)
:
valueOf
(
sum
,
rscale
,
0
);
}
private
static
BigDecimal
add
(
BigInteger
fst
,
int
scale1
,
BigInteger
snd
,
int
scale2
)
{
int
rscale
=
scale1
;
long
sdiff
=
(
long
)
rscale
-
scale2
;
if
(
sdiff
!=
0
)
{
if
(
sdiff
<
0
)
{
int
raise
=
checkScale
(
fst
,-
sdiff
);
rscale
=
scale2
;
fst
=
bigMultiplyPowerTen
(
fst
,
raise
);
}
else
{
int
raise
=
checkScale
(
snd
,
sdiff
);
snd
=
bigMultiplyPowerTen
(
snd
,
raise
);
}
}
BigInteger
sum
=
fst
.
add
(
snd
);
return
(
fst
.
signum
==
snd
.
signum
)
?
new
BigDecimal
(
sum
,
INFLATED
,
rscale
,
0
)
:
valueOf
(
sum
,
rscale
,
0
);
}
private
static
BigInteger
bigMultiplyPowerTen
(
long
value
,
int
n
)
{
if
(
n
<=
0
)
return
BigInteger
.
valueOf
(
value
);
return
bigTenToThe
(
n
).
multiply
(
value
);
}
private
static
BigInteger
bigMultiplyPowerTen
(
BigInteger
value
,
int
n
)
{
if
(
n
<=
0
)
return
value
;
if
(
n
<
LONG_TEN_POWERS_TABLE
.
length
)
{
return
value
.
multiply
(
LONG_TEN_POWERS_TABLE
[
n
]);
}
return
value
.
multiply
(
bigTenToThe
(
n
));
}
/**
* Returns a {@code BigDecimal} whose value is {@code (xs /
* ys)}, with rounding according to the context settings.
*
* Fast path - used only when (xscale <= yscale && yscale < 18
* && mc.presision<18) {
*/
private
static
BigDecimal
divideSmallFastPath
(
final
long
xs
,
int
xscale
,
final
long
ys
,
int
yscale
,
long
preferredScale
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
int
roundingMode
=
mc
.
roundingMode
.
oldMode
;
assert
(
xscale
<=
yscale
)
&&
(
yscale
<
18
)
&&
(
mcp
<
18
);
int
xraise
=
yscale
-
xscale
;
// xraise >=0
long
scaledX
=
(
xraise
==
0
)
?
xs
:
longMultiplyPowerTen
(
xs
,
xraise
);
// can't overflow here!
BigDecimal
quotient
;
int
cmp
=
longCompareMagnitude
(
scaledX
,
ys
);
if
(
cmp
>
0
)
{
// satisfy constraint (b)
yscale
-=
1
;
// [that is, divisor *= 10]
int
scl
=
checkScaleNonZero
(
preferredScale
+
yscale
-
xscale
+
mcp
);
if
(
checkScaleNonZero
((
long
)
mcp
+
yscale
)
>
xscale
)
{
// assert newScale >= xscale
int
raise
=
checkScaleNonZero
((
long
)
mcp
+
yscale
-
xscale
);
long
scaledXs
;
if
((
scaledXs
=
longMultiplyPowerTen
(
xs
,
raise
))
==
INFLATED
)
{
quotient
=
null
;
if
((
mcp
-
1
)
>=
0
&&
(
mcp
-
1
)<
LONG_TEN_POWERS_TABLE
.
length
)
{
quotient
=
multiplyDivideAndRound
(
LONG_TEN_POWERS_TABLE
[
mcp
-
1
],
scaledX
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
if
(
quotient
==
null
)
{
BigInteger
rb
=
bigMultiplyPowerTen
(
scaledX
,
mcp
-
1
);
quotient
=
divideAndRound
(
rb
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
else
{
quotient
=
divideAndRound
(
scaledXs
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
else
{
int
newScale
=
checkScaleNonZero
((
long
)
xscale
-
mcp
);
// assert newScale >= yscale
if
(
newScale
==
yscale
)
{
// easy case
quotient
=
divideAndRound
(
xs
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
int
raise
=
checkScaleNonZero
((
long
)
newScale
-
yscale
);
long
scaledYs
;
if
((
scaledYs
=
longMultiplyPowerTen
(
ys
,
raise
))
==
INFLATED
)
{
BigInteger
rb
=
bigMultiplyPowerTen
(
ys
,
raise
);
quotient
=
divideAndRound
(
BigInteger
.
valueOf
(
xs
),
rb
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
quotient
=
divideAndRound
(
xs
,
scaledYs
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
}
}
else
{
// abs(scaledX) <= abs(ys)
// result is "scaledX * 10^msp / ys"
int
scl
=
checkScaleNonZero
(
preferredScale
+
yscale
-
xscale
+
mcp
);
if
(
cmp
==
0
)
{
// abs(scaleX)== abs(ys) => result will be scaled 10^mcp + correct sign
quotient
=
roundedTenPower
(((
scaledX
<
0
)
==
(
ys
<
0
))
?
1
:
-
1
,
mcp
,
scl
,
checkScaleNonZero
(
preferredScale
));
}
else
{
// abs(scaledX) < abs(ys)
long
scaledXs
;
if
((
scaledXs
=
longMultiplyPowerTen
(
scaledX
,
mcp
))
==
INFLATED
)
{
quotient
=
null
;
if
(
mcp
<
LONG_TEN_POWERS_TABLE
.
length
)
{
quotient
=
multiplyDivideAndRound
(
LONG_TEN_POWERS_TABLE
[
mcp
],
scaledX
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
if
(
quotient
==
null
)
{
BigInteger
rb
=
bigMultiplyPowerTen
(
scaledX
,
mcp
);
quotient
=
divideAndRound
(
rb
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
else
{
quotient
=
divideAndRound
(
scaledXs
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
}
// doRound, here, only affects 1000000000 case.
return
doRound
(
quotient
,
mc
);
}
/**
* Returns a {@code BigDecimal} whose value is {@code (xs /
* ys)}, with rounding according to the context settings.
*/
private
static
BigDecimal
divide
(
final
long
xs
,
int
xscale
,
final
long
ys
,
int
yscale
,
long
preferredScale
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
if
(
xscale
<=
yscale
&&
yscale
<
18
&&
mcp
<
18
)
{
return
divideSmallFastPath
(
xs
,
xscale
,
ys
,
yscale
,
preferredScale
,
mc
);
}
if
(
compareMagnitudeNormalized
(
xs
,
xscale
,
ys
,
yscale
)
>
0
)
{
// satisfy constraint (b)
yscale
-=
1
;
// [that is, divisor *= 10]
}
int
roundingMode
=
mc
.
roundingMode
.
oldMode
;
// In order to find out whether the divide generates the exact result,
// we avoid calling the above divide method. 'quotient' holds the
// return BigDecimal object whose scale will be set to 'scl'.
int
scl
=
checkScaleNonZero
(
preferredScale
+
yscale
-
xscale
+
mcp
);
BigDecimal
quotient
;
if
(
checkScaleNonZero
((
long
)
mcp
+
yscale
)
>
xscale
)
{
int
raise
=
checkScaleNonZero
((
long
)
mcp
+
yscale
-
xscale
);
long
scaledXs
;
if
((
scaledXs
=
longMultiplyPowerTen
(
xs
,
raise
))
==
INFLATED
)
{
BigInteger
rb
=
bigMultiplyPowerTen
(
xs
,
raise
);
quotient
=
divideAndRound
(
rb
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
quotient
=
divideAndRound
(
scaledXs
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
else
{
int
newScale
=
checkScaleNonZero
((
long
)
xscale
-
mcp
);
// assert newScale >= yscale
if
(
newScale
==
yscale
)
{
// easy case
quotient
=
divideAndRound
(
xs
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
int
raise
=
checkScaleNonZero
((
long
)
newScale
-
yscale
);
long
scaledYs
;
if
((
scaledYs
=
longMultiplyPowerTen
(
ys
,
raise
))
==
INFLATED
)
{
BigInteger
rb
=
bigMultiplyPowerTen
(
ys
,
raise
);
quotient
=
divideAndRound
(
BigInteger
.
valueOf
(
xs
),
rb
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
quotient
=
divideAndRound
(
xs
,
scaledYs
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
}
// doRound, here, only affects 1000000000 case.
return
doRound
(
quotient
,
mc
);
}
/**
* Returns a {@code BigDecimal} whose value is {@code (xs /
* ys)}, with rounding according to the context settings.
*/
private
static
BigDecimal
divide
(
BigInteger
xs
,
int
xscale
,
long
ys
,
int
yscale
,
long
preferredScale
,
MathContext
mc
)
{
// Normalize dividend & divisor so that both fall into [0.1, 0.999...]
if
((-
compareMagnitudeNormalized
(
ys
,
yscale
,
xs
,
xscale
))
>
0
)
{
// satisfy constraint (b)
yscale
-=
1
;
// [that is, divisor *= 10]
}
int
mcp
=
mc
.
precision
;
int
roundingMode
=
mc
.
roundingMode
.
oldMode
;
// In order to find out whether the divide generates the exact result,
// we avoid calling the above divide method. 'quotient' holds the
// return BigDecimal object whose scale will be set to 'scl'.
BigDecimal
quotient
;
int
scl
=
checkScaleNonZero
(
preferredScale
+
yscale
-
xscale
+
mcp
);
if
(
checkScaleNonZero
((
long
)
mcp
+
yscale
)
>
xscale
)
{
int
raise
=
checkScaleNonZero
((
long
)
mcp
+
yscale
-
xscale
);
BigInteger
rb
=
bigMultiplyPowerTen
(
xs
,
raise
);
quotient
=
divideAndRound
(
rb
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
int
newScale
=
checkScaleNonZero
((
long
)
xscale
-
mcp
);
// assert newScale >= yscale
if
(
newScale
==
yscale
)
{
// easy case
quotient
=
divideAndRound
(
xs
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
int
raise
=
checkScaleNonZero
((
long
)
newScale
-
yscale
);
long
scaledYs
;
if
((
scaledYs
=
longMultiplyPowerTen
(
ys
,
raise
))
==
INFLATED
)
{
BigInteger
rb
=
bigMultiplyPowerTen
(
ys
,
raise
);
quotient
=
divideAndRound
(
xs
,
rb
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
quotient
=
divideAndRound
(
xs
,
scaledYs
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
}
}
// doRound, here, only affects 1000000000 case.
return
doRound
(
quotient
,
mc
);
}
/**
* Returns a {@code BigDecimal} whose value is {@code (xs /
* ys)}, with rounding according to the context settings.
*/
private
static
BigDecimal
divide
(
long
xs
,
int
xscale
,
BigInteger
ys
,
int
yscale
,
long
preferredScale
,
MathContext
mc
)
{
// Normalize dividend & divisor so that both fall into [0.1, 0.999...]
if
(
compareMagnitudeNormalized
(
xs
,
xscale
,
ys
,
yscale
)
>
0
)
{
// satisfy constraint (b)
yscale
-=
1
;
// [that is, divisor *= 10]
}
int
mcp
=
mc
.
precision
;
int
roundingMode
=
mc
.
roundingMode
.
oldMode
;
// In order to find out whether the divide generates the exact result,
// we avoid calling the above divide method. 'quotient' holds the
// return BigDecimal object whose scale will be set to 'scl'.
BigDecimal
quotient
;
int
scl
=
checkScaleNonZero
(
preferredScale
+
yscale
-
xscale
+
mcp
);
if
(
checkScaleNonZero
((
long
)
mcp
+
yscale
)
>
xscale
)
{
int
raise
=
checkScaleNonZero
((
long
)
mcp
+
yscale
-
xscale
);
BigInteger
rb
=
bigMultiplyPowerTen
(
xs
,
raise
);
quotient
=
divideAndRound
(
rb
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
int
newScale
=
checkScaleNonZero
((
long
)
xscale
-
mcp
);
int
raise
=
checkScaleNonZero
((
long
)
newScale
-
yscale
);
BigInteger
rb
=
bigMultiplyPowerTen
(
ys
,
raise
);
quotient
=
divideAndRound
(
BigInteger
.
valueOf
(
xs
),
rb
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
// doRound, here, only affects 1000000000 case.
return
doRound
(
quotient
,
mc
);
}
/**
* Returns a {@code BigDecimal} whose value is {@code (xs /
* ys)}, with rounding according to the context settings.
*/
private
static
BigDecimal
divide
(
BigInteger
xs
,
int
xscale
,
BigInteger
ys
,
int
yscale
,
long
preferredScale
,
MathContext
mc
)
{
// Normalize dividend & divisor so that both fall into [0.1, 0.999...]
if
(
compareMagnitudeNormalized
(
xs
,
xscale
,
ys
,
yscale
)
>
0
)
{
// satisfy constraint (b)
yscale
-=
1
;
// [that is, divisor *= 10]
}
int
mcp
=
mc
.
precision
;
int
roundingMode
=
mc
.
roundingMode
.
oldMode
;
// In order to find out whether the divide generates the exact result,
// we avoid calling the above divide method. 'quotient' holds the
// return BigDecimal object whose scale will be set to 'scl'.
BigDecimal
quotient
;
int
scl
=
checkScaleNonZero
(
preferredScale
+
yscale
-
xscale
+
mcp
);
if
(
checkScaleNonZero
((
long
)
mcp
+
yscale
)
>
xscale
)
{
int
raise
=
checkScaleNonZero
((
long
)
mcp
+
yscale
-
xscale
);
BigInteger
rb
=
bigMultiplyPowerTen
(
xs
,
raise
);
quotient
=
divideAndRound
(
rb
,
ys
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
else
{
int
newScale
=
checkScaleNonZero
((
long
)
xscale
-
mcp
);
int
raise
=
checkScaleNonZero
((
long
)
newScale
-
yscale
);
BigInteger
rb
=
bigMultiplyPowerTen
(
ys
,
raise
);
quotient
=
divideAndRound
(
xs
,
rb
,
scl
,
roundingMode
,
checkScaleNonZero
(
preferredScale
));
}
// doRound, here, only affects 1000000000 case.
return
doRound
(
quotient
,
mc
);
}
/*
* performs divideAndRound for (dividend0*dividend1, divisor)
* returns null if quotient can't fit into long value;
*/
private
static
BigDecimal
multiplyDivideAndRound
(
long
dividend0
,
long
dividend1
,
long
divisor
,
int
scale
,
int
roundingMode
,
int
preferredScale
)
{
int
qsign
=
Long
.
signum
(
dividend0
)*
Long
.
signum
(
dividend1
)*
Long
.
signum
(
divisor
);
dividend0
=
Math
.
abs
(
dividend0
);
dividend1
=
Math
.
abs
(
dividend1
);
divisor
=
Math
.
abs
(
divisor
);
// multiply dividend0 * dividend1
long
d0_hi
=
dividend0
>>>
32
;
long
d0_lo
=
dividend0
&
LONG_MASK
;
long
d1_hi
=
dividend1
>>>
32
;
long
d1_lo
=
dividend1
&
LONG_MASK
;
long
product
=
d0_lo
*
d1_lo
;
long
d0
=
product
&
LONG_MASK
;
long
d1
=
product
>>>
32
;
product
=
d0_hi
*
d1_lo
+
d1
;
d1
=
product
&
LONG_MASK
;
long
d2
=
product
>>>
32
;
product
=
d0_lo
*
d1_hi
+
d1
;
d1
=
product
&
LONG_MASK
;
d2
+=
product
>>>
32
;
long
d3
=
d2
>>>
32
;
d2
&=
LONG_MASK
;
product
=
d0_hi
*
d1_hi
+
d2
;
d2
=
product
&
LONG_MASK
;
d3
=
((
product
>>>
32
)
+
d3
)
&
LONG_MASK
;
final
long
dividendHi
=
make64
(
d3
,
d2
);
final
long
dividendLo
=
make64
(
d1
,
d0
);
// divide
return
divideAndRound128
(
dividendHi
,
dividendLo
,
divisor
,
qsign
,
scale
,
roundingMode
,
preferredScale
);
}
private
static
final
long
DIV_NUM_BASE
=
(
1L
<<
32
);
// Number base (32 bits).
/*
* divideAndRound 128-bit value by long divisor.
* returns null if quotient can't fit into long value;
* Specialized version of Knuth's division
*/
private
static
BigDecimal
divideAndRound128
(
final
long
dividendHi
,
final
long
dividendLo
,
long
divisor
,
int
sign
,
int
scale
,
int
roundingMode
,
int
preferredScale
)
{
if
(
dividendHi
>=
divisor
)
{
return
null
;
}
final
int
shift
=
Long
.
numberOfLeadingZeros
(
divisor
);
divisor
<<=
shift
;
final
long
v1
=
divisor
>>>
32
;
final
long
v0
=
divisor
&
LONG_MASK
;
long
q1
,
q0
;
long
r_tmp
;
long
tmp
=
dividendLo
<<
shift
;
long
u1
=
tmp
>>>
32
;
long
u0
=
tmp
&
LONG_MASK
;
tmp
=
(
dividendHi
<<
shift
)
|
(
dividendLo
>>>
64
-
shift
);
long
u2
=
tmp
&
LONG_MASK
;
tmp
=
divWord
(
tmp
,
v1
);
q1
=
tmp
&
LONG_MASK
;
r_tmp
=
tmp
>>>
32
;
while
(
q1
>=
DIV_NUM_BASE
||
unsignedLongCompare
(
q1
*
v0
,
make64
(
r_tmp
,
u1
)))
{
q1
--;
r_tmp
+=
v1
;
if
(
r_tmp
>=
DIV_NUM_BASE
)
break
;
}
tmp
=
mulsub
(
u2
,
u1
,
v1
,
v0
,
q1
);
u1
=
tmp
&
LONG_MASK
;
tmp
=
divWord
(
tmp
,
v1
);
q0
=
tmp
&
LONG_MASK
;
r_tmp
=
tmp
>>>
32
;
while
(
q0
>=
DIV_NUM_BASE
||
unsignedLongCompare
(
q0
*
v0
,
make64
(
r_tmp
,
u0
)))
{
q0
--;
r_tmp
+=
v1
;
if
(
r_tmp
>=
DIV_NUM_BASE
)
break
;
}
if
((
int
)
q1
<
0
)
{
// result (which is positive and unsigned here)
// can't fit into long due to sign bit is used for value
MutableBigInteger
mq
=
new
MutableBigInteger
(
new
int
[]{(
int
)
q1
,
(
int
)
q0
});
if
(
roundingMode
==
ROUND_DOWN
&&
scale
==
preferredScale
)
{
return
mq
.
toBigDecimal
(
sign
,
scale
);
}
long
r
=
mulsub
(
u1
,
u0
,
v1
,
v0
,
q0
)
>>>
shift
;
if
(
r
!=
0
)
{
if
(
needIncrement
(
divisor
>>>
shift
,
roundingMode
,
sign
,
mq
,
r
)){
mq
.
add
(
MutableBigInteger
.
ONE
);
}
return
mq
.
toBigDecimal
(
sign
,
scale
);
}
else
{
if
(
preferredScale
!=
scale
)
{
BigInteger
intVal
=
mq
.
toBigInteger
(
sign
);
return
createAndStripZerosToMatchScale
(
intVal
,
scale
,
preferredScale
);
}
else
{
return
mq
.
toBigDecimal
(
sign
,
scale
);
}
}
}
long
q
=
make64
(
q1
,
q0
);
q
*=
sign
;
if
(
roundingMode
==
ROUND_DOWN
&&
scale
==
preferredScale
)
return
valueOf
(
q
,
scale
);
long
r
=
mulsub
(
u1
,
u0
,
v1
,
v0
,
q0
)
>>>
shift
;
if
(
r
!=
0
)
{
boolean
increment
=
needIncrement
(
divisor
>>>
shift
,
roundingMode
,
sign
,
q
,
r
);
return
valueOf
((
increment
?
q
+
sign
:
q
),
scale
);
}
else
{
if
(
preferredScale
!=
scale
)
{
return
createAndStripZerosToMatchScale
(
q
,
scale
,
preferredScale
);
}
else
{
return
valueOf
(
q
,
scale
);
}
}
}
/*
* calculate divideAndRound for ldividend*10^raise / divisor
* when abs(dividend)==abs(divisor);
*/
private
static
BigDecimal
roundedTenPower
(
int
qsign
,
int
raise
,
int
scale
,
int
preferredScale
)
{
if
(
scale
>
preferredScale
)
{
int
diff
=
scale
-
preferredScale
;
if
(
diff
<
raise
)
{
return
scaledTenPow
(
raise
-
diff
,
qsign
,
preferredScale
);
}
else
{
return
valueOf
(
qsign
,
scale
-
raise
);
}
}
else
{
return
scaledTenPow
(
raise
,
qsign
,
scale
);
}
}
static
BigDecimal
scaledTenPow
(
int
n
,
int
sign
,
int
scale
)
{
if
(
n
<
LONG_TEN_POWERS_TABLE
.
length
)
return
valueOf
(
sign
*
LONG_TEN_POWERS_TABLE
[
n
],
scale
);
else
{
BigInteger
unscaledVal
=
bigTenToThe
(
n
);
if
(
sign
==-
1
)
{
unscaledVal
=
unscaledVal
.
negate
();
}
return
new
BigDecimal
(
unscaledVal
,
INFLATED
,
scale
,
n
+
1
);
}
}
private
static
long
divWord
(
long
n
,
long
dLong
)
{
long
r
;
long
q
;
if
(
dLong
==
1
)
{
q
=
(
int
)
n
;
return
(
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 <dLong, hence we're done.
return
(
r
<<
32
)
|
(
q
&
LONG_MASK
);
}
private
static
long
make64
(
long
hi
,
long
lo
)
{
return
hi
<<
32
|
lo
;
}
private
static
long
mulsub
(
long
u1
,
long
u0
,
final
long
v1
,
final
long
v0
,
long
q0
)
{
long
tmp
=
u0
-
q0
*
v0
;
return
make64
(
u1
+
(
tmp
>>>
32
)
-
q0
*
v1
,
tmp
&
LONG_MASK
);
}
private
static
boolean
unsignedLongCompare
(
long
one
,
long
two
)
{
return
(
one
+
Long
.
MIN_VALUE
)
>
(
two
+
Long
.
MIN_VALUE
);
}
private
static
boolean
unsignedLongCompareEq
(
long
one
,
long
two
)
{
return
(
one
+
Long
.
MIN_VALUE
)
>=
(
two
+
Long
.
MIN_VALUE
);
}
// Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...]
private
static
int
compareMagnitudeNormalized
(
long
xs
,
int
xscale
,
long
ys
,
int
yscale
)
{
// assert xs!=0 && ys!=0
int
sdiff
=
xscale
-
yscale
;
if
(
sdiff
!=
0
)
{
if
(
sdiff
<
0
)
{
xs
=
longMultiplyPowerTen
(
xs
,
-
sdiff
);
}
else
{
// sdiff > 0
ys
=
longMultiplyPowerTen
(
ys
,
sdiff
);
}
}
if
(
xs
!=
INFLATED
)
return
(
ys
!=
INFLATED
)
?
longCompareMagnitude
(
xs
,
ys
)
:
-
1
;
else
return
1
;
}
// Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...]
private
static
int
compareMagnitudeNormalized
(
long
xs
,
int
xscale
,
BigInteger
ys
,
int
yscale
)
{
// assert "ys can't be represented as long"
if
(
xs
==
0
)
return
-
1
;
int
sdiff
=
xscale
-
yscale
;
if
(
sdiff
<
0
)
{
if
(
longMultiplyPowerTen
(
xs
,
-
sdiff
)
==
INFLATED
)
{
return
bigMultiplyPowerTen
(
xs
,
-
sdiff
).
compareMagnitude
(
ys
);
}
}
return
-
1
;
}
// Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...]
private
static
int
compareMagnitudeNormalized
(
BigInteger
xs
,
int
xscale
,
BigInteger
ys
,
int
yscale
)
{
int
sdiff
=
xscale
-
yscale
;
if
(
sdiff
<
0
)
{
return
bigMultiplyPowerTen
(
xs
,
-
sdiff
).
compareMagnitude
(
ys
);
}
else
{
// sdiff >= 0
return
xs
.
compareMagnitude
(
bigMultiplyPowerTen
(
ys
,
sdiff
));
}
}
private
static
long
multiply
(
long
x
,
long
y
){
long
product
=
x
*
y
;
long
ax
=
Math
.
abs
(
x
);
long
ay
=
Math
.
abs
(
y
);
if
(((
ax
|
ay
)
>>>
31
==
0
)
||
(
y
==
0
)
||
(
product
/
y
==
x
)){
return
product
;
}
return
INFLATED
;
}
private
static
BigDecimal
multiply
(
long
x
,
long
y
,
int
scale
)
{
long
product
=
multiply
(
x
,
y
);
if
(
product
!=
INFLATED
)
{
return
valueOf
(
product
,
scale
);
}
return
new
BigDecimal
(
BigInteger
.
valueOf
(
x
).
multiply
(
y
),
INFLATED
,
scale
,
0
);
}
private
static
BigDecimal
multiply
(
long
x
,
BigInteger
y
,
int
scale
)
{
if
(
x
==
0
)
{
return
zeroValueOf
(
scale
);
}
return
new
BigDecimal
(
y
.
multiply
(
x
),
INFLATED
,
scale
,
0
);
}
private
static
BigDecimal
multiply
(
BigInteger
x
,
BigInteger
y
,
int
scale
)
{
return
new
BigDecimal
(
x
.
multiply
(
y
),
INFLATED
,
scale
,
0
);
}
/**
* Multiplies two long values and rounds according {@code MathContext}
*/
private
static
BigDecimal
multiplyAndRound
(
long
x
,
long
y
,
int
scale
,
MathContext
mc
)
{
long
product
=
multiply
(
x
,
y
);
if
(
product
!=
INFLATED
)
{
return
doRound
(
product
,
scale
,
mc
);
}
// attempt to do it in 128 bits
int
rsign
=
1
;
if
(
x
<
0
)
{
x
=
-
x
;
rsign
=
-
1
;
}
if
(
y
<
0
)
{
y
=
-
y
;
rsign
*=
-
1
;
}
// multiply dividend0 * dividend1
long
m0_hi
=
x
>>>
32
;
long
m0_lo
=
x
&
LONG_MASK
;
long
m1_hi
=
y
>>>
32
;
long
m1_lo
=
y
&
LONG_MASK
;
product
=
m0_lo
*
m1_lo
;
long
m0
=
product
&
LONG_MASK
;
long
m1
=
product
>>>
32
;
product
=
m0_hi
*
m1_lo
+
m1
;
m1
=
product
&
LONG_MASK
;
long
m2
=
product
>>>
32
;
product
=
m0_lo
*
m1_hi
+
m1
;
m1
=
product
&
LONG_MASK
;
m2
+=
product
>>>
32
;
long
m3
=
m2
>>>
32
;
m2
&=
LONG_MASK
;
product
=
m0_hi
*
m1_hi
+
m2
;
m2
=
product
&
LONG_MASK
;
m3
=
((
product
>>>
32
)
+
m3
)
&
LONG_MASK
;
final
long
mHi
=
make64
(
m3
,
m2
);
final
long
mLo
=
make64
(
m1
,
m0
);
BigDecimal
res
=
doRound128
(
mHi
,
mLo
,
rsign
,
scale
,
mc
);
if
(
res
!=
null
)
{
return
res
;
}
res
=
new
BigDecimal
(
BigInteger
.
valueOf
(
x
).
multiply
(
y
*
rsign
),
INFLATED
,
scale
,
0
);
return
doRound
(
res
,
mc
);
}
private
static
BigDecimal
multiplyAndRound
(
long
x
,
BigInteger
y
,
int
scale
,
MathContext
mc
)
{
if
(
x
==
0
)
{
return
zeroValueOf
(
scale
);
}
return
doRound
(
y
.
multiply
(
x
),
scale
,
mc
);
}
private
static
BigDecimal
multiplyAndRound
(
BigInteger
x
,
BigInteger
y
,
int
scale
,
MathContext
mc
)
{
return
doRound
(
x
.
multiply
(
y
),
scale
,
mc
);
}
/**
* rounds 128-bit value according {@code MathContext}
* returns null if result can't be repsented as compact BigDecimal.
*/
private
static
BigDecimal
doRound128
(
long
hi
,
long
lo
,
int
sign
,
int
scale
,
MathContext
mc
)
{
int
mcp
=
mc
.
precision
;
int
drop
;
BigDecimal
res
=
null
;
if
(((
drop
=
precision
(
hi
,
lo
)
-
mcp
)
>
0
)&&(
drop
<
LONG_TEN_POWERS_TABLE
.
length
))
{
scale
=
checkScaleNonZero
((
long
)
scale
-
drop
);
res
=
divideAndRound128
(
hi
,
lo
,
LONG_TEN_POWERS_TABLE
[
drop
],
sign
,
scale
,
mc
.
roundingMode
.
oldMode
,
scale
);
}
if
(
res
!=
null
)
{
return
doRound
(
res
,
mc
);
}
return
null
;
}
private
static
final
long
[][]
LONGLONG_TEN_POWERS_TABLE
=
{
{
0L
,
0x8AC7230489E80000
L
},
//10^19
{
0x5
L
,
0x6bc75e2d63100000
L
},
//10^20
{
0x36
L
,
0x35c9adc5dea00000
L
},
//10^21
{
0x21e
L
,
0x19e0c9bab2400000
L
},
//10^22
{
0x152d
L
,
0x02c7e14af6800000
L
},
//10^23
{
0xd3c2
L
,
0x1bcecceda1000000
L
},
//10^24
{
0x84595
L
,
0x161401484a000000
L
},
//10^25
{
0x52b7d2
L
,
0xdcc80cd2e4000000
L
},
//10^26
{
0x33b2e3c
L
,
0x9fd0803ce8000000
L
},
//10^27
{
0x204fce5e
L
,
0x3e25026110000000
L
},
//10^28
{
0x1431e0fae
L
,
0x6d7217caa0000000
L
},
//10^29
{
0xc9f2c9cd0
L
,
0x4674edea40000000
L
},
//10^30
{
0x7e37be2022
L
,
0xc0914b2680000000
L
},
//10^31
{
0x4ee2d6d415b
L
,
0x85acef8100000000
L
},
//10^32
{
0x314dc6448d93
L
,
0x38c15b0a00000000
L
},
//10^33
{
0x1ed09bead87c0
L
,
0x378d8e6400000000
L
},
//10^34
{
0x13426172c74d82
L
,
0x2b878fe800000000
L
},
//10^35
{
0xc097ce7bc90715
L
,
0xb34b9f1000000000
L
},
//10^36
{
0x785ee10d5da46d9
L
,
0x00f436a000000000
L
},
//10^37
{
0x4b3b4ca85a86c47a
L
,
0x098a224000000000
L
},
//10^38
};
/*
* returns precision of 128-bit value
*/
private
static
int
precision
(
long
hi
,
long
lo
){
if
(
hi
==
0
)
{
if
(
lo
>=
0
)
{
return
longDigitLength
(
lo
);
}
return
(
unsignedLongCompareEq
(
lo
,
LONGLONG_TEN_POWERS_TABLE
[
0
][
1
]))
?
20
:
19
;
// 0x8AC7230489E80000L = unsigned 2^19
}
int
r
=
((
128
-
Long
.
numberOfLeadingZeros
(
hi
)
+
1
)
*
1233
)
>>>
12
;
int
idx
=
r
-
19
;
return
(
idx
>=
LONGLONG_TEN_POWERS_TABLE
.
length
||
longLongCompareMagnitude
(
hi
,
lo
,
LONGLONG_TEN_POWERS_TABLE
[
idx
][
0
],
LONGLONG_TEN_POWERS_TABLE
[
idx
][
1
]))
?
r
:
r
+
1
;
}
/*
* returns true if 128 bit number <hi0,lo0> is less then <hi1,lo1>
* hi0 & hi1 should be non-negative
*/
private
static
boolean
longLongCompareMagnitude
(
long
hi0
,
long
lo0
,
long
hi1
,
long
lo1
)
{
if
(
hi0
!=
hi1
)
{
return
hi0
<
hi1
;
}
return
(
lo0
+
Long
.
MIN_VALUE
)
<(
lo1
+
Long
.
MIN_VALUE
);
}
private
static
BigDecimal
divide
(
long
dividend
,
int
dividendScale
,
long
divisor
,
int
divisorScale
,
int
scale
,
int
roundingMode
)
{
if
(
checkScale
(
dividend
,(
long
)
scale
+
divisorScale
)
>
dividendScale
)
{
int
newScale
=
scale
+
divisorScale
;
int
raise
=
newScale
-
dividendScale
;
if
(
raise
<
LONG_TEN_POWERS_TABLE
.
length
)
{
long
xs
=
dividend
;
if
((
xs
=
longMultiplyPowerTen
(
xs
,
raise
))
!=
INFLATED
)
{
return
divideAndRound
(
xs
,
divisor
,
scale
,
roundingMode
,
scale
);
}
BigDecimal
q
=
multiplyDivideAndRound
(
LONG_TEN_POWERS_TABLE
[
raise
],
dividend
,
divisor
,
scale
,
roundingMode
,
scale
);
if
(
q
!=
null
)
{
return
q
;
}
}
BigInteger
scaledDividend
=
bigMultiplyPowerTen
(
dividend
,
raise
);
return
divideAndRound
(
scaledDividend
,
divisor
,
scale
,
roundingMode
,
scale
);
}
else
{
int
newScale
=
checkScale
(
divisor
,(
long
)
dividendScale
-
scale
);
int
raise
=
newScale
-
divisorScale
;
if
(
raise
<
LONG_TEN_POWERS_TABLE
.
length
)
{
long
ys
=
divisor
;
if
((
ys
=
longMultiplyPowerTen
(
ys
,
raise
))
!=
INFLATED
)
{
return
divideAndRound
(
dividend
,
ys
,
scale
,
roundingMode
,
scale
);
}
}
BigInteger
scaledDivisor
=
bigMultiplyPowerTen
(
divisor
,
raise
);
return
divideAndRound
(
BigInteger
.
valueOf
(
dividend
),
scaledDivisor
,
scale
,
roundingMode
,
scale
);
}
}
private
static
BigDecimal
divide
(
BigInteger
dividend
,
int
dividendScale
,
long
divisor
,
int
divisorScale
,
int
scale
,
int
roundingMode
)
{
if
(
checkScale
(
dividend
,(
long
)
scale
+
divisorScale
)
>
dividendScale
)
{
int
newScale
=
scale
+
divisorScale
;
int
raise
=
newScale
-
dividendScale
;
BigInteger
scaledDividend
=
bigMultiplyPowerTen
(
dividend
,
raise
);
return
divideAndRound
(
scaledDividend
,
divisor
,
scale
,
roundingMode
,
scale
);
}
else
{
int
newScale
=
checkScale
(
divisor
,(
long
)
dividendScale
-
scale
);
int
raise
=
newScale
-
divisorScale
;
if
(
raise
<
LONG_TEN_POWERS_TABLE
.
length
)
{
long
ys
=
divisor
;
if
((
ys
=
longMultiplyPowerTen
(
ys
,
raise
))
!=
INFLATED
)
{
return
divideAndRound
(
dividend
,
ys
,
scale
,
roundingMode
,
scale
);
}
}
BigInteger
scaledDivisor
=
bigMultiplyPowerTen
(
divisor
,
raise
);
return
divideAndRound
(
dividend
,
scaledDivisor
,
scale
,
roundingMode
,
scale
);
}
}
private
static
BigDecimal
divide
(
long
dividend
,
int
dividendScale
,
BigInteger
divisor
,
int
divisorScale
,
int
scale
,
int
roundingMode
)
{
if
(
checkScale
(
dividend
,(
long
)
scale
+
divisorScale
)
>
dividendScale
)
{
int
newScale
=
scale
+
divisorScale
;
int
raise
=
newScale
-
dividendScale
;
BigInteger
scaledDividend
=
bigMultiplyPowerTen
(
dividend
,
raise
);
return
divideAndRound
(
scaledDividend
,
divisor
,
scale
,
roundingMode
,
scale
);
}
else
{
int
newScale
=
checkScale
(
divisor
,(
long
)
dividendScale
-
scale
);
int
raise
=
newScale
-
divisorScale
;
BigInteger
scaledDivisor
=
bigMultiplyPowerTen
(
divisor
,
raise
);
return
divideAndRound
(
BigInteger
.
valueOf
(
dividend
),
scaledDivisor
,
scale
,
roundingMode
,
scale
);
}
}
private
static
BigDecimal
divide
(
BigInteger
dividend
,
int
dividendScale
,
BigInteger
divisor
,
int
divisorScale
,
int
scale
,
int
roundingMode
)
{
if
(
checkScale
(
dividend
,(
long
)
scale
+
divisorScale
)
>
dividendScale
)
{
int
newScale
=
scale
+
divisorScale
;
int
raise
=
newScale
-
dividendScale
;
BigInteger
scaledDividend
=
bigMultiplyPowerTen
(
dividend
,
raise
);
return
divideAndRound
(
scaledDividend
,
divisor
,
scale
,
roundingMode
,
scale
);
}
else
{
int
newScale
=
checkScale
(
divisor
,(
long
)
dividendScale
-
scale
);
int
raise
=
newScale
-
divisorScale
;
BigInteger
scaledDivisor
=
bigMultiplyPowerTen
(
divisor
,
raise
);
return
divideAndRound
(
dividend
,
scaledDivisor
,
scale
,
roundingMode
,
scale
);
}
}
}
}
src/share/classes/java/math/BigInteger.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 1996, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -353,27 +353,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -353,27 +353,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
mag
=
trustedStripLeadingZeroInts
(
magnitude
);
mag
=
trustedStripLeadingZeroInts
(
magnitude
);
}
}
// Constructs a new BigInteger using a char array with radix=10
/*
BigInteger
(
char
[]
val
)
{
* Constructs a new BigInteger using a char array with radix=10.
* Sign is precalculated outside and not allowed in the val.
*/
BigInteger
(
char
[]
val
,
int
sign
,
int
len
)
{
int
cursor
=
0
,
numDigits
;
int
cursor
=
0
,
numDigits
;
int
len
=
val
.
length
;
// Check for leading minus sign
int
sign
=
1
;
if
(
val
[
0
]
==
'-'
)
{
if
(
len
==
1
)
throw
new
NumberFormatException
(
"Zero length BigInteger"
);
sign
=
-
1
;
cursor
=
1
;
}
else
if
(
val
[
0
]
==
'+'
)
{
if
(
len
==
1
)
throw
new
NumberFormatException
(
"Zero length BigInteger"
);
cursor
=
1
;
}
// Skip leading zeros and compute number of digits in magnitude
// Skip leading zeros and compute number of digits in magnitude
while
(
cursor
<
len
&&
Character
.
digit
(
val
[
cursor
],
10
)
==
0
)
while
(
cursor
<
len
&&
Character
.
digit
(
val
[
cursor
],
10
)
==
0
)
{
cursor
++;
cursor
++;
}
if
(
cursor
==
len
)
{
if
(
cursor
==
len
)
{
signum
=
0
;
signum
=
0
;
mag
=
ZERO
.
mag
;
mag
=
ZERO
.
mag
;
...
@@ -382,7 +372,6 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -382,7 +372,6 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
numDigits
=
len
-
cursor
;
numDigits
=
len
-
cursor
;
signum
=
sign
;
signum
=
sign
;
// Pre-allocate array of expected size
// Pre-allocate array of expected size
int
numWords
;
int
numWords
;
if
(
len
<
10
)
{
if
(
len
<
10
)
{
...
@@ -1057,6 +1046,73 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -1057,6 +1046,73 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
return
new
BigInteger
(
resultMag
,
cmp
==
signum
?
1
:
-
1
);
return
new
BigInteger
(
resultMag
,
cmp
==
signum
?
1
:
-
1
);
}
}
/**
* Package private methods used by BigDecimal code to add a BigInteger
* with a long. Assumes val is not equal to INFLATED.
*/
BigInteger
add
(
long
val
)
{
if
(
val
==
0
)
return
this
;
if
(
signum
==
0
)
return
valueOf
(
val
);
if
(
Long
.
signum
(
val
)
==
signum
)
return
new
BigInteger
(
add
(
mag
,
Math
.
abs
(
val
)),
signum
);
int
cmp
=
compareMagnitude
(
val
);
if
(
cmp
==
0
)
return
ZERO
;
int
[]
resultMag
=
(
cmp
>
0
?
subtract
(
mag
,
Math
.
abs
(
val
))
:
subtract
(
Math
.
abs
(
val
),
mag
));
resultMag
=
trustedStripLeadingZeroInts
(
resultMag
);
return
new
BigInteger
(
resultMag
,
cmp
==
signum
?
1
:
-
1
);
}
/**
* Adds the contents of the int array x and long value val. This
* method allocates a new int array to hold the answer and returns
* a reference to that array. Assumes x.length > 0 and val is
* non-negative
*/
private
static
int
[]
add
(
int
[]
x
,
long
val
)
{
int
[]
y
;
long
sum
=
0
;
int
xIndex
=
x
.
length
;
int
[]
result
;
int
highWord
=
(
int
)(
val
>>>
32
);
if
(
highWord
==
0
)
{
result
=
new
int
[
xIndex
];
sum
=
(
x
[--
xIndex
]
&
LONG_MASK
)
+
val
;
result
[
xIndex
]
=
(
int
)
sum
;
}
else
{
if
(
xIndex
==
1
)
{
result
=
new
int
[
2
];
sum
=
val
+
(
x
[
0
]
&
LONG_MASK
);
result
[
1
]
=
(
int
)
sum
;
result
[
0
]
=
(
int
)(
sum
>>>
32
);
return
result
;
}
else
{
result
=
new
int
[
xIndex
];
sum
=
(
x
[--
xIndex
]
&
LONG_MASK
)
+
(
val
&
LONG_MASK
);
result
[
xIndex
]
=
(
int
)
sum
;
sum
=
(
x
[--
xIndex
]
&
LONG_MASK
)
+
(
highWord
&
LONG_MASK
)
+
(
sum
>>>
32
);
result
[
xIndex
]
=
(
int
)
sum
;
}
}
// Copy remainder of longer number while carry propagation is required
boolean
carry
=
(
sum
>>>
32
!=
0
);
while
(
xIndex
>
0
&&
carry
)
carry
=
((
result
[--
xIndex
]
=
x
[
xIndex
]
+
1
)
==
0
);
// Copy remainder of longer number
while
(
xIndex
>
0
)
result
[--
xIndex
]
=
x
[
xIndex
];
// Grow result if necessary
if
(
carry
)
{
int
bigger
[]
=
new
int
[
result
.
length
+
1
];
System
.
arraycopy
(
result
,
0
,
bigger
,
1
,
result
.
length
);
bigger
[
0
]
=
0x01
;
return
bigger
;
}
return
result
;
}
/**
/**
* Adds the contents of the int arrays x and y. This method allocates
* Adds the contents of the int arrays x and y. This method allocates
* a new int array to hold the answer and returns a reference to that
* a new int array to hold the answer and returns a reference to that
...
@@ -1074,14 +1130,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -1074,14 +1130,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
int
yIndex
=
y
.
length
;
int
yIndex
=
y
.
length
;
int
result
[]
=
new
int
[
xIndex
];
int
result
[]
=
new
int
[
xIndex
];
long
sum
=
0
;
long
sum
=
0
;
if
(
yIndex
==
1
)
{
// Add common parts of both numbers
sum
=
(
x
[--
xIndex
]
&
LONG_MASK
)
+
(
y
[
0
]
&
LONG_MASK
)
;
while
(
yIndex
>
0
)
{
sum
=
(
x
[--
xIndex
]
&
LONG_MASK
)
+
(
y
[--
yIndex
]
&
LONG_MASK
)
+
(
sum
>>>
32
);
result
[
xIndex
]
=
(
int
)
sum
;
result
[
xIndex
]
=
(
int
)
sum
;
}
else
{
// Add common parts of both numbers
while
(
yIndex
>
0
)
{
sum
=
(
x
[--
xIndex
]
&
LONG_MASK
)
+
(
y
[--
yIndex
]
&
LONG_MASK
)
+
(
sum
>>>
32
);
result
[
xIndex
]
=
(
int
)
sum
;
}
}
}
// Copy remainder of longer number while carry propagation is required
// Copy remainder of longer number while carry propagation is required
boolean
carry
=
(
sum
>>>
32
!=
0
);
boolean
carry
=
(
sum
>>>
32
!=
0
);
while
(
xIndex
>
0
&&
carry
)
while
(
xIndex
>
0
&&
carry
)
...
@@ -1101,6 +1160,71 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -1101,6 +1160,71 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
return
result
;
return
result
;
}
}
private
static
int
[]
subtract
(
long
val
,
int
[]
little
)
{
int
highWord
=
(
int
)(
val
>>>
32
);
if
(
highWord
==
0
)
{
int
result
[]
=
new
int
[
1
];
result
[
0
]
=
(
int
)(
val
-
(
little
[
0
]
&
LONG_MASK
));
return
result
;
}
else
{
int
result
[]
=
new
int
[
2
];
if
(
little
.
length
==
1
)
{
long
difference
=
((
int
)
val
&
LONG_MASK
)
-
(
little
[
0
]
&
LONG_MASK
);
result
[
1
]
=
(
int
)
difference
;
// Subtract remainder of longer number while borrow propagates
boolean
borrow
=
(
difference
>>
32
!=
0
);
if
(
borrow
)
{
result
[
0
]
=
highWord
-
1
;
}
else
{
// Copy remainder of longer number
result
[
0
]
=
highWord
;
}
return
result
;
}
else
{
// little.length==2
long
difference
=
((
int
)
val
&
LONG_MASK
)
-
(
little
[
1
]
&
LONG_MASK
);
result
[
1
]
=
(
int
)
difference
;
difference
=
(
highWord
&
LONG_MASK
)
-
(
little
[
0
]
&
LONG_MASK
)
+
(
difference
>>
32
);
result
[
0
]
=
(
int
)
difference
;
return
result
;
}
}
}
/**
* Subtracts the contents of the second argument (val) from the
* first (big). The first int array (big) must represent a larger number
* than the second. This method allocates the space necessary to hold the
* answer.
* assumes val >= 0
*/
private
static
int
[]
subtract
(
int
[]
big
,
long
val
)
{
int
highWord
=
(
int
)(
val
>>>
32
);
int
bigIndex
=
big
.
length
;
int
result
[]
=
new
int
[
bigIndex
];
long
difference
=
0
;
if
(
highWord
==
0
)
{
difference
=
(
big
[--
bigIndex
]
&
LONG_MASK
)
-
val
;
result
[
bigIndex
]
=
(
int
)
difference
;
}
else
{
difference
=
(
big
[--
bigIndex
]
&
LONG_MASK
)
-
(
val
&
LONG_MASK
);
result
[
bigIndex
]
=
(
int
)
difference
;
difference
=
(
big
[--
bigIndex
]
&
LONG_MASK
)
-
(
highWord
&
LONG_MASK
)
+
(
difference
>>
32
);
result
[
bigIndex
]
=
(
int
)
difference
;
}
// Subtract remainder of longer number while borrow propagates
boolean
borrow
=
(
difference
>>
32
!=
0
);
while
(
bigIndex
>
0
&&
borrow
)
borrow
=
((
result
[--
bigIndex
]
=
big
[
bigIndex
]
-
1
)
==
-
1
);
// Copy remainder of longer number
while
(
bigIndex
>
0
)
result
[--
bigIndex
]
=
big
[
bigIndex
];
return
result
;
}
/**
/**
* Returns a BigInteger whose value is {@code (this - val)}.
* Returns a BigInteger whose value is {@code (this - val)}.
*
*
...
@@ -1165,11 +1289,39 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -1165,11 +1289,39 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
public
BigInteger
multiply
(
BigInteger
val
)
{
public
BigInteger
multiply
(
BigInteger
val
)
{
if
(
val
.
signum
==
0
||
signum
==
0
)
if
(
val
.
signum
==
0
||
signum
==
0
)
return
ZERO
;
return
ZERO
;
int
resultSign
=
signum
==
val
.
signum
?
1
:
-
1
;
if
(
val
.
mag
.
length
==
1
)
{
return
multiplyByInt
(
mag
,
val
.
mag
[
0
],
resultSign
);
}
if
(
mag
.
length
==
1
)
{
return
multiplyByInt
(
val
.
mag
,
mag
[
0
],
resultSign
);
}
int
[]
result
=
multiplyToLen
(
mag
,
mag
.
length
,
int
[]
result
=
multiplyToLen
(
mag
,
mag
.
length
,
val
.
mag
,
val
.
mag
.
length
,
null
);
val
.
mag
,
val
.
mag
.
length
,
null
);
result
=
trustedStripLeadingZeroInts
(
result
);
result
=
trustedStripLeadingZeroInts
(
result
);
return
new
BigInteger
(
result
,
signum
==
val
.
signum
?
1
:
-
1
);
return
new
BigInteger
(
result
,
resultSign
);
}
private
static
BigInteger
multiplyByInt
(
int
[]
x
,
int
y
,
int
sign
)
{
if
(
Integer
.
bitCount
(
y
)==
1
)
{
return
new
BigInteger
(
shiftLeft
(
x
,
Integer
.
numberOfTrailingZeros
(
y
)),
sign
);
}
int
xlen
=
x
.
length
;
int
[]
rmag
=
new
int
[
xlen
+
1
];
long
carry
=
0
;
long
yl
=
y
&
LONG_MASK
;
int
rstart
=
rmag
.
length
-
1
;
for
(
int
i
=
xlen
-
1
;
i
>=
0
;
i
--)
{
long
product
=
(
x
[
i
]
&
LONG_MASK
)
*
yl
+
carry
;
rmag
[
rstart
--]
=
(
int
)
product
;
carry
=
product
>>>
32
;
}
if
(
carry
==
0L
)
{
rmag
=
java
.
util
.
Arrays
.
copyOfRange
(
rmag
,
1
,
rmag
.
length
);
}
else
{
rmag
[
rstart
]
=
(
int
)
carry
;
}
return
new
BigInteger
(
rmag
,
sign
);
}
}
/**
/**
...
@@ -1339,8 +1491,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -1339,8 +1491,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
a
=
new
MutableBigInteger
(
this
.
mag
),
a
=
new
MutableBigInteger
(
this
.
mag
),
b
=
new
MutableBigInteger
(
val
.
mag
);
b
=
new
MutableBigInteger
(
val
.
mag
);
a
.
divide
(
b
,
q
);
a
.
divide
(
b
,
q
,
false
);
return
q
.
toBigInteger
(
this
.
signum
==
val
.
signum
?
1
:
-
1
);
return
q
.
toBigInteger
(
this
.
signum
*
val
.
signum
);
}
}
/**
/**
...
@@ -2069,7 +2221,12 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -2069,7 +2221,12 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
return
shiftRight
(-
n
);
return
shiftRight
(-
n
);
}
}
}
}
int
[]
newMag
=
shiftLeft
(
mag
,
n
);
return
new
BigInteger
(
newMag
,
signum
);
}
private
static
int
[]
shiftLeft
(
int
[]
mag
,
int
n
)
{
int
nInts
=
n
>>>
5
;
int
nInts
=
n
>>>
5
;
int
nBits
=
n
&
0x1f
;
int
nBits
=
n
&
0x1f
;
int
magLen
=
mag
.
length
;
int
magLen
=
mag
.
length
;
...
@@ -2094,8 +2251,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -2094,8 +2251,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
newMag
[
i
++]
=
mag
[
j
++]
<<
nBits
|
mag
[
j
]
>>>
nBits2
;
newMag
[
i
++]
=
mag
[
j
++]
<<
nBits
|
mag
[
j
]
>>>
nBits2
;
newMag
[
i
]
=
mag
[
j
]
<<
nBits
;
newMag
[
i
]
=
mag
[
j
]
<<
nBits
;
}
}
return
newMag
;
return
new
BigInteger
(
newMag
,
signum
);
}
}
/**
/**
...
@@ -2529,6 +2685,49 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
...
@@ -2529,6 +2685,49 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
return
0
;
return
0
;
}
}
/**
* Version of compareMagnitude that compares magnitude with long value.
* val can't be Long.MIN_VALUE.
*/
final
int
compareMagnitude
(
long
val
)
{
assert
val
!=
Long
.
MIN_VALUE
;
int
[]
m1
=
mag
;
int
len
=
m1
.
length
;
if
(
len
>
2
)
{
return
1
;
}
if
(
val
<
0
)
{
val
=
-
val
;
}
int
highWord
=
(
int
)(
val
>>>
32
);
if
(
highWord
==
0
)
{
if
(
len
<
1
)
return
-
1
;
if
(
len
>
1
)
return
1
;
int
a
=
m1
[
0
];
int
b
=
(
int
)
val
;
if
(
a
!=
b
)
{
return
((
a
&
LONG_MASK
)
<
(
b
&
LONG_MASK
))?
-
1
:
1
;
}
return
0
;
}
else
{
if
(
len
<
2
)
return
-
1
;
int
a
=
m1
[
0
];
int
b
=
highWord
;
if
(
a
!=
b
)
{
return
((
a
&
LONG_MASK
)
<
(
b
&
LONG_MASK
))?
-
1
:
1
;
}
a
=
m1
[
1
];
b
=
(
int
)
val
;
if
(
a
!=
b
)
{
return
((
a
&
LONG_MASK
)
<
(
b
&
LONG_MASK
))?
-
1
:
1
;
}
return
0
;
}
}
/**
/**
* Compares this BigInteger with the specified Object for equality.
* Compares this BigInteger with the specified Object for equality.
*
*
...
...
src/share/classes/java/math/MutableBigInteger.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 1999, 20
07
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -160,7 +160,7 @@ class MutableBigInteger {
...
@@ -160,7 +160,7 @@ class MutableBigInteger {
*/
*/
BigDecimal
toBigDecimal
(
int
sign
,
int
scale
)
{
BigDecimal
toBigDecimal
(
int
sign
,
int
scale
)
{
if
(
intLen
==
0
||
sign
==
0
)
if
(
intLen
==
0
||
sign
==
0
)
return
BigDecimal
.
valueOf
(
0
,
scale
);
return
BigDecimal
.
zeroValueOf
(
scale
);
int
[]
mag
=
getMagnitudeArray
();
int
[]
mag
=
getMagnitudeArray
();
int
len
=
mag
.
length
;
int
len
=
mag
.
length
;
int
d
=
mag
[
0
];
int
d
=
mag
[
0
];
...
@@ -171,7 +171,28 @@ class MutableBigInteger {
...
@@ -171,7 +171,28 @@ class MutableBigInteger {
long
v
=
(
len
==
2
)
?
long
v
=
(
len
==
2
)
?
((
mag
[
1
]
&
LONG_MASK
)
|
(
d
&
LONG_MASK
)
<<
32
)
:
((
mag
[
1
]
&
LONG_MASK
)
|
(
d
&
LONG_MASK
)
<<
32
)
:
d
&
LONG_MASK
;
d
&
LONG_MASK
;
return
new
BigDecimal
(
null
,
sign
==
-
1
?
-
v
:
v
,
scale
,
0
);
return
BigDecimal
.
valueOf
(
sign
==
-
1
?
-
v
:
v
,
scale
);
}
/**
* This is for internal use in converting from a MutableBigInteger
* object into a long value given a specified sign.
* returns INFLATED if value is not fit into long
*/
long
toCompactValue
(
int
sign
)
{
if
(
intLen
==
0
||
sign
==
0
)
return
0L
;
int
[]
mag
=
getMagnitudeArray
();
int
len
=
mag
.
length
;
int
d
=
mag
[
0
];
// If this MutableBigInteger can not be fitted into long, we need to
// make a BigInteger object for the resultant BigDecimal object.
if
(
len
>
2
||
(
d
<
0
&&
len
==
2
))
return
INFLATED
;
long
v
=
(
len
==
2
)
?
((
mag
[
1
]
&
LONG_MASK
)
|
(
d
&
LONG_MASK
)
<<
32
)
:
d
&
LONG_MASK
;
return
sign
==
-
1
?
-
v
:
v
;
}
}
/**
/**
...
@@ -543,6 +564,24 @@ class MutableBigInteger {
...
@@ -543,6 +564,24 @@ class MutableBigInteger {
return
(
int
)
carry
;
return
(
int
)
carry
;
}
}
/**
* The method is the same as mulsun, except the fact that q array is not
* updated, the only result of the method is borrow flag.
*/
private
int
mulsubBorrow
(
int
[]
q
,
int
[]
a
,
int
x
,
int
len
,
int
offset
)
{
long
xLong
=
x
&
LONG_MASK
;
long
carry
=
0
;
offset
+=
len
;
for
(
int
j
=
len
-
1
;
j
>=
0
;
j
--)
{
long
product
=
(
a
[
j
]
&
LONG_MASK
)
*
xLong
+
carry
;
long
difference
=
q
[
offset
--]
-
product
;
carry
=
(
product
>>>
32
)
+
(((
difference
&
LONG_MASK
)
>
(((~(
int
)
product
)
&
LONG_MASK
)))
?
1
:
0
);
}
return
(
int
)
carry
;
}
/**
/**
* Right shift this MutableBigInteger n bits, where n is
* Right shift this MutableBigInteger n bits, where n is
* less than 32.
* less than 32.
...
@@ -842,20 +881,20 @@ class MutableBigInteger {
...
@@ -842,20 +881,20 @@ class MutableBigInteger {
rem
=
(
int
)
(
remLong
-
(
quotient
.
value
[
0
]
*
divisorLong
));
rem
=
(
int
)
(
remLong
-
(
quotient
.
value
[
0
]
*
divisorLong
));
remLong
=
rem
&
LONG_MASK
;
remLong
=
rem
&
LONG_MASK
;
}
}
int
xlen
=
intLen
;
int
xlen
=
intLen
;
int
[]
qWord
=
new
int
[
2
];
while
(--
xlen
>
0
)
{
while
(--
xlen
>
0
)
{
long
dividendEstimate
=
(
remLong
<<
32
)
|
long
dividendEstimate
=
(
remLong
<<
32
)
|
(
value
[
offset
+
intLen
-
xlen
]
&
LONG_MASK
);
(
value
[
offset
+
intLen
-
xlen
]
&
LONG_MASK
);
int
q
;
if
(
dividendEstimate
>=
0
)
{
if
(
dividendEstimate
>=
0
)
{
q
Word
[
0
]
=
(
int
)
(
dividendEstimate
/
divisorLong
);
q
=
(
int
)
(
dividendEstimate
/
divisorLong
);
qWord
[
1
]
=
(
int
)
(
dividendEstimate
-
qWord
[
0
]
*
divisorLong
);
rem
=
(
int
)
(
dividendEstimate
-
q
*
divisorLong
);
}
else
{
}
else
{
divWord
(
qWord
,
dividendEstimate
,
divisor
);
long
tmp
=
divWord
(
dividendEstimate
,
divisor
);
q
=
(
int
)
(
tmp
&
LONG_MASK
);
rem
=
(
int
)
(
tmp
>>>
32
);
}
}
quotient
.
value
[
intLen
-
xlen
]
=
qWord
[
0
];
quotient
.
value
[
intLen
-
xlen
]
=
q
;
rem
=
qWord
[
1
];
remLong
=
rem
&
LONG_MASK
;
remLong
=
rem
&
LONG_MASK
;
}
}
...
@@ -879,40 +918,45 @@ class MutableBigInteger {
...
@@ -879,40 +918,45 @@ class MutableBigInteger {
*
*
*/
*/
MutableBigInteger
divide
(
MutableBigInteger
b
,
MutableBigInteger
quotient
)
{
MutableBigInteger
divide
(
MutableBigInteger
b
,
MutableBigInteger
quotient
)
{
return
divide
(
b
,
quotient
,
true
);
}
MutableBigInteger
divide
(
MutableBigInteger
b
,
MutableBigInteger
quotient
,
boolean
needReminder
)
{
if
(
b
.
intLen
==
0
)
if
(
b
.
intLen
==
0
)
throw
new
ArithmeticException
(
"BigInteger divide by zero"
);
throw
new
ArithmeticException
(
"BigInteger divide by zero"
);
// Dividend is zero
// Dividend is zero
if
(
intLen
==
0
)
{
if
(
intLen
==
0
)
{
quotient
.
intLen
=
quotient
.
offset
;
quotient
.
intLen
=
quotient
.
offset
;
return
ne
w
MutableBigInteger
()
;
return
ne
edReminder
?
new
MutableBigInteger
()
:
null
;
}
}
int
cmp
=
compare
(
b
);
int
cmp
=
compare
(
b
);
// Dividend less than divisor
// Dividend less than divisor
if
(
cmp
<
0
)
{
if
(
cmp
<
0
)
{
quotient
.
intLen
=
quotient
.
offset
=
0
;
quotient
.
intLen
=
quotient
.
offset
=
0
;
return
ne
w
MutableBigInteger
(
this
)
;
return
ne
edReminder
?
new
MutableBigInteger
(
this
)
:
null
;
}
}
// Dividend equal to divisor
// Dividend equal to divisor
if
(
cmp
==
0
)
{
if
(
cmp
==
0
)
{
quotient
.
value
[
0
]
=
quotient
.
intLen
=
1
;
quotient
.
value
[
0
]
=
quotient
.
intLen
=
1
;
quotient
.
offset
=
0
;
quotient
.
offset
=
0
;
return
ne
w
MutableBigInteger
()
;
return
ne
edReminder
?
new
MutableBigInteger
()
:
null
;
}
}
quotient
.
clear
();
quotient
.
clear
();
// Special case one word divisor
// Special case one word divisor
if
(
b
.
intLen
==
1
)
{
if
(
b
.
intLen
==
1
)
{
int
r
=
divideOneWord
(
b
.
value
[
b
.
offset
],
quotient
);
int
r
=
divideOneWord
(
b
.
value
[
b
.
offset
],
quotient
);
if
(
r
==
0
)
if
(
needReminder
)
{
return
new
MutableBigInteger
();
if
(
r
==
0
)
return
new
MutableBigInteger
(
r
);
return
new
MutableBigInteger
();
return
new
MutableBigInteger
(
r
);
}
else
{
return
null
;
}
}
}
return
divideMagnitude
(
b
,
quotient
,
needReminder
);
// Copy divisor value to protect divisor
int
[]
div
=
Arrays
.
copyOfRange
(
b
.
value
,
b
.
offset
,
b
.
offset
+
b
.
intLen
);
return
divideMagnitude
(
div
,
quotient
);
}
}
/**
/**
...
@@ -940,30 +984,72 @@ class MutableBigInteger {
...
@@ -940,30 +984,72 @@ class MutableBigInteger {
if
(
d
==
0
)
if
(
d
==
0
)
return
divideOneWord
((
int
)
v
,
quotient
)
&
LONG_MASK
;
return
divideOneWord
((
int
)
v
,
quotient
)
&
LONG_MASK
;
else
{
else
{
int
[]
div
=
new
int
[]{
d
,
(
int
)(
v
&
LONG_MASK
)
};
return
divideLongMagnitude
(
v
,
quotient
).
toLong
();
return
divideMagnitude
(
div
,
quotient
).
toLong
();
}
}
private
static
void
copyAndShift
(
int
[]
src
,
int
srcFrom
,
int
srcLen
,
int
[]
dst
,
int
dstFrom
,
int
shift
)
{
int
n2
=
32
-
shift
;
int
c
=
src
[
srcFrom
];
for
(
int
i
=
0
;
i
<
srcLen
-
1
;
i
++)
{
int
b
=
c
;
c
=
src
[++
srcFrom
];
dst
[
dstFrom
+
i
]
=
(
b
<<
shift
)
|
(
c
>>>
n2
);
}
}
dst
[
dstFrom
+
srcLen
-
1
]
=
c
<<
shift
;
}
}
/**
/**
* Divide this MutableBigInteger by the divisor
represented by its magnitude
* Divide this MutableBigInteger by the divisor
.
*
array.
The quotient will be placed into the provided quotient object &
* The quotient will be placed into the provided quotient object &
* the remainder object is returned.
* the remainder object is returned.
*/
*/
private
MutableBigInteger
divideMagnitude
(
int
[]
divisor
,
private
MutableBigInteger
divideMagnitude
(
MutableBigInteger
div
,
MutableBigInteger
quotient
)
{
MutableBigInteger
quotient
,
boolean
needReminder
)
{
// Remainder starts as dividend with space for a leading zero
// assert div.intLen > 1
MutableBigInteger
rem
=
new
MutableBigInteger
(
new
int
[
intLen
+
1
]);
// D1 normalize the divisor
System
.
arraycopy
(
value
,
offset
,
rem
.
value
,
1
,
intLen
);
int
shift
=
Integer
.
numberOfLeadingZeros
(
div
.
value
[
div
.
offset
]);
rem
.
intLen
=
intLen
;
// Copy divisor value to protect divisor
rem
.
offset
=
1
;
final
int
dlen
=
div
.
intLen
;
int
[]
divisor
;
MutableBigInteger
rem
;
// Remainder starts as dividend with space for a leading zero
if
(
shift
>
0
)
{
divisor
=
new
int
[
dlen
];
copyAndShift
(
div
.
value
,
div
.
offset
,
dlen
,
divisor
,
0
,
shift
);
if
(
Integer
.
numberOfLeadingZeros
(
value
[
offset
])>=
shift
)
{
int
[]
remarr
=
new
int
[
intLen
+
1
];
rem
=
new
MutableBigInteger
(
remarr
);
rem
.
intLen
=
intLen
;
rem
.
offset
=
1
;
copyAndShift
(
value
,
offset
,
intLen
,
remarr
,
1
,
shift
);
}
else
{
int
[]
remarr
=
new
int
[
intLen
+
2
];
rem
=
new
MutableBigInteger
(
remarr
);
rem
.
intLen
=
intLen
+
1
;
rem
.
offset
=
1
;
int
rFrom
=
offset
;
int
c
=
0
;
int
n2
=
32
-
shift
;
for
(
int
i
=
1
;
i
<
intLen
+
1
;
i
++,
rFrom
++)
{
int
b
=
c
;
c
=
value
[
rFrom
];
remarr
[
i
]
=
(
b
<<
shift
)
|
(
c
>>>
n2
);
}
remarr
[
intLen
+
1
]
=
c
<<
shift
;
}
}
else
{
divisor
=
Arrays
.
copyOfRange
(
div
.
value
,
div
.
offset
,
div
.
offset
+
div
.
intLen
);
rem
=
new
MutableBigInteger
(
new
int
[
intLen
+
1
]);
System
.
arraycopy
(
value
,
offset
,
rem
.
value
,
1
,
intLen
);
rem
.
intLen
=
intLen
;
rem
.
offset
=
1
;
}
int
nlen
=
rem
.
intLen
;
int
nlen
=
rem
.
intLen
;
// Set the quotient size
// Set the quotient size
int
dlen
=
divisor
.
length
;
final
int
limit
=
nlen
-
dlen
+
1
;
int
limit
=
nlen
-
dlen
+
1
;
if
(
quotient
.
value
.
length
<
limit
)
{
if
(
quotient
.
value
.
length
<
limit
)
{
quotient
.
value
=
new
int
[
limit
];
quotient
.
value
=
new
int
[
limit
];
quotient
.
offset
=
0
;
quotient
.
offset
=
0
;
...
@@ -971,14 +1057,6 @@ class MutableBigInteger {
...
@@ -971,14 +1057,6 @@ class MutableBigInteger {
quotient
.
intLen
=
limit
;
quotient
.
intLen
=
limit
;
int
[]
q
=
quotient
.
value
;
int
[]
q
=
quotient
.
value
;
// D1 normalize the divisor
int
shift
=
Integer
.
numberOfLeadingZeros
(
divisor
[
0
]);
if
(
shift
>
0
)
{
// First shift will not grow array
BigInteger
.
primitiveLeftShift
(
divisor
,
dlen
,
shift
);
// But this one might
rem
.
leftShift
(
shift
);
}
// Must insert leading 0 in rem if its length did not change
// Must insert leading 0 in rem if its length did not change
if
(
rem
.
intLen
==
nlen
)
{
if
(
rem
.
intLen
==
nlen
)
{
...
@@ -990,10 +1068,9 @@ class MutableBigInteger {
...
@@ -990,10 +1068,9 @@ class MutableBigInteger {
int
dh
=
divisor
[
0
];
int
dh
=
divisor
[
0
];
long
dhLong
=
dh
&
LONG_MASK
;
long
dhLong
=
dh
&
LONG_MASK
;
int
dl
=
divisor
[
1
];
int
dl
=
divisor
[
1
];
int
[]
qWord
=
new
int
[
2
];
// D2 Initialize j
// D2 Initialize j
for
(
int
j
=
0
;
j
<
limit
;
j
++)
{
for
(
int
j
=
0
;
j
<
limit
-
1
;
j
++)
{
// D3 Calculate qhat
// D3 Calculate qhat
// estimate qhat
// estimate qhat
int
qhat
=
0
;
int
qhat
=
0
;
...
@@ -1013,9 +1090,9 @@ class MutableBigInteger {
...
@@ -1013,9 +1090,9 @@ class MutableBigInteger {
qhat
=
(
int
)
(
nChunk
/
dhLong
);
qhat
=
(
int
)
(
nChunk
/
dhLong
);
qrem
=
(
int
)
(
nChunk
-
(
qhat
*
dhLong
));
qrem
=
(
int
)
(
nChunk
-
(
qhat
*
dhLong
));
}
else
{
}
else
{
divWord
(
qWord
,
nChunk
,
dh
);
long
tmp
=
divWord
(
nChunk
,
dh
);
qhat
=
qWord
[
0
]
;
qhat
=
(
int
)
(
tmp
&
LONG_MASK
)
;
qrem
=
qWord
[
1
]
;
qrem
=
(
int
)
(
tmp
>>>
32
)
;
}
}
}
}
...
@@ -1053,6 +1130,181 @@ class MutableBigInteger {
...
@@ -1053,6 +1130,181 @@ class MutableBigInteger {
// Store the quotient digit
// Store the quotient digit
q
[
j
]
=
qhat
;
q
[
j
]
=
qhat
;
}
// D7 loop on j
}
// D7 loop on j
// D3 Calculate qhat
// estimate qhat
int
qhat
=
0
;
int
qrem
=
0
;
boolean
skipCorrection
=
false
;
int
nh
=
rem
.
value
[
limit
-
1
+
rem
.
offset
];
int
nh2
=
nh
+
0x80000000
;
int
nm
=
rem
.
value
[
limit
+
rem
.
offset
];
if
(
nh
==
dh
)
{
qhat
=
~
0
;
qrem
=
nh
+
nm
;
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
);
}
}
if
(
qhat
!=
0
)
{
if
(!
skipCorrection
)
{
// Correct qhat
long
nl
=
rem
.
value
[
limit
+
1
+
rem
.
offset
]
&
LONG_MASK
;
long
rs
=
((
qrem
&
LONG_MASK
)
<<
32
)
|
nl
;
long
estProduct
=
(
dl
&
LONG_MASK
)
*
(
qhat
&
LONG_MASK
);
if
(
unsignedLongCompare
(
estProduct
,
rs
))
{
qhat
--;
qrem
=
(
int
)
((
qrem
&
LONG_MASK
)
+
dhLong
);
if
((
qrem
&
LONG_MASK
)
>=
dhLong
)
{
estProduct
-=
(
dl
&
LONG_MASK
);
rs
=
((
qrem
&
LONG_MASK
)
<<
32
)
|
nl
;
if
(
unsignedLongCompare
(
estProduct
,
rs
))
qhat
--;
}
}
}
// D4 Multiply and subtract
int
borrow
;
rem
.
value
[
limit
-
1
+
rem
.
offset
]
=
0
;
if
(
needReminder
)
borrow
=
mulsub
(
rem
.
value
,
divisor
,
qhat
,
dlen
,
limit
-
1
+
rem
.
offset
);
else
borrow
=
mulsubBorrow
(
rem
.
value
,
divisor
,
qhat
,
dlen
,
limit
-
1
+
rem
.
offset
);
// D5 Test remainder
if
(
borrow
+
0x80000000
>
nh2
)
{
// D6 Add back
if
(
needReminder
)
divadd
(
divisor
,
rem
.
value
,
limit
-
1
+
1
+
rem
.
offset
);
qhat
--;
}
// Store the quotient digit
q
[(
limit
-
1
)]
=
qhat
;
}
if
(
needReminder
)
{
// D8 Unnormalize
if
(
shift
>
0
)
rem
.
rightShift
(
shift
);
rem
.
normalize
();
}
quotient
.
normalize
();
return
needReminder
?
rem
:
null
;
}
/**
* Divide this MutableBigInteger by the divisor represented by positive long
* value. The quotient will be placed into the provided quotient object &
* the remainder object is returned.
*/
private
MutableBigInteger
divideLongMagnitude
(
long
ldivisor
,
MutableBigInteger
quotient
)
{
// Remainder starts as dividend with space for a leading zero
MutableBigInteger
rem
=
new
MutableBigInteger
(
new
int
[
intLen
+
1
]);
System
.
arraycopy
(
value
,
offset
,
rem
.
value
,
1
,
intLen
);
rem
.
intLen
=
intLen
;
rem
.
offset
=
1
;
int
nlen
=
rem
.
intLen
;
int
limit
=
nlen
-
2
+
1
;
if
(
quotient
.
value
.
length
<
limit
)
{
quotient
.
value
=
new
int
[
limit
];
quotient
.
offset
=
0
;
}
quotient
.
intLen
=
limit
;
int
[]
q
=
quotient
.
value
;
// D1 normalize the divisor
int
shift
=
Long
.
numberOfLeadingZeros
(
ldivisor
);
if
(
shift
>
0
)
{
ldivisor
<<=
shift
;
rem
.
leftShift
(
shift
);
}
// Must insert leading 0 in rem if its length did not change
if
(
rem
.
intLen
==
nlen
)
{
rem
.
offset
=
0
;
rem
.
value
[
0
]
=
0
;
rem
.
intLen
++;
}
int
dh
=
(
int
)(
ldivisor
>>>
32
);
long
dhLong
=
dh
&
LONG_MASK
;
int
dl
=
(
int
)(
ldivisor
&
LONG_MASK
);
// D2 Initialize j
for
(
int
j
=
0
;
j
<
limit
;
j
++)
{
// D3 Calculate qhat
// estimate qhat
int
qhat
=
0
;
int
qrem
=
0
;
boolean
skipCorrection
=
false
;
int
nh
=
rem
.
value
[
j
+
rem
.
offset
];
int
nh2
=
nh
+
0x80000000
;
int
nm
=
rem
.
value
[
j
+
1
+
rem
.
offset
];
if
(
nh
==
dh
)
{
qhat
=
~
0
;
qrem
=
nh
+
nm
;
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
);
}
}
if
(
qhat
==
0
)
continue
;
if
(!
skipCorrection
)
{
// Correct qhat
long
nl
=
rem
.
value
[
j
+
2
+
rem
.
offset
]
&
LONG_MASK
;
long
rs
=
((
qrem
&
LONG_MASK
)
<<
32
)
|
nl
;
long
estProduct
=
(
dl
&
LONG_MASK
)
*
(
qhat
&
LONG_MASK
);
if
(
unsignedLongCompare
(
estProduct
,
rs
))
{
qhat
--;
qrem
=
(
int
)
((
qrem
&
LONG_MASK
)
+
dhLong
);
if
((
qrem
&
LONG_MASK
)
>=
dhLong
)
{
estProduct
-=
(
dl
&
LONG_MASK
);
rs
=
((
qrem
&
LONG_MASK
)
<<
32
)
|
nl
;
if
(
unsignedLongCompare
(
estProduct
,
rs
))
qhat
--;
}
}
}
// D4 Multiply and subtract
rem
.
value
[
j
+
rem
.
offset
]
=
0
;
int
borrow
=
mulsubLong
(
rem
.
value
,
dh
,
dl
,
qhat
,
j
+
rem
.
offset
);
// D5 Test remainder
if
(
borrow
+
0x80000000
>
nh2
)
{
// D6 Add back
divaddLong
(
dh
,
dl
,
rem
.
value
,
j
+
1
+
rem
.
offset
);
qhat
--;
}
// Store the quotient digit
q
[
j
]
=
qhat
;
}
// D7 loop on j
// D8 Unnormalize
// D8 Unnormalize
if
(
shift
>
0
)
if
(
shift
>
0
)
...
@@ -1063,6 +1315,46 @@ class MutableBigInteger {
...
@@ -1063,6 +1315,46 @@ class MutableBigInteger {
return
rem
;
return
rem
;
}
}
/**
* A primitive used for division by long.
* Specialized version of the method divadd.
* dh is a high part of the divisor, dl is a low part
*/
private
int
divaddLong
(
int
dh
,
int
dl
,
int
[]
result
,
int
offset
)
{
long
carry
=
0
;
long
sum
=
(
dl
&
LONG_MASK
)
+
(
result
[
1
+
offset
]
&
LONG_MASK
);
result
[
1
+
offset
]
=
(
int
)
sum
;
sum
=
(
dh
&
LONG_MASK
)
+
(
result
[
offset
]
&
LONG_MASK
)
+
carry
;
result
[
offset
]
=
(
int
)
sum
;
carry
=
sum
>>>
32
;
return
(
int
)
carry
;
}
/**
* This method is used for division by long.
* Specialized version of the method sulsub.
* dh is a high part of the divisor, dl is a low part
*/
private
int
mulsubLong
(
int
[]
q
,
int
dh
,
int
dl
,
int
x
,
int
offset
)
{
long
xLong
=
x
&
LONG_MASK
;
offset
+=
2
;
long
product
=
(
dl
&
LONG_MASK
)
*
xLong
;
long
difference
=
q
[
offset
]
-
product
;
q
[
offset
--]
=
(
int
)
difference
;
long
carry
=
(
product
>>>
32
)
+
(((
difference
&
LONG_MASK
)
>
(((~(
int
)
product
)
&
LONG_MASK
)))
?
1
:
0
);
product
=
(
dh
&
LONG_MASK
)
*
xLong
+
carry
;
difference
=
q
[
offset
]
-
product
;
q
[
offset
--]
=
(
int
)
difference
;
carry
=
(
product
>>>
32
)
+
(((
difference
&
LONG_MASK
)
>
(((~(
int
)
product
)
&
LONG_MASK
)))
?
1
:
0
);
return
(
int
)
carry
;
}
/**
/**
* Compare two longs as if they were unsigned.
* Compare two longs as if they were unsigned.
* Returns true iff one is bigger than two.
* Returns true iff one is bigger than two.
...
@@ -1075,19 +1367,22 @@ class MutableBigInteger {
...
@@ -1075,19 +1367,22 @@ class MutableBigInteger {
* This method divides a long quantity by an int to estimate
* This method divides a long quantity by an int to estimate
* qhat for two multi precision numbers. It is used when
* qhat for two multi precision numbers. It is used when
* the signed value of n is less than zero.
* the signed value of n is less than zero.
* Returns long value where high 32 bits contain reminder value and
* low 32 bits contain quotient value.
*/
*/
private
void
divWord
(
int
[]
result
,
long
n
,
int
d
)
{
static
long
divWord
(
long
n
,
int
d
)
{
long
dLong
=
d
&
LONG_MASK
;
long
dLong
=
d
&
LONG_MASK
;
long
r
;
long
q
;
if
(
dLong
==
1
)
{
if
(
dLong
==
1
)
{
result
[
0
]
=
(
int
)
n
;
q
=
(
int
)
n
;
r
esult
[
1
]
=
0
;
r
=
0
;
return
;
return
(
r
<<
32
)
|
(
q
&
LONG_MASK
)
;
}
}
// Approximate the quotient and remainder
// Approximate the quotient and remainder
long
q
=
(
n
>>>
1
)
/
(
dLong
>>>
1
);
q
=
(
n
>>>
1
)
/
(
dLong
>>>
1
);
long
r
=
n
-
q
*
dLong
;
r
=
n
-
q
*
dLong
;
// Correct the approximation
// Correct the approximation
while
(
r
<
0
)
{
while
(
r
<
0
)
{
...
@@ -1098,10 +1393,8 @@ class MutableBigInteger {
...
@@ -1098,10 +1393,8 @@ class MutableBigInteger {
r
-=
dLong
;
r
-=
dLong
;
q
++;
q
++;
}
}
// n - q*dlong == r && 0 <= r <dLong, hence we're done.
// n - q*dlong == r && 0 <= r <dLong, hence we're done.
result
[
0
]
=
(
int
)
q
;
return
(
r
<<
32
)
|
(
q
&
LONG_MASK
);
result
[
1
]
=
(
int
)
r
;
}
}
/**
/**
...
@@ -1473,5 +1766,4 @@ class MutableBigInteger {
...
@@ -1473,5 +1766,4 @@ class MutableBigInteger {
mod
.
subtract
(
t1
);
mod
.
subtract
(
t1
);
return
mod
;
return
mod
;
}
}
}
}
test/java/math/BigDecimal/DivideMcTests.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 20
03, 20
11, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
...
test/java/math/BigDecimal/FloatDoubleValueTests.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005,
2011
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
/*
/*
* @test
* @test
* @bug 6274390
* @bug 6274390
7082971
* @summary Verify {float, double}Value methods work with condensed representation
* @summary Verify {float, double}Value methods work with condensed representation
* @run main FloatDoubleValueTests
* @run main FloatDoubleValueTests
* @run main/othervm -XX:+AggressiveOpts FloatDoubleValueTests
* @run main/othervm -XX:+AggressiveOpts FloatDoubleValueTests
...
@@ -79,6 +79,7 @@ public class FloatDoubleValueTests {
...
@@ -79,6 +79,7 @@ public class FloatDoubleValueTests {
// and double.
// and double.
static
void
testFloatDoubleValue
()
{
static
void
testFloatDoubleValue
()
{
long
longValues
[]
=
{
long
longValues
[]
=
{
Long
.
MIN_VALUE
,
// -2^63
0
,
0
,
1
,
1
,
2
,
2
,
...
...
test/java/math/BigDecimal/RangeTests.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 20
03, 20
11, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
...
test/java/math/BigDecimal/StrippingZerosTest.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003,
2011
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
...
test/java/math/BigDecimal/ToPlainStringTests.java
浏览文件 @
60839a4f
/*
/*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004,
2011,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录