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 }
|