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