88 */
99package org .elasticsearch .search .aggregations .metrics ;
1010
11+ import org .elasticsearch .common .util .BigArrays ;
1112import org .elasticsearch .common .util .DoubleArray ;
1213import org .elasticsearch .core .Releasables ;
1314import org .elasticsearch .index .fielddata .NumericDoubleValues ;
2526
2627public class SumAggregator extends NumericMetricsAggregator .SingleDoubleValue {
2728
28- private final DocValueFormat format ;
29-
30- private DoubleArray sums ;
31- private DoubleArray compensations ;
29+ protected final DocValueFormat format ;
30+ protected DoubleArray sums ;
31+ protected DoubleArray compensations ;
3232
3333 SumAggregator (
3434 String name ,
@@ -40,72 +40,98 @@ public class SumAggregator extends NumericMetricsAggregator.SingleDoubleValue {
4040 super (name , valuesSourceConfig , context , parent , metadata );
4141 assert valuesSourceConfig .hasValues ();
4242 this .format = valuesSourceConfig .format ();
43- sums = bigArrays ().newDoubleArray (1 , true );
44- compensations = bigArrays ().newDoubleArray (1 , true );
43+ var bigArrays = context .bigArrays ();
44+ sums = bigArrays .newDoubleArray (1 , true );
45+ compensations = bigArrays .newDoubleArray (1 , true );
4546 }
4647
4748 @ Override
4849 protected LeafBucketCollector getLeafCollector (SortedNumericDoubleValues values , final LeafBucketCollector sub ) {
49- final CompensatedSum kahanSummation = new CompensatedSum (0 , 0 );
5050 return new LeafBucketCollectorBase (sub , values ) {
5151 @ Override
5252 public void collect (int doc , long bucket ) throws IOException {
5353 if (values .advanceExact (doc )) {
5454 maybeGrow (bucket );
55- // Compute the sum of double values with Kahan summation algorithm which is more
56- // accurate than naive summation.
57- kahanSummation .reset (sums .get (bucket ), compensations .get (bucket ));
58- for (int i = 0 ; i < values .docValueCount (); i ++) {
59- kahanSummation .add (values .nextValue ());
60- }
61- compensations .set (bucket , kahanSummation .delta ());
62- sums .set (bucket , kahanSummation .value ());
55+ sumSortedDoubles (bucket , values , sums , compensations );
6356 }
6457 }
6558 };
6659 }
6760
61+ // returns number of values added
62+ static int sumSortedDoubles (long bucket , SortedNumericDoubleValues values , DoubleArray sums , DoubleArray compensations )
63+ throws IOException {
64+ final int valueCount = values .docValueCount ();
65+ // Compute the sum of double values with Kahan summation algorithm which is more
66+ // accurate than naive summation.
67+ double value = sums .get (bucket );
68+ double delta = compensations .get (bucket );
69+ for (int i = 0 ; i < valueCount ; i ++) {
70+ double added = values .nextValue ();
71+ value = addIfNonOrInf (added , value );
72+ if (Double .isFinite (value )) {
73+ double correctedSum = added + delta ;
74+ double updatedValue = value + correctedSum ;
75+ delta = correctedSum - (updatedValue - value );
76+ value = updatedValue ;
77+ }
78+ }
79+ compensations .set (bucket , delta );
80+ sums .set (bucket , value );
81+ return valueCount ;
82+ }
83+
84+ private static double addIfNonOrInf (double added , double value ) {
85+ // If the value is Inf or NaN, just add it to the running tally to "convert" to
86+ // Inf/NaN. This keeps the behavior bwc from before kahan summing
87+ if (Double .isFinite (added )) {
88+ return value ;
89+ }
90+ return added + value ;
91+ }
92+
6893 @ Override
6994 protected LeafBucketCollector getLeafCollector (NumericDoubleValues values , final LeafBucketCollector sub ) {
7095 return new LeafBucketCollectorBase (sub , values ) {
7196 @ Override
7297 public void collect (int doc , long bucket ) throws IOException {
7398 if (values .advanceExact (doc )) {
7499 maybeGrow (bucket );
75- var sums = SumAggregator .this .sums ;
76- // Compute the sum of double values with Kahan summation algorithm which is more
77- // accurate than naive summation.
78- double value = sums .get (bucket );
79- // If the value is Inf or NaN, just add it to the running tally to "convert" to
80- // Inf/NaN. This keeps the behavior bwc from before kahan summing
81- double v = values .doubleValue ();
82- if (Double .isFinite (v ) == false ) {
83- value = v + value ;
84- }
85-
86- if (Double .isFinite (value )) {
87- var compensations = SumAggregator .this .compensations ;
88- double delta = compensations .get (bucket );
89- double correctedSum = v + delta ;
90- double updatedValue = value + correctedSum ;
91- delta = correctedSum - (updatedValue - value );
92- value = updatedValue ;
93- compensations .set (bucket , delta );
94- }
95-
96- sums .set (bucket , value );
100+ computeSum (bucket , values , sums , compensations );
97101 }
98102 }
99103 };
100104 }
101105
102- private void maybeGrow (long bucket ) {
106+ static void computeSum (long bucket , NumericDoubleValues values , DoubleArray sums , DoubleArray compensations ) throws IOException {
107+ // Compute the sum of double values with Kahan summation algorithm which is more
108+ // accurate than naive summation.
109+ double added = values .doubleValue ();
110+ double value = addIfNonOrInf (added , sums .get (bucket ));
111+ if (Double .isFinite (value )) {
112+ double delta = compensations .get (bucket );
113+ double correctedSum = added + delta ;
114+ double updatedValue = value + correctedSum ;
115+ delta = correctedSum - (updatedValue - value );
116+ value = updatedValue ;
117+ compensations .set (bucket , delta );
118+ }
119+
120+ sums .set (bucket , value );
121+ }
122+
123+ protected final void maybeGrow (long bucket ) {
103124 if (bucket >= sums .size ()) {
104- sums = bigArrays (). grow ( sums , bucket + 1 );
105- compensations = bigArrays (). grow ( compensations , bucket + 1 );
125+ var bigArrays = bigArrays ();
126+ doGrow ( bucket , bigArrays );
106127 }
107128 }
108129
130+ protected void doGrow (long bucket , BigArrays bigArrays ) {
131+ sums = bigArrays .grow (sums , bucket + 1 );
132+ compensations = bigArrays .grow (compensations , bucket + 1 );
133+ }
134+
109135 @ Override
110136 public double metric (long owningBucketOrd ) {
111137 if (owningBucketOrd >= sums .size ()) {
0 commit comments