001 /*
002 * Java Genetic Algorithm Library (jenetics-5.2.0).
003 * Copyright (c) 2007-2020 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@gmail.com)
019 */
020 package io.jenetics.stat;
021
022 import static java.lang.Double.NaN;
023 import static java.util.Objects.requireNonNull;
024 import static io.jenetics.internal.util.Hashes.hash;
025
026 import java.io.Serializable;
027 import java.util.DoubleSummaryStatistics;
028 import java.util.function.ToDoubleFunction;
029 import java.util.stream.Collector;
030
031 import io.jenetics.internal.math.DoubleAdder;
032
033 /**
034 * <i>Value</i> objects which contains statistical summary information.
035 *
036 * @see java.util.DoubleSummaryStatistics
037 *
038 * @implNote
039 * This class is immutable and thread-safe.
040 *
041 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
042 * @since 3.0
043 * @version 5.2
044 */
045 public final /*record*/ class DoubleSummary implements Serializable {
046
047 private static final long serialVersionUID = 1L;
048
049 private final long _count;
050 private final double _min;
051 private final double _max;
052 private final double _sum;
053 private final double _mean;
054
055 /**
056 * Create an immutable object which contains statistical summary values.
057 *
058 * @param count the count of values recorded
059 * @param min the minimum value
060 * @param max the maximum value
061 * @param sum the sum of the recorded values
062 * @param mean the arithmetic mean of values
063 */
064 private DoubleSummary(
065 final long count,
066 final double min,
067 final double max,
068 final double sum,
069 final double mean
070 ) {
071 _count = count;
072 _min = min;
073 _max = max;
074 _sum = sum;
075 _mean = mean;
076 }
077
078 /**
079 * Returns the count of values recorded.
080 *
081 * @return the count of recorded values
082 */
083 public long count() {
084 return _count;
085 }
086
087 /**
088 * Returns the count of values recorded.
089 *
090 * @return the count of recorded values
091 * @deprecated Use {@link #count()} instead
092 */
093 @Deprecated
094 public long getCount() {
095 return _count;
096 }
097
098 /**
099 * Return the minimum value recorded, or {@code Double.POSITIVE_INFINITY} if
100 * no values have been recorded.
101 *
102 * @return the minimum value, or {@code Double.POSITIVE_INFINITY} if none
103 */
104 public double min() {
105 return _min;
106 }
107
108 /**
109 * Return the minimum value recorded, or {@code Double.POSITIVE_INFINITY} if
110 * no values have been recorded.
111 *
112 * @return the minimum value, or {@code Double.POSITIVE_INFINITY} if none
113 * @deprecated Use {@link #min()} instead
114 */
115 @Deprecated
116 public double getMin() {
117 return _min;
118 }
119
120 /**
121 * Return the maximum value recorded, or {@code Double.NEGATIVE_INFINITY} if
122 * no values have been recorded.
123 *
124 * @return the maximum value, or {@code Double.NEGATIVE_INFINITY} if none
125 */
126 public double max() {
127 return _max;
128 }
129
130 /**
131 * Return the maximum value recorded, or {@code Double.NEGATIVE_INFINITY} if
132 * no values have been recorded.
133 *
134 * @return the maximum value, or {@code Double.NEGATIVE_INFINITY} if none
135 * @deprecated Use {@link #max()} instead
136 */
137 @Deprecated
138 public double getMax() {
139 return _max;
140 }
141
142 /**
143 * Return the sum of values recorded, or zero if no values have been
144 * recorded.
145 *
146 * @return the sum of values, or zero if none
147 */
148 public double sum() {
149 return _sum;
150 }
151
152 /**
153 * Return the sum of values recorded, or zero if no values have been
154 * recorded.
155 *
156 * @return the sum of values, or zero if none
157 * @deprecated Use {@link #sum()} instead
158 */
159 @Deprecated
160 public double getSum() {
161 return _sum;
162 }
163
164 /**
165 * Return the arithmetic mean of values recorded, or zero if no values have
166 * been recorded.
167 *
168 * @return the arithmetic mean of values, or zero if none
169 */
170 public double mean() {
171 return _mean;
172 }
173
174 /**
175 * Return the arithmetic mean of values recorded, or zero if no values have
176 * been recorded.
177 *
178 * @return the arithmetic mean of values, or zero if none
179 * @deprecated Use {@link #mean()} instead
180 */
181 @Deprecated
182 public double getMean() {
183 return _mean;
184 }
185
186 @Override
187 public int hashCode() {
188 return
189 hash(_count,
190 hash(_sum,
191 hash(_min,
192 hash(_max,
193 hash(_mean)))));
194 }
195
196 @Override
197 public boolean equals(final Object obj) {
198 return obj == this ||
199 obj instanceof DoubleSummary &&
200 _count == ((DoubleSummary)obj)._count &&
201 Double.compare(_sum, ((DoubleSummary)obj)._sum) == 0 &&
202 Double.compare(_min, ((DoubleSummary)obj)._min) == 0 &&
203 Double.compare(_max, ((DoubleSummary)obj)._max) == 0 &&
204 Double.compare(_mean, ((DoubleSummary)obj)._mean) == 0;
205 }
206
207 @Override
208 public String toString() {
209 return String.format(
210 "DoubleSummary[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s]",
211 count(), min(), max(), sum(), mean()
212 );
213 }
214
215 /**
216 * Create an immutable object which contains statistical summary values.
217 *
218 * @param count the count of values recorded
219 * @param min the minimum value
220 * @param max the maximum value
221 * @param sum the sum of the recorded values
222 * @param mean the arithmetic mean of values
223 * @return an immutable object which contains statistical summary values
224 */
225 public static DoubleSummary of(
226 final long count,
227 final double min,
228 final double max,
229 final double sum,
230 final double mean
231 ) {
232 return new DoubleSummary(
233 count,
234 min,
235 max,
236 sum,
237 mean
238 );
239 }
240
241 /**
242 * Return a new value object of the statistical summary, currently
243 * represented by the {@code statistics} object.
244 *
245 * @param statistics the creating (mutable) statistics class
246 * @return the statistical moments
247 */
248 public static DoubleSummary of(final DoubleSummaryStatistics statistics) {
249 return new DoubleSummary(
250 statistics.getCount(),
251 statistics.getMin(),
252 statistics.getMax(),
253 statistics.getSum(),
254 statistics.getAverage()
255 );
256 }
257
258 /**
259 * Return a {@code Collector} which applies an double-producing mapping
260 * function to each input element, and returns summary-statistics for the
261 * resulting values.
262 *
263 * <pre>{@code
264 * final Stream<SomeObject> stream = ...
265 * final DoubleSummary summary = stream
266 * .collect(toDoubleSummary(v -> v.doubleValue()));
267 * }</pre>
268 *
269 * @param mapper a mapping function to apply to each element
270 * @param <T> the type of the input elements
271 * @return a {@code Collector} implementing the summary-statistics reduction
272 * @throws java.lang.NullPointerException if the given {@code mapper} is
273 * {@code null}
274 */
275 public static <T> Collector<T, ?, DoubleSummary>
276 toDoubleSummary(final ToDoubleFunction<? super T> mapper) {
277 requireNonNull(mapper);
278 return Collector.of(
279 DoubleSummaryStatistics::new,
280 (a, b) -> a.accept(mapper.applyAsDouble(b)),
281 (a, b) -> {a.combine(b); return a;},
282 DoubleSummary::of
283 );
284 }
285
286
287 /* *************************************************************************
288 * Some static helper methods.
289 **************************************************************************/
290
291 /**
292 * Return the minimum value of the given double array.
293 *
294 * @since 4.0
295 *
296 * @param values the double array.
297 * @return the minimum value or {@link Double#NaN} if the given array is
298 * empty.
299 * @throws NullPointerException if the given array is {@code null}.
300 */
301 public static double min(final double[] values) {
302 double min = NaN;
303 if (values.length > 0) {
304 min = values[0];
305
306 for (double value : values) {
307 if (value < min) {
308 min = value;
309 }
310 }
311 }
312
313 return min;
314 }
315
316 /**
317 * Return the maximum value of the given double array.
318 *
319 * @since 4.0
320 *
321 * @param values the double array.
322 * @return the maximum value or {@link Double#NaN} if the given array is
323 * empty.
324 * @throws NullPointerException if the given array is {@code null}.
325 */
326 public static double max(final double[] values) {
327 double max = NaN;
328 if (values.length > 0) {
329 max = values[0];
330
331 for (double value : values) {
332 if (value > max) {
333 max = value;
334 }
335 }
336 }
337
338 return max;
339 }
340
341 /**
342 * Return the sum of the given double array.
343 *
344 * @since 4.0
345 *
346 * @param values the values to sum up.
347 * @return the sum of the given {@code values}.
348 * @throws NullPointerException if the given array is {@code null}.
349 */
350 public static double sum(final double[] values) {
351 return DoubleAdder.sum(values);
352 }
353
354 /**
355 * Returns a double describing the arithmetic mean of the values, or
356 * {@link Double#NaN} if the {@code values} array is empty.
357 *
358 * @since 4.0
359 *
360 * @param values the values to calculate the mean of
361 * @return the arithmetic mean of the given {@code values} or
362 * {@link Double#NaN} if the {@code values} array is empty
363 * @throws NullPointerException if the given array is {@code null}.
364 */
365 public static double mean(final double[] values) {
366 return values.length > 0 ? sum(values)/values.length : NaN;
367 }
368
369 }
|