Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
8fba8ab9
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看板
提交
8fba8ab9
编写于
1月 03, 2014
作者:
D
darcy
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8030212: Several api.java.util.stream tests got "NaN" value instead of "Infinity" or "-Infinity"
Reviewed-by: mduigou, psandoz
上级
4766f23e
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
126 addition
and
32 deletion
+126
-32
src/share/classes/java/util/DoubleSummaryStatistics.java
src/share/classes/java/util/DoubleSummaryStatistics.java
+12
-1
src/share/classes/java/util/stream/Collectors.java
src/share/classes/java/util/stream/Collectors.java
+30
-13
src/share/classes/java/util/stream/DoublePipeline.java
src/share/classes/java/util/stream/DoublePipeline.java
+15
-10
test/java/util/stream/TestDoubleSumAverage.java
test/java/util/stream/TestDoubleSumAverage.java
+69
-8
未找到文件。
src/share/classes/java/util/DoubleSummaryStatistics.java
浏览文件 @
8fba8ab9
...
...
@@ -64,6 +64,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
private
long
count
;
private
double
sum
;
private
double
sumCompensation
;
// Low order bits of sum
private
double
simpleSum
;
// Used to compute right sum for non-finite inputs
private
double
min
=
Double
.
POSITIVE_INFINITY
;
private
double
max
=
Double
.
NEGATIVE_INFINITY
;
...
...
@@ -82,6 +83,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
@Override
public
void
accept
(
double
value
)
{
++
count
;
simpleSum
+=
value
;
sumWithCompensation
(
value
);
min
=
Math
.
min
(
min
,
value
);
max
=
Math
.
max
(
max
,
value
);
...
...
@@ -96,6 +98,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
*/
public
void
combine
(
DoubleSummaryStatistics
other
)
{
count
+=
other
.
count
;
simpleSum
+=
other
.
simpleSum
;
sumWithCompensation
(
other
.
sum
);
sumWithCompensation
(
other
.
sumCompensation
);
min
=
Math
.
min
(
min
,
other
.
min
);
...
...
@@ -147,7 +150,15 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
*/
public
final
double
getSum
()
{
// Better error bounds to add both terms as the final sum
return
sum
+
sumCompensation
;
double
tmp
=
sum
+
sumCompensation
;
if
(
Double
.
isNaN
(
tmp
)
&&
Double
.
isInfinite
(
simpleSum
))
// If the compensated sum is spuriously NaN from
// accumulating one or more same-signed infinite values,
// return the correctly-signed infinity stored in
// simpleSum.
return
simpleSum
;
else
return
tmp
;
}
/**
...
...
src/share/classes/java/util/stream/Collectors.java
浏览文件 @
8fba8ab9
...
...
@@ -507,16 +507,20 @@ public final class Collectors {
summingDouble
(
ToDoubleFunction
<?
super
T
>
mapper
)
{
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum and index 1
* holds the low-order bits of the sum computed via
* compensated summation.
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
return
new
CollectorImpl
<>(
()
->
new
double
[
2
],
(
a
,
t
)
->
{
sumWithCompensation
(
a
,
mapper
.
applyAsDouble
(
t
));
},
(
a
,
b
)
->
{
sumWithCompensation
(
a
,
b
[
0
]);
return
sumWithCompensation
(
a
,
b
[
1
]);
},
// Better error bounds to add both terms as the final sum
a
->
a
[
0
]
+
a
[
1
],
()
->
new
double
[
3
],
(
a
,
t
)
->
{
sumWithCompensation
(
a
,
mapper
.
applyAsDouble
(
t
));
a
[
2
]
+=
mapper
.
applyAsDouble
(
t
);},
(
a
,
b
)
->
{
sumWithCompensation
(
a
,
b
[
0
]);
a
[
2
]
+=
b
[
2
];
return
sumWithCompensation
(
a
,
b
[
1
]);
},
a
->
computeFinalSum
(
a
),
CH_NOID
);
}
...
...
@@ -540,6 +544,20 @@ public final class Collectors {
return
intermediateSum
;
}
/**
* If the compensated sum is spuriously NaN from accumulating one
* or more same-signed infinite values, return the
* correctly-signed infinity stored in the simple sum.
*/
static
double
computeFinalSum
(
double
[]
summands
)
{
// Better error bounds to add both terms as the final sum
double
tmp
=
summands
[
0
]
+
summands
[
1
];
double
simpleSum
=
summands
[
summands
.
length
-
1
];
if
(
Double
.
isNaN
(
tmp
)
&&
Double
.
isInfinite
(
simpleSum
))
return
simpleSum
;
else
return
tmp
;
}
/**
* Returns a {@code Collector} that produces the arithmetic mean of an integer-valued
...
...
@@ -608,11 +626,10 @@ public final class Collectors {
* summation, and index 2 holds the number of values seen.
*/
return
new
CollectorImpl
<>(
()
->
new
double
[
3
],
(
a
,
t
)
->
{
sumWithCompensation
(
a
,
mapper
.
applyAsDouble
(
t
));
a
[
2
]++;
},
(
a
,
b
)
->
{
sumWithCompensation
(
a
,
b
[
0
]);
sumWithCompensation
(
a
,
b
[
1
]);
a
[
2
]
+=
b
[
2
];
return
a
;
},
// Better error bounds to add both terms as the final sum to compute average
a
->
(
a
[
2
]
==
0
)
?
0.0d
:
((
a
[
0
]
+
a
[
1
])
/
a
[
2
]),
()
->
new
double
[
4
],
(
a
,
t
)
->
{
sumWithCompensation
(
a
,
mapper
.
applyAsDouble
(
t
));
a
[
2
]++;
a
[
3
]+=
mapper
.
applyAsDouble
(
t
);},
(
a
,
b
)
->
{
sumWithCompensation
(
a
,
b
[
0
]);
sumWithCompensation
(
a
,
b
[
1
]);
a
[
2
]
+=
b
[
2
];
a
[
3
]
+=
b
[
3
];
return
a
;
},
a
->
(
a
[
2
]
==
0
)
?
0.0d
:
(
computeFinalSum
(
a
)
/
a
[
2
]),
CH_NOID
);
}
...
...
src/share/classes/java/util/stream/DoublePipeline.java
浏览文件 @
8fba8ab9
...
...
@@ -379,21 +379,24 @@ abstract class DoublePipeline<E_IN>
public
final
double
sum
()
{
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum and index 1
* holds the low-order bits of the sum computed via
* compensated summation.
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the simple sum used to compute
* the proper result if the stream contains infinite values of
* the same sign.
*/
double
[]
summation
=
collect
(()
->
new
double
[
2
],
double
[]
summation
=
collect
(()
->
new
double
[
3
],
(
ll
,
d
)
->
{
Collectors
.
sumWithCompensation
(
ll
,
d
);
ll
[
2
]
+=
d
;
},
(
ll
,
rr
)
->
{
Collectors
.
sumWithCompensation
(
ll
,
rr
[
0
]);
Collectors
.
sumWithCompensation
(
ll
,
rr
[
1
]);
ll
[
2
]
+=
rr
[
2
];
});
// Better error bounds to add both terms as the final sum
return
summation
[
0
]
+
summation
[
1
];
return
Collectors
.
computeFinalSum
(
summation
);
}
@Override
...
...
@@ -421,21 +424,23 @@ abstract class DoublePipeline<E_IN>
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
* summation, index 2 holds the number of values seen, index 3
* holds the simple sum.
*/
double
[]
avg
=
collect
(()
->
new
double
[
3
],
double
[]
avg
=
collect
(()
->
new
double
[
4
],
(
ll
,
d
)
->
{
ll
[
2
]++;
Collectors
.
sumWithCompensation
(
ll
,
d
);
ll
[
3
]
+=
d
;
},
(
ll
,
rr
)
->
{
Collectors
.
sumWithCompensation
(
ll
,
rr
[
0
]);
Collectors
.
sumWithCompensation
(
ll
,
rr
[
1
]);
ll
[
2
]
+=
rr
[
2
];
ll
[
3
]
+=
rr
[
3
];
});
return
avg
[
2
]
>
0
// Better error bounds to add both terms as the final sum to compute average
?
OptionalDouble
.
of
((
avg
[
0
]
+
avg
[
1
])
/
avg
[
2
])
?
OptionalDouble
.
of
(
Collectors
.
computeFinalSum
(
avg
)
/
avg
[
2
])
:
OptionalDouble
.
empty
();
}
...
...
test/java/util/stream/TestDoubleSumAverage.java
浏览文件 @
8fba8ab9
...
...
@@ -25,23 +25,35 @@ import java.util.*;
import
java.util.function.*
;
import
java.util.stream.*
;
import
static
java
.
lang
.
Double
.*;
/*
* @test
* @bug 8006572
* @bug 8006572
8030212
* @summary Test for use of non-naive summation in stream-related sum and average operations.
*/
public
class
TestDoubleSumAverage
{
public
static
void
main
(
String
...
args
)
{
int
failures
=
0
;
failures
+=
testForCompenstation
();
failures
+=
testZeroAverageOfNonEmptyStream
();
failures
+=
testForCompenstation
();
failures
+=
testNonfiniteSum
();
if
(
failures
>
0
)
{
throw
new
RuntimeException
(
"Found "
+
failures
+
" numerical failure(s)."
);
}
}
/**
* Test to verify that a non-empty stream with a zero average is non-empty.
*/
private
static
int
testZeroAverageOfNonEmptyStream
()
{
Supplier
<
DoubleStream
>
ds
=
()
->
DoubleStream
.
iterate
(
0.0
,
e
->
0.0
).
limit
(
10
);
return
compareUlpDifference
(
0.0
,
ds
.
get
().
average
().
getAsDouble
(),
0
);
}
/**
* Compute the sum and average of a sequence of double values in
* various ways and report an error if naive summation is used.
...
...
@@ -83,19 +95,68 @@ public class TestDoubleSumAverage {
return
failures
;
}
/**
* Test to verify that a non-empty stream with a zero average is non-empty.
*/
private
static
int
testZeroAverageOfNonEmptyStream
()
{
Supplier
<
DoubleStream
>
ds
=
()
->
DoubleStream
.
iterate
(
0.0
,
e
->
0.0
).
limit
(
10
);
private
static
int
testNonfiniteSum
()
{
int
failures
=
0
;
return
compareUlpDifference
(
0.0
,
ds
.
get
().
average
().
getAsDouble
(),
0
);
Map
<
Supplier
<
DoubleStream
>,
Double
>
testCases
=
new
LinkedHashMap
<>();
testCases
.
put
(()
->
DoubleStream
.
of
(
MAX_VALUE
,
MAX_VALUE
),
POSITIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(-
MAX_VALUE
,
-
MAX_VALUE
),
NEGATIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
1.0d
,
POSITIVE_INFINITY
,
1.0d
),
POSITIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
POSITIVE_INFINITY
),
POSITIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
POSITIVE_INFINITY
,
POSITIVE_INFINITY
),
POSITIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
POSITIVE_INFINITY
,
POSITIVE_INFINITY
,
0.0
),
POSITIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
1.0d
,
NEGATIVE_INFINITY
,
1.0d
),
NEGATIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NEGATIVE_INFINITY
),
NEGATIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NEGATIVE_INFINITY
,
NEGATIVE_INFINITY
),
NEGATIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NEGATIVE_INFINITY
,
NEGATIVE_INFINITY
,
0.0
),
NEGATIVE_INFINITY
);
testCases
.
put
(()
->
DoubleStream
.
of
(
1.0d
,
NaN
,
1.0d
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NaN
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
1.0d
,
NEGATIVE_INFINITY
,
POSITIVE_INFINITY
,
1.0d
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
1.0d
,
POSITIVE_INFINITY
,
NEGATIVE_INFINITY
,
1.0d
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
POSITIVE_INFINITY
,
NaN
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NEGATIVE_INFINITY
,
NaN
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NaN
,
POSITIVE_INFINITY
),
NaN
);
testCases
.
put
(()
->
DoubleStream
.
of
(
NaN
,
NEGATIVE_INFINITY
),
NaN
);
for
(
Map
.
Entry
<
Supplier
<
DoubleStream
>,
Double
>
testCase
:
testCases
.
entrySet
())
{
Supplier
<
DoubleStream
>
ds
=
testCase
.
getKey
();
double
expected
=
testCase
.
getValue
();
DoubleSummaryStatistics
stats
=
ds
.
get
().
collect
(
DoubleSummaryStatistics:
:
new
,
DoubleSummaryStatistics:
:
accept
,
DoubleSummaryStatistics:
:
combine
);
failures
+=
compareUlpDifference
(
expected
,
stats
.
getSum
(),
0
);
failures
+=
compareUlpDifference
(
expected
,
stats
.
getAverage
(),
0
);
failures
+=
compareUlpDifference
(
expected
,
ds
.
get
().
sum
(),
0
);
failures
+=
compareUlpDifference
(
expected
,
ds
.
get
().
average
().
getAsDouble
(),
0
);
failures
+=
compareUlpDifference
(
expected
,
ds
.
get
().
boxed
().
collect
(
Collectors
.
summingDouble
(
d
->
d
)),
0
);
failures
+=
compareUlpDifference
(
expected
,
ds
.
get
().
boxed
().
collect
(
Collectors
.
averagingDouble
(
d
->
d
)),
0
);
}
return
failures
;
}
/**
* Compute the ulp difference of two double values and compare against an error threshold.
*/
private
static
int
compareUlpDifference
(
double
expected
,
double
computed
,
double
threshold
)
{
if
(!
Double
.
isFinite
(
expected
))
{
// Handle NaN and infinity cases
if
(
Double
.
compare
(
expected
,
computed
)
==
0
)
return
0
;
else
{
System
.
err
.
printf
(
"Unexpected sum, %g rather than %g.%n"
,
computed
,
expected
);
return
1
;
}
}
double
ulpDifference
=
Math
.
abs
(
expected
-
computed
)
/
Math
.
ulp
(
expected
);
if
(
ulpDifference
>
threshold
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录