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