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