001/*
002 * Copyright (C) 2012 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.math;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019import static com.google.common.base.Preconditions.checkState;
020import static com.google.common.math.DoubleUtils.ensureNonNegative;
021import static com.google.common.math.StatsAccumulator.calculateNewMeanNonFinite;
022import static com.google.common.primitives.Doubles.isFinite;
023import static java.lang.Double.NaN;
024import static java.lang.Double.doubleToLongBits;
025import static java.lang.Double.isNaN;
026
027import com.google.common.annotations.GwtIncompatible;
028import com.google.common.annotations.J2ktIncompatible;
029import com.google.common.base.MoreObjects;
030import com.google.common.base.Objects;
031import java.io.Serializable;
032import java.nio.ByteBuffer;
033import java.nio.ByteOrder;
034import java.util.Iterator;
035import java.util.stream.Collector;
036import java.util.stream.DoubleStream;
037import java.util.stream.IntStream;
038import java.util.stream.LongStream;
039import javax.annotation.CheckForNull;
040
041/**
042 * A bundle of statistical summary values -- sum, count, mean/average, min and max, and several
043 * forms of variance -- that were computed from a single set of zero or more floating-point values.
044 *
045 * <p>There are two ways to obtain a {@code Stats} instance:
046 *
047 * <ul>
048 *   <li>If all the values you want to summarize are already known, use the appropriate {@code
049 *       Stats.of} factory method below. Primitive arrays, iterables and iterators of any kind of
050 *       {@code Number}, and primitive varargs are supported.
051 *   <li>Or, to avoid storing up all the data first, create a {@link StatsAccumulator} instance,
052 *       feed values to it as you get them, then call {@link StatsAccumulator#snapshot}.
053 * </ul>
054 *
055 * <p>Static convenience methods called {@code meanOf} are also provided for users who wish to
056 * calculate <i>only</i> the mean.
057 *
058 * <p><b>Java 8+ users:</b> If you are not using any of the variance statistics, you may wish to use
059 * built-in JDK libraries instead of this class.
060 *
061 * @author Pete Gillin
062 * @author Kevin Bourrillion
063 * @since 20.0
064 */
065@J2ktIncompatible
066@GwtIncompatible
067@ElementTypesAreNonnullByDefault
068public final class Stats implements Serializable {
069
070  private final long count;
071  private final double mean;
072  private final double sumOfSquaresOfDeltas;
073  private final double min;
074  private final double max;
075
076  /**
077   * Internal constructor. Users should use {@link #of} or {@link StatsAccumulator#snapshot}.
078   *
079   * <p>To ensure that the created instance obeys its contract, the parameters should satisfy the
080   * following constraints. This is the callers responsibility and is not enforced here.
081   *
082   * <ul>
083   *   <li>If {@code count} is 0, {@code mean} may have any finite value (its only usage will be to
084   *       get multiplied by 0 to calculate the sum), and the other parameters may have any values
085   *       (they will not be used).
086   *   <li>If {@code count} is 1, {@code sumOfSquaresOfDeltas} must be exactly 0.0 or {@link
087   *       Double#NaN}.
088   * </ul>
089   */
090  Stats(long count, double mean, double sumOfSquaresOfDeltas, double min, double max) {
091    this.count = count;
092    this.mean = mean;
093    this.sumOfSquaresOfDeltas = sumOfSquaresOfDeltas;
094    this.min = min;
095    this.max = max;
096  }
097
098  /**
099   * Returns statistics over a dataset containing the given values.
100   *
101   * @param values a series of values, which will be converted to {@code double} values (this may
102   *     cause loss of precision)
103   */
104  public static Stats of(Iterable<? extends Number> values) {
105    StatsAccumulator accumulator = new StatsAccumulator();
106    accumulator.addAll(values);
107    return accumulator.snapshot();
108  }
109
110  /**
111   * Returns statistics over a dataset containing the given values. The iterator will be completely
112   * consumed by this method.
113   *
114   * @param values a series of values, which will be converted to {@code double} values (this may
115   *     cause loss of precision)
116   */
117  public static Stats of(Iterator<? extends Number> values) {
118    StatsAccumulator accumulator = new StatsAccumulator();
119    accumulator.addAll(values);
120    return accumulator.snapshot();
121  }
122
123  /**
124   * Returns statistics over a dataset containing the given values.
125   *
126   * @param values a series of values
127   */
128  public static Stats of(double... values) {
129    StatsAccumulator accumulator = new StatsAccumulator();
130    accumulator.addAll(values);
131    return accumulator.snapshot();
132  }
133
134  /**
135   * Returns statistics over a dataset containing the given values.
136   *
137   * @param values a series of values
138   */
139  public static Stats of(int... values) {
140    StatsAccumulator accumulator = new StatsAccumulator();
141    accumulator.addAll(values);
142    return accumulator.snapshot();
143  }
144
145  /**
146   * Returns statistics over a dataset containing the given values.
147   *
148   * @param values a series of values, which will be converted to {@code double} values (this may
149   *     cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
150   */
151  public static Stats of(long... values) {
152    StatsAccumulator accumulator = new StatsAccumulator();
153    accumulator.addAll(values);
154    return accumulator.snapshot();
155  }
156
157  /**
158   * Returns statistics over a dataset containing the given values. The stream will be completely
159   * consumed by this method.
160   *
161   * <p>If you have a {@code Stream<Double>} rather than a {@code DoubleStream}, you should collect
162   * the values using {@link #toStats()} instead.
163   *
164   * @param values a series of values
165   * @since 28.2 (but only since 33.4.0 in the Android flavor)
166   */
167  public static Stats of(DoubleStream values) {
168    return values
169        .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll)
170        .snapshot();
171  }
172
173  /**
174   * Returns statistics over a dataset containing the given values. The stream will be completely
175   * consumed by this method.
176   *
177   * <p>If you have a {@code Stream<Integer>} rather than an {@code IntStream}, you should collect
178   * the values using {@link #toStats()} instead.
179   *
180   * @param values a series of values
181   * @since 28.2 (but only since 33.4.0 in the Android flavor)
182   */
183  public static Stats of(IntStream values) {
184    return values
185        .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll)
186        .snapshot();
187  }
188
189  /**
190   * Returns statistics over a dataset containing the given values. The stream will be completely
191   * consumed by this method.
192   *
193   * <p>If you have a {@code Stream<Long>} rather than a {@code LongStream}, you should collect the
194   * values using {@link #toStats()} instead.
195   *
196   * @param values a series of values, which will be converted to {@code double} values (this may
197   *     cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
198   * @since 28.2 (but only since 33.4.0 in the Android flavor)
199   */
200  public static Stats of(LongStream values) {
201    return values
202        .collect(StatsAccumulator::new, StatsAccumulator::add, StatsAccumulator::addAll)
203        .snapshot();
204  }
205
206  /**
207   * Returns a {@link Collector} which accumulates statistics from a {@link java.util.stream.Stream}
208   * of any type of boxed {@link Number} into a {@link Stats}. Use by calling {@code
209   * boxedNumericStream.collect(toStats())}. The numbers will be converted to {@code double} values
210   * (which may cause loss of precision).
211   *
212   * <p>If you have any of the primitive streams {@code DoubleStream}, {@code IntStream}, or {@code
213   * LongStream}, you should use the factory method {@link #of} instead.
214   *
215   * @since 28.2 (but only since 33.4.0 in the Android flavor)
216   */
217  public static Collector<Number, StatsAccumulator, Stats> toStats() {
218    return Collector.of(
219        StatsAccumulator::new,
220        (a, x) -> a.add(x.doubleValue()),
221        (l, r) -> {
222          l.addAll(r);
223          return l;
224        },
225        StatsAccumulator::snapshot,
226        Collector.Characteristics.UNORDERED);
227  }
228
229  /** Returns the number of values. */
230  public long count() {
231    return count;
232  }
233
234  /**
235   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the
236   * values. The count must be non-zero.
237   *
238   * <p>If these values are a sample drawn from a population, this is also an unbiased estimator of
239   * the arithmetic mean of the population.
240   *
241   * <h3>Non-finite values</h3>
242   *
243   * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it
244   * contains both {@link Double#POSITIVE_INFINITY} and {@link Double#NEGATIVE_INFINITY} then the
245   * result is {@link Double#NaN}. If it contains {@link Double#POSITIVE_INFINITY} and finite values
246   * only or {@link Double#POSITIVE_INFINITY} only, the result is {@link Double#POSITIVE_INFINITY}.
247   * If it contains {@link Double#NEGATIVE_INFINITY} and finite values only or {@link
248   * Double#NEGATIVE_INFINITY} only, the result is {@link Double#NEGATIVE_INFINITY}.
249   *
250   * <p>If you only want to calculate the mean, use {@link #meanOf} instead of creating a {@link
251   * Stats} instance.
252   *
253   * @throws IllegalStateException if the dataset is empty
254   */
255  public double mean() {
256    checkState(count != 0);
257    return mean;
258  }
259
260  /**
261   * Returns the sum of the values.
262   *
263   * <h3>Non-finite values</h3>
264   *
265   * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it
266   * contains both {@link Double#POSITIVE_INFINITY} and {@link Double#NEGATIVE_INFINITY} then the
267   * result is {@link Double#NaN}. If it contains {@link Double#POSITIVE_INFINITY} and finite values
268   * only or {@link Double#POSITIVE_INFINITY} only, the result is {@link Double#POSITIVE_INFINITY}.
269   * If it contains {@link Double#NEGATIVE_INFINITY} and finite values only or {@link
270   * Double#NEGATIVE_INFINITY} only, the result is {@link Double#NEGATIVE_INFINITY}.
271   */
272  public double sum() {
273    return mean * count;
274  }
275
276  /**
277   * Returns the <a href="http://en.wikipedia.org/wiki/Variance#Population_variance">population
278   * variance</a> of the values. The count must be non-zero.
279   *
280   * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It
281   * is not guaranteed to return zero when the dataset consists of the same value multiple times,
282   * due to numerical errors. However, it is guaranteed never to return a negative result.
283   *
284   * <h3>Non-finite values</h3>
285   *
286   * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link
287   * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}.
288   *
289   * @throws IllegalStateException if the dataset is empty
290   */
291  public double populationVariance() {
292    checkState(count > 0);
293    if (isNaN(sumOfSquaresOfDeltas)) {
294      return NaN;
295    }
296    if (count == 1) {
297      return 0.0;
298    }
299    return ensureNonNegative(sumOfSquaresOfDeltas) / count();
300  }
301
302  /**
303   * Returns the <a
304   * href="http://en.wikipedia.org/wiki/Standard_deviation#Definition_of_population_values">
305   * population standard deviation</a> of the values. The count must be non-zero.
306   *
307   * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It
308   * is not guaranteed to return zero when the dataset consists of the same value multiple times,
309   * due to numerical errors. However, it is guaranteed never to return a negative result.
310   *
311   * <h3>Non-finite values</h3>
312   *
313   * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link
314   * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}.
315   *
316   * @throws IllegalStateException if the dataset is empty
317   */
318  public double populationStandardDeviation() {
319    return Math.sqrt(populationVariance());
320  }
321
322  /**
323   * Returns the <a href="http://en.wikipedia.org/wiki/Variance#Sample_variance">unbiased sample
324   * variance</a> of the values. If this dataset is a sample drawn from a population, this is an
325   * unbiased estimator of the population variance of the population. The count must be greater than
326   * one.
327   *
328   * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple
329   * times, due to numerical errors. However, it is guaranteed never to return a negative result.
330   *
331   * <h3>Non-finite values</h3>
332   *
333   * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link
334   * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}.
335   *
336   * @throws IllegalStateException if the dataset is empty or contains a single value
337   */
338  public double sampleVariance() {
339    checkState(count > 1);
340    if (isNaN(sumOfSquaresOfDeltas)) {
341      return NaN;
342    }
343    return ensureNonNegative(sumOfSquaresOfDeltas) / (count - 1);
344  }
345
346  /**
347   * Returns the <a
348   * href="http://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation">
349   * corrected sample standard deviation</a> of the values. If this dataset is a sample drawn from a
350   * population, this is an estimator of the population standard deviation of the population which
351   * is less biased than {@link #populationStandardDeviation()} (the unbiased estimator depends on
352   * the distribution). The count must be greater than one.
353   *
354   * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple
355   * times, due to numerical errors. However, it is guaranteed never to return a negative result.
356   *
357   * <h3>Non-finite values</h3>
358   *
359   * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link
360   * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}.
361   *
362   * @throws IllegalStateException if the dataset is empty or contains a single value
363   */
364  public double sampleStandardDeviation() {
365    return Math.sqrt(sampleVariance());
366  }
367
368  /**
369   * Returns the lowest value in the dataset. The count must be non-zero.
370   *
371   * <h3>Non-finite values</h3>
372   *
373   * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it
374   * contains {@link Double#NEGATIVE_INFINITY} and not {@link Double#NaN} then the result is {@link
375   * Double#NEGATIVE_INFINITY}. If it contains {@link Double#POSITIVE_INFINITY} and finite values
376   * only then the result is the lowest finite value. If it contains {@link
377   * Double#POSITIVE_INFINITY} only then the result is {@link Double#POSITIVE_INFINITY}.
378   *
379   * @throws IllegalStateException if the dataset is empty
380   */
381  public double min() {
382    checkState(count != 0);
383    return min;
384  }
385
386  /**
387   * Returns the highest value in the dataset. The count must be non-zero.
388   *
389   * <h3>Non-finite values</h3>
390   *
391   * <p>If the dataset contains {@link Double#NaN} then the result is {@link Double#NaN}. If it
392   * contains {@link Double#POSITIVE_INFINITY} and not {@link Double#NaN} then the result is {@link
393   * Double#POSITIVE_INFINITY}. If it contains {@link Double#NEGATIVE_INFINITY} and finite values
394   * only then the result is the highest finite value. If it contains {@link
395   * Double#NEGATIVE_INFINITY} only then the result is {@link Double#NEGATIVE_INFINITY}.
396   *
397   * @throws IllegalStateException if the dataset is empty
398   */
399  public double max() {
400    checkState(count != 0);
401    return max;
402  }
403
404  /**
405   * {@inheritDoc}
406   *
407   * <p><b>Note:</b> This tests exact equality of the calculated statistics, including the floating
408   * point values. Two instances are guaranteed to be considered equal if one is copied from the
409   * other using {@code second = new StatsAccumulator().addAll(first).snapshot()}, if both were
410   * obtained by calling {@code snapshot()} on the same {@link StatsAccumulator} without adding any
411   * values in between the two calls, or if one is obtained from the other after round-tripping
412   * through java serialization. However, floating point rounding errors mean that it may be false
413   * for some instances where the statistics are mathematically equal, including instances
414   * constructed from the same values in a different order... or (in the general case) even in the
415   * same order. (It is guaranteed to return true for instances constructed from the same values in
416   * the same order if {@code strictfp} is in effect, or if the system architecture guarantees
417   * {@code strictfp}-like semantics.)
418   */
419  @Override
420  public boolean equals(@CheckForNull Object obj) {
421    if (obj == null) {
422      return false;
423    }
424    if (getClass() != obj.getClass()) {
425      return false;
426    }
427    Stats other = (Stats) obj;
428    return count == other.count
429        && doubleToLongBits(mean) == doubleToLongBits(other.mean)
430        && doubleToLongBits(sumOfSquaresOfDeltas) == doubleToLongBits(other.sumOfSquaresOfDeltas)
431        && doubleToLongBits(min) == doubleToLongBits(other.min)
432        && doubleToLongBits(max) == doubleToLongBits(other.max);
433  }
434
435  /**
436   * {@inheritDoc}
437   *
438   * <p><b>Note:</b> This hash code is consistent with exact equality of the calculated statistics,
439   * including the floating point values. See the note on {@link #equals} for details.
440   */
441  @Override
442  public int hashCode() {
443    return Objects.hashCode(count, mean, sumOfSquaresOfDeltas, min, max);
444  }
445
446  @Override
447  public String toString() {
448    if (count() > 0) {
449      return MoreObjects.toStringHelper(this)
450          .add("count", count)
451          .add("mean", mean)
452          .add("populationStandardDeviation", populationStandardDeviation())
453          .add("min", min)
454          .add("max", max)
455          .toString();
456    } else {
457      return MoreObjects.toStringHelper(this).add("count", count).toString();
458    }
459  }
460
461  double sumOfSquaresOfDeltas() {
462    return sumOfSquaresOfDeltas;
463  }
464
465  /**
466   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the
467   * values. The count must be non-zero.
468   *
469   * <p>The definition of the mean is the same as {@link Stats#mean}.
470   *
471   * @param values a series of values, which will be converted to {@code double} values (this may
472   *     cause loss of precision)
473   * @throws IllegalArgumentException if the dataset is empty
474   */
475  public static double meanOf(Iterable<? extends Number> values) {
476    return meanOf(values.iterator());
477  }
478
479  /**
480   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the
481   * values. The count must be non-zero.
482   *
483   * <p>The definition of the mean is the same as {@link Stats#mean}.
484   *
485   * @param values a series of values, which will be converted to {@code double} values (this may
486   *     cause loss of precision)
487   * @throws IllegalArgumentException if the dataset is empty
488   */
489  public static double meanOf(Iterator<? extends Number> values) {
490    checkArgument(values.hasNext());
491    long count = 1;
492    double mean = values.next().doubleValue();
493    while (values.hasNext()) {
494      double value = values.next().doubleValue();
495      count++;
496      if (isFinite(value) && isFinite(mean)) {
497        // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
498        mean += (value - mean) / count;
499      } else {
500        mean = calculateNewMeanNonFinite(mean, value);
501      }
502    }
503    return mean;
504  }
505
506  /**
507   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the
508   * values. The count must be non-zero.
509   *
510   * <p>The definition of the mean is the same as {@link Stats#mean}.
511   *
512   * @param values a series of values
513   * @throws IllegalArgumentException if the dataset is empty
514   */
515  public static double meanOf(double... values) {
516    checkArgument(values.length > 0);
517    double mean = values[0];
518    for (int index = 1; index < values.length; index++) {
519      double value = values[index];
520      if (isFinite(value) && isFinite(mean)) {
521        // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
522        mean += (value - mean) / (index + 1);
523      } else {
524        mean = calculateNewMeanNonFinite(mean, value);
525      }
526    }
527    return mean;
528  }
529
530  /**
531   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the
532   * values. The count must be non-zero.
533   *
534   * <p>The definition of the mean is the same as {@link Stats#mean}.
535   *
536   * @param values a series of values
537   * @throws IllegalArgumentException if the dataset is empty
538   */
539  public static double meanOf(int... values) {
540    checkArgument(values.length > 0);
541    double mean = values[0];
542    for (int index = 1; index < values.length; index++) {
543      double value = values[index];
544      if (isFinite(value) && isFinite(mean)) {
545        // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
546        mean += (value - mean) / (index + 1);
547      } else {
548        mean = calculateNewMeanNonFinite(mean, value);
549      }
550    }
551    return mean;
552  }
553
554  /**
555   * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the
556   * values. The count must be non-zero.
557   *
558   * <p>The definition of the mean is the same as {@link Stats#mean}.
559   *
560   * @param values a series of values, which will be converted to {@code double} values (this may
561   *     cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
562   * @throws IllegalArgumentException if the dataset is empty
563   */
564  public static double meanOf(long... values) {
565    checkArgument(values.length > 0);
566    double mean = values[0];
567    for (int index = 1; index < values.length; index++) {
568      double value = values[index];
569      if (isFinite(value) && isFinite(mean)) {
570        // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
571        mean += (value - mean) / (index + 1);
572      } else {
573        mean = calculateNewMeanNonFinite(mean, value);
574      }
575    }
576    return mean;
577  }
578
579  // Serialization helpers
580
581  /** The size of byte array representation in bytes. */
582  static final int BYTES = (Long.SIZE + Double.SIZE * 4) / Byte.SIZE;
583
584  /**
585   * Gets a byte array representation of this instance.
586   *
587   * <p><b>Note:</b> No guarantees are made regarding stability of the representation between
588   * versions.
589   */
590  public byte[] toByteArray() {
591    ByteBuffer buff = ByteBuffer.allocate(BYTES).order(ByteOrder.LITTLE_ENDIAN);
592    writeTo(buff);
593    return buff.array();
594  }
595
596  /**
597   * Writes to the given {@link ByteBuffer} a byte representation of this instance.
598   *
599   * <p><b>Note:</b> No guarantees are made regarding stability of the representation between
600   * versions.
601   *
602   * @param buffer A {@link ByteBuffer} with at least BYTES {@link ByteBuffer#remaining}, ordered as
603   *     {@link ByteOrder#LITTLE_ENDIAN}, to which a BYTES-long byte representation of this instance
604   *     is written. In the process increases the position of {@link ByteBuffer} by BYTES.
605   */
606  void writeTo(ByteBuffer buffer) {
607    checkNotNull(buffer);
608    checkArgument(
609        buffer.remaining() >= BYTES,
610        "Expected at least Stats.BYTES = %s remaining , got %s",
611        BYTES,
612        buffer.remaining());
613    buffer
614        .putLong(count)
615        .putDouble(mean)
616        .putDouble(sumOfSquaresOfDeltas)
617        .putDouble(min)
618        .putDouble(max);
619  }
620
621  /**
622   * Creates a Stats instance from the given byte representation which was obtained by {@link
623   * #toByteArray}.
624   *
625   * <p><b>Note:</b> No guarantees are made regarding stability of the representation between
626   * versions.
627   */
628  public static Stats fromByteArray(byte[] byteArray) {
629    checkNotNull(byteArray);
630    checkArgument(
631        byteArray.length == BYTES,
632        "Expected Stats.BYTES = %s remaining , got %s",
633        BYTES,
634        byteArray.length);
635    return readFrom(ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN));
636  }
637
638  /**
639   * Creates a Stats instance from the byte representation read from the given {@link ByteBuffer}.
640   *
641   * <p><b>Note:</b> No guarantees are made regarding stability of the representation between
642   * versions.
643   *
644   * @param buffer A {@link ByteBuffer} with at least BYTES {@link ByteBuffer#remaining}, ordered as
645   *     {@link ByteOrder#LITTLE_ENDIAN}, from which a BYTES-long byte representation of this
646   *     instance is read. In the process increases the position of {@link ByteBuffer} by BYTES.
647   */
648  static Stats readFrom(ByteBuffer buffer) {
649    checkNotNull(buffer);
650    checkArgument(
651        buffer.remaining() >= BYTES,
652        "Expected at least Stats.BYTES = %s remaining , got %s",
653        BYTES,
654        buffer.remaining());
655    return new Stats(
656        buffer.getLong(),
657        buffer.getDouble(),
658        buffer.getDouble(),
659        buffer.getDouble(),
660        buffer.getDouble());
661  }
662
663  private static final long serialVersionUID = 0;
664}