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