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