DoubleAdder.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.5.0).
003  * Copyright (c) 2007-2016 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.internal.math;
021 
022 import static java.lang.Double.isInfinite;
023 import static java.lang.Double.isNaN;
024 import static java.util.Objects.requireNonNull;
025 import static org.jenetics.internal.util.Equality.eq;
026 
027 import org.jenetics.internal.util.Hash;
028 
029 /**
030  * This class implements the the
031  * <a href="http://en.wikipedia.org/wiki/Kahan_summation_algorithm">Kahan
032  * summation algorithm</a>, which significantly reduces the numerical error when
033  * adding double values.
034  *
035  * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
036  * @since 3.0
037  * @version 3.0
038  */
039 public final class DoubleAdder
040     extends Number
041     implements Comparable<DoubleAdder>
042 {
043     private static final long serialVersionUID = 1L;
044 
045     private double _sum = 0.0;
046     private double _simpleSum = 0.0;
047     private double _compensation = 0.0;
048 
049     /**
050      * Create a new adder with the given default {@code value}.
051      *
052      * @param value the initial {@code value} of this adder.
053      */
054     public DoubleAdder(final double value) {
055         add(value);
056     }
057 
058     /**
059      * Create a new adder with the initial value of {@code 0.0}.
060      */
061     public DoubleAdder() {
062     }
063 
064     /**
065      * Reset the adder to the initial value of {@code 0.0}.
066      *
067      * @return {@code this} adder, for command chaining
068      */
069     private DoubleAdder reset() {
070         _sum = 0.0;
071         _simpleSum = 0.0;
072         _compensation = 0.0;
073         return this;
074     }
075 
076     /**
077      * Set the adder to the given {@code value}.
078      *
079      * @param value the new adder value
080      * @return {@code this} adder, for command chaining
081      */
082     public DoubleAdder set(final double value) {
083         return reset().add(value);
084     }
085 
086     /**
087      * Set the adder to the given {@code value}.
088      *
089      * @param value the new adder value
090      * @return {@code this} adder, for command chaining
091      * @throws java.lang.NullPointerException if the given {@code value} is
092      *         {@code null}
093      */
094     public DoubleAdder set(final DoubleAdder value) {
095         return reset().add(requireNonNull(value));
096     }
097 
098     /**
099      * Add the given {@code value} to this adder, using the
100      * <a href="http://en.wikipedia.org/wiki/Kahan_summation_algorithm">Kahan
101      * summation algorithm</a>
102      *
103      * @param value the {@code value} to add
104      * @return {@code this} adder, for command chaining
105      */
106     public DoubleAdder add(final double value) {
107         addWithCompensation(value);
108         _simpleSum += value;
109         return this;
110     }
111 
112     /**
113      * Add the given values to this adder.
114      *
115      * @param values the values to add.
116      * @return {@code this} adder, for command chaining
117      */
118     public DoubleAdder add(final double[] values) {
119         for (int i = values.length; --i >= 0;) {
120             add(values[i]);
121         }
122 
123         return this;
124     }
125 
126     private void addWithCompensation(final double value) {
127         final double y = value - _compensation;
128         final double t = _sum + y;
129         _compensation = (t - _sum) - y;
130         _sum = t;
131     }
132 
133     /**
134      * Add the given {@code value} to this adder, using the
135      * <a href="http://en.wikipedia.org/wiki/Kahan_summation_algorithm">Kahan
136      * summation algorithm</a>
137      *
138      * @param value the {@code value} to add
139      * @return {@code this} adder, for command chaining
140      * @throws java.lang.NullPointerException if the given {@code value} is
141      *         {@code null}
142      */
143     public DoubleAdder add(final DoubleAdder value) {
144         addWithCompensation(value._sum);
145         addWithCompensation(value._compensation);
146         _simpleSum += value._simpleSum;
147         return this;
148     }
149 
150     /**
151      * Add the given {@code value} to this adder, using the
152      * <a href="http://en.wikipedia.org/wiki/Kahan_summation_algorithm">Kahan
153      * summation algorithm</a>
154      *
155      * @param other the {@code value} to add
156      * @return {@code this} adder, for command chaining
157      * @throws java.lang.NullPointerException if the given {@code value} is
158      *         {@code null}
159      */
160     public DoubleAdder combine(final DoubleAdder other) {
161         return add(other);
162     }
163 
164     public double value() {
165         final double result =  _sum + _compensation;
166         return isNaN(result) && isInfinite(_simpleSum) ? _simpleSum : result;
167     }
168 
169     @Override
170     public int intValue() {
171         return (int)value();
172     }
173 
174     @Override
175     public long longValue() {
176         return (long)value();
177     }
178 
179     @Override
180     public float floatValue() {
181         return (float)value();
182     }
183 
184     @Override
185     public double doubleValue() {
186         return value();
187     }
188 
189     @Override
190     public int compareTo(final DoubleAdder other) {
191         return Double.compare(doubleValue(), other.doubleValue());
192     }
193 
194     @Override
195     public int hashCode() {
196         return Hash.of(DoubleAdder.class).and(doubleValue()).value();
197     }
198 
199     @Override
200     public boolean equals(final Object obj) {
201         return obj instanceof DoubleAdder &&
202             eq(doubleValue(), ((DoubleAdder)obj).doubleValue());
203     }
204 
205     @Override
206     public String toString() {
207         return Double.toString(doubleValue());
208     }
209 
210 
211     /* *************************************************************************
212      * Some static helper methods.
213      **************************************************************************/
214 
215     /**
216      * Return the sum of the given double array.
217      *
218      * @param values the values to sum up.
219      * @return the sum of the given {@code values}.
220      * @throws NullPointerException if the given array is {@code null}.
221      */
222     public static double sum(final double[] values) {
223         return new DoubleAdder().add(values).doubleValue();
224     }
225 }