Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
afc47100
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看板
提交
afc47100
编写于
10月 02, 2012
作者:
O
olagneau
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7050528: Improve performance of java.text.DecimalFormat.format() call stack
Reviewed-by: darcy
上级
7d09db22
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
4471 addition
and
19 deletion
+4471
-19
src/share/classes/java/text/DecimalFormat.java
src/share/classes/java/text/DecimalFormat.java
+905
-18
src/share/classes/java/text/NumberFormat.java
src/share/classes/java/text/NumberFormat.java
+12
-1
test/java/text/Format/DecimalFormat/FormatMicroBenchmark.java
.../java/text/Format/DecimalFormat/FormatMicroBenchmark.java
+926
-0
test/java/text/Format/DecimalFormat/GoldenDoubleValues.java
test/java/text/Format/DecimalFormat/GoldenDoubleValues.java
+965
-0
test/java/text/Format/DecimalFormat/GoldenFormattedValues.java
...java/text/Format/DecimalFormat/GoldenFormattedValues.java
+868
-0
test/java/text/Format/DecimalFormat/RoundingAndPropertyTest.java
...va/text/Format/DecimalFormat/RoundingAndPropertyTest.java
+795
-0
未找到文件。
src/share/classes/java/text/DecimalFormat.java
浏览文件 @
afc47100
...
...
@@ -529,9 +529,25 @@ public class DecimalFormat extends NumberFormat {
@Override
public
StringBuffer
format
(
double
number
,
StringBuffer
result
,
FieldPosition
fieldPosition
)
{
fieldPosition
.
setBeginIndex
(
0
);
fieldPosition
.
setEndIndex
(
0
);
// If fieldPosition is a DontCareFieldPosition instance we can
// try to go to fast-path code.
boolean
tryFastPath
=
false
;
if
(
fieldPosition
==
DontCareFieldPosition
.
INSTANCE
)
tryFastPath
=
true
;
else
{
fieldPosition
.
setBeginIndex
(
0
);
fieldPosition
.
setEndIndex
(
0
);
}
if
(
tryFastPath
)
{
String
tempResult
=
fastFormat
(
number
);
if
(
tempResult
!=
null
)
{
result
.
append
(
tempResult
);
return
result
;
}
}
// if fast-path could not work, we fallback to standard code.
return
format
(
number
,
result
,
fieldPosition
.
getFieldDelegate
());
}
...
...
@@ -869,6 +885,720 @@ public class DecimalFormat extends NumberFormat {
return
delegate
.
getIterator
(
sb
.
toString
());
}
// ==== Begin fast-path formating logic for double =========================
/* Fast-path formatting will be used for format(double ...) methods iff a
* number of conditions are met (see checkAndSetFastPathStatus()):
* - Only if instance properties meet the right predefined conditions.
* - The abs value of the double to format is <= Integer.MAX_VALUE.
*
* The basic approach is to split the binary to decimal conversion of a
* double value into two phases:
* * The conversion of the integer portion of the double.
* * The conversion of the fractional portion of the double
* (limited to two or three digits).
*
* The isolation and conversion of the integer portion of the double is
* straightforward. The conversion of the fraction is more subtle and relies
* on some rounding properties of double to the decimal precisions in
* question. Using the terminology of BigDecimal, this fast-path algorithm
* is applied when a double value has a magnitude less than Integer.MAX_VALUE
* and rounding is to nearest even and the destination format has two or
* three digits of *scale* (digits after the decimal point).
*
* Under a rounding to nearest even policy, the returned result is a digit
* string of a number in the (in this case decimal) destination format
* closest to the exact numerical value of the (in this case binary) input
* value. If two destination format numbers are equally distant, the one
* with the last digit even is returned. To compute such a correctly rounded
* value, some information about digits beyond the smallest returned digit
* position needs to be consulted.
*
* In general, a guard digit, a round digit, and a sticky *bit* are needed
* beyond the returned digit position. If the discarded portion of the input
* is sufficiently large, the returned digit string is incremented. In round
* to nearest even, this threshold to increment occurs near the half-way
* point between digits. The sticky bit records if there are any remaining
* trailing digits of the exact input value in the new format; the sticky bit
* is consulted only in close to half-way rounding cases.
*
* Given the computation of the digit and bit values, rounding is then
* reduced to a table lookup problem. For decimal, the even/odd cases look
* like this:
*
* Last Round Sticky
* 6 5 0 => 6 // exactly halfway, return even digit.
* 6 5 1 => 7 // a little bit more than halfway, round up.
* 7 5 0 => 8 // exactly halfway, round up to even.
* 7 5 1 => 8 // a little bit more than halfway, round up.
* With analogous entries for other even and odd last-returned digits.
*
* However, decimal negative powers of 5 smaller than 0.5 are *not* exactly
* representable as binary fraction. In particular, 0.005 (the round limit
* for a two-digit scale) and 0.0005 (the round limit for a three-digit
* scale) are not representable. Therefore, for input values near these cases
* the sticky bit is known to be set which reduces the rounding logic to:
*
* Last Round Sticky
* 6 5 1 => 7 // a little bit more than halfway, round up.
* 7 5 1 => 8 // a little bit more than halfway, round up.
*
* In other words, if the round digit is 5, the sticky bit is known to be
* set. If the round digit is something other than 5, the sticky bit is not
* relevant. Therefore, some of the logic about whether or not to increment
* the destination *decimal* value can occur based on tests of *binary*
* computations of the binary input number.
*/
/**
* Check validity of using fast-path for this instance. If fast-path is valid
* for this instance, sets fast-path state as true and initializes fast-path
* utility fields as needed.
*
* This method is supposed to be called rarely, otherwise that will break the
* fast-path performance. That means avoiding frequent changes of the
* properties of the instance, since for most properties, each time a change
* happens, a call to this method is needed at the next format call.
*
* FAST-PATH RULES:
* Similar to the default DecimalFormat instantiation case.
* More precisely:
* - HALF_EVEN rounding mode,
* - isGroupingUsed() is true,
* - groupingSize of 3,
* - multiplier is 1,
* - Decimal separator not mandatory,
* - No use of exponential notation,
* - minimumIntegerDigits is exactly 1 and maximumIntegerDigits at least 10
* - For number of fractional digits, the exact values found in the default case:
* Currency : min = max = 2.
* Decimal : min = 0. max = 3.
*
*/
private
void
checkAndSetFastPathStatus
()
{
boolean
fastPathWasOn
=
isFastPath
;
if
((
roundingMode
==
RoundingMode
.
HALF_EVEN
)
&&
(
isGroupingUsed
())
&&
(
groupingSize
==
3
)
&&
(
multiplier
==
1
)
&&
(!
decimalSeparatorAlwaysShown
)
&&
(!
useExponentialNotation
))
{
// The fast-path algorithm is semi-hardcoded against
// minimumIntegerDigits and maximumIntegerDigits.
isFastPath
=
((
minimumIntegerDigits
==
1
)
&&
(
maximumIntegerDigits
>=
10
));
// The fast-path algorithm is hardcoded against
// minimumFractionDigits and maximumFractionDigits.
if
(
isFastPath
)
{
if
(
isCurrencyFormat
)
{
if
((
minimumFractionDigits
!=
2
)
||
(
maximumFractionDigits
!=
2
))
isFastPath
=
false
;
}
else
if
((
minimumFractionDigits
!=
0
)
||
(
maximumFractionDigits
!=
3
))
isFastPath
=
false
;
}
}
else
isFastPath
=
false
;
// Since some instance properties may have changed while still falling
// in the fast-path case, we need to reinitialize fastPathData anyway.
if
(
isFastPath
)
{
// We need to instantiate fastPathData if not already done.
if
(
fastPathData
==
null
)
fastPathData
=
new
FastPathData
();
// Sets up the locale specific constants used when formatting.
// '0' is our default representation of zero.
fastPathData
.
zeroDelta
=
symbols
.
getZeroDigit
()
-
'0'
;
fastPathData
.
groupingChar
=
symbols
.
getGroupingSeparator
();
// Sets up fractional constants related to currency/decimal pattern.
fastPathData
.
fractionalMaxIntBound
=
(
isCurrencyFormat
)
?
99
:
999
;
fastPathData
.
fractionalScaleFactor
=
(
isCurrencyFormat
)
?
100.0d
:
1000.0d
;
// Records the need for adding prefix or suffix
fastPathData
.
positiveAffixesRequired
=
(
positivePrefix
.
length
()
!=
0
)
||
(
positiveSuffix
.
length
()
!=
0
);
fastPathData
.
negativeAffixesRequired
=
(
negativePrefix
.
length
()
!=
0
)
||
(
negativeSuffix
.
length
()
!=
0
);
// Creates a cached char container for result, with max possible size.
int
maxNbIntegralDigits
=
10
;
int
maxNbGroups
=
3
;
int
containerSize
=
Math
.
max
(
positivePrefix
.
length
(),
negativePrefix
.
length
())
+
maxNbIntegralDigits
+
maxNbGroups
+
1
+
maximumFractionDigits
+
Math
.
max
(
positiveSuffix
.
length
(),
negativeSuffix
.
length
());
fastPathData
.
fastPathContainer
=
new
char
[
containerSize
];
// Sets up prefix and suffix char arrays constants.
fastPathData
.
charsPositiveSuffix
=
positiveSuffix
.
toCharArray
();
fastPathData
.
charsNegativeSuffix
=
negativeSuffix
.
toCharArray
();
fastPathData
.
charsPositivePrefix
=
positivePrefix
.
toCharArray
();
fastPathData
.
charsNegativePrefix
=
negativePrefix
.
toCharArray
();
// Sets up fixed index positions for integral and fractional digits.
// Sets up decimal point in cached result container.
int
longestPrefixLength
=
Math
.
max
(
positivePrefix
.
length
(),
negativePrefix
.
length
());
int
decimalPointIndex
=
maxNbIntegralDigits
+
maxNbGroups
+
longestPrefixLength
;
fastPathData
.
integralLastIndex
=
decimalPointIndex
-
1
;
fastPathData
.
fractionalFirstIndex
=
decimalPointIndex
+
1
;
fastPathData
.
fastPathContainer
[
decimalPointIndex
]
=
isCurrencyFormat
?
symbols
.
getMonetaryDecimalSeparator
()
:
symbols
.
getDecimalSeparator
();
}
else
if
(
fastPathWasOn
)
{
// Previous state was fast-path and is no more.
// Resets cached array constants.
fastPathData
.
fastPathContainer
=
null
;
fastPathData
.
charsPositiveSuffix
=
null
;
fastPathData
.
charsNegativeSuffix
=
null
;
fastPathData
.
charsPositivePrefix
=
null
;
fastPathData
.
charsNegativePrefix
=
null
;
}
fastPathCheckNeeded
=
false
;
}
/**
* Returns true if rounding-up must be done on {@code scaledFractionalPartAsInt},
* false otherwise.
*
* This is a utility method that takes correct half-even rounding decision on
* passed fractional value at the scaled decimal point (2 digits for currency
* case and 3 for decimal case), when the approximated fractional part after
* scaled decimal point is exactly 0.5d. This is done by means of exact
* calculations on the {@code fractionalPart} floating-point value.
*
* This method is supposed to be called by private {@code fastDoubleFormat}
* method only.
*
* The algorithms used for the exact calculations are :
*
* The <b><i>FastTwoSum</i></b> algorithm, from T.J.Dekker, described in the
* papers "<i>A Floating-Point Technique for Extending the Available
* Precision</i>" by Dekker, and in "<i>Adaptive Precision Floating-Point
* Arithmetic and Fast Robust Geometric Predicates</i>" from J.Shewchuk.
*
* A modified version of <b><i>Sum2S</i></b> cascaded summation described in
* "<i>Accurate Sum and Dot Product</i>" from Takeshi Ogita and All. As
* Ogita says in this paper this is an equivalent of the Kahan-Babuska's
* summation algorithm because we order the terms by magnitude before summing
* them. For this reason we can use the <i>FastTwoSum</i> algorithm rather
* than the more expensive Knuth's <i>TwoSum</i>.
*
* We do this to avoid a more expensive exact "<i>TwoProduct</i>" algorithm,
* like those described in Shewchuk's paper above. See comments in the code
* below.
*
* @param fractionalPart The fractional value on which we take rounding
* decision.
* @param scaledFractionalPartAsInt The integral part of the scaled
* fractional value.
*
* @return the decision that must be taken regarding half-even rounding.
*/
private
boolean
exactRoundUp
(
double
fractionalPart
,
int
scaledFractionalPartAsInt
)
{
/* exactRoundUp() method is called by fastDoubleFormat() only.
* The precondition expected to be verified by the passed parameters is :
* scaledFractionalPartAsInt ==
* (int) (fractionalPart * fastPathData.fractionalScaleFactor).
* This is ensured by fastDoubleFormat() code.
*/
/* We first calculate roundoff error made by fastDoubleFormat() on
* the scaled fractional part. We do this with exact calculation on the
* passed fractionalPart. Rounding decision will then be taken from roundoff.
*/
/* ---- TwoProduct(fractionalPart, scale factor (i.e. 1000.0d or 100.0d)).
*
* The below is an optimized exact "TwoProduct" calculation of passed
* fractional part with scale factor, using Ogita's Sum2S cascaded
* summation adapted as Kahan-Babuska equivalent by using FastTwoSum
* (much faster) rather than Knuth's TwoSum.
*
* We can do this because we order the summation from smallest to
* greatest, so that FastTwoSum can be used without any additional error.
*
* The "TwoProduct" exact calculation needs 17 flops. We replace this by
* a cascaded summation of FastTwoSum calculations, each involving an
* exact multiply by a power of 2.
*
* Doing so saves overall 4 multiplications and 1 addition compared to
* using traditional "TwoProduct".
*
* The scale factor is either 100 (currency case) or 1000 (decimal case).
* - when 1000, we replace it by (1024 - 16 - 8) = 1000.
* - when 100, we replace it by (128 - 32 + 4) = 100.
* Every multiplication by a power of 2 (1024, 128, 32, 16, 8, 4) is exact.
*
*/
double
approxMax
;
// Will always be positive.
double
approxMedium
;
// Will always be negative.
double
approxMin
;
double
fastTwoSumApproximation
=
0.0d
;
double
fastTwoSumRoundOff
=
0.0d
;
double
bVirtual
=
0.0d
;
if
(
isCurrencyFormat
)
{
// Scale is 100 = 128 - 32 + 4.
// Multiply by 2**n is a shift. No roundoff. No error.
approxMax
=
fractionalPart
*
128.00d
;
approxMedium
=
-
(
fractionalPart
*
32.00d
);
approxMin
=
fractionalPart
*
4.00d
;
}
else
{
// Scale is 1000 = 1024 - 16 - 8.
// Multiply by 2**n is a shift. No roundoff. No error.
approxMax
=
fractionalPart
*
1024.00d
;
approxMedium
=
-
(
fractionalPart
*
16.00d
);
approxMin
=
-
(
fractionalPart
*
8.00d
);
}
// Shewchuk/Dekker's FastTwoSum(approxMedium, approxMin).
assert
(-
approxMedium
>=
Math
.
abs
(
approxMin
));
fastTwoSumApproximation
=
approxMedium
+
approxMin
;
bVirtual
=
fastTwoSumApproximation
-
approxMedium
;
fastTwoSumRoundOff
=
approxMin
-
bVirtual
;
double
approxS1
=
fastTwoSumApproximation
;
double
roundoffS1
=
fastTwoSumRoundOff
;
// Shewchuk/Dekker's FastTwoSum(approxMax, approxS1);
assert
(
approxMax
>=
Math
.
abs
(
approxS1
));
fastTwoSumApproximation
=
approxMax
+
approxS1
;
bVirtual
=
fastTwoSumApproximation
-
approxMax
;
fastTwoSumRoundOff
=
approxS1
-
bVirtual
;
double
roundoff1000
=
fastTwoSumRoundOff
;
double
approx1000
=
fastTwoSumApproximation
;
double
roundoffTotal
=
roundoffS1
+
roundoff1000
;
// Shewchuk/Dekker's FastTwoSum(approx1000, roundoffTotal);
assert
(
approx1000
>=
Math
.
abs
(
roundoffTotal
));
fastTwoSumApproximation
=
approx1000
+
roundoffTotal
;
bVirtual
=
fastTwoSumApproximation
-
approx1000
;
// Now we have got the roundoff for the scaled fractional
double
scaledFractionalRoundoff
=
roundoffTotal
-
bVirtual
;
// ---- TwoProduct(fractionalPart, scale (i.e. 1000.0d or 100.0d)) end.
/* ---- Taking the rounding decision
*
* We take rounding decision based on roundoff and half-even rounding
* rule.
*
* The above TwoProduct gives us the exact roundoff on the approximated
* scaled fractional, and we know that this approximation is exactly
* 0.5d, since that has already been tested by the caller
* (fastDoubleFormat).
*
* Decision comes first from the sign of the calculated exact roundoff.
* - Since being exact roundoff, it cannot be positive with a scaled
* fractional less than 0.5d, as well as negative with a scaled
* fractional greater than 0.5d. That leaves us with following 3 cases.
* - positive, thus scaled fractional == 0.500....0fff ==> round-up.
* - negative, thus scaled fractional == 0.499....9fff ==> don't round-up.
* - is zero, thus scaled fractioanl == 0.5 ==> half-even rounding applies :
* we round-up only if the integral part of the scaled fractional is odd.
*
*/
if
(
scaledFractionalRoundoff
>
0.0
)
{
return
true
;
}
else
if
(
scaledFractionalRoundoff
<
0.0
)
{
return
false
;
}
else
if
((
scaledFractionalPartAsInt
&
1
)
!=
0
)
{
return
true
;
}
return
false
;
// ---- Taking the rounding decision end
}
/**
* Collects integral digits from passed {@code number}, while setting
* grouping chars as needed. Updates {@code firstUsedIndex} accordingly.
*
* Loops downward starting from {@code backwardIndex} position (inclusive).
*
* @param number The int value from which we collect digits.
* @param digitsBuffer The char array container where digits and grouping chars
* are stored.
* @param backwardIndex the position from which we start storing digits in
* digitsBuffer.
*
*/
private
void
collectIntegralDigits
(
int
number
,
char
[]
digitsBuffer
,
int
backwardIndex
)
{
int
index
=
backwardIndex
;
int
q
;
int
r
;
while
(
number
>
999
)
{
// Generates 3 digits per iteration.
q
=
number
/
1000
;
r
=
number
-
(
q
<<
10
)
+
(
q
<<
4
)
+
(
q
<<
3
);
// -1024 +16 +8 = 1000.
number
=
q
;
digitsBuffer
[
index
--]
=
DigitArrays
.
DigitOnes1000
[
r
];
digitsBuffer
[
index
--]
=
DigitArrays
.
DigitTens1000
[
r
];
digitsBuffer
[
index
--]
=
DigitArrays
.
DigitHundreds1000
[
r
];
digitsBuffer
[
index
--]
=
fastPathData
.
groupingChar
;
}
// Collects last 3 or less digits.
digitsBuffer
[
index
]
=
DigitArrays
.
DigitOnes1000
[
number
];
if
(
number
>
9
)
{
digitsBuffer
[--
index
]
=
DigitArrays
.
DigitTens1000
[
number
];
if
(
number
>
99
)
digitsBuffer
[--
index
]
=
DigitArrays
.
DigitHundreds1000
[
number
];
}
fastPathData
.
firstUsedIndex
=
index
;
}
/**
* Collects the 2 (currency) or 3 (decimal) fractional digits from passed
* {@code number}, starting at {@code startIndex} position
* inclusive. There is no punctuation to set here (no grouping chars).
* Updates {@code fastPathData.lastFreeIndex} accordingly.
*
*
* @param number The int value from which we collect digits.
* @param digitsBuffer The char array container where digits are stored.
* @param startIndex the position from which we start storing digits in
* digitsBuffer.
*
*/
private
void
collectFractionalDigits
(
int
number
,
char
[]
digitsBuffer
,
int
startIndex
)
{
int
index
=
startIndex
;
char
digitOnes
=
DigitArrays
.
DigitOnes1000
[
number
];
char
digitTens
=
DigitArrays
.
DigitTens1000
[
number
];
if
(
isCurrencyFormat
)
{
// Currency case. Always collects fractional digits.
digitsBuffer
[
index
++]
=
digitTens
;
digitsBuffer
[
index
++]
=
digitOnes
;
}
else
if
(
number
!=
0
)
{
// Decimal case. Hundreds will always be collected
digitsBuffer
[
index
++]
=
DigitArrays
.
DigitHundreds1000
[
number
];
// Ending zeros won't be collected.
if
(
digitOnes
!=
'0'
)
{
digitsBuffer
[
index
++]
=
digitTens
;
digitsBuffer
[
index
++]
=
digitOnes
;
}
else
if
(
digitTens
!=
'0'
)
digitsBuffer
[
index
++]
=
digitTens
;
}
else
// This is decimal pattern and fractional part is zero.
// We must remove decimal point from result.
index
--;
fastPathData
.
lastFreeIndex
=
index
;
}
/**
* Internal utility.
* Adds the passed {@code prefix} and {@code suffix} to {@code container}.
*
* @param container Char array container which to prepend/append the
* prefix/suffix.
* @param prefix Char sequence to prepend as a prefix.
* @param suffix Char sequence to append as a suffix.
*
*/
// private void addAffixes(boolean isNegative, char[] container) {
private
void
addAffixes
(
char
[]
container
,
char
[]
prefix
,
char
[]
suffix
)
{
// We add affixes only if needed (affix length > 0).
int
pl
=
prefix
.
length
;
int
sl
=
suffix
.
length
;
if
(
pl
!=
0
)
prependPrefix
(
prefix
,
pl
,
container
);
if
(
sl
!=
0
)
appendSuffix
(
suffix
,
sl
,
container
);
}
/**
* Prepends the passed {@code prefix} chars to given result
* {@code container}. Updates {@code fastPathData.firstUsedIndex}
* accordingly.
*
* @param prefix The prefix characters to prepend to result.
* @param len The number of chars to prepend.
* @param container Char array container which to prepend the prefix
*/
private
void
prependPrefix
(
char
[]
prefix
,
int
len
,
char
[]
container
)
{
fastPathData
.
firstUsedIndex
-=
len
;
int
startIndex
=
fastPathData
.
firstUsedIndex
;
// If prefix to prepend is only 1 char long, just assigns this char.
// If prefix is less or equal 4, we use a dedicated algorithm that
// has shown to run faster than System.arraycopy.
// If more than 4, we use System.arraycopy.
if
(
len
==
1
)
container
[
startIndex
]
=
prefix
[
0
];
else
if
(
len
<=
4
)
{
int
dstLower
=
startIndex
;
int
dstUpper
=
dstLower
+
len
-
1
;
int
srcUpper
=
len
-
1
;
container
[
dstLower
]
=
prefix
[
0
];
container
[
dstUpper
]
=
prefix
[
srcUpper
];
if
(
len
>
2
)
container
[++
dstLower
]
=
prefix
[
1
];
if
(
len
==
4
)
container
[--
dstUpper
]
=
prefix
[
2
];
}
else
System
.
arraycopy
(
prefix
,
0
,
container
,
startIndex
,
len
);
}
/**
* Appends the passed {@code suffix} chars to given result
* {@code container}. Updates {@code fastPathData.lastFreeIndex}
* accordingly.
*
* @param suffix The suffix characters to append to result.
* @param len The number of chars to append.
* @param container Char array container which to append the suffix
*/
private
void
appendSuffix
(
char
[]
suffix
,
int
len
,
char
[]
container
)
{
int
startIndex
=
fastPathData
.
lastFreeIndex
;
// If suffix to append is only 1 char long, just assigns this char.
// If suffix is less or equal 4, we use a dedicated algorithm that
// has shown to run faster than System.arraycopy.
// If more than 4, we use System.arraycopy.
if
(
len
==
1
)
container
[
startIndex
]
=
suffix
[
0
];
else
if
(
len
<=
4
)
{
int
dstLower
=
startIndex
;
int
dstUpper
=
dstLower
+
len
-
1
;
int
srcUpper
=
len
-
1
;
container
[
dstLower
]
=
suffix
[
0
];
container
[
dstUpper
]
=
suffix
[
srcUpper
];
if
(
len
>
2
)
container
[++
dstLower
]
=
suffix
[
1
];
if
(
len
==
4
)
container
[--
dstUpper
]
=
suffix
[
2
];
}
else
System
.
arraycopy
(
suffix
,
0
,
container
,
startIndex
,
len
);
fastPathData
.
lastFreeIndex
+=
len
;
}
/**
* Converts digit chars from {@code digitsBuffer} to current locale.
*
* Must be called before adding affixes since we refer to
* {@code fastPathData.firstUsedIndex} and {@code fastPathData.lastFreeIndex},
* and do not support affixes (for speed reason).
*
* We loop backward starting from last used index in {@code fastPathData}.
*
* @param digitsBuffer The char array container where the digits are stored.
*/
private
void
localizeDigits
(
char
[]
digitsBuffer
)
{
// We will localize only the digits, using the groupingSize,
// and taking into account fractional part.
// First take into account fractional part.
int
digitsCounter
=
fastPathData
.
lastFreeIndex
-
fastPathData
.
fractionalFirstIndex
;
// The case when there is no fractional digits.
if
(
digitsCounter
<
0
)
digitsCounter
=
groupingSize
;
// Only the digits remains to localize.
for
(
int
cursor
=
fastPathData
.
lastFreeIndex
-
1
;
cursor
>=
fastPathData
.
firstUsedIndex
;
cursor
--)
{
if
(
digitsCounter
!=
0
)
{
// This is a digit char, we must localize it.
digitsBuffer
[
cursor
]
+=
fastPathData
.
zeroDelta
;
digitsCounter
--;
}
else
{
// Decimal separator or grouping char. Reinit counter only.
digitsCounter
=
groupingSize
;
}
}
}
/**
* This is the main entry point for the fast-path format algorithm.
*
* At this point we are sure to be in the expected conditions to run it.
* This algorithm builds the formatted result and puts it in the dedicated
* {@code fastPathData.fastPathContainer}.
*
* @param d the double value to be formatted.
* @param negative Flag precising if {@code d} is negative.
*/
private
void
fastDoubleFormat
(
double
d
,
boolean
negative
)
{
char
[]
container
=
fastPathData
.
fastPathContainer
;
/*
* The principle of the algorithm is to :
* - Break the passed double into its integral and fractional parts
* converted into integers.
* - Then decide if rounding up must be applied or not by following
* the half-even rounding rule, first using approximated scaled
* fractional part.
* - For the difficult cases (approximated scaled fractional part
* being exactly 0.5d), we refine the rounding decision by calling
* exactRoundUp utility method that both calculates the exact roundoff
* on the approximation and takes correct rounding decision.
* - We round-up the fractional part if needed, possibly propagating the
* rounding to integral part if we meet a "all-nine" case for the
* scaled fractional part.
* - We then collect digits from the resulting integral and fractional
* parts, also setting the required grouping chars on the fly.
* - Then we localize the collected digits if needed, and
* - Finally prepend/append prefix/suffix if any is needed.
*/
// Exact integral part of d.
int
integralPartAsInt
=
(
int
)
d
;
// Exact fractional part of d (since we subtract it's integral part).
double
exactFractionalPart
=
d
-
(
double
)
integralPartAsInt
;
// Approximated scaled fractional part of d (due to multiplication).
double
scaledFractional
=
exactFractionalPart
*
fastPathData
.
fractionalScaleFactor
;
// Exact integral part of scaled fractional above.
int
fractionalPartAsInt
=
(
int
)
scaledFractional
;
// Exact fractional part of scaled fractional above.
scaledFractional
=
scaledFractional
-
(
double
)
fractionalPartAsInt
;
// Only when scaledFractional is exactly 0.5d do we have to do exact
// calculations and take fine-grained rounding decision, since
// approximated results above may lead to incorrect decision.
// Otherwise comparing against 0.5d (strictly greater or less) is ok.
boolean
roundItUp
=
false
;
if
(
scaledFractional
>=
0.5d
)
{
if
(
scaledFractional
==
0.5d
)
// Rounding need fine-grained decision.
roundItUp
=
exactRoundUp
(
exactFractionalPart
,
fractionalPartAsInt
);
else
roundItUp
=
true
;
if
(
roundItUp
)
{
// Rounds up both fractional part (and also integral if needed).
if
(
fractionalPartAsInt
<
fastPathData
.
fractionalMaxIntBound
)
{
fractionalPartAsInt
++;
}
else
{
// Propagates rounding to integral part since "all nines" case.
fractionalPartAsInt
=
0
;
integralPartAsInt
++;
}
}
}
// Collecting digits.
collectFractionalDigits
(
fractionalPartAsInt
,
container
,
fastPathData
.
fractionalFirstIndex
);
collectIntegralDigits
(
integralPartAsInt
,
container
,
fastPathData
.
integralLastIndex
);
// Localizing digits.
if
(
fastPathData
.
zeroDelta
!=
0
)
localizeDigits
(
container
);
// Adding prefix and suffix.
if
(
negative
)
{
if
(
fastPathData
.
negativeAffixesRequired
)
addAffixes
(
container
,
fastPathData
.
charsNegativePrefix
,
fastPathData
.
charsNegativeSuffix
);
}
else
if
(
fastPathData
.
positiveAffixesRequired
)
addAffixes
(
container
,
fastPathData
.
charsPositivePrefix
,
fastPathData
.
charsPositiveSuffix
);
}
/**
* A fast-path shortcut of format(double) to be called by NumberFormat, or by
* format(double, ...) public methods.
*
* If instance can be applied fast-path and passed double is not NaN or
* Infinity, is in the integer range, we call {@code fastDoubleFormat}
* after changing {@code d} to its positive value if necessary.
*
* Otherwise returns null by convention since fast-path can't be exercized.
*
* @param d The double value to be formatted
*
* @return the formatted result for {@code d} as a string.
*/
String
fastFormat
(
double
d
)
{
// (Re-)Evaluates fast-path status if needed.
if
(
fastPathCheckNeeded
)
checkAndSetFastPathStatus
();
if
(!
isFastPath
)
// DecimalFormat instance is not in a fast-path state.
return
null
;
if
(!
Double
.
isFinite
(
d
))
// Should not use fast-path for Infinity and NaN.
return
null
;
// Extracts and records sign of double value, possibly changing it
// to a positive one, before calling fastDoubleFormat().
boolean
negative
=
false
;
if
(
d
<
0.0d
)
{
negative
=
true
;
d
=
-
d
;
}
else
if
(
d
==
0.0d
)
{
negative
=
(
Math
.
copySign
(
1.0d
,
d
)
==
-
1.0d
);
d
=
+
0.0d
;
}
if
(
d
>
MAX_INT_AS_DOUBLE
)
// Filters out values that are outside expected fast-path range
return
null
;
else
fastDoubleFormat
(
d
,
negative
);
// Returns a new string from updated fastPathContainer.
return
new
String
(
fastPathData
.
fastPathContainer
,
fastPathData
.
firstUsedIndex
,
fastPathData
.
lastFreeIndex
-
fastPathData
.
firstUsedIndex
);
}
// ======== End fast-path formating logic for double =========================
/**
* Complete the formatting of a finite number. On entry, the digitList must
* be filled in with the correct digits.
...
...
@@ -1168,8 +1898,7 @@ public class DecimalFormat extends NumberFormat {
if
(
isNegative
)
{
append
(
result
,
negativeSuffix
,
delegate
,
getNegativeSuffixFieldPositions
(),
Field
.
SIGN
);
}
else
{
}
else
{
append
(
result
,
positiveSuffix
,
delegate
,
getPositiveSuffixFieldPositions
(),
Field
.
SIGN
);
}
...
...
@@ -1557,8 +2286,7 @@ public class DecimalFormat extends NumberFormat {
sawExponent
=
true
;
}
break
;
// Whether we fail or succeed, we exit this loop
}
else
{
}
else
{
break
;
}
}
...
...
@@ -1653,6 +2381,7 @@ public class DecimalFormat extends NumberFormat {
// don't allow multiple references
symbols
=
(
DecimalFormatSymbols
)
newSymbols
.
clone
();
expandAffixes
();
fastPathCheckNeeded
=
true
;
}
catch
(
Exception
foo
)
{
// should never happen
}
...
...
@@ -1674,6 +2403,7 @@ public class DecimalFormat extends NumberFormat {
positivePrefix
=
newValue
;
posPrefixPattern
=
null
;
positivePrefixFieldPositions
=
null
;
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1688,8 +2418,7 @@ public class DecimalFormat extends NumberFormat {
if
(
positivePrefixFieldPositions
==
null
)
{
if
(
posPrefixPattern
!=
null
)
{
positivePrefixFieldPositions
=
expandAffix
(
posPrefixPattern
);
}
else
{
}
else
{
positivePrefixFieldPositions
=
EmptyFieldPositionArray
;
}
}
...
...
@@ -1711,6 +2440,7 @@ public class DecimalFormat extends NumberFormat {
public
void
setNegativePrefix
(
String
newValue
)
{
negativePrefix
=
newValue
;
negPrefixPattern
=
null
;
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1725,8 +2455,7 @@ public class DecimalFormat extends NumberFormat {
if
(
negativePrefixFieldPositions
==
null
)
{
if
(
negPrefixPattern
!=
null
)
{
negativePrefixFieldPositions
=
expandAffix
(
negPrefixPattern
);
}
else
{
}
else
{
negativePrefixFieldPositions
=
EmptyFieldPositionArray
;
}
}
...
...
@@ -1748,6 +2477,7 @@ public class DecimalFormat extends NumberFormat {
public
void
setPositiveSuffix
(
String
newValue
)
{
positiveSuffix
=
newValue
;
posSuffixPattern
=
null
;
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1762,8 +2492,7 @@ public class DecimalFormat extends NumberFormat {
if
(
positiveSuffixFieldPositions
==
null
)
{
if
(
posSuffixPattern
!=
null
)
{
positiveSuffixFieldPositions
=
expandAffix
(
posSuffixPattern
);
}
else
{
}
else
{
positiveSuffixFieldPositions
=
EmptyFieldPositionArray
;
}
}
...
...
@@ -1785,6 +2514,7 @@ public class DecimalFormat extends NumberFormat {
public
void
setNegativeSuffix
(
String
newValue
)
{
negativeSuffix
=
newValue
;
negSuffixPattern
=
null
;
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1799,8 +2529,7 @@ public class DecimalFormat extends NumberFormat {
if
(
negativeSuffixFieldPositions
==
null
)
{
if
(
negSuffixPattern
!=
null
)
{
negativeSuffixFieldPositions
=
expandAffix
(
negSuffixPattern
);
}
else
{
}
else
{
negativeSuffixFieldPositions
=
EmptyFieldPositionArray
;
}
}
...
...
@@ -1834,6 +2563,16 @@ public class DecimalFormat extends NumberFormat {
multiplier
=
newValue
;
bigDecimalMultiplier
=
null
;
bigIntegerMultiplier
=
null
;
fastPathCheckNeeded
=
true
;
}
/**
* {@inheritDoc}
*/
@Override
public
void
setGroupingUsed
(
boolean
newValue
)
{
super
.
setGroupingUsed
(
newValue
);
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1860,6 +2599,7 @@ public class DecimalFormat extends NumberFormat {
*/
public
void
setGroupingSize
(
int
newValue
)
{
groupingSize
=
(
byte
)
newValue
;
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1878,6 +2618,7 @@ public class DecimalFormat extends NumberFormat {
*/
public
void
setDecimalSeparatorAlwaysShown
(
boolean
newValue
)
{
decimalSeparatorAlwaysShown
=
newValue
;
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -1908,6 +2649,20 @@ public class DecimalFormat extends NumberFormat {
DecimalFormat
other
=
(
DecimalFormat
)
super
.
clone
();
other
.
symbols
=
(
DecimalFormatSymbols
)
symbols
.
clone
();
other
.
digitList
=
(
DigitList
)
digitList
.
clone
();
// Fast-path is almost stateless algorithm. The only logical state is the
// isFastPath flag. In addition fastPathCheckNeeded is a sentinel flag
// that forces recalculation of all fast-path fields when set to true.
//
// There is thus no need to clone all the fast-path fields.
// We just only need to set fastPathCheckNeeded to true when cloning,
// and init fastPathData to null as if it were a truly new instance.
// Every fast-path field will be recalculated (only once) at next usage of
// fast-path algorithm.
other
.
fastPathCheckNeeded
=
true
;
other
.
isFastPath
=
false
;
other
.
fastPathData
=
null
;
return
other
;
}
...
...
@@ -1917,8 +2672,10 @@ public class DecimalFormat extends NumberFormat {
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
obj
==
null
)
return
false
;
if
(!
super
.
equals
(
obj
))
return
false
;
// super does class check
if
(
obj
==
null
)
return
false
;
if
(!
super
.
equals
(
obj
))
return
false
;
// super does class check
DecimalFormat
other
=
(
DecimalFormat
)
obj
;
return
((
posPrefixPattern
==
other
.
posPrefixPattern
&&
positivePrefix
.
equals
(
other
.
positivePrefix
))
...
...
@@ -2206,8 +2963,7 @@ public class DecimalFormat extends NumberFormat {
||
affix
.
indexOf
(
symbols
.
getPatternSeparator
())
>=
0
||
affix
.
indexOf
(
symbols
.
getMinusSign
())
>=
0
||
affix
.
indexOf
(
CURRENCY_SIGN
)
>=
0
;
}
else
{
}
else
{
needQuote
=
affix
.
indexOf
(
PATTERN_ZERO_DIGIT
)
>=
0
||
affix
.
indexOf
(
PATTERN_GROUPING_SEPARATOR
)
>=
0
||
affix
.
indexOf
(
PATTERN_DECIMAL_SEPARATOR
)
>=
0
...
...
@@ -2694,6 +3450,7 @@ public class DecimalFormat extends NumberFormat {
super
.
setMinimumIntegerDigits
((
minimumIntegerDigits
>
DOUBLE_INTEGER_DIGITS
)
?
DOUBLE_INTEGER_DIGITS
:
minimumIntegerDigits
);
}
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -2714,6 +3471,7 @@ public class DecimalFormat extends NumberFormat {
super
.
setMaximumIntegerDigits
((
maximumIntegerDigits
>
DOUBLE_INTEGER_DIGITS
)
?
DOUBLE_INTEGER_DIGITS
:
maximumIntegerDigits
);
}
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -2734,6 +3492,7 @@ public class DecimalFormat extends NumberFormat {
super
.
setMinimumFractionDigits
((
minimumFractionDigits
>
DOUBLE_FRACTION_DIGITS
)
?
DOUBLE_FRACTION_DIGITS
:
minimumFractionDigits
);
}
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -2754,6 +3513,7 @@ public class DecimalFormat extends NumberFormat {
super
.
setMaximumFractionDigits
((
maximumFractionDigits
>
DOUBLE_FRACTION_DIGITS
)
?
DOUBLE_FRACTION_DIGITS
:
maximumFractionDigits
);
}
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -2843,6 +3603,7 @@ public class DecimalFormat extends NumberFormat {
expandAffixes
();
}
}
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -2873,6 +3634,7 @@ public class DecimalFormat extends NumberFormat {
this
.
roundingMode
=
roundingMode
;
digitList
.
setRoundingMode
(
roundingMode
);
fastPathCheckNeeded
=
true
;
}
/**
...
...
@@ -2924,6 +3686,12 @@ public class DecimalFormat extends NumberFormat {
stream
.
defaultReadObject
();
digitList
=
new
DigitList
();
// We force complete fast-path reinitialization when the instance is
// deserialized. See clone() comment on fastPathCheckNeeded.
fastPathCheckNeeded
=
true
;
isFastPath
=
false
;
fastPathData
=
null
;
if
(
serialVersionOnStream
<
4
)
{
setRoundingMode
(
RoundingMode
.
HALF_EVEN
);
}
...
...
@@ -3195,6 +3963,77 @@ public class DecimalFormat extends NumberFormat {
*/
private
RoundingMode
roundingMode
=
RoundingMode
.
HALF_EVEN
;
// ------ DecimalFormat fields for fast-path for double algorithm ------
/**
* Helper inner utility class for storing the data used in the fast-path
* algorithm. Almost all fields related to fast-path are encapsulated in
* this class.
*
* Any {@code DecimalFormat} instance has a {@code fastPathData}
* reference field that is null unless both the properties of the instance
* are such that the instance is in the "fast-path" state, and a format call
* has been done at least once while in this state.
*
* Almost all fields are related to the "fast-path" state only and don't
* change until one of the instance properties is changed.
*
* {@code firstUsedIndex} and {@code lastFreeIndex} are the only
* two fields that are used and modified while inside a call to
* {@code fastDoubleFormat}.
*
*/
private
static
class
FastPathData
{
// --- Temporary fields used in fast-path, shared by several methods.
/** The first unused index at the end of the formatted result. */
int
lastFreeIndex
;
/** The first used index at the beginning of the formatted result */
int
firstUsedIndex
;
// --- State fields related to fast-path status. Changes due to a
// property change only. Set by checkAndSetFastPathStatus() only.
/** Difference between locale zero and default zero representation. */
int
zeroDelta
;
/** Locale char for grouping separator. */
char
groupingChar
;
/** Fixed index position of last integral digit of formatted result */
int
integralLastIndex
;
/** Fixed index position of first fractional digit of formatted result */
int
fractionalFirstIndex
;
/** Fractional constants depending on decimal|currency state */
double
fractionalScaleFactor
;
int
fractionalMaxIntBound
;
/** The char array buffer that will contain the formatted result */
char
[]
fastPathContainer
;
/** Suffixes recorded as char array for efficiency. */
char
[]
charsPositivePrefix
;
char
[]
charsNegativePrefix
;
char
[]
charsPositiveSuffix
;
char
[]
charsNegativeSuffix
;
boolean
positiveAffixesRequired
=
true
;
boolean
negativeAffixesRequired
=
true
;
}
/** The format fast-path status of the instance. Logical state. */
private
transient
boolean
isFastPath
=
false
;
/** Flag stating need of check and reinit fast-path status on next format call. */
private
transient
boolean
fastPathCheckNeeded
=
true
;
/** DecimalFormat reference to its FastPathData */
private
transient
FastPathData
fastPathData
;
//----------------------------------------------------------------------
static
final
int
currentSerialVersion
=
4
;
...
...
@@ -3228,6 +4067,54 @@ public class DecimalFormat extends NumberFormat {
// CONSTANTS
//----------------------------------------------------------------------
// ------ Fast-Path for double Constants ------
/** Maximum valid integer value for applying fast-path algorithm */
private
static
final
double
MAX_INT_AS_DOUBLE
=
(
double
)
Integer
.
MAX_VALUE
;
/**
* The digit arrays used in the fast-path methods for collecting digits.
* Using 3 constants arrays of chars ensures a very fast collection of digits
*/
private
static
class
DigitArrays
{
static
final
char
[]
DigitOnes1000
=
new
char
[
1000
];
static
final
char
[]
DigitTens1000
=
new
char
[
1000
];
static
final
char
[]
DigitHundreds1000
=
new
char
[
1000
];
// initialize on demand holder class idiom for arrays of digits
static
{
int
tenIndex
=
0
;
int
hundredIndex
=
0
;
char
digitOne
=
'0'
;
char
digitTen
=
'0'
;
char
digitHundred
=
'0'
;
for
(
int
i
=
0
;
i
<
1000
;
i
++
)
{
DigitOnes1000
[
i
]
=
digitOne
;
if
(
digitOne
==
'9'
)
digitOne
=
'0'
;
else
digitOne
++;
DigitTens1000
[
i
]
=
digitTen
;
if
(
i
==
(
tenIndex
+
9
))
{
tenIndex
+=
10
;
if
(
digitTen
==
'9'
)
digitTen
=
'0'
;
else
digitTen
++;
}
DigitHundreds1000
[
i
]
=
digitHundred
;
if
(
i
==
(
hundredIndex
+
99
))
{
digitHundred
++;
hundredIndex
+=
100
;
}
}
}
}
// ------ Fast-Path for double Constants end ------
// Constants for characters used in programmatic (unlocalized) patterns.
private
static
final
char
PATTERN_ZERO_DIGIT
=
'0'
;
private
static
final
char
PATTERN_GROUPING_SEPARATOR
=
','
;
...
...
src/share/classes/java/text/NumberFormat.java
浏览文件 @
afc47100
/*
* Copyright (c) 1996, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
2
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
...
...
@@ -286,10 +286,21 @@ public abstract class NumberFormat extends Format {
* @see java.text.Format#format
*/
public
final
String
format
(
double
number
)
{
// Use fast-path for double result if that works
String
result
=
fastFormat
(
number
);
if
(
result
!=
null
)
return
result
;
return
format
(
number
,
new
StringBuffer
(),
DontCareFieldPosition
.
INSTANCE
).
toString
();
}
/*
* fastFormat() is supposed to be implemented in concrete subclasses only.
* Default implem always returns null.
*/
String
fastFormat
(
double
number
)
{
return
null
;
}
/**
* Specialization of format.
* @exception ArithmeticException if rounding is needed with rounding
...
...
test/java/text/Format/DecimalFormat/FormatMicroBenchmark.java
0 → 100644
浏览文件 @
afc47100
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7050528
* @summary Set of micro-benchmarks testing throughput of java.text.DecimalFormat.format()
* @author Olivier Lagneau
* @run main FormatMicroBenchmark
*/
/* This is a set of micro-benchmarks testing throughput of java.text.DecimalFormat.format().
* It never fails.
*
* Usage and arguments:
* - Run with no argument skips the whole benchmark and exits.
* - Run with "-help" as first argument calls the usage() method and exits.
* - Run with "-doit" runs the benchmark with summary details.
* - Run with "-verbose" provides additional details on the run.
*
* Example run :
* java -Xms500m -Xmx500m -XX:NewSize=400m FormatMicroBenchmark -doit -verbose
*
* Running with jtreg:
* The jtreg header "run" tag options+args must be changed to avoid skipping
* the execution. here is an example of run options:
* "main/othervm -Xms500m -Xmx500m -XX:NewSize=400m FormatMicroBenchmark -doit"
*
* Note:
* - Vm options -Xms, -Xmx, -XX:NewSize must be set correctly for
* getting reliable numbers. Otherwise GC activity may corrupt results.
* As of jdk80b48 using "-Xms500m -Xmx500m -XX:NewSize=400m" covers
* all cases.
* - Optionally using "-XX:+printGC" option provides information that
* helps checking any GC activity while benches are run.
*
* Vm Options:
* - Vm options to use (as of jdk80b48):
* fast-path case : -Xms128m -Xmx128m -XX:NewSize=100m
* non fast-path case: -Xms500m -Xmx500m -XX:NewSize=400m
* or use worst case (non fast-path above) with both types of algorithm.
*
* - use -XX:+PrintGC to verify memory consumption of the benchmarks.
* (See "Checking Memory Consumption" below).
*
* Description:
*
* Fast-path algorithm for format(double...) call stack is very different of
* the standard call stack. Where the standard algorithm for formating double
* uses internal class sun.misc.FloatingDecimal and its dtoa(double) method to
* provide digits, fast-path embeds its own algorithm for binary to decimal
* string conversion.
*
* FloatingDecimal always converts completely the passed double to a string.
* Fast-path converts only to the needed digits since it follows constraints
* on both the pattern rule, the DecimalFormat instance properties, and the
* passed double.
*
* Micro benchmarks below measure the throughput for formating double values
* using NumberFormat.format(double) call stack. The standard DecimalFormat
* call stack as well as the fast-path algorithm implementation are sensitive
* to the nature of the passed double values regarding throughput performance.
*
* These benchmarks are useful both for measuring the global performance gain
* of fast-path and to check that any modification done on fast-path algorithm
* does not bring any regression in the performance boost of fast-path.
*
* Note that these benchmarks will provide numbers without any knowledge of
* the implementation of DecimalFormat class. So to check regression any run
* should be compared to another reference run with a previous JDK, wether or
* not this previous reference JDK contains fast-path implementation.
*
* The eight benchmarks below are dedicated to measure throughput on different
* kinds of double that all fall in the fast-path case (all in Integer range):
*
* - Integer case : used double values are all "integer-like" (ex: -12345.0).
* This is the benchFormatInteger micro-benchmark.
*
* - Fractional case : double values are "fractional" (ex: -0.12345).
* This is the benchFormatFractional micro-benchmark.
*
* - Small integral case : like Integer case but double values are all limited
* in their magnitude, from -500.0 to 500.0 if the number of iterations N is
* set to 500000.
* This is the benchFormatSmallIntegral micro-benchmark.
*
* - Fractional All Nines : doubles values have fractional part that is very
* close to "999" (decimal pattern), or "99" (currency pattern),
* or "0000...".
* This is the benchFormatFractionalAllNines micro-benchmark.
*
* - All Nines : double values are such that both integral and fractional
* part consist only of '9' digits. None of these values are rounded up.
* This is the benchFormatAllNines micro-benchmark.
*
* - Fair simple case : calling J the loop variable and iterating over
* the N number of iterations, used double values are computed as
* d = (double) J + J*seed
* where seed is a very small value that adds a fractional part and adds a
* small number to integral part. Provides fairly distributed double values.
* This is the benchFormatFairSimple micro-benchmark.
*
* - Fair case : this is a combination of small integral case and fair simple
* case. Double values are limited in their magnitude but follow a parabolic
* curve y = x**2 / K, keeping large magnitude only for large values of J.
* The intent is trying to reproduce a distribution of double values as could
* be found in a business application, with most values in either the low
* range or the high range.
* This is the benchFormatFair micro-benchmark.
*
* - Tie cases: values are very close to a tie case (iii...ii.fff5)
* That is the worst situation that can happen for Fast-path algorithm when
* considering throughput.
* This is the benchFormatTie micro-benchmark.
*
* For all of the micro-benchmarks, the throughput load of the eventual
* additional computations inside the loop is calculated prior to running the
* benchmark, and provided in the output. That may be useful since this load
* may vary for each architecture or machine configuration.
*
* The "-verbose" flag, when set, provides the throughput load numbers, the
* time spent for each run of a benchmark, as well as an estimation of the
* memory consumed by the runs. Beware of incremental GCs, see "Checking
* Memory Consumption" section below. Every run should be done with correct
* ms, mx, and NewSize vm options to get fully reliable numbers.
*
* The output provides the mean time needed for a benchmark after the server
* jit compiler has done its optimization work if any. Thus only the last but
* first three runs are taken into account in the time measurement (server jit
* compiler shows to have done full optimization in most cases after the
* second run, given a base number of iterations set to 500000).
*
* The program cleans up memory (stabilizeMemory() method) between each run of
* the benchmarks to make sure that no garbage collection activity happens in
* measurements. However that does not preclude incremental GCs activity that
* may happen during the micro-benchmark if -Xms, -Xmx, and NewSize options
* have not been tuned and set correctly.
*
* Checking Memory Consumption:
*
* For getting confidence in the throughput numbers, there must not give any
* GC activity during the benchmark runs. That means that specific VM options
* related to memory must be tuned for any given implementation of the JDK.
*
* Running with "-verbose" arguments will provide clues of the memory consumed
* but is not enough, since any unexpected incremental GC may lower
* artificially the estimation of the memory consumption.
*
* Options to set are -Xms, -Xmx, -XX:NewSize, plus -XX:+PrintGC to evaluate
* correctly the values of these options. When running "-verbose", varying
* numbers reported for memory consumption may indicate bad choices for these
* options.
*
* For jdk80b25, fast-path shows a consuption of ~60Mbs for 500000 iterations
* while a jdk without fast-path will consume ~260Mbs for each benchmark run.
* Indeed these values will vary depending on the jdk used.
*
* Correct option settings found jdk80b48 were :
* fast-path : -Xms128m -Xmx128m -XX:NewSize=100m
* non fast-path : -Xms500m -Xmx500m -XX:NewSize=400m
* Greater values can be provided safely but not smaller ones.
* ----------------------------------------------------------------------
*/
import
java.util.*
;
import
java.text.NumberFormat
;
import
java.text.DecimalFormat
;
public
class
FormatMicroBenchmark
{
// The number of times the bench method will be run (must be at least 4).
private
static
final
int
NB_RUNS
=
20
;
// The bench* methods below all iterates over [-MAX_RANGE , +MAX_RANGE] integer values.
private
static
final
int
MAX_RANGE
=
500000
;
// Flag for more details on each bench run (default is no).
private
static
boolean
Verbose
=
false
;
// Should we really execute the benches ? (no by default).
private
static
boolean
DoIt
=
false
;
// Prints out a message describing how to run the program.
private
static
void
usage
()
{
System
.
out
.
println
(
"This is a set of micro-benchmarks testing throughput of "
+
"java.text.DecimalFormat.format(). It never fails.\n\n"
+
"Usage and arguments:\n"
+
" - Run with no argument skips the whole benchmark and exits.\n"
+
" - Run with \"-help\" as first argument prints this message and exits.\n"
+
" - Run with \"-doit\" runs the benchmark with summary details.\n"
+
" - Run with \"-verbose\" provides additional details on the run.\n\n"
+
"Example run :\n"
+
" java -Xms500m -Xmx500m -XX:NewSize=400m FormatMicroBenchmark -doit -verbose\n\n"
+
"Note: \n"
+
" - Vm options -Xms, -Xmx, -XX:NewSize must be set correctly for \n"
+
" getting reliable numbers. Otherwise GC activity may corrupt results.\n"
+
" As of jdk80b48 using \"-Xms500m -Xmx500m -XX:NewSize=400m\" covers \n"
+
" all cases.\n"
+
" - Optionally using \"-XX:+printGC\" option provides information that \n"
+
" helps checking any GC activity while benches are run.\n\n"
+
"Look at the heading comments and description in source code for "
+
"detailed information.\n"
);
}
/* We will call stabilizeMemory before each call of benchFormat***().
* This in turn tries to clean up as much memory as possible.
* As a safe bound we limit number of System.gc() calls to 10,
* but most of the time two calls to System.gc() will be enough.
* If memory reporting is asked for, the method returns the difference
* of free memory between entering an leaving the method.
*/
private
static
long
stabilizeMemory
(
boolean
reportConsumedMemory
)
{
final
long
oneMegabyte
=
1024L
*
1024L
;
long
refMemory
=
0
;
long
initialMemoryLeft
=
Runtime
.
getRuntime
().
freeMemory
();
long
currMemoryLeft
=
initialMemoryLeft
;
int
nbGCCalls
=
0
;
do
{
nbGCCalls
++;
refMemory
=
currMemoryLeft
;
System
.
gc
();
currMemoryLeft
=
Runtime
.
getRuntime
().
freeMemory
();
}
while
((
Math
.
abs
(
currMemoryLeft
-
refMemory
)
>
oneMegabyte
)
&&
(
nbGCCalls
<
10
));
if
(
Verbose
&&
reportConsumedMemory
)
System
.
out
.
println
(
"Memory consumed by previous run : "
+
(
currMemoryLeft
-
initialMemoryLeft
)/
oneMegabyte
+
"Mbs."
);
return
currMemoryLeft
;
}
// ---------- Integer only based bench --------------------
private
static
final
String
INTEGER_BENCH
=
"benchFormatInteger"
;
private
static
String
benchFormatInteger
(
NumberFormat
nf
)
{
String
str
=
""
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
str
=
nf
.
format
((
double
)
j
);
return
str
;
}
// This reproduces the throughput load added in benchFormatInteger
static
double
integerThroughputLoad
()
{
double
d
=
0.0d
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
(
double
)
j
;
}
return
d
;
}
// Runs integerThroughputLoad and calculate its mean load
static
void
calculateIntegerThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
integerThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
INTEGER_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// ---------- Fractional only based bench --------------------
private
static
final
String
FRACTIONAL_BENCH
=
"benchFormatFractional"
;
private
static
String
benchFormatFractional
(
NumberFormat
nf
)
{
String
str
=
""
;
double
floatingN
=
1.0d
/
(
double
)
MAX_RANGE
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
str
=
nf
.
format
(
floatingN
*
(
double
)
j
);
return
str
;
}
// This reproduces the throughput load added in benchFormatFractional
static
double
fractionalThroughputLoad
()
{
double
d
=
0.0d
;
double
floatingN
=
1.0d
/
(
double
)
MAX_RANGE
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
floatingN
*
(
double
)
j
;
}
return
d
;
}
// Runs fractionalThroughputLoad and calculate its mean load
static
void
calculateFractionalThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
fractionalThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
FRACTIONAL_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// ---------- An Small Integral bench --------------------
// that limits the magnitude of tested double values
private
static
final
String
SMALL_INTEGRAL_BENCH
=
"benchFormatSmallIntegral"
;
private
static
String
benchFormatSmallIntegral
(
NumberFormat
nf
)
{
String
str
=
""
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
str
=
nf
.
format
(((
double
)
j
)
/
1000.0d
);
return
str
;
}
// This reproduces the throughput load added in benchFormatSmallIntegral
static
double
smallIntegralThroughputLoad
()
{
double
d
=
0.0d
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
(
double
)
j
/
1000.0d
;
}
return
d
;
}
// Runs small_integralThroughputLoad and calculate its mean load
static
void
calculateSmallIntegralThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
smallIntegralThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
SMALL_INTEGRAL_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// ---------- A fair and simple bench --------------------
private
static
final
String
FAIR_SIMPLE_BENCH
=
"benchFormatFairSimple"
;
private
static
String
benchFormatFairSimple
(
NumberFormat
nf
,
boolean
isCurrency
)
{
String
str
=
""
;
double
seed
=
isCurrency
?
0.0010203040506070809
:
0.00010203040506070809
;
double
d
=
(
double
)
-
MAX_RANGE
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
d
+
1.0d
+
seed
;
str
=
nf
.
format
(
d
);
}
return
str
;
}
// This reproduces the throughput load added in benchFormatFairSimple
static
double
fairSimpleThroughputLoad
()
{
double
seed
=
0.00010203040506070809
;
double
delta
=
0.0d
;
double
d
=
(
double
)
-
MAX_RANGE
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
d
+
1.0d
+
seed
;
}
return
d
;
}
// Runs fairThroughputLoad and calculate its mean load
static
void
calculateFairSimpleThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
fairSimpleThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
FAIR_SIMPLE_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// ---------- Fractional part is only made of nines bench --------------
private
static
final
String
FRACTIONAL_ALL_NINES_BENCH
=
"benchFormatFractionalAllNines"
;
private
static
String
benchFormatFractionalAllNines
(
NumberFormat
nf
,
boolean
isCurrency
)
{
String
str
=
""
;
double
fractionalEven
=
isCurrency
?
0.993000001
:
0.99930000001
;
double
fractionalOdd
=
isCurrency
?
0.996000001
:
0.99960000001
;
double
fractional
;
double
d
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
if
((
j
&
1
)
==
0
)
fractional
=
fractionalEven
;
else
fractional
=
fractionalOdd
;
if
(
j
>=
0
)
d
=
(
double
)
j
+
fractional
;
else
d
=
(
double
)
j
-
fractional
;
str
=
nf
.
format
(
d
);
}
return
str
;
}
// This reproduces the throughput load added in benchFormatFractionalAllNines
static
double
fractionalAllNinesThroughputLoad
()
{
double
fractionalEven
=
0.99930000001
;
double
fractionalOdd
=
0.99960000001
;
double
fractional
;
double
d
=
0.0d
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
if
((
j
&
1
)
==
0
)
fractional
=
fractionalEven
;
else
fractional
=
fractionalOdd
;
if
(
j
>=
0
)
d
=
(
double
)
j
+
fractional
;
else
d
=
(
double
)
j
-
fractional
;
}
return
d
;
}
// Runs fractionalAllNinesThroughputLoad and calculate its mean load
static
void
calculateFractionalAllNinesThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
fractionalAllNinesThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
FRACTIONAL_ALL_NINES_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// ---------- Number is only made of nines bench --------------
private
static
final
String
ALL_NINES_BENCH
=
"benchFormatAllNines"
;
private
static
String
benchFormatAllNines
(
NumberFormat
nf
,
boolean
isCurrency
)
{
String
str
=
""
;
double
[]
decimaAllNines
=
{
9.9993
,
99.9993
,
999.9993
,
9999.9993
,
99999.9993
,
999999.9993
,
9999999.9993
,
99999999.9993
,
999999999.9993
};
double
[]
currencyAllNines
=
{
9.993
,
99.993
,
999.993
,
9999.993
,
99999.993
,
999999.993
,
9999999.993
,
99999999.993
,
999999999.993
};
double
[]
valuesArray
=
(
isCurrency
)
?
currencyAllNines
:
decimaAllNines
;
double
seed
=
1.0
/
(
double
)
MAX_RANGE
;
double
d
;
int
id
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
id
=
(
j
>=
0
)
?
j
%
9
:
-
j
%
9
;
if
((
j
&
1
)
==
0
)
d
=
valuesArray
[
id
]
+
id
*
seed
;
else
d
=
valuesArray
[
id
]
-
id
*
seed
;
str
=
nf
.
format
(
d
);
}
return
str
;
}
// This reproduces the throughput load added in benchFormatAllNines
static
double
allNinesThroughputLoad
()
{
double
[]
decimaAllNines
=
{
9.9993
,
99.9993
,
999.9993
,
9999.9993
,
99999.9993
,
999999.9993
,
9999999.9993
,
99999999.9993
,
999999999.9993
};
double
[]
valuesArray
=
decimaAllNines
;
double
seed
=
1.0
/
(
double
)
MAX_RANGE
;
double
d
=
0.0d
;
int
id
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
id
=
(
j
>=
0
)
?
j
%
9
:
-
j
%
9
;
if
((
j
&
1
)
==
0
)
d
=
valuesArray
[
id
]
+
id
*
seed
;
else
d
=
valuesArray
[
id
]
-
id
*
seed
;
}
return
d
;
}
// Runs allNinesThroughputLoad and calculate its mean load
static
void
calculateAllNinesThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
allNinesThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
ALL_NINES_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// --- A fair bench trying (hopefully) to reproduce business applicatons ---
/* benchFormatFair uses the following formula :
* y = F(x) = sign(x) * x**2 * ((1000/MAX_RANGE)**2).
*
* which converts in the loop as (if j is the loop index) :
* x = double(j)
* k = 1000.0d * double(MAX_RANGE)
* y = sign(j) * x**2 * k**2
*
* This is a flattened parabolic curve where only the j values
* in [-1000, 1000] will provide y results in [-1, +1] interval,
* and for abs(j) >= 1000 the result y will be greater than 1.
*
* The difference with benchFormatSmallIntegral is that since y results
* follow a parabolic curve the magnitude of y grows much more rapidly
* and closer to j values when abs(j) >= 1000:
* - for |j| < 1000, SmallIntegral(j) < 1.0 and fair(j) < 1.0
* - for j in [1000, 10000[
* SmallIntegral(j) is in [1, 10[
* Fair(j) is in [4, 400[
* - for j in [10000,100000[
* SmallIntegral(j) is in [10, 100[
* Fair(j) is in [400,40000[
* - for j in [100000,1000000[
* SmallIntegral(j) is in [100, 1000[
* Fair(j) is in [40000, 4000000[
*
* Since double values for j less than 100000 provide only 4 digits in the
* integral, values greater than 250000 provide at least 6 digits, and 500000
* computes to 1000000, the distribution is roughly half with less than 5
* digits and half with at least 6 digits in the integral part.
*
* Compared to FairSimple bench, this represents an application where 20% of
* the double values to format are less than 40000.0 absolute value.
*
* Fair(j) is close to the magnitude of j when j > 100000 and is hopefully
* more representative of what may be found in general in business apps.
* (assumption : there will be mainly either small or large values, and
* less values in middle range).
*
* We could get even more precise distribution of values using formula :
* y = sign(x) * abs(x)**n * ((1000 / MAX_RANGE)**n) where n > 2,
* or even well-known statistics function to fine target such distribution,
* but we have considred that the throughput load for calculating y would
* then be too high. We thus restrain the use of a power of 2 formula.
*/
private
static
final
String
FAIR_BENCH
=
"benchFormatFair"
;
private
static
String
benchFormatFair
(
NumberFormat
nf
)
{
String
str
=
""
;
double
k
=
1000.0d
/
(
double
)
MAX_RANGE
;
k
*=
k
;
double
d
;
double
absj
;
double
jPowerOf2
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
absj
=
(
double
)
j
;
jPowerOf2
=
absj
*
absj
;
d
=
k
*
jPowerOf2
;
if
(
j
<
0
)
d
=
-
d
;
str
=
nf
.
format
(
d
);
}
return
str
;
}
// This is the exact throughput load added in benchFormatFair
static
double
fairThroughputLoad
()
{
double
k
=
1000.0d
/
(
double
)
MAX_RANGE
;
k
*=
k
;
double
d
=
0.0d
;
double
absj
;
double
jPowerOf2
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
absj
=
(
double
)
j
;
jPowerOf2
=
absj
*
absj
;
d
=
k
*
jPowerOf2
;
if
(
j
<
0
)
d
=
-
d
;
}
return
d
;
}
// Runs fairThroughputLoad and calculate its mean load
static
void
calculateFairThroughputLoad
()
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
fairThroughputLoad
();
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
FAIR_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// ---------- All double values are very close to a tie --------------------
// i.e. like 123.1235 (for decimal case) or 123.125 (for currency case).
private
static
final
String
TIE_BENCH
=
"benchFormatTie"
;
private
static
String
benchFormatTie
(
NumberFormat
nf
,
boolean
isCurrency
)
{
double
d
;
String
str
=
""
;
double
fractionaScaling
=
(
isCurrency
)
?
1000.0d
:
10000.0d
;
int
fixedFractionalPart
=
(
isCurrency
)
?
125
:
1235
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
(((
double
)
j
*
fractionaScaling
)
+
(
double
)
fixedFractionalPart
)
/
fractionaScaling
;
str
=
nf
.
format
(
d
);
}
return
str
;
}
// This is the exact throughput load added in benchFormatTie
static
double
tieThroughputLoad
(
boolean
isCurrency
)
{
double
d
=
0.0d
;
double
fractionaScaling
=
(
isCurrency
)
?
1000.0d
:
10000.0d
;
int
fixedFractionalPart
=
(
isCurrency
)
?
125
:
1235
;
for
(
int
j
=
-
MAX_RANGE
;
j
<=
MAX_RANGE
;
j
++)
{
d
=
(((
double
)
j
*
fractionaScaling
)
+
(
double
)
fixedFractionalPart
)
/
fractionaScaling
;
}
return
d
;
}
// Runs tieThroughputLoad and calculate its mean load
static
void
calculateTieThroughputLoad
(
boolean
isCurrency
)
{
int
nbRuns
=
NB_RUNS
;
long
elapsedTime
=
0
;
double
foo
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
long
startTime
=
System
.
nanoTime
();
foo
=
tieThroughputLoad
(
isCurrency
);
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTime
+=
estimatedTime
/
1000
;
}
if
(
Verbose
)
System
.
out
.
println
(
"calculated throughput load for "
+
TIE_BENCH
+
" bench is = "
+
(
elapsedTime
/
(
nbRuns
-
3
))
+
" microseconds"
);
}
// Print statistics for passed times results of benchName.
static
void
printPerfResults
(
long
[]
times
,
String
benchName
)
{
int
nbBenches
=
times
.
length
;
long
totalTimeSpent
=
0
;
long
meanTimeSpent
;
double
variance
=
0
;
double
standardDeviation
=
0
;
// Calculates mean spent time
for
(
int
i
=
1
;
i
<=
nbBenches
;
i
++)
totalTimeSpent
+=
times
[
i
-
1
];
meanTimeSpent
=
totalTimeSpent
/
nbBenches
;
// Calculates standard deviation
for
(
int
j
=
1
;
j
<=
nbBenches
;
j
++)
variance
+=
Math
.
pow
(((
double
)
times
[
j
-
1
]
-
(
double
)
meanTimeSpent
),
2
);
variance
=
variance
/
(
double
)
times
.
length
;
standardDeviation
=
Math
.
sqrt
(
variance
)
/
meanTimeSpent
;
// Print result and statistics for benchName
System
.
out
.
println
(
"Statistics (starting at 4th bench) for bench "
+
benchName
+
"\n for last "
+
nbBenches
+
" runs out of "
+
NB_RUNS
+
" , each with 2x"
+
MAX_RANGE
+
" format(double) calls : "
+
"\n mean exec time = "
+
meanTimeSpent
+
" microseconds"
+
"\n standard deviation = "
+
String
.
format
(
"%.3f"
,
standardDeviation
)
+
"% \n"
);
}
public
static
void
main
(
String
[]
args
)
{
if
(
args
.
length
>=
1
)
{
// Parse args, just checks expected ones. Ignore others or dups.
if
(
args
[
0
].
equals
(
"-help"
))
{
usage
();
return
;
}
for
(
String
s
:
args
)
{
if
(
s
.
equals
(
"-doit"
))
DoIt
=
true
;
else
if
(
s
.
equals
(
"-verbose"
))
Verbose
=
true
;
}
}
else
{
// No arguments, skips the benchmarks and exits.
System
.
out
.
println
(
"Test skipped with success by default. See -help for details."
);
return
;
}
if
(!
DoIt
)
{
if
(
Verbose
)
usage
();
System
.
out
.
println
(
"Test skipped and considered successful."
);
return
;
}
System
.
out
.
println
(
"Single Threaded micro benchmark evaluating "
+
"the throughput of java.text.DecimalFormat.format() call stack.\n"
);
String
fooString
=
""
;
// Run benches for decimal instance
DecimalFormat
df
=
(
DecimalFormat
)
NumberFormat
.
getInstance
(
Locale
.
US
);
System
.
out
.
println
(
"Running with a decimal instance of DecimalFormat."
);
calculateIntegerThroughputLoad
();
fooString
=
BenchType
.
INTEGER_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateFractionalThroughputLoad
();
fooString
=
BenchType
.
FRACTIONAL_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateSmallIntegralThroughputLoad
();
fooString
=
BenchType
.
SMALL_INTEGRAL_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateFractionalAllNinesThroughputLoad
();
fooString
=
BenchType
.
FRACTIONAL_ALL_NINES_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateAllNinesThroughputLoad
();
fooString
=
BenchType
.
ALL_NINES_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateFairSimpleThroughputLoad
();
fooString
=
BenchType
.
FAIR_SIMPLE_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateFairThroughputLoad
();
fooString
=
BenchType
.
FAIR_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
calculateTieThroughputLoad
(
false
);
fooString
=
BenchType
.
TIE_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
df
,
false
);
// Run benches for currency instance
DecimalFormat
cf
=
(
DecimalFormat
)
NumberFormat
.
getCurrencyInstance
(
Locale
.
US
);
System
.
out
.
println
(
"Running with a currency instance of DecimalFormat."
);
calculateIntegerThroughputLoad
();
fooString
=
BenchType
.
INTEGER_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateFractionalThroughputLoad
();
fooString
=
BenchType
.
FRACTIONAL_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateSmallIntegralThroughputLoad
();
fooString
=
BenchType
.
SMALL_INTEGRAL_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateFractionalAllNinesThroughputLoad
();
fooString
=
BenchType
.
FRACTIONAL_ALL_NINES_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateAllNinesThroughputLoad
();
fooString
=
BenchType
.
ALL_NINES_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateFairSimpleThroughputLoad
();
fooString
=
BenchType
.
FAIR_SIMPLE_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateFairThroughputLoad
();
fooString
=
BenchType
.
FAIR_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
calculateTieThroughputLoad
(
false
);
fooString
=
BenchType
.
TIE_BENCH
.
runBenchAndPrintStatistics
(
NB_RUNS
,
cf
,
false
);
}
// This class to factorise what would be duplicated otherwise.
static
enum
BenchType
{
INTEGER_BENCH
(
"benchFormatInteger"
),
FRACTIONAL_BENCH
(
"benchFormatFractional"
),
SMALL_INTEGRAL_BENCH
(
"benchFormatSmallIntegral"
),
FAIR_SIMPLE_BENCH
(
"benchFormatFairSimple"
),
FRACTIONAL_ALL_NINES_BENCH
(
"benchFormatFractionalAllNines"
),
ALL_NINES_BENCH
(
"benchFormatAllNines"
),
FAIR_BENCH
(
"benchFormatFair"
),
TIE_BENCH
(
"benchFormatTie"
);
private
final
String
name
;
BenchType
(
String
name
)
{
this
.
name
=
name
;
}
String
runBenchAndPrintStatistics
(
int
nbRuns
,
NumberFormat
nf
,
boolean
isCurrency
)
{
// We eliminate the first 3 runs in the time measurements
// to let C2 do complete compilation and optimization work.
long
[]
elapsedTimes
=
new
long
[
nbRuns
-
3
];
System
.
out
.
println
(
"Now running "
+
nbRuns
+
" times bench "
+
name
);
String
str
=
""
;
for
(
int
i
=
1
;
i
<=
nbRuns
;
i
++)
{
stabilizeMemory
(
false
);
long
startTime
=
System
.
nanoTime
();
switch
(
this
)
{
case
INTEGER_BENCH
:
str
=
benchFormatInteger
(
nf
);
break
;
case
FRACTIONAL_BENCH
:
str
=
benchFormatFractional
(
nf
);
break
;
case
SMALL_INTEGRAL_BENCH
:
str
=
benchFormatSmallIntegral
(
nf
);
break
;
case
FRACTIONAL_ALL_NINES_BENCH
:
str
=
benchFormatFractionalAllNines
(
nf
,
isCurrency
);
break
;
case
ALL_NINES_BENCH
:
str
=
benchFormatAllNines
(
nf
,
isCurrency
);
break
;
case
FAIR_SIMPLE_BENCH
:
str
=
benchFormatFairSimple
(
nf
,
isCurrency
);
break
;
case
FAIR_BENCH
:
str
=
benchFormatFair
(
nf
);
break
;
case
TIE_BENCH
:
str
=
benchFormatTie
(
nf
,
isCurrency
);
break
;
default
:
}
long
estimatedTime
=
System
.
nanoTime
()
-
startTime
;
if
(
i
>
3
)
elapsedTimes
[
i
-
4
]
=
estimatedTime
/
1000
;
if
(
Verbose
)
System
.
out
.
println
(
"calculated time for "
+
name
+
" bench "
+
i
+
" is = "
+
(
estimatedTime
/
1000
)
+
" microseconds"
);
else
System
.
out
.
print
(
"."
);
stabilizeMemory
(
true
);
}
System
.
out
.
println
(
name
+
" Done."
);
printPerfResults
(
elapsedTimes
,
name
);
return
str
;
}
}
}
test/java/text/Format/DecimalFormat/GoldenDoubleValues.java
0 → 100644
浏览文件 @
afc47100
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* Set of constants and values used in RoundingAndPropertyTest.java.
*
* There are 5 different information in this class:
* - TestLocale is the locale used by RoundingAndPropertyTest regression test
* when calling DecimalFormat.format() on either the set of DecimalGoldenValues
* or CurrencyGoldenValues.
* See main method of RoundingAndPropertyTest.
*
* - FullLocalizationTestLocale is the locale used by RoundingAndPropertyTest
* regression test when calling DecimalFormat.format() on the set of values
* (DecimalLocalizationValues) used to test that localization of digits
* happens correctly when needed.
* See main method of RoundingAndPropertyTest.
*
* - DecimalLocalizationValues is an array containing all the double values used
* to check that localization of digits happens correctly when needed.
* See RoundingAndPropertyTest.testLocalizationValues() method.
*
* - DecimalGoldenValues and CurrencyGoldenValues are arrays containing all the
* double values that will be used as input when checking correctness of
* results returned by DecimalFormat.format().
* 2 arrays are needed since decimal and currency formatting patterns require
* a different number of digits after decimal point.
* See RoundingAndPropertyTest.testGoldenValues() method.
*
* - PROPERTY_CHECK_POSITIVE_VALUE and PROPERTY_CHECK_NEGATIVE_VALUE are the
* double values used for testing the validity of the property changes call
* in the fast-path case. The locale used in that case is TestLocale.
* See RoundingAndPropertyTest.testSettersAndFastPath() method.
*/
import
java.util.*
;
class
GoldenDoubleValues
{
// TestLocale is the testing locale used by RoundingAndPropertyTest test,
// when testing the golden double values
static
final
Locale
TestLocale
=
new
Locale
(
"en"
,
"US"
);
// FullTestLocale is the testing locale used by RoundingAndPropertyTest test,
// when testing full localization of double values.
static
final
Locale
FullLocalizationTestLocale
=
new
Locale
(
"hi"
,
"IN"
);
/* Below are the two double values used for exercising the changes of
* of DecimalFormat properties and symbols. These values are also used
* as golden values (see golden arrays below).
*/
/* PROPERTY_CHECK_NEGATIVE_VALUE is the negative double value used for
* testing the validity of the property changes for fast-path.
* See testSettersAndFastPath() in RoundingAndPropertyTest test.
*/
static
final
double
PROPERTY_CHECK_NEGATIVE_VALUE
=
-
2147483646.2334997d
;
/* PROPERTY_CHECK_POSITIVE_VALUE is the positive double value used for
* testing the validity of the property changes for fast-path.
* See testSettersAndFastPath() in RoundingAndPropertyTest test.
*/
static
final
double
PROPERTY_CHECK_POSITIVE_VALUE
=
2147483646.2335003d
;
/* --- Array of double values to test localization ------------------------
*
* For most locales, effective localization does not happen on digits, i.e.
* the digits are not changed due to localization. In order to check that
* fast-path localize correctly digits in such a case, the array of double
* values below deals with all the case of localization that may happen on
* digits
*/
static
final
double
[]
DecimalLocalizationValues
=
{
1.123
,
12.123
,
123.123
,
1234.123
,
12345.123
,
123456.123
,
1234567.123
,
12345678.123
,
123456789.123
,
1234567890.123
,
1234.0
,
1234.9
,
1234.99
,
1234.999
};
/* --- Arrays of golden double values ----------------------------------
*
* The GoldenValues arrays are used as input values for checking the
* correctness of the DecimalFormat.format() call results done in
* RoundingAndPropertyTest regression test. The results are compared to the
* expected ones found in GoldenFormattedValues. For each value in the
* arrays there is a corresponding expected string result found,
* represented as an array of unicode values, at the same index in the
* related GoldenFormattedValues array. The string returned by the format
* call and the found in GoldenFormattedValues array must be equal for the
* result to be considered valid.
* See RoundingAndPropertyTest.testGoldenValues() method.
*
* We need 2 such GoldenValues arrays since the decimal and currency
* formatting rules require different number of digits after decimal point.
*
* Thus we have two different arrays of golden values:
* - DecimalGoldenValues for the decimal case.
* - CurrencyGoldenValues for the currency case.
*
* They are associated to related GoldenFormattedValues arrays, generated by
* running RoundingAndPropertyTest with a "gengold" argument:
* - DecimalGoldenFormattedValues for the decimal case.
* - CurrencyGoldenFormattedValues for the currency case.
* These two generated arrays are found in GoldenFormattedValues.java file.
*
* The impact of the formatting rules is as follows, because the pattern
* rule for the fractional part is different for decimal and currency
* patterns:
* - in decimal case one must output the first non-zero 3 digits of
* fractional part 1.1232 => "1.123" and 1.12016789 => "1.12"
* - in currency case the first 2 fractional digits are always output
* 1.1232 => "1.12" and 1.0016789 => "1.00"
*
* Thus we need a different number of fractional digits when we specify
* below the golden double values to check, and most of the decimal and
* currency golden values differ only in the number of fractional digits.
*
* The list below exercises almost all code pathes of the fast-path
* algorithm except localization of digits.
*/
// --- The set of golden values for the Decimal formatting case --------
static
final
double
[]
DecimalGoldenValues
=
{
// Testing of specific values
+
0.0
,
-
0.0
,
Double
.
MIN_VALUE
,
Double
.
MIN_NORMAL
,
PROPERTY_CHECK_NEGATIVE_VALUE
,
PROPERTY_CHECK_POSITIVE_VALUE
,
-
2147483647.9996
,
2147483647.9996
,
-
1999999999.9994997
,
1999999999.9995003
,
// Testing fast-path range checks (all outside bounds)
Double
.
NaN
,
Double
.
POSITIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
MAX_VALUE
,
-
9876543210.9876543
,
9876543210.9876543
,
-
1234567890.1234567E128
,
1234567890.1234567E128
,
// Testing of integral string size
1.123
,
12.123
,
123.123
,
1234.123
,
12345.123
,
123456.123
,
1234567.123
,
12345678.123
,
123456789.123
,
1234567890.123
,
-
1.123
,
-
12.123
,
-
123.123
,
-
1234.123
,
-
12345.123
,
-
123456.123
,
-
1234567.123
,
-
12345678.123
,
-
123456789.123
,
-
1234567890.123
,
// Testing of fractional string size
0.1
,
0.12
,
0.123
,
0.1234
,
10.1
,
10.12
,
10.123
,
10.1234
,
100.1
,
100.12
,
100.123
,
100.1234
,
1000.1
,
1000.12
,
1000.123
,
1000.1234
,
10000.1
,
10000.12
,
10000.123
,
10000.1234
,
100000.1
,
100000.12
,
100000.123
,
100000.1234
,
1000000.1
,
1000000.12
,
1000000.123
,
1000000.1234
,
10000000.1
,
10000000.12
,
10000000.123
,
10000000.1234
,
100000000.1
,
100000000.12
,
100000000.123
,
100000000.1234
,
1000000000.1
,
1000000000.12
,
1000000000.123
,
1000000000.1234
,
-
0.1
,
-
0.12
,
-
0.123
,
-
0.1234
,
-
10.1
,
-
10.12
,
-
10.123
,
-
10.1234
,
-
100.1
,
-
100.12
,
-
100.123
,
-
100.1234
,
-
1000.1
,
-
1000.12
,
-
1000.123
,
-
1000.1234
,
-
10000.1
,
-
10000.12
,
-
10000.123
,
-
10000.1234
,
-
100000.1
,
-
100000.12
,
-
100000.123
,
-
100000.1234
,
-
1000000.1
,
-
1000000.12
,
-
1000000.123
,
-
1000000.1234
,
-
10000000.1
,
-
10000000.12
,
-
10000000.123
,
-
10000000.1234
,
-
100000000.1
,
-
100000000.12
,
-
100000000.123
,
-
100000000.1234
,
-
1000000000.1
,
-
1000000000.12
,
-
1000000000.123
,
-
1000000000.1234
,
// Testing of special rounding cases
1.9993
,
12.9993
,
123.9993
,
1234.9993
,
12345.9993
,
123456.9993
,
1234567.9993
,
12345678.9993
,
123456789.9993
,
1234567890.9993
,
1.9996
,
12.9996
,
123.9996
,
1234.9996
,
12345.9996
,
123456.9996
,
1234567.9996
,
12345678.9996
,
123456789.9996
,
1234567890.9996
,
-
1.9993
,
-
12.9993
,
-
123.9993
,
-
1234.9993
,
-
12345.9993
,
-
123456.9993
,
-
1234567.9993
,
-
12345678.9993
,
-
123456789.9993
,
-
1234567890.9993
,
-
1.9996
,
-
12.9996
,
-
123.9996
,
-
1234.9996
,
-
12345.9996
,
-
123456.9996
,
-
1234567.9996
,
-
12345678.9996
,
-
123456789.9996
,
-
1234567890.9996
,
109.9996
,
1099.9996
,
10999.9996
,
109999.9996
,
1099999.9996
,
10999999.9996
,
109999999.9996
,
1099999999.9996
,
-
109.9996
,
-
1099.9996
,
-
10999.9996
,
-
109999.9996
,
-
1099999.9996
,
-
10999999.9996
,
-
109999999.9996
,
-
1099999999.9996
,
1.9996
,
19.9996
,
199.9996
,
1999.9996
,
19999.9996
,
199999.9996
,
1999999.9996
,
19999999.9996
,
199999999.9996
,
1999999999.9996
,
-
1.9996
,
-
19.9996
,
-
199.9996
,
-
1999.9996
,
-
19999.9996
,
-
199999.9996
,
-
1999999.9996
,
-
19999999.9996
,
-
199999999.9996
,
-
1999999999.9996
,
// Testing for all nines cases
9.9996
,
99.9996
,
999.9996
,
9999.9996
,
99999.9996
,
999999.9996
,
9999999.9996
,
99999999.9996
,
999999999.9996
,
9.999
,
99.999
,
999.999
,
9999.999
,
99999.999
,
999999.999
,
9999999.999
,
99999999.999
,
999999999.999
,
-
9.9996
,
-
99.9996
,
-
999.9996
,
-
9999.9996
,
-
99999.9996
,
-
999999.9996
,
-
9999999.9996
,
-
99999999.9996
,
-
999999999.9996
,
-
9.999
,
-
99.999
,
-
999.999
,
-
9999.999
,
-
99999.999
,
-
999999.999
,
-
9999999.999
,
-
99999999.999
,
-
999999999.999
,
// Testing for no Fractional part cases
1.0
,
12.0
,
123.0
,
1234.0
,
12345.0
,
123456.0
,
1234567.0
,
12345678.0
,
123456789.0
,
1234567890.0
,
-
1.0
,
-
12.0
,
-
123.0
,
-
1234.0
,
-
12345.0
,
-
123456.0
,
-
1234567.0
,
-
12345678.0
,
-
123456789.0
,
-
1234567890.0
,
// Testing of tricky cases
-
2599.399999990123
,
-
2599.339999990123
,
-
2599.333999990123
,
1.000099999999818
,
1.000199999999818
,
1.000299999999818
,
1.000399999999818
,
1.000499999999818
,
1.000599999999818
,
1.000699999999818
,
1.000799999999818
,
1.000899999999818
,
1.000999999999818
,
1.2224999999999980
,
1.2224999999999981
,
1.2224999999999982
,
1.2224999999999983
,
1.2224999999999984
,
1.2224999999999985
,
1.2224999999999986
,
1.2224999999999987
,
1.2224999999999988
,
1.2224999999999989
,
1.2224999999999990
,
1.2224999999999991
,
1.2224999999999992
,
1.2224999999999993
,
1.2224999999999994
,
1.2224999999999995
,
1.2224999999999996
,
1.2224999999999997
,
1.2224999999999998
,
// 1.2225 and 1.2224999999999999 have the same double approximation
1.2225
,
1.2225000000000001
,
1.2225000000000002
,
1.2225000000000003
,
1.2225000000000004
,
1.2225000000000005
,
1.2225000000000006
,
1.2225000000000007
,
1.2225000000000008
,
1.2225000000000009
,
1.2225000000000010
,
1.2225000000000011
,
1.2225000000000012
,
1.2225000000000013
,
1.2225000000000014
,
1.2225000000000015
,
1.2225000000000016
,
1.2225000000000017
,
1.2225000000000018
,
1.2225000000000019
,
// Tricky rounding cases around tie values
100913.67050000005
,
199999.99895901306
,
251846.3465
,
253243.8825000001
,
365045.85349999997
,
314734.9615
,
541133.9755
,
858372.1225
,
1000999.9995000001
,
1347505.7825
,
3358844.1975
,
9997979.4085
,
9993743.1585
,
9938671.9085
,
3385302.5465
,
3404642.6605
,
3431280.0865
,
3438756.4754999997
,
3446053.7874999996
,
3457917.5125
,
3465393.9014999997
,
3484734.0154999997
,
3492031.3274999997
,
3503895.0525
,
3511371.4414999997
,
3518668.7534999996
,
3530532.4785
,
3538008.8674999997
,
3545306.1794999996
,
3557169.9045
,
3557348.9814999998
,
3564646.2934999997
,
3583986.4074999997
,
3591283.7194999997
,
3603147.4445
,
3610623.8334999997
,
3617921.1454999996
,
3629784.8705
,
3637261.2594999997
,
3656422.2965
,
3656601.3734999998
,
3663898.6854999997
,
3675762.4105
,
3683238.7994999997
,
3690536.1114999996
,
3702399.8365
,
3709876.2254999997
,
3717173.5374999996
,
3729037.2625
,
3736513.6514999997
,
3755853.7654999997
,
3763151.0774999997
,
3775014.8025
,
3782491.1914999997
,
3789788.5034999996
,
3801652.2285
,
3809128.6174999997
,
3816425.9294999996
,
3828289.6545
,
3828468.7314999998
,
3835766.0434999997
,
3855106.1574999997
,
3862403.4694999997
,
3874267.1945
,
3881743.5834999997
,
3889040.8954999996
,
3900904.6205
,
3908381.0094999997
,
3927542.0465
,
3927721.1234999998
,
3935018.4354999997
,
3946882.1605
,
3954358.5494999997
,
3961655.8614999996
,
3973519.5865
,
3980995.9754999997
,
3988293.2874999996
,
4000157.0125
,
4007633.4014999997
,
4026973.5154999997
,
4034270.8274999997
,
4046134.5525
,
4053610.9414999997
,
4060908.2534999996
,
4072771.9785
,
4080248.3674999997
,
4087545.6794999996
,
4099409.4045
,
4099588.4814999998
,
4106885.7934999997
,
4126225.9074999997
,
4133523.2194999997
,
4145386.9445
,
4152863.3334999997
,
4160160.6454999996
,
4172024.3705
,
4179500.7594999997
,
4198661.7965
,
4203407.2865
,
4210704.5985
,
4213435.4975
};
// --- The set of golden values for the currency formatting case --------
static
final
double
[]
CurrencyGoldenValues
=
{
// Testing of specific values
+
0.0
,
-
0.0
,
Double
.
MIN_VALUE
,
Double
.
MIN_NORMAL
,
PROPERTY_CHECK_NEGATIVE_VALUE
,
PROPERTY_CHECK_POSITIVE_VALUE
,
-
2147483647.996
,
2147483647.996
,
-
1999999999.9949997
,
1999999999.9950003
,
// Testing fast-path range checks (all outside bounds)
Double
.
NaN
,
Double
.
POSITIVE_INFINITY
,
Double
.
NEGATIVE_INFINITY
,
Double
.
MAX_VALUE
,
-
9876543210.9876543
,
9876543210.9876543
,
-
1234567890.1234567E128
,
1234567890.1234567E128
,
// Testing of integral string size
1.12
,
12.12
,
123.12
,
1234.12
,
12345.12
,
123456.12
,
1234567.12
,
12345678.12
,
123456789.12
,
1234567890.12
,
-
1.12
,
-
12.12
,
-
123.12
,
-
1234.12
,
-
12345.12
,
-
123456.12
,
-
1234567.12
,
-
12345678.12
,
-
123456789.12
,
-
1234567890.12
,
// Testing of fractional string size
0.1
,
0.12
,
0.123
,
10.1
,
10.12
,
10.123
,
100.1
,
100.12
,
100.123
,
1000.1
,
1000.12
,
1000.123
,
10000.1
,
10000.12
,
10000.123
,
100000.1
,
100000.12
,
100000.123
,
1000000.1
,
1000000.12
,
1000000.123
,
10000000.1
,
10000000.12
,
10000000.123
,
100000000.1
,
100000000.12
,
100000000.123
,
1000000000.1
,
1000000000.12
,
1000000000.123
,
-
0.1
,
-
0.12
,
-
0.123
,
-
10.1
,
-
10.12
,
-
10.123
,
-
100.1
,
-
100.12
,
-
100.123
,
-
1000.1
,
-
1000.12
,
-
1000.123
,
-
10000.1
,
-
10000.12
,
-
10000.123
,
-
100000.1
,
-
100000.12
,
-
100000.123
,
-
1000000.1
,
-
1000000.12
,
-
1000000.123
,
-
10000000.1
,
-
10000000.12
,
-
10000000.123
,
-
100000000.1
,
-
100000000.12
,
-
100000000.123
,
-
1000000000.1
,
-
1000000000.12
,
-
1000000000.123
,
// Testing of special rounding cases
1.993
,
12.993
,
123.993
,
1234.993
,
12345.993
,
123456.993
,
1234567.993
,
12345678.993
,
123456789.993
,
1234567890.993
,
1.996
,
12.996
,
123.996
,
1234.996
,
12345.996
,
123456.996
,
1234567.996
,
12345678.996
,
123456789.996
,
1234567890.996
,
-
1.993
,
-
12.993
,
-
123.993
,
-
1234.993
,
-
12345.993
,
-
123456.993
,
-
1234567.993
,
-
12345678.993
,
-
123456789.993
,
-
1234567890.993
,
-
1.996
,
-
12.996
,
-
123.996
,
-
1234.996
,
-
12345.996
,
-
123456.996
,
-
1234567.996
,
-
12345678.996
,
-
123456789.996
,
-
1234567890.996
,
109.996
,
1099.996
,
10999.996
,
109999.996
,
1099999.996
,
10999999.996
,
109999999.996
,
1099999999.996
,
-
109.996
,
-
1099.996
,
-
10999.996
,
-
109999.996
,
-
1099999.996
,
-
10999999.996
,
-
109999999.996
,
-
1099999999.996
,
1.996
,
19.996
,
199.996
,
1999.996
,
19999.996
,
199999.996
,
1999999.996
,
19999999.996
,
199999999.996
,
1999999999.996
,
-
1.996
,
-
19.996
,
-
199.996
,
-
1999.996
,
-
19999.996
,
-
199999.996
,
-
1999999.996
,
-
19999999.996
,
-
199999999.996
,
-
1999999999.996
,
// Testing of all nines cases
9.996
,
99.996
,
999.996
,
9999.996
,
99999.996
,
999999.996
,
9999999.996
,
99999999.996
,
999999999.996
,
9.99
,
99.99
,
999.99
,
9999.99
,
99999.99
,
999999.99
,
9999999.99
,
99999999.99
,
999999999.99
,
-
9.996
,
-
99.996
,
-
999.996
,
-
9999.996
,
-
99999.996
,
-
999999.996
,
-
9999999.996
,
-
99999999.996
,
-
999999999.996
,
-
9.99
,
-
99.99
,
-
999.99
,
-
9999.99
,
-
99999.99
,
-
999999.99
,
-
9999999.99
,
-
99999999.99
,
-
999999999.99
,
// Testing of no Fractional part cases
1.0
,
12.0
,
123.0
,
1234.0
,
12345.0
,
123456.0
,
1234567.0
,
12345678.0
,
123456789.0
,
1234567890.0
,
-
1.0
,
-
12.0
,
-
123.0
,
-
1234.0
,
-
12345.0
,
-
123456.0
,
-
1234567.0
,
-
12345678.0
,
-
123456789.0
,
-
1234567890.0
,
// Testing of tricky cases
-
2599.399999990123
,
-
2599.339999990123
,
-
2599.333999990123
,
1.000999999999818
,
1.001999999999818
,
1.002999999999818
,
1.003999999999818
,
1.004999999999818
,
1.005999999999818
,
1.006999999999818
,
1.007999999999818
,
1.008999999999818
,
1.009999999999818
,
1.224999999999980
,
1.224999999999981
,
1.224999999999982
,
1.224999999999983
,
1.224999999999984
,
1.224999999999985
,
1.224999999999986
,
1.224999999999987
,
1.224999999999988
,
1.224999999999989
,
1.224999999999990
,
1.224999999999991
,
1.224999999999992
,
1.224999999999993
,
1.224999999999994
,
1.224999999999995
,
1.224999999999996
,
1.224999999999997
,
1.224999999999998
,
1.224999999999999
,
1.225
,
1.225000000000001
,
1.225000000000002
,
1.225000000000003
,
1.225000000000004
,
1.225000000000005
,
1.225000000000006
,
1.225000000000007
,
1.225000000000008
,
1.225000000000009
,
1.225000000000010
,
1.225000000000011
,
1.225000000000012
,
1.225000000000013
,
1.225000000000014
,
1.225000000000015
,
1.225000000000016
,
1.225000000000017
,
1.225000000000018
,
1.225000000000019
,
// Tricky rounding cases around tie values
1009136.7050000005
,
2518463.465
,
2532438.825000001
,
3650458.5349999997
,
3147349.615
,
5411339.755
,
8583721.225
,
13475057.825
,
33588441.975
,
99979794.085
,
99937431.585
,
99386719.085
,
33853025.465
,
34046426.605
,
34312800.865
,
34387564.754999997
,
34460537.874999996
,
34579175.125
,
34653939.014999997
,
34847340.154999997
,
34920313.274999997
,
35038950.525
,
35113714.414999997
,
35186687.534999996
,
35305324.785
,
35380088.674999997
,
35453061.794999996
,
35571699.045
,
35573489.814999998
,
35646462.934999997
,
35839864.074999997
,
35912837.194999997
,
36031474.445
,
36106238.334999997
,
36179211.454999996
,
36297848.705
,
36372612.594999997
,
36564222.965
,
36566013.734999998
,
36638986.854999997
,
36757624.105
,
36832387.994999997
,
36905361.114999996
,
37023998.365
,
37098762.254999997
,
37171735.374999996
,
37290372.625
,
37365136.514999997
,
37558537.654999997
,
37631510.774999997
,
37750148.025
,
37824911.914999997
,
37897885.034999996
,
38016522.285
,
38091286.174999997
,
38164259.294999996
,
38282896.545
,
38284687.314999998
,
38357660.434999997
,
38551061.574999997
,
38624034.694999997
,
38742671.945
,
38817435.834999997
,
38890408.954999996
,
39009046.205
,
39083810.094999997
,
39275420.465
,
39277211.234999998
,
39350184.354999997
,
39468821.605
,
39543585.494999997
,
39616558.614999996
,
39735195.865
,
39809959.754999997
,
39882932.874999996
,
40001570.125
,
40076334.014999997
,
40269735.154999997
,
40342708.274999997
,
40461345.525
,
40536109.414999997
,
40609082.534999996
,
40727719.785
,
40802483.674999997
,
40875456.794999996
,
40994094.045
,
40995884.814999998
,
41068857.934999997
,
41262259.074999997
,
41335232.194999997
,
41453869.445
,
41528633.334999997
,
41601606.454999996
,
41720243.705
,
41795007.594999997
,
41986617.965
,
42034072.865
,
42107045.985
,
42134354.975
};
}
test/java/text/Format/DecimalFormat/GoldenFormattedValues.java
0 → 100644
浏览文件 @
afc47100
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* This is a machine generated file - Please DO NOT EDIT !
* Change RoundingAndPropertyTest instead,
* and run with "-gengold" argument to regenerate (without copyright header).
*/
/* This file contains the set of result Strings expected from calling inside
* RoundingAndPropertyTest the method NumberFormat.format() upon the set of
* double values provided in GoldenDoubleValues.java. It contains three arrays,
* each containing arrays of unicode values representing the expected string
* result when calling format() on the corresponding (i.e. same index) double
* value found in GoldenDoubleValues arrays :
* - DecimalDigitsLocalizedFormattedValues corresponds to DecimalLocalizationValues,
* when using FullLocalizationTestLocale to format.
* - DecimalGoldenFormattedValues corresponds to DecimalGoldenValues, when used
* in the decimal pattern case together with TestLocale.
* - CurrencyGoldenFormattedValues corresponds to CurrencyGoldenValues. when used
* in the currency pattern case together with TestLocale.
* Please see documentation in RoundingAndPropertyTest.java for more details.
*
* This file generated by running RoundingAndPropertyTest with "-gengold" argument.
*/
class
GoldenFormattedValues
{
// The formatted values below were generated from golden values
// listed in GoldenDoubleValues.java, using the following jvm version :
// Oracle Corporation Java HotSpot(TM) Server VM 1.8.0-ea
// locale for golden double values : en_US
// locale for testing digit localization : hi_IN
// The array of int[] unicode values storing the expected results
// when experiencing full localization of digits on DecimalLocalizationValues.
static
int
[][]
DecimalDigitsLocalizedFormattedValues
=
{
{
2407
,
46
,
2407
,
2408
,
2409
},
{
2407
,
2408
,
46
,
2407
,
2408
,
2409
},
{
2407
,
2408
,
2409
,
46
,
2407
,
2408
,
2409
},
{
2407
,
44
,
2408
,
2409
,
2410
,
46
,
2407
,
2408
,
2409
},
{
2407
,
2408
,
44
,
2409
,
2410
,
2411
,
46
,
2407
,
2408
,
2409
},
{
2407
,
2408
,
2409
,
44
,
2410
,
2411
,
2412
,
46
,
2407
,
2408
,
2409
},
{
2407
,
44
,
2408
,
2409
,
2410
,
44
,
2411
,
2412
,
2413
,
46
,
2407
,
2408
,
2409
},
{
2407
,
2408
,
44
,
2409
,
2410
,
2411
,
44
,
2412
,
2413
,
2414
,
46
,
2407
,
2408
,
2409
},
{
2407
,
2408
,
2409
,
44
,
2410
,
2411
,
2412
,
44
,
2413
,
2414
,
2415
,
46
,
2407
,
2408
,
2409
},
{
2407
,
44
,
2408
,
2409
,
2410
,
44
,
2411
,
2412
,
2413
,
44
,
2414
,
2415
,
2406
,
46
,
2407
,
2408
,
2409
},
{
2407
,
44
,
2408
,
2409
,
2410
},
{
2407
,
44
,
2408
,
2409
,
2410
,
46
,
2415
},
{
2407
,
44
,
2408
,
2409
,
2410
,
46
,
2415
,
2415
},
{
2407
,
44
,
2408
,
2409
,
2410
,
46
,
2415
,
2415
,
2415
},
};
// The array of int[] unicode values storing the expected results
// when calling Decimal.format(double) on the decimal GoldenDoubleValues.
static
int
[][]
DecimalGoldenFormattedValues
=
{
{
48
},
{
45
,
48
},
{
48
},
{
48
},
{
45
,
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
54
,
46
,
50
,
51
,
51
},
{
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
54
,
46
,
50
,
51
,
52
},
{
45
,
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
56
},
{
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
56
},
{
45
,
49
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
65533
},
{
8734
},
{
45
,
8734
},
{
49
,
55
,
57
,
44
,
55
,
54
,
57
,
44
,
51
,
49
,
51
,
44
,
52
,
56
,
54
,
44
,
50
,
51
,
49
,
44
,
53
,
55
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
57
,
44
,
56
,
55
,
54
,
44
,
53
,
52
,
51
,
44
,
50
,
49
,
48
,
46
,
57
,
56
,
56
},
{
57
,
44
,
56
,
55
,
54
,
44
,
53
,
52
,
51
,
44
,
50
,
49
,
48
,
46
,
57
,
56
,
56
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
44
,
48
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
44
,
48
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
46
,
49
,
50
,
51
},
{
49
,
50
,
46
,
49
,
50
,
51
},
{
49
,
50
,
51
,
46
,
49
,
50
,
51
},
{
49
,
44
,
50
,
51
,
52
,
46
,
49
,
50
,
51
},
{
49
,
50
,
44
,
51
,
52
,
53
,
46
,
49
,
50
,
51
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
49
,
50
,
51
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
49
,
50
,
51
},
{
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
49
,
50
,
51
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
49
,
50
,
51
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
46
,
49
,
50
,
51
},
{
45
,
49
,
50
,
46
,
49
,
50
,
51
},
{
45
,
49
,
50
,
51
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
50
,
51
,
52
,
46
,
49
,
50
,
51
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
49
,
50
,
51
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
49
,
50
,
51
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
49
,
50
,
51
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
49
,
50
,
51
},
{
48
,
46
,
49
},
{
48
,
46
,
49
,
50
},
{
48
,
46
,
49
,
50
,
51
},
{
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
46
,
49
},
{
49
,
48
,
46
,
49
,
50
},
{
49
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
48
,
46
,
49
},
{
49
,
48
,
48
,
46
,
49
,
50
},
{
49
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
48
,
46
,
49
},
{
45
,
48
,
46
,
49
,
50
},
{
45
,
48
,
46
,
49
,
50
,
51
},
{
45
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
46
,
49
},
{
45
,
49
,
48
,
46
,
49
,
50
},
{
45
,
49
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
48
,
46
,
49
},
{
45
,
49
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
51
},
{
49
,
46
,
57
,
57
,
57
},
{
49
,
50
,
46
,
57
,
57
,
57
},
{
49
,
50
,
51
,
46
,
57
,
57
,
57
},
{
49
,
44
,
50
,
51
,
52
,
46
,
57
,
57
,
57
},
{
49
,
50
,
44
,
51
,
52
,
53
,
46
,
57
,
57
,
57
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
57
,
57
,
57
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
57
,
57
,
57
},
{
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
57
,
57
,
57
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
57
,
57
,
57
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
57
,
57
,
57
},
{
50
},
{
49
,
51
},
{
49
,
50
,
52
},
{
49
,
44
,
50
,
51
,
53
},
{
49
,
50
,
44
,
51
,
52
,
54
},
{
49
,
50
,
51
,
44
,
52
,
53
,
55
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
56
},
{
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
57
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
57
,
48
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
49
},
{
45
,
49
,
46
,
57
,
57
,
57
},
{
45
,
49
,
50
,
46
,
57
,
57
,
57
},
{
45
,
49
,
50
,
51
,
46
,
57
,
57
,
57
},
{
45
,
49
,
44
,
50
,
51
,
52
,
46
,
57
,
57
,
57
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
57
,
57
,
57
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
57
,
57
,
57
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
57
,
57
,
57
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
57
,
57
,
57
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
57
,
57
,
57
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
57
,
57
,
57
},
{
45
,
50
},
{
45
,
49
,
51
},
{
45
,
49
,
50
,
52
},
{
45
,
49
,
44
,
50
,
51
,
53
},
{
45
,
49
,
50
,
44
,
51
,
52
,
54
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
55
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
56
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
57
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
57
,
48
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
49
},
{
49
,
49
,
48
},
{
49
,
44
,
49
,
48
,
48
},
{
49
,
49
,
44
,
48
,
48
,
48
},
{
49
,
49
,
48
,
44
,
48
,
48
,
48
},
{
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
49
,
48
},
{
45
,
49
,
44
,
49
,
48
,
48
},
{
45
,
49
,
49
,
44
,
48
,
48
,
48
},
{
45
,
49
,
49
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
50
},
{
50
,
48
},
{
50
,
48
,
48
},
{
50
,
44
,
48
,
48
,
48
},
{
50
,
48
,
44
,
48
,
48
,
48
},
{
50
,
48
,
48
,
44
,
48
,
48
,
48
},
{
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
50
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
50
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
50
},
{
45
,
50
,
48
},
{
45
,
50
,
48
,
48
},
{
45
,
50
,
44
,
48
,
48
,
48
},
{
45
,
50
,
48
,
44
,
48
,
48
,
48
},
{
45
,
50
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
50
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
50
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
48
},
{
49
,
48
,
48
},
{
49
,
44
,
48
,
48
,
48
},
{
49
,
48
,
44
,
48
,
48
,
48
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
57
,
46
,
57
,
57
,
57
},
{
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
57
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
49
,
48
},
{
45
,
49
,
48
,
48
},
{
45
,
49
,
44
,
48
,
48
,
48
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
},
{
45
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
45
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
49
},
{
49
,
50
},
{
49
,
50
,
51
},
{
49
,
44
,
50
,
51
,
52
},
{
49
,
50
,
44
,
51
,
52
,
53
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
},
{
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
},
{
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
},
{
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
},
{
45
,
49
},
{
45
,
49
,
50
},
{
45
,
49
,
50
,
51
},
{
45
,
49
,
44
,
50
,
51
,
52
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
},
{
45
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
},
{
45
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
},
{
45
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
},
{
45
,
50
,
44
,
53
,
57
,
57
,
46
,
52
},
{
45
,
50
,
44
,
53
,
57
,
57
,
46
,
51
,
52
},
{
45
,
50
,
44
,
53
,
57
,
57
,
46
,
51
,
51
,
52
},
{
49
},
{
49
},
{
49
},
{
49
},
{
49
},
{
49
,
46
,
48
,
48
,
49
},
{
49
,
46
,
48
,
48
,
49
},
{
49
,
46
,
48
,
48
,
49
},
{
49
,
46
,
48
,
48
,
49
},
{
49
,
46
,
48
,
48
,
49
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
50
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
46
,
50
,
50
,
51
},
{
49
,
48
,
48
,
44
,
57
,
49
,
51
,
46
,
54
,
55
,
49
},
{
49
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
57
},
{
50
,
53
,
49
,
44
,
56
,
52
,
54
,
46
,
51
,
52
,
55
},
{
50
,
53
,
51
,
44
,
50
,
52
,
51
,
46
,
56
,
56
,
51
},
{
51
,
54
,
53
,
44
,
48
,
52
,
53
,
46
,
56
,
53
,
51
},
{
51
,
49
,
52
,
44
,
55
,
51
,
52
,
46
,
57
,
54
,
49
},
{
53
,
52
,
49
,
44
,
49
,
51
,
51
,
46
,
57
,
55
,
53
},
{
56
,
53
,
56
,
44
,
51
,
55
,
50
,
46
,
49
,
50
,
51
},
{
49
,
44
,
48
,
48
,
49
,
44
,
48
,
48
,
48
},
{
49
,
44
,
51
,
52
,
55
,
44
,
53
,
48
,
53
,
46
,
55
,
56
,
50
},
{
51
,
44
,
51
,
53
,
56
,
44
,
56
,
52
,
52
,
46
,
49
,
57
,
55
},
{
57
,
44
,
57
,
57
,
55
,
44
,
57
,
55
,
57
,
46
,
52
,
48
,
57
},
{
57
,
44
,
57
,
57
,
51
,
44
,
55
,
52
,
51
,
46
,
49
,
53
,
57
},
{
57
,
44
,
57
,
51
,
56
,
44
,
54
,
55
,
49
,
46
,
57
,
48
,
57
},
{
51
,
44
,
51
,
56
,
53
,
44
,
51
,
48
,
50
,
46
,
53
,
52
,
55
},
{
51
,
44
,
52
,
48
,
52
,
44
,
54
,
52
,
50
,
46
,
54
,
54
,
49
},
{
51
,
44
,
52
,
51
,
49
,
44
,
50
,
56
,
48
,
46
,
48
,
56
,
55
},
{
51
,
44
,
52
,
51
,
56
,
44
,
55
,
53
,
54
,
46
,
52
,
55
,
53
},
{
51
,
44
,
52
,
52
,
54
,
44
,
48
,
53
,
51
,
46
,
55
,
56
,
55
},
{
51
,
44
,
52
,
53
,
55
,
44
,
57
,
49
,
55
,
46
,
53
,
49
,
51
},
{
51
,
44
,
52
,
54
,
53
,
44
,
51
,
57
,
51
,
46
,
57
,
48
,
49
},
{
51
,
44
,
52
,
56
,
52
,
44
,
55
,
51
,
52
,
46
,
48
,
49
,
53
},
{
51
,
44
,
52
,
57
,
50
,
44
,
48
,
51
,
49
,
46
,
51
,
50
,
55
},
{
51
,
44
,
53
,
48
,
51
,
44
,
56
,
57
,
53
,
46
,
48
,
53
,
51
},
{
51
,
44
,
53
,
49
,
49
,
44
,
51
,
55
,
49
,
46
,
52
,
52
,
49
},
{
51
,
44
,
53
,
49
,
56
,
44
,
54
,
54
,
56
,
46
,
55
,
53
,
51
},
{
51
,
44
,
53
,
51
,
48
,
44
,
53
,
51
,
50
,
46
,
52
,
55
,
57
},
{
51
,
44
,
53
,
51
,
56
,
44
,
48
,
48
,
56
,
46
,
56
,
54
,
55
},
{
51
,
44
,
53
,
52
,
53
,
44
,
51
,
48
,
54
,
46
,
49
,
55
,
57
},
{
51
,
44
,
53
,
53
,
55
,
44
,
49
,
54
,
57
,
46
,
57
,
48
,
53
},
{
51
,
44
,
53
,
53
,
55
,
44
,
51
,
52
,
56
,
46
,
57
,
56
,
49
},
{
51
,
44
,
53
,
54
,
52
,
44
,
54
,
52
,
54
,
46
,
50
,
57
,
51
},
{
51
,
44
,
53
,
56
,
51
,
44
,
57
,
56
,
54
,
46
,
52
,
48
,
55
},
{
51
,
44
,
53
,
57
,
49
,
44
,
50
,
56
,
51
,
46
,
55
,
49
,
57
},
{
51
,
44
,
54
,
48
,
51
,
44
,
49
,
52
,
55
,
46
,
52
,
52
,
53
},
{
51
,
44
,
54
,
49
,
48
,
44
,
54
,
50
,
51
,
46
,
56
,
51
,
51
},
{
51
,
44
,
54
,
49
,
55
,
44
,
57
,
50
,
49
,
46
,
49
,
52
,
53
},
{
51
,
44
,
54
,
50
,
57
,
44
,
55
,
56
,
52
,
46
,
56
,
55
,
49
},
{
51
,
44
,
54
,
51
,
55
,
44
,
50
,
54
,
49
,
46
,
50
,
53
,
57
},
{
51
,
44
,
54
,
53
,
54
,
44
,
52
,
50
,
50
,
46
,
50
,
57
,
55
},
{
51
,
44
,
54
,
53
,
54
,
44
,
54
,
48
,
49
,
46
,
51
,
55
,
51
},
{
51
,
44
,
54
,
54
,
51
,
44
,
56
,
57
,
56
,
46
,
54
,
56
,
53
},
{
51
,
44
,
54
,
55
,
53
,
44
,
55
,
54
,
50
,
46
,
52
,
49
,
49
},
{
51
,
44
,
54
,
56
,
51
,
44
,
50
,
51
,
56
,
46
,
55
,
57
,
57
},
{
51
,
44
,
54
,
57
,
48
,
44
,
53
,
51
,
54
,
46
,
49
,
49
,
49
},
{
51
,
44
,
55
,
48
,
50
,
44
,
51
,
57
,
57
,
46
,
56
,
51
,
55
},
{
51
,
44
,
55
,
48
,
57
,
44
,
56
,
55
,
54
,
46
,
50
,
50
,
53
},
{
51
,
44
,
55
,
49
,
55
,
44
,
49
,
55
,
51
,
46
,
53
,
51
,
55
},
{
51
,
44
,
55
,
50
,
57
,
44
,
48
,
51
,
55
,
46
,
50
,
54
,
51
},
{
51
,
44
,
55
,
51
,
54
,
44
,
53
,
49
,
51
,
46
,
54
,
53
,
49
},
{
51
,
44
,
55
,
53
,
53
,
44
,
56
,
53
,
51
,
46
,
55
,
54
,
53
},
{
51
,
44
,
55
,
54
,
51
,
44
,
49
,
53
,
49
,
46
,
48
,
55
,
55
},
{
51
,
44
,
55
,
55
,
53
,
44
,
48
,
49
,
52
,
46
,
56
,
48
,
51
},
{
51
,
44
,
55
,
56
,
50
,
44
,
52
,
57
,
49
,
46
,
49
,
57
,
49
},
{
51
,
44
,
55
,
56
,
57
,
44
,
55
,
56
,
56
,
46
,
53
,
48
,
51
},
{
51
,
44
,
56
,
48
,
49
,
44
,
54
,
53
,
50
,
46
,
50
,
50
,
57
},
{
51
,
44
,
56
,
48
,
57
,
44
,
49
,
50
,
56
,
46
,
54
,
49
,
55
},
{
51
,
44
,
56
,
49
,
54
,
44
,
52
,
50
,
53
,
46
,
57
,
50
,
57
},
{
51
,
44
,
56
,
50
,
56
,
44
,
50
,
56
,
57
,
46
,
54
,
53
,
53
},
{
51
,
44
,
56
,
50
,
56
,
44
,
52
,
54
,
56
,
46
,
55
,
51
,
49
},
{
51
,
44
,
56
,
51
,
53
,
44
,
55
,
54
,
54
,
46
,
48
,
52
,
51
},
{
51
,
44
,
56
,
53
,
53
,
44
,
49
,
48
,
54
,
46
,
49
,
53
,
55
},
{
51
,
44
,
56
,
54
,
50
,
44
,
52
,
48
,
51
,
46
,
52
,
54
,
57
},
{
51
,
44
,
56
,
55
,
52
,
44
,
50
,
54
,
55
,
46
,
49
,
57
,
53
},
{
51
,
44
,
56
,
56
,
49
,
44
,
55
,
52
,
51
,
46
,
53
,
56
,
51
},
{
51
,
44
,
56
,
56
,
57
,
44
,
48
,
52
,
48
,
46
,
56
,
57
,
53
},
{
51
,
44
,
57
,
48
,
48
,
44
,
57
,
48
,
52
,
46
,
54
,
50
,
49
},
{
51
,
44
,
57
,
48
,
56
,
44
,
51
,
56
,
49
,
46
,
48
,
48
,
57
},
{
51
,
44
,
57
,
50
,
55
,
44
,
53
,
52
,
50
,
46
,
48
,
52
,
55
},
{
51
,
44
,
57
,
50
,
55
,
44
,
55
,
50
,
49
,
46
,
49
,
50
,
51
},
{
51
,
44
,
57
,
51
,
53
,
44
,
48
,
49
,
56
,
46
,
52
,
51
,
53
},
{
51
,
44
,
57
,
52
,
54
,
44
,
56
,
56
,
50
,
46
,
49
,
54
,
49
},
{
51
,
44
,
57
,
53
,
52
,
44
,
51
,
53
,
56
,
46
,
53
,
52
,
57
},
{
51
,
44
,
57
,
54
,
49
,
44
,
54
,
53
,
53
,
46
,
56
,
54
,
49
},
{
51
,
44
,
57
,
55
,
51
,
44
,
53
,
49
,
57
,
46
,
53
,
56
,
55
},
{
51
,
44
,
57
,
56
,
48
,
44
,
57
,
57
,
53
,
46
,
57
,
55
,
53
},
{
51
,
44
,
57
,
56
,
56
,
44
,
50
,
57
,
51
,
46
,
50
,
56
,
55
},
{
52
,
44
,
48
,
48
,
48
,
44
,
49
,
53
,
55
,
46
,
48
,
49
,
51
},
{
52
,
44
,
48
,
48
,
55
,
44
,
54
,
51
,
51
,
46
,
52
,
48
,
49
},
{
52
,
44
,
48
,
50
,
54
,
44
,
57
,
55
,
51
,
46
,
53
,
49
,
53
},
{
52
,
44
,
48
,
51
,
52
,
44
,
50
,
55
,
48
,
46
,
56
,
50
,
55
},
{
52
,
44
,
48
,
52
,
54
,
44
,
49
,
51
,
52
,
46
,
53
,
53
,
51
},
{
52
,
44
,
48
,
53
,
51
,
44
,
54
,
49
,
48
,
46
,
57
,
52
,
49
},
{
52
,
44
,
48
,
54
,
48
,
44
,
57
,
48
,
56
,
46
,
50
,
53
,
51
},
{
52
,
44
,
48
,
55
,
50
,
44
,
55
,
55
,
49
,
46
,
57
,
55
,
57
},
{
52
,
44
,
48
,
56
,
48
,
44
,
50
,
52
,
56
,
46
,
51
,
54
,
55
},
{
52
,
44
,
48
,
56
,
55
,
44
,
53
,
52
,
53
,
46
,
54
,
55
,
57
},
{
52
,
44
,
48
,
57
,
57
,
44
,
52
,
48
,
57
,
46
,
52
,
48
,
53
},
{
52
,
44
,
48
,
57
,
57
,
44
,
53
,
56
,
56
,
46
,
52
,
56
,
49
},
{
52
,
44
,
49
,
48
,
54
,
44
,
56
,
56
,
53
,
46
,
55
,
57
,
51
},
{
52
,
44
,
49
,
50
,
54
,
44
,
50
,
50
,
53
,
46
,
57
,
48
,
55
},
{
52
,
44
,
49
,
51
,
51
,
44
,
53
,
50
,
51
,
46
,
50
,
49
,
57
},
{
52
,
44
,
49
,
52
,
53
,
44
,
51
,
56
,
54
,
46
,
57
,
52
,
53
},
{
52
,
44
,
49
,
53
,
50
,
44
,
56
,
54
,
51
,
46
,
51
,
51
,
51
},
{
52
,
44
,
49
,
54
,
48
,
44
,
49
,
54
,
48
,
46
,
54
,
52
,
53
},
{
52
,
44
,
49
,
55
,
50
,
44
,
48
,
50
,
52
,
46
,
51
,
55
,
49
},
{
52
,
44
,
49
,
55
,
57
,
44
,
53
,
48
,
48
,
46
,
55
,
53
,
57
},
{
52
,
44
,
49
,
57
,
56
,
44
,
54
,
54
,
49
,
46
,
55
,
57
,
55
},
{
52
,
44
,
50
,
48
,
51
,
44
,
52
,
48
,
55
,
46
,
50
,
56
,
55
},
{
52
,
44
,
50
,
49
,
48
,
44
,
55
,
48
,
52
,
46
,
53
,
57
,
57
},
{
52
,
44
,
50
,
49
,
51
,
44
,
52
,
51
,
53
,
46
,
52
,
57
,
55
},
};
// The array of int[] unicode values storing the expected results
// when calling Decimal.format(double) on the currency GoldenDoubleValues.
static
int
[][]
CurrencyGoldenFormattedValues
=
{
{
36
,
48
,
46
,
48
,
48
},
{
40
,
36
,
48
,
46
,
48
,
48
,
41
},
{
36
,
48
,
46
,
48
,
48
},
{
36
,
48
,
46
,
48
,
48
},
{
40
,
36
,
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
54
,
46
,
50
,
51
,
41
},
{
36
,
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
54
,
46
,
50
,
51
},
{
40
,
36
,
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
56
,
46
,
48
,
48
,
41
},
{
36
,
50
,
44
,
49
,
52
,
55
,
44
,
52
,
56
,
51
,
44
,
54
,
52
,
56
,
46
,
48
,
48
},
{
40
,
36
,
49
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
36
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
65533
},
{
36
,
8734
},
{
40
,
36
,
8734
,
41
},
{
36
,
49
,
55
,
57
,
44
,
55
,
54
,
57
,
44
,
51
,
49
,
51
,
44
,
52
,
56
,
54
,
44
,
50
,
51
,
49
,
44
,
53
,
55
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
40
,
36
,
57
,
44
,
56
,
55
,
54
,
44
,
53
,
52
,
51
,
44
,
50
,
49
,
48
,
46
,
57
,
57
,
41
},
{
36
,
57
,
44
,
56
,
55
,
54
,
44
,
53
,
52
,
51
,
44
,
50
,
49
,
48
,
46
,
57
,
57
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
44
,
48
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
44
,
48
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
46
,
49
,
50
},
{
36
,
49
,
50
,
46
,
49
,
50
},
{
36
,
49
,
50
,
51
,
46
,
49
,
50
},
{
36
,
49
,
44
,
50
,
51
,
52
,
46
,
49
,
50
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
49
,
50
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
49
,
50
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
49
,
50
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
49
,
50
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
49
,
50
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
49
,
50
},
{
40
,
36
,
49
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
50
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
50
,
51
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
49
,
50
,
41
},
{
36
,
48
,
46
,
49
,
48
},
{
36
,
48
,
46
,
49
,
50
},
{
36
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
46
,
49
,
48
},
{
36
,
49
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
},
{
40
,
36
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
48
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
49
,
50
,
41
},
{
36
,
49
,
46
,
57
,
57
},
{
36
,
49
,
50
,
46
,
57
,
57
},
{
36
,
49
,
50
,
51
,
46
,
57
,
57
},
{
36
,
49
,
44
,
50
,
51
,
52
,
46
,
57
,
57
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
57
,
57
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
57
,
57
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
57
,
57
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
57
,
57
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
57
,
57
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
57
,
57
},
{
36
,
50
,
46
,
48
,
48
},
{
36
,
49
,
51
,
46
,
48
,
48
},
{
36
,
49
,
50
,
52
,
46
,
48
,
48
},
{
36
,
49
,
44
,
50
,
51
,
53
,
46
,
48
,
48
},
{
36
,
49
,
50
,
44
,
51
,
52
,
54
,
46
,
48
,
48
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
55
,
46
,
48
,
48
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
56
,
46
,
48
,
48
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
57
,
46
,
48
,
48
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
57
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
49
,
46
,
48
,
48
},
{
40
,
36
,
49
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
50
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
50
,
51
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
57
,
57
,
41
},
{
40
,
36
,
50
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
51
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
52
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
53
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
54
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
55
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
56
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
57
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
57
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
49
,
46
,
48
,
48
,
41
},
{
36
,
49
,
49
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
49
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
49
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
40
,
36
,
49
,
49
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
49
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
49
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
36
,
50
,
46
,
48
,
48
},
{
36
,
50
,
48
,
46
,
48
,
48
},
{
36
,
50
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
40
,
36
,
50
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
36
,
49
,
48
,
46
,
48
,
48
},
{
36
,
49
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
},
{
36
,
57
,
46
,
57
,
57
},
{
36
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
},
{
36
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
},
{
40
,
36
,
49
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
44
,
48
,
48
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
40
,
36
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
44
,
57
,
57
,
57
,
46
,
57
,
57
,
41
},
{
36
,
49
,
46
,
48
,
48
},
{
36
,
49
,
50
,
46
,
48
,
48
},
{
36
,
49
,
50
,
51
,
46
,
48
,
48
},
{
36
,
49
,
44
,
50
,
51
,
52
,
46
,
48
,
48
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
48
,
48
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
48
,
48
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
48
,
48
},
{
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
48
,
48
},
{
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
48
,
48
},
{
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
48
,
48
},
{
40
,
36
,
49
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
51
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
44
,
51
,
52
,
53
,
44
,
54
,
55
,
56
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
50
,
51
,
44
,
52
,
53
,
54
,
44
,
55
,
56
,
57
,
46
,
48
,
48
,
41
},
{
40
,
36
,
49
,
44
,
50
,
51
,
52
,
44
,
53
,
54
,
55
,
44
,
56
,
57
,
48
,
46
,
48
,
48
,
41
},
{
40
,
36
,
50
,
44
,
53
,
57
,
57
,
46
,
52
,
48
,
41
},
{
40
,
36
,
50
,
44
,
53
,
57
,
57
,
46
,
51
,
52
,
41
},
{
40
,
36
,
50
,
44
,
53
,
57
,
57
,
46
,
51
,
51
,
41
},
{
36
,
49
,
46
,
48
,
48
},
{
36
,
49
,
46
,
48
,
48
},
{
36
,
49
,
46
,
48
,
48
},
{
36
,
49
,
46
,
48
,
48
},
{
36
,
49
,
46
,
48
,
48
},
{
36
,
49
,
46
,
48
,
49
},
{
36
,
49
,
46
,
48
,
49
},
{
36
,
49
,
46
,
48
,
49
},
{
36
,
49
,
46
,
48
,
49
},
{
36
,
49
,
46
,
48
,
49
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
50
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
46
,
50
,
51
},
{
36
,
49
,
44
,
48
,
48
,
57
,
44
,
49
,
51
,
54
,
46
,
55
,
49
},
{
36
,
50
,
44
,
53
,
49
,
56
,
44
,
52
,
54
,
51
,
46
,
52
,
54
},
{
36
,
50
,
44
,
53
,
51
,
50
,
44
,
52
,
51
,
56
,
46
,
56
,
51
},
{
36
,
51
,
44
,
54
,
53
,
48
,
44
,
52
,
53
,
56
,
46
,
53
,
51
},
{
36
,
51
,
44
,
49
,
52
,
55
,
44
,
51
,
52
,
57
,
46
,
54
,
50
},
{
36
,
53
,
44
,
52
,
49
,
49
,
44
,
51
,
51
,
57
,
46
,
55
,
53
},
{
36
,
56
,
44
,
53
,
56
,
51
,
44
,
55
,
50
,
49
,
46
,
50
,
50
},
{
36
,
49
,
51
,
44
,
52
,
55
,
53
,
44
,
48
,
53
,
55
,
46
,
56
,
50
},
{
36
,
51
,
51
,
44
,
53
,
56
,
56
,
44
,
52
,
52
,
49
,
46
,
57
,
56
},
{
36
,
57
,
57
,
44
,
57
,
55
,
57
,
44
,
55
,
57
,
52
,
46
,
48
,
56
},
{
36
,
57
,
57
,
44
,
57
,
51
,
55
,
44
,
52
,
51
,
49
,
46
,
53
,
56
},
{
36
,
57
,
57
,
44
,
51
,
56
,
54
,
44
,
55
,
49
,
57
,
46
,
48
,
56
},
{
36
,
51
,
51
,
44
,
56
,
53
,
51
,
44
,
48
,
50
,
53
,
46
,
52
,
55
},
{
36
,
51
,
52
,
44
,
48
,
52
,
54
,
44
,
52
,
50
,
54
,
46
,
54
,
48
},
{
36
,
51
,
52
,
44
,
51
,
49
,
50
,
44
,
56
,
48
,
48
,
46
,
56
,
55
},
{
36
,
51
,
52
,
44
,
51
,
56
,
55
,
44
,
53
,
54
,
52
,
46
,
55
,
53
},
{
36
,
51
,
52
,
44
,
52
,
54
,
48
,
44
,
53
,
51
,
55
,
46
,
56
,
55
},
{
36
,
51
,
52
,
44
,
53
,
55
,
57
,
44
,
49
,
55
,
53
,
46
,
49
,
50
},
{
36
,
51
,
52
,
44
,
54
,
53
,
51
,
44
,
57
,
51
,
57
,
46
,
48
,
50
},
{
36
,
51
,
52
,
44
,
56
,
52
,
55
,
44
,
51
,
52
,
48
,
46
,
49
,
53
},
{
36
,
51
,
52
,
44
,
57
,
50
,
48
,
44
,
51
,
49
,
51
,
46
,
50
,
55
},
{
36
,
51
,
53
,
44
,
48
,
51
,
56
,
44
,
57
,
53
,
48
,
46
,
53
,
50
},
{
36
,
51
,
53
,
44
,
49
,
49
,
51
,
44
,
55
,
49
,
52
,
46
,
52
,
49
},
{
36
,
51
,
53
,
44
,
49
,
56
,
54
,
44
,
54
,
56
,
55
,
46
,
53
,
51
},
{
36
,
51
,
53
,
44
,
51
,
48
,
53
,
44
,
51
,
50
,
52
,
46
,
55
,
56
},
{
36
,
51
,
53
,
44
,
51
,
56
,
48
,
44
,
48
,
56
,
56
,
46
,
54
,
55
},
{
36
,
51
,
53
,
44
,
52
,
53
,
51
,
44
,
48
,
54
,
49
,
46
,
55
,
57
},
{
36
,
51
,
53
,
44
,
53
,
55
,
49
,
44
,
54
,
57
,
57
,
46
,
48
,
53
},
{
36
,
51
,
53
,
44
,
53
,
55
,
51
,
44
,
52
,
56
,
57
,
46
,
56
,
49
},
{
36
,
51
,
53
,
44
,
54
,
52
,
54
,
44
,
52
,
54
,
50
,
46
,
57
,
51
},
{
36
,
51
,
53
,
44
,
56
,
51
,
57
,
44
,
56
,
54
,
52
,
46
,
48
,
55
},
{
36
,
51
,
53
,
44
,
57
,
49
,
50
,
44
,
56
,
51
,
55
,
46
,
50
,
48
},
{
36
,
51
,
54
,
44
,
48
,
51
,
49
,
44
,
52
,
55
,
52
,
46
,
52
,
53
},
{
36
,
51
,
54
,
44
,
49
,
48
,
54
,
44
,
50
,
51
,
56
,
46
,
51
,
51
},
{
36
,
51
,
54
,
44
,
49
,
55
,
57
,
44
,
50
,
49
,
49
,
46
,
52
,
53
},
{
36
,
51
,
54
,
44
,
50
,
57
,
55
,
44
,
56
,
52
,
56
,
46
,
55
,
48
},
{
36
,
51
,
54
,
44
,
51
,
55
,
50
,
44
,
54
,
49
,
50
,
46
,
53
,
57
},
{
36
,
51
,
54
,
44
,
53
,
54
,
52
,
44
,
50
,
50
,
50
,
46
,
57
,
55
},
{
36
,
51
,
54
,
44
,
53
,
54
,
54
,
44
,
48
,
49
,
51
,
46
,
55
,
51
},
{
36
,
51
,
54
,
44
,
54
,
51
,
56
,
44
,
57
,
56
,
54
,
46
,
56
,
53
},
{
36
,
51
,
54
,
44
,
55
,
53
,
55
,
44
,
54
,
50
,
52
,
46
,
49
,
48
},
{
36
,
51
,
54
,
44
,
56
,
51
,
50
,
44
,
51
,
56
,
55
,
46
,
57
,
57
},
{
36
,
51
,
54
,
44
,
57
,
48
,
53
,
44
,
51
,
54
,
49
,
46
,
49
,
49
},
{
36
,
51
,
55
,
44
,
48
,
50
,
51
,
44
,
57
,
57
,
56
,
46
,
51
,
55
},
{
36
,
51
,
55
,
44
,
48
,
57
,
56
,
44
,
55
,
54
,
50
,
46
,
50
,
53
},
{
36
,
51
,
55
,
44
,
49
,
55
,
49
,
44
,
55
,
51
,
53
,
46
,
51
,
55
},
{
36
,
51
,
55
,
44
,
50
,
57
,
48
,
44
,
51
,
55
,
50
,
46
,
54
,
50
},
{
36
,
51
,
55
,
44
,
51
,
54
,
53
,
44
,
49
,
51
,
54
,
46
,
53
,
50
},
{
36
,
51
,
55
,
44
,
53
,
53
,
56
,
44
,
53
,
51
,
55
,
46
,
54
,
53
},
{
36
,
51
,
55
,
44
,
54
,
51
,
49
,
44
,
53
,
49
,
48
,
46
,
55
,
55
},
{
36
,
51
,
55
,
44
,
55
,
53
,
48
,
44
,
49
,
52
,
56
,
46
,
48
,
50
},
{
36
,
51
,
55
,
44
,
56
,
50
,
52
,
44
,
57
,
49
,
49
,
46
,
57
,
49
},
{
36
,
51
,
55
,
44
,
56
,
57
,
55
,
44
,
56
,
56
,
53
,
46
,
48
,
51
},
{
36
,
51
,
56
,
44
,
48
,
49
,
54
,
44
,
53
,
50
,
50
,
46
,
50
,
56
},
{
36
,
51
,
56
,
44
,
48
,
57
,
49
,
44
,
50
,
56
,
54
,
46
,
49
,
55
},
{
36
,
51
,
56
,
44
,
49
,
54
,
52
,
44
,
50
,
53
,
57
,
46
,
50
,
57
},
{
36
,
51
,
56
,
44
,
50
,
56
,
50
,
44
,
56
,
57
,
54
,
46
,
53
,
53
},
{
36
,
51
,
56
,
44
,
50
,
56
,
52
,
44
,
54
,
56
,
55
,
46
,
51
,
49
},
{
36
,
51
,
56
,
44
,
51
,
53
,
55
,
44
,
54
,
54
,
48
,
46
,
52
,
51
},
{
36
,
51
,
56
,
44
,
53
,
53
,
49
,
44
,
48
,
54
,
49
,
46
,
53
,
55
},
{
36
,
51
,
56
,
44
,
54
,
50
,
52
,
44
,
48
,
51
,
52
,
46
,
55
,
48
},
{
36
,
51
,
56
,
44
,
55
,
52
,
50
,
44
,
54
,
55
,
49
,
46
,
57
,
53
},
{
36
,
51
,
56
,
44
,
56
,
49
,
55
,
44
,
52
,
51
,
53
,
46
,
56
,
51
},
{
36
,
51
,
56
,
44
,
56
,
57
,
48
,
44
,
52
,
48
,
56
,
46
,
57
,
53
},
{
36
,
51
,
57
,
44
,
48
,
48
,
57
,
44
,
48
,
52
,
54
,
46
,
50
,
48
},
{
36
,
51
,
57
,
44
,
48
,
56
,
51
,
44
,
56
,
49
,
48
,
46
,
48
,
57
},
{
36
,
51
,
57
,
44
,
50
,
55
,
53
,
44
,
52
,
50
,
48
,
46
,
52
,
55
},
{
36
,
51
,
57
,
44
,
50
,
55
,
55
,
44
,
50
,
49
,
49
,
46
,
50
,
51
},
{
36
,
51
,
57
,
44
,
51
,
53
,
48
,
44
,
49
,
56
,
52
,
46
,
51
,
53
},
{
36
,
51
,
57
,
44
,
52
,
54
,
56
,
44
,
56
,
50
,
49
,
46
,
54
,
48
},
{
36
,
51
,
57
,
44
,
53
,
52
,
51
,
44
,
53
,
56
,
53
,
46
,
52
,
57
},
{
36
,
51
,
57
,
44
,
54
,
49
,
54
,
44
,
53
,
53
,
56
,
46
,
54
,
49
},
{
36
,
51
,
57
,
44
,
55
,
51
,
53
,
44
,
49
,
57
,
53
,
46
,
56
,
55
},
{
36
,
51
,
57
,
44
,
56
,
48
,
57
,
44
,
57
,
53
,
57
,
46
,
55
,
53
},
{
36
,
51
,
57
,
44
,
56
,
56
,
50
,
44
,
57
,
51
,
50
,
46
,
56
,
55
},
{
36
,
52
,
48
,
44
,
48
,
48
,
49
,
44
,
53
,
55
,
48
,
46
,
49
,
50
},
{
36
,
52
,
48
,
44
,
48
,
55
,
54
,
44
,
51
,
51
,
52
,
46
,
48
,
50
},
{
36
,
52
,
48
,
44
,
50
,
54
,
57
,
44
,
55
,
51
,
53
,
46
,
49
,
53
},
{
36
,
52
,
48
,
44
,
51
,
52
,
50
,
44
,
55
,
48
,
56
,
46
,
50
,
55
},
{
36
,
52
,
48
,
44
,
52
,
54
,
49
,
44
,
51
,
52
,
53
,
46
,
53
,
50
},
{
36
,
52
,
48
,
44
,
53
,
51
,
54
,
44
,
49
,
48
,
57
,
46
,
52
,
49
},
{
36
,
52
,
48
,
44
,
54
,
48
,
57
,
44
,
48
,
56
,
50
,
46
,
53
,
51
},
{
36
,
52
,
48
,
44
,
55
,
50
,
55
,
44
,
55
,
49
,
57
,
46
,
55
,
56
},
{
36
,
52
,
48
,
44
,
56
,
48
,
50
,
44
,
52
,
56
,
51
,
46
,
54
,
55
},
{
36
,
52
,
48
,
44
,
56
,
55
,
53
,
44
,
52
,
53
,
54
,
46
,
55
,
57
},
{
36
,
52
,
48
,
44
,
57
,
57
,
52
,
44
,
48
,
57
,
52
,
46
,
48
,
53
},
{
36
,
52
,
48
,
44
,
57
,
57
,
53
,
44
,
56
,
56
,
52
,
46
,
56
,
49
},
{
36
,
52
,
49
,
44
,
48
,
54
,
56
,
44
,
56
,
53
,
55
,
46
,
57
,
51
},
{
36
,
52
,
49
,
44
,
50
,
54
,
50
,
44
,
50
,
53
,
57
,
46
,
48
,
55
},
{
36
,
52
,
49
,
44
,
51
,
51
,
53
,
44
,
50
,
51
,
50
,
46
,
50
,
48
},
{
36
,
52
,
49
,
44
,
52
,
53
,
51
,
44
,
56
,
54
,
57
,
46
,
52
,
53
},
{
36
,
52
,
49
,
44
,
53
,
50
,
56
,
44
,
54
,
51
,
51
,
46
,
51
,
51
},
{
36
,
52
,
49
,
44
,
54
,
48
,
49
,
44
,
54
,
48
,
54
,
46
,
52
,
53
},
{
36
,
52
,
49
,
44
,
55
,
50
,
48
,
44
,
50
,
52
,
51
,
46
,
55
,
48
},
{
36
,
52
,
49
,
44
,
55
,
57
,
53
,
44
,
48
,
48
,
55
,
46
,
53
,
57
},
{
36
,
52
,
49
,
44
,
57
,
56
,
54
,
44
,
54
,
49
,
55
,
46
,
57
,
55
},
{
36
,
52
,
50
,
44
,
48
,
51
,
52
,
44
,
48
,
55
,
50
,
46
,
56
,
55
},
{
36
,
52
,
50
,
44
,
49
,
48
,
55
,
44
,
48
,
52
,
53
,
46
,
57
,
56
},
{
36
,
52
,
50
,
44
,
49
,
51
,
52
,
44
,
51
,
53
,
52
,
46
,
57
,
56
},
};
}
test/java/text/Format/DecimalFormat/RoundingAndPropertyTest.java
0 → 100644
浏览文件 @
afc47100
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @bug 7050528
* @summary Test java.text.DecimalFormat fast-path for format(double...)
* @author Olivier Lagneau
* @run main RoundingAndPropertyTest
*
*/
/* -----------------------------------------------------------------------------
* Note :
* Since fast-path algorithm does not modify any feature of DecimalFormat,
* some tests or values in this program may have to be adapted/added/removed
* when any change has been done in the fast-path source code, because the
* conditions for exercising fast-path may change.
*
* This is specially true if the set of constraints to fall in the fast-path
* case is relaxed in any manner.
*
* Usage :
* - Run main without any argument to test against a set of golden values and
* associated results hard-coded in the source code. That will do the tests
* described below
* See below comment section named "Description".
*
* or
*
* - Run main with string argument "-gengold" to output source code of
* GoldenFormattedValues.java class file with the jdk version used while
* generating the code.
* See below comment section named : "Modifying Golden Values".
*
* In case of error while running the test, a Runtime exception is generated
* providing the numbers of errors detected (format of golden values checks and
* property changes checks), and the program exit.
*
* Description :
*
* This test first checks that localization of digits is done correctly when
* calling DecimalFormat.format() on the array of values DecimalLocalizationValues
* found in GoldenDoubleValues, using the locale FullLocalizationTestLocale
* (from GoldenDoubleValues) that implies localization of digits. it checks the
* the results against expected returned string. In case of formatting error,
* it provides a message informing which value was wrongly formatted.
*
* Then it checks the results of calling NumberFormat.format(double) on a set
* of predefined golden values and checks results against expected returned
* string. It does this both for the decimal case, with an instance returned
* NumberFormat.getInstance() call and for the currency case, with an instance
* returned by NumberFormat.getCurrencyInstance(). Almost all the tested double
* values satisfy the constraints assumed by the fast-path algorithm for
* format(double ...). Some are voluntarily outside the scope of fast-path to
* check that the algorithm correctly eliminate them. In case of formatting
* error a message provides information on the golden value raising the error
* (value, exact decimal value (using BidDecimal), expected result, formatted result).
*
* Last the test checks the status and behavior of a DecimalFormat instance
* when changing properties that make this instance satisfy/invalidate its
* fast-path status, depending on the predefined set of fast-path constraints.
*
* The golden results are predefined arrays of int[] containing the unicode
* ints of the chars in the expected formatted string, when using locale
* provided in GoldenDoubleValues class. The results are those obtained by
* using a reference jdk version (for example one that does not contains the
* DecimalFormat fast-path algorithm, like jdk80-b25).
*
* The double values from which we get golden results are stored inside two
* arrays of double values:
* - DecimalGoldenValues for testing NumberFormat.getInstance().
* - CurrencyGoldenValues for testing NumberFormat.getCurrencyInstance().
* These arrays are located in GoldenDoubleValues.java source file.
*
* For each double value in the arrays above, there is an associated golden
* result. These results are stored in arrays of int[]:
* - DecimalGoldenFormattedValues for expected decimal golden results.
* - CurrencyGoldenFormattedValues for expected currency golden results.
* - DecimalDigitsLocalizedFormattedValues for expected localized digit results.
*
* We store the results in int[] arrays containing the expected unicode values
* because the compiler that will compile the containing java file may use a
* different locale than the one registered in GoldenDoubleValues.java. These
* arrays are located in a separate GoldenFormattedValues.java source file
* that is generated by RoundingAndPropertyTest using "-gengold" parameter.
* See below "Modifying Golden Values".
*
* The golden value arrays can be expanded, modified ... to test additional
* or different double values. In that case, the source file of class
* GoldenFormattedValues must be regenerated to replace the existing one..
*
* Modifying Golden Values :
*
* In order to ease further modification of the list of double values checked
* and associated golden results, the test includes the method
* generatesGoldenFormattedValuesClass() that writes on standard output stream
* the source code for GoldenFormattedValues class that includes the expected
* results arrays.
*
* Here are the steps to follow for updating/modifying golden values and results:
* 1- Edit GoldenDoubleValues.java to add/remove/modify golden or localization
* values.
* 2- Run main with "-gengold" string argument with a target jdk.
* (at the creation of this test file, the target jdk used was jdk1.8.0-ea).
* 2- Copy this java code that has been writen on standard output and replace
* GoldenFormattedValues.java contents by the generated output.
* 3- Check that this updated code compiles.
* [4]- If needed replaces existing GoldenDoubleValues and GoldenFormattedValues
* files in jdk/test section, respectively by the one modified at step 1 and
* generated at step 2.
* -----------------------------------------------------------------------------
*/
import
java.util.*
;
import
java.text.NumberFormat
;
import
java.text.DecimalFormat
;
import
java.text.DecimalFormatSymbols
;
import
java.math.RoundingMode
;
import
java.math.BigDecimal
;
public
class
RoundingAndPropertyTest
{
// Prints on standard output stream the unicode values of chars as a
// comma-separated list of int values
private
static
void
printUnicodeValuesArray
(
char
[]
chars
)
{
for
(
int
i
=
0
;
i
<
chars
.
length
;
i
++)
{
System
.
out
.
print
((
int
)
chars
[
i
]);
if
(
i
!=
(
chars
.
length
-
1
))
System
.
out
.
print
(
", "
);
}
}
// Converts given array of unicode values as an array of chars.
// Returns this converted array.
private
static
char
[]
getCharsFromUnicodeArray
(
int
[]
unicodeValues
)
{
char
[]
chars
=
new
char
[
unicodeValues
.
length
];
for
(
int
i
=
0
;
i
<
unicodeValues
.
length
;
i
++)
{
chars
[
i
]
=
(
char
)
unicodeValues
[
i
];
}
return
chars
;
}
/* Prints on standard output stream the java code of resulting
* GoldenFormattedValues class for the golden values found in
* class GoldenDoubleValues.
*/
private
static
void
generatesGoldenFormattedValuesClass
()
{
String
fourWhiteSpaces
=
" "
;
String
eightWhiteSpaces
=
" "
;
// Prints header without Copyright header.
System
.
out
.
println
(
"/* This is a machine generated file - Please DO NOT EDIT !"
);
System
.
out
.
println
(
" * Change RoundingAndPropertyTest instead,"
);
System
.
out
.
println
(
" * and run with \"-gengold\" argument to regenerate (without copyright header)."
);
System
.
out
.
println
(
" */"
);
System
.
out
.
println
();
System
.
out
.
println
(
"/* This file contains the set of result Strings expected from calling inside"
);
System
.
out
.
println
(
" * RoundingAndPropertyTest the method NumberFormat.format() upon the set of"
);
System
.
out
.
println
(
" * double values provided in GoldenDoubleValues.java. It contains three arrays,"
);
System
.
out
.
println
(
" * each containing arrays of unicode values representing the expected string"
);
System
.
out
.
println
(
" * result when calling format() on the corresponding (i.e. same index) double"
);
System
.
out
.
println
(
" * value found in GoldenDoubleValues arrays :"
);
System
.
out
.
println
(
" * - DecimalDigitsLocalizedFormattedValues corresponds to DecimalLocalizationValues,"
);
System
.
out
.
println
(
" * when using FullLocalizationTestLocale to format."
);
System
.
out
.
println
(
" * - DecimalGoldenFormattedValues corresponds to DecimalGoldenValues, when used"
);
System
.
out
.
println
(
" * in the decimal pattern case together with TestLocale."
);
System
.
out
.
println
(
" * - CurrencyGoldenFormattedValues corresponds to CurrencyGoldenValues. when used"
);
System
.
out
.
println
(
" * in the currency pattern case together with TestLocale."
);
System
.
out
.
println
(
" * Please see documentation in RoundingAndPropertyTest.java for more details."
);
System
.
out
.
println
(
" *"
);
System
.
out
.
println
(
" * This file generated by running RoundingAndPropertyTest with \"-gengold\" argument."
);
System
.
out
.
println
(
" */"
);
System
.
out
.
println
();
// Prints beginning of class GoldenFormattedValues.
System
.
out
.
println
(
"class GoldenFormattedValues {"
);
System
.
out
.
println
();
System
.
out
.
println
(
fourWhiteSpaces
+
"// The formatted values below were generated from golden values"
);
System
.
out
.
print
(
fourWhiteSpaces
+
"// listed in GoldenDoubleValues.java,"
);
System
.
out
.
println
(
" using the following jvm version :"
);
System
.
out
.
println
(
fourWhiteSpaces
+
"// "
+
System
.
getProperty
(
"java.vendor"
)
+
" "
+
System
.
getProperty
(
"java.vm.name"
)
+
" "
+
System
.
getProperty
(
"java.version"
));
System
.
out
.
println
(
fourWhiteSpaces
+
"// locale for golden double values : "
+
GoldenDoubleValues
.
TestLocale
);
System
.
out
.
println
(
fourWhiteSpaces
+
"// locale for testing digit localization : "
+
GoldenDoubleValues
.
FullLocalizationTestLocale
);
System
.
out
.
println
();
// Prints the expected results when digit localization happens
System
.
out
.
println
(
fourWhiteSpaces
+
"// The array of int[] unicode values storing the expected results"
);
System
.
out
.
print
(
fourWhiteSpaces
+
"// when experiencing full localization of digits"
);
System
.
out
.
println
(
" on DecimalLocalizationValues."
);
System
.
out
.
println
(
fourWhiteSpaces
+
"static int[][] DecimalDigitsLocalizedFormattedValues = {"
);
NumberFormat
df
=
NumberFormat
.
getInstance
(
GoldenDoubleValues
.
FullLocalizationTestLocale
);
for
(
int
i
=
0
;
i
<
GoldenDoubleValues
.
DecimalLocalizationValues
.
length
;
i
++)
{
double
d
=
GoldenDoubleValues
.
DecimalLocalizationValues
[
i
];
String
formatted
=
df
.
format
(
d
);
char
[]
decFmtChars
=
formatted
.
toCharArray
();
System
.
out
.
print
(
eightWhiteSpaces
+
"{ "
);
printUnicodeValuesArray
(
decFmtChars
);
System
.
out
.
println
(
" },"
);
}
System
.
out
.
println
(
fourWhiteSpaces
+
"};"
);
System
.
out
.
println
();
// Prints the golden expected results for the decimal pattern case
System
.
out
.
println
(
fourWhiteSpaces
+
"// The array of int[] unicode values storing the expected results"
);
System
.
out
.
print
(
fourWhiteSpaces
+
"// when calling Decimal.format(double)"
);
System
.
out
.
println
(
" on the decimal GoldenDoubleValues."
);
System
.
out
.
println
(
fourWhiteSpaces
+
"static int[][] DecimalGoldenFormattedValues = {"
);
df
=
NumberFormat
.
getInstance
(
GoldenDoubleValues
.
TestLocale
);
for
(
int
i
=
0
;
i
<
GoldenDoubleValues
.
DecimalGoldenValues
.
length
;
i
++)
{
double
d
=
GoldenDoubleValues
.
DecimalGoldenValues
[
i
];
String
formatted
=
df
.
format
(
d
);
char
[]
decFmtChars
=
formatted
.
toCharArray
();
System
.
out
.
print
(
eightWhiteSpaces
+
"{ "
);
printUnicodeValuesArray
(
decFmtChars
);
System
.
out
.
println
(
" },"
);
}
System
.
out
.
println
(
fourWhiteSpaces
+
"};"
);
System
.
out
.
println
();
// Prints the golden expected results for the currency pattern case
System
.
out
.
println
(
fourWhiteSpaces
+
"// The array of int[] unicode values storing the expected results"
);
System
.
out
.
print
(
fourWhiteSpaces
+
"// when calling Decimal.format(double)"
);
System
.
out
.
println
(
" on the currency GoldenDoubleValues."
);
System
.
out
.
println
(
fourWhiteSpaces
+
"static int[][] CurrencyGoldenFormattedValues = {"
);
NumberFormat
cf
=
NumberFormat
.
getCurrencyInstance
(
GoldenDoubleValues
.
TestLocale
);
for
(
int
i
=
0
;
i
<
GoldenDoubleValues
.
CurrencyGoldenValues
.
length
;
i
++)
{
double
d
=
GoldenDoubleValues
.
CurrencyGoldenValues
[
i
];
String
formatted
=
cf
.
format
(
d
);
char
[]
decFmtChars
=
formatted
.
toCharArray
();
System
.
out
.
print
(
eightWhiteSpaces
+
"{ "
);
printUnicodeValuesArray
(
decFmtChars
);
System
.
out
.
println
(
" },"
);
}
System
.
out
.
println
(
fourWhiteSpaces
+
"};"
);
System
.
out
.
println
();
// Prints end of GoldenFormattedValues class.
System
.
out
.
println
(
"}"
);
}
private
static
int
testLocalizationValues
()
{
DecimalFormat
df
=
(
DecimalFormat
)
NumberFormat
.
getInstance
(
GoldenDoubleValues
.
FullLocalizationTestLocale
);
double
[]
localizationValues
=
GoldenDoubleValues
.
DecimalLocalizationValues
;
int
size
=
localizationValues
.
length
;
int
successCounter
=
0
;
int
failureCounter
=
0
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
double
d
=
localizationValues
[
i
];
String
formatted
=
df
.
format
(
d
);
char
[]
expectedUnicodeArray
=
getCharsFromUnicodeArray
(
GoldenFormattedValues
.
DecimalDigitsLocalizedFormattedValues
[
i
]);
String
expected
=
new
String
(
expectedUnicodeArray
);
if
(!
formatted
.
equals
(
expected
))
{
failureCounter
++;
System
.
out
.
println
(
"--- Localization error for value d = "
+
d
+
". Exact value = "
+
new
BigDecimal
(
d
).
toString
()
+
". Expected result = "
+
expected
+
". Output result = "
+
formatted
);
}
else
successCounter
++;
}
System
.
out
.
println
(
"Checked positively "
+
successCounter
+
" golden decimal values out of "
+
size
+
" tests. There were "
+
failureCounter
+
" format failure"
);
return
failureCounter
;
}
private
static
int
testGoldenValues
(
java
.
text
.
DecimalFormat
df
,
java
.
text
.
DecimalFormat
cf
)
{
double
[]
goldenDecimalValues
=
GoldenDoubleValues
.
DecimalGoldenValues
;
int
decimalSize
=
goldenDecimalValues
.
length
;
int
decimalSuccessCounter
=
0
;
int
decimalFailureCounter
=
0
;
for
(
int
i
=
0
;
i
<
decimalSize
;
i
++)
{
double
d
=
goldenDecimalValues
[
i
];
String
formatted
=
df
.
format
(
d
);
char
[]
expectedUnicodeArray
=
getCharsFromUnicodeArray
(
GoldenFormattedValues
.
DecimalGoldenFormattedValues
[
i
]);
String
expected
=
new
String
(
expectedUnicodeArray
);
if
(!
formatted
.
equals
(
expected
))
{
decimalFailureCounter
++;
System
.
out
.
println
(
"--- Error for golden value d = "
+
d
+
". Exact value = "
+
new
BigDecimal
(
d
).
toString
()
+
". Expected result = "
+
expected
+
". Output result = "
+
formatted
);
}
else
decimalSuccessCounter
++;
}
System
.
out
.
println
(
"Checked positively "
+
decimalSuccessCounter
+
" golden decimal values out of "
+
decimalSize
+
" tests. There were "
+
decimalFailureCounter
+
" format failure"
);
double
[]
goldenCurrencyValues
=
GoldenDoubleValues
.
CurrencyGoldenValues
;
int
currencySize
=
goldenCurrencyValues
.
length
;
int
currencySuccessCounter
=
0
;
int
currencyFailureCounter
=
0
;
for
(
int
i
=
0
;
i
<
currencySize
;
i
++)
{
double
d
=
goldenCurrencyValues
[
i
];
String
formatted
=
cf
.
format
(
d
);
char
[]
expectedUnicodeArray
=
getCharsFromUnicodeArray
(
GoldenFormattedValues
.
CurrencyGoldenFormattedValues
[
i
]);
String
expected
=
new
String
(
expectedUnicodeArray
);
if
(!
formatted
.
equals
(
expected
))
{
currencyFailureCounter
++;
System
.
out
.
println
(
"--- Error for golden value d = "
+
d
+
". Exact value = "
+
new
BigDecimal
(
d
).
toString
()
+
". Expected result = "
+
expected
+
". Output result = "
+
formatted
);
}
else
currencySuccessCounter
++;
}
System
.
out
.
println
(
"Checked positively "
+
currencySuccessCounter
+
" golden currency values out of "
+
currencySize
+
" tests. There were "
+
currencyFailureCounter
+
" format failure"
);
return
(
decimalFailureCounter
+
currencyFailureCounter
);
}
// Checks that the two passed s1 and s2 string are equal, and prints
// out message in case of error.
private
static
boolean
resultsEqual
(
String
propertyName
,
String
s1
,
String
s2
)
{
boolean
equality
=
s1
.
equals
(
s2
);
if
(!
equality
)
System
.
out
.
println
(
"\n*** Error while reverting to default "
+
propertyName
+
" property.\n"
+
" initial output = "
+
s1
+
". reverted output = "
+
s2
+
"."
);
else
System
.
out
.
println
(
" Test passed."
);
return
equality
;
}
/* This methods checks the behaviour of the management of properties
* of a DecimalFormat instance that satisfies fast-path constraints.
*
* It does this by comparing the results of the format(double) output
* obtained from initial fast-path state with the output provided by
* the same instance that has been pushed and exercised outside
* fast-path rules and finally "reverted" to its initial fast-path state.
*
* The schema of actions is this :
* - Call format(double) on a known DecimalFormat fast-path instance,
* and store this result.
* - Record the current state of a given property.
* - Change the property to invalidate the fast-path state.
* - Call again format(double) on the instance.
* - Revert state of property to validate again fast-path context.
* - Call format(double) again.
* - Check that first and last call to format(double) provide same result
* - Record failure if any.
* - Do the same for another property with the same instance.
* So all the property changes are chained one after the other on only the
* same instance.
*
* Some properties that currently do not influence the fast-path state
* are also tested. This is not useful with current fast-path source
* but is here for testing the whole set of properties. This is the case
* for prefixes and suffixes, and parseBigDecimal properties.
*/
private
static
int
testSettersAndFastPath
(
DecimalFormat
df
,
boolean
isCurrency
)
{
final
double
d1
=
GoldenDoubleValues
.
PROPERTY_CHECK_POSITIVE_VALUE
;
final
double
d2
=
GoldenDoubleValues
.
PROPERTY_CHECK_NEGATIVE_VALUE
;
int
errors
=
0
;
boolean
testSucceeded
=
false
;
String
firstFormatResult
;
String
secondFormatResult
;
String
propertyName
;
// ---- positivePrefix property test ----
testSucceeded
=
false
;
propertyName
=
"positivePrefix"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
String
initialPrefix
=
df
.
getPositivePrefix
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setPositivePrefix
(
"positivePrefix:"
);
df
.
format
(
d1
);
df
.
setPositivePrefix
(
initialPrefix
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- positiveSuffix property test ----
testSucceeded
=
false
;
propertyName
=
"positiveSuffix"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
String
initialSuffix
=
df
.
getPositiveSuffix
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setPositiveSuffix
(
"positiveSuffix:"
);
df
.
format
(
d1
);
df
.
setPositiveSuffix
(
initialSuffix
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- negativePrefix property test ----
testSucceeded
=
false
;
propertyName
=
"negativePrefix"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
initialPrefix
=
df
.
getNegativePrefix
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setNegativePrefix
(
"negativePrefix:"
);
df
.
format
(
d1
);
df
.
setNegativePrefix
(
initialPrefix
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- negativeSuffix property test ----
testSucceeded
=
false
;
propertyName
=
"negativeSuffix"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
initialSuffix
=
df
.
getNegativeSuffix
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setNegativeSuffix
(
"negativeSuffix:"
);
df
.
format
(
d1
);
df
.
setNegativeSuffix
(
initialSuffix
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- multiplier property test ----
testSucceeded
=
false
;
propertyName
=
"multiplier"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
int
initialMultiplier
=
df
.
getMultiplier
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setMultiplier
(
10
);
df
.
format
(
d1
);
df
.
setMultiplier
(
initialMultiplier
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- groupingUsed property test ----
testSucceeded
=
false
;
propertyName
=
"groupingUsed"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
boolean
initialGroupingUsed
=
df
.
isGroupingUsed
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setGroupingUsed
(!
initialGroupingUsed
);
df
.
format
(
d1
);
df
.
setGroupingUsed
(
initialGroupingUsed
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- groupingSize property test ----
testSucceeded
=
false
;
propertyName
=
"groupingSize"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
int
initialGroupingSize
=
df
.
getGroupingSize
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setGroupingSize
(
initialGroupingSize
+
1
);
df
.
format
(
d1
);
df
.
setGroupingSize
(
initialGroupingSize
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- decimalSeparatorAlwaysShown property test ----
testSucceeded
=
false
;
propertyName
=
"decimalSeparatorAlwaysShown"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
boolean
initialDSShown
=
df
.
isDecimalSeparatorAlwaysShown
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setDecimalSeparatorAlwaysShown
(!
initialDSShown
);
df
.
format
(
d1
);
df
.
setDecimalSeparatorAlwaysShown
(
initialDSShown
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- parseBigDecimal property test ----
testSucceeded
=
false
;
propertyName
=
"parseBigDecimal"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
boolean
initialParseBigdecimal
=
df
.
isParseBigDecimal
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setParseBigDecimal
(!
initialParseBigdecimal
);
df
.
format
(
d1
);
df
.
setParseBigDecimal
(
initialParseBigdecimal
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- maximumIntegerDigits property test ----
testSucceeded
=
false
;
propertyName
=
"maximumIntegerDigits"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
int
initialMaxIDs
=
df
.
getMaximumIntegerDigits
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setMaximumIntegerDigits
(
8
);
df
.
format
(
d1
);
df
.
setMaximumIntegerDigits
(
initialMaxIDs
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- minimumIntegerDigits property test ----
testSucceeded
=
false
;
propertyName
=
"minimumIntegerDigits"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
int
initialMinIDs
=
df
.
getMinimumIntegerDigits
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setMinimumIntegerDigits
(
2
);
df
.
format
(
d1
);
df
.
setMinimumIntegerDigits
(
initialMinIDs
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- maximumFractionDigits property test ----
testSucceeded
=
false
;
propertyName
=
"maximumFractionDigits"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
firstFormatResult
=
df
.
format
(
d1
);
df
.
setMaximumFractionDigits
(
8
);
df
.
format
(
d1
);
if
(
isCurrency
)
{
df
.
setMinimumFractionDigits
(
2
);
df
.
setMaximumFractionDigits
(
2
);
}
else
{
df
.
setMinimumFractionDigits
(
0
);
df
.
setMaximumFractionDigits
(
3
);
}
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- minimumFractionDigits property test ----
testSucceeded
=
false
;
propertyName
=
"minimumFractionDigits"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
firstFormatResult
=
df
.
format
(
d1
);
df
.
setMinimumFractionDigits
(
1
);
df
.
format
(
d1
);
if
(
isCurrency
)
{
df
.
setMinimumFractionDigits
(
2
);
df
.
setMaximumFractionDigits
(
2
);
}
else
{
df
.
setMinimumFractionDigits
(
0
);
df
.
setMaximumFractionDigits
(
3
);
}
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- currency property test ----
testSucceeded
=
false
;
propertyName
=
"currency"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
Currency
initialCurrency
=
df
.
getCurrency
();
Currency
japanCur
=
java
.
util
.
Currency
.
getInstance
(
Locale
.
JAPAN
);
firstFormatResult
=
df
.
format
(
d1
);
df
.
setCurrency
(
japanCur
);
df
.
format
(
d1
);
df
.
setCurrency
(
initialCurrency
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- roundingMode property test ----
testSucceeded
=
false
;
propertyName
=
"roundingMode"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
RoundingMode
initialRMode
=
df
.
getRoundingMode
();
firstFormatResult
=
df
.
format
(
d1
);
df
.
setRoundingMode
(
RoundingMode
.
HALF_UP
);
df
.
format
(
d1
);
df
.
setRoundingMode
(
RoundingMode
.
HALF_EVEN
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
// ---- decimalFormatSymbols property test ----
testSucceeded
=
false
;
propertyName
=
"decimalFormatSymbols"
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
DecimalFormatSymbols
initialDecimalFormatSymbols
=
df
.
getDecimalFormatSymbols
();
firstFormatResult
=
df
.
format
(
d1
);
Locale
bizarreLocale
=
new
Locale
(
"fr"
,
"FR"
);
DecimalFormatSymbols
unusualSymbols
=
new
DecimalFormatSymbols
(
bizarreLocale
);
unusualSymbols
.
setDecimalSeparator
(
'@'
);
unusualSymbols
.
setGroupingSeparator
(
'|'
);
df
.
setDecimalFormatSymbols
(
unusualSymbols
);
df
.
format
(
d1
);
df
.
setDecimalFormatSymbols
(
initialDecimalFormatSymbols
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
testSucceeded
=
false
;
System
.
out
.
print
(
"Checking "
+
propertyName
+
" property."
);
initialDecimalFormatSymbols
=
df
.
getDecimalFormatSymbols
();
firstFormatResult
=
df
.
format
(
d1
);
Locale
japanLocale
=
Locale
.
JAPAN
;
unusualSymbols
=
new
DecimalFormatSymbols
(
japanLocale
);
unusualSymbols
.
setDecimalSeparator
(
'9'
);
unusualSymbols
.
setGroupingSeparator
(
'0'
);
df
.
setDecimalFormatSymbols
(
unusualSymbols
);
df
.
format
(
d1
);
df
.
setDecimalFormatSymbols
(
initialDecimalFormatSymbols
);
secondFormatResult
=
df
.
format
(
d1
);
testSucceeded
=
resultsEqual
(
propertyName
,
firstFormatResult
,
secondFormatResult
);
if
(!
testSucceeded
)
errors
++;
return
errors
;
}
// Main for RoundingAndPropertyTest. We test first the golden values,
// and then the property setters and getters.
public
static
void
main
(
String
[]
args
)
{
if
((
args
.
length
>=
1
)
&&
(
args
[
0
].
equals
(
"-gengold"
)))
generatesGoldenFormattedValuesClass
();
else
{
System
.
out
.
println
(
"\nChecking correctness of formatting with digit localization."
);
System
.
out
.
println
(
"============================================================="
);
int
localizationErrors
=
testLocalizationValues
();
if
(
localizationErrors
!=
0
)
System
.
out
.
println
(
"*** Failure in localization tests : "
+
localizationErrors
+
" errors detected "
);
else
System
.
out
.
println
(
" Tests for full localization of digits all passed."
);
DecimalFormat
df
=
(
DecimalFormat
)
NumberFormat
.
getInstance
(
GoldenDoubleValues
.
TestLocale
);
DecimalFormat
cf
=
(
DecimalFormat
)
NumberFormat
.
getCurrencyInstance
(
GoldenDoubleValues
.
TestLocale
);
System
.
out
.
println
(
"\nChecking correctness of formating for golden values."
);
System
.
out
.
println
(
"============================================================="
);
int
goldenValuesErrors
=
testGoldenValues
(
df
,
cf
);
if
(
goldenValuesErrors
!=
0
)
System
.
out
.
println
(
"*** Failure in goldenValues tests : "
+
goldenValuesErrors
+
" errors detected "
);
else
System
.
out
.
println
(
" Tests for golden values all passed."
);
System
.
out
.
println
(
"\nChecking behavior of property changes for decimal case."
);
System
.
out
.
println
(
"============================================================="
);
int
decimalTestsErrors
=
testSettersAndFastPath
(
df
,
false
);
if
(
decimalTestsErrors
!=
0
)
System
.
out
.
println
(
"*** Failure in decimal property changes tests : "
+
decimalTestsErrors
+
" errors detected "
);
else
System
.
out
.
println
(
" Tests for decimal property changes all passed."
);
System
.
out
.
println
(
"\nChecking behavior of property changes for currency case."
);
System
.
out
.
println
(
"============================================================="
);
int
currencyTestsErrors
=
testSettersAndFastPath
(
cf
,
true
);
if
(
currencyTestsErrors
!=
0
)
System
.
out
.
println
(
"*** Failure in currency property changes tests : "
+
currencyTestsErrors
+
" errors detected "
);
else
System
.
out
.
println
(
" Tests for currency property chamges all passed."
);
if
((
localizationErrors
>
0
)
||
(
goldenValuesErrors
>
0
)
||
(
decimalTestsErrors
>
0
)
||
(
currencyTestsErrors
>
0
))
throw
new
RuntimeException
(
"Failed with "
+
(
localizationErrors
+
goldenValuesErrors
+
decimalTestsErrors
+
currencyTestsErrors
)
+
" error(s)."
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录