All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.statistics.descriptive.Statistics Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.statistics.descriptive;

import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;

/**
 * Utility methods for statistics.
 *
 * @since 1.1
 */
final class Statistics {
    /** A no-operation double consumer. This is exposed for testing. */
    static final DoubleConsumer DOUBLE_NOOP = new DoubleConsumer() {
        @Override
        public void accept(double value) {
            // Do nothing
        }

        @Override
        public DoubleConsumer andThen(DoubleConsumer after) {
            // Delegate to the after consumer
            return after;
        }
    };

    /** A no-operation int consumer. This is exposed for testing. */
    static final IntConsumer INT_NOOP = new IntConsumer() {
        @Override
        public void accept(int value) {
            // Do nothing
        }

        @Override
        public IntConsumer andThen(IntConsumer after) {
            // Delegate to the after consumer
            return after;
        }
    };

    /** A no-operation long consumer. This is exposed for testing. */
    static final LongConsumer LONG_NOOP = new LongConsumer() {
        @Override
        public void accept(long value) {
            // Do nothing
        }

        @Override
        public LongConsumer andThen(LongConsumer after) {
            // Delegate to the after consumer
            return after;
        }
    };

    /** Error message for an incompatible statistics. */
    private static final String INCOMPATIBLE_STATISTICS = "Incompatible statistics";

    /** No instances. */
    private Statistics() {}

    /**
     * Add all the {@code values} to the {@code statistic}.
     *
     * @param  Type of the statistic
     * @param statistic Statistic.
     * @param values Values.
     * @return the statistic
     */
    static  T add(T statistic, double[] values) {
        for (final double x : values) {
            statistic.accept(x);
        }
        return statistic;
    }

    /**
     * Add all the {@code values} to the {@code statistic}.
     *
     * @param  Type of the statistic
     * @param statistic Statistic.
     * @param values Values.
     * @return the statistic
     */
    static  T add(T statistic, int[] values) {
        for (final double x : values) {
            statistic.accept(x);
        }
        return statistic;
    }

    /**
     * Add all the {@code values} to the {@code statistic}.
     *
     * @param  Type of the statistic
     * @param statistic Statistic.
     * @param values Values.
     * @return the statistic
     */
    static  T add(T statistic, long[] values) {
        for (final double x : values) {
            statistic.accept(x);
        }
        return statistic;
    }

    /**
     * Add all the {@code values} to the {@code statistic}.
     *
     * @param  Type of the statistic
     * @param statistic Statistic.
     * @param values Values.
     * @return the statistic
     */
    static  T add(T statistic, int[] values) {
        for (final int x : values) {
            statistic.accept(x);
        }
        return statistic;
    }

    /**
     * Add all the {@code values} to the {@code statistic}.
     *
     * @param  Type of the statistic
     * @param statistic Statistic.
     * @param values Values.
     * @return the statistic
     */
    static  T add(T statistic, long[] values) {
        for (final long x : values) {
            statistic.accept(x);
        }
        return statistic;
    }

    /**
     * Returns {@code true} if the second central moment {@code m2} is effectively
     * zero given the magnitude of the first raw moment {@code m1}.
     *
     * 

This method shares the logic for detecting a zero variance among implementations * that divide by the variance (e.g. skewness, kurtosis). * * @param m1 First raw moment (mean). * @param m2 Second central moment (biased variance). * @return true if the variance is zero */ static boolean zeroVariance(double m1, double m2) { // Note: Commons Math checks the variance is < 1e-19. // The absolute threshold does not account for the magnitude of the sample. // This checks the average squared deviation from the mean (m2) // is smaller than the squared precision of the mean (m1). // Precision is set to 15 decimal digits // (1e-15 ~ 4.5 eps where eps = 2^-52). final double meanPrecision = 1e-15 * m1; return m2 <= meanPrecision * meanPrecision; } /** * Chain the {@code consumers} into a single composite consumer. Ignore any {@code null} * consumer. Returns {@code null} if all arguments are {@code null}. * * @param consumers Consumers. * @return a composed consumer (or null) */ static DoubleConsumer compose(DoubleConsumer... consumers) { DoubleConsumer action = DOUBLE_NOOP; for (final DoubleConsumer consumer : consumers) { if (consumer != null) { action = action.andThen(consumer); } } return action == DOUBLE_NOOP ? null : action; } /** * Chain the {@code consumers} into a single composite consumer. Ignore any {@code null} * consumer. Returns {@code null} if all arguments are {@code null}. * * @param consumers Consumers. * @return a composed consumer (or null) */ static IntConsumer compose(IntConsumer... consumers) { IntConsumer action = INT_NOOP; for (final IntConsumer consumer : consumers) { if (consumer != null) { action = action.andThen(consumer); } } return action == INT_NOOP ? null : action; } /** * Chain the {@code consumers} into a single composite consumer. Ignore any {@code null} * consumer. Returns {@code null} if all arguments are {@code null}. * * @param consumers Consumers. * @return a composed consumer (or null) */ static LongConsumer compose(LongConsumer... consumers) { LongConsumer action = LONG_NOOP; for (final LongConsumer consumer : consumers) { if (consumer != null) { action = action.andThen(consumer); } } return action == LONG_NOOP ? null : action; } /** * Gets the statistic result using the {@code int} value. * Return {@code null} is the statistic is {@code null}. * * @param s Statistic. * @return the result or null */ static StatisticResult getResultAsIntOrNull(StatisticResult s) { if (s != null) { return (IntStatisticResult) s::getAsInt; } return null; } /** * Gets the statistic result using the {@code long} value. * Return {@code null} is the statistic is {@code null}. * * @param s Statistic. * @return the result or null */ static StatisticResult getResultAsLongOrNull(StatisticResult s) { if (s != null) { return (LongStatisticResult) s::getAsLong; } return null; } /** * Gets the statistic result using the {@code double} value. * Return {@code null} is the statistic is {@code null}. * * @param s Statistic. * @return the result or null */ static StatisticResult getResultAsDoubleOrNull(StatisticResult s) { if (s != null) { return s::getAsDouble; } return null; } /** * Gets the statistic result using the {@code BigInteger} value. * Return {@code null} is the statistic is {@code null}. * * @param s Statistic. * @return the result or null */ static StatisticResult getResultAsBigIntegerOrNull(StatisticResult s) { if (s != null) { return (BigIntegerStatisticResult) s::getAsBigInteger; } return null; } /** * Check left-hand side argument {@code a} is {@code null} or else the right-hand side * argument {@code b} must also be non-{@code null} so the statistics can be combined. * * @param {@link StatisticResult} being accumulated. * @param a LHS. * @param b RHS. * @throws IllegalArgumentException if the objects cannot be combined */ static > void checkCombineCompatible(T a, T b) { if (a != null && b == null) { throw new IllegalArgumentException(INCOMPATIBLE_STATISTICS); } } /** * Check left-hand side argument {@code a} is {@code null} or else the right-hand side * argument {@code b} must be run-time assignable to the same class as {@code a} * so the statistics can be combined. * * @param a LHS. * @param b RHS. * @throws IllegalArgumentException if the objects cannot be combined */ static void checkCombineAssignable(FirstMoment a, FirstMoment b) { if (a != null && (b == null || !a.getClass().isAssignableFrom(b.getClass()))) { throw new IllegalArgumentException(INCOMPATIBLE_STATISTICS); } } /** * If the left-hand side argument {@code a} is non-{@code null}, combine it with the * right-hand side argument {@code b}. * * @param {@link StatisticResult} being accumulated. * @param a LHS. * @param b RHS. */ static > void combine(T a, T b) { if (a != null) { a.combine(b); } } /** * If the left-hand side argument {@code a} is non-{@code null}, combine it with the * right-hand side argument {@code b}. Assumes that the RHS is run-time assignable * to the same class as LHS. * * @param a LHS. * @param b RHS. * @see #checkCombineAssignable(FirstMoment, FirstMoment) */ static void combineMoment(FirstMoment a, FirstMoment b) { // Avoid reflection and use the simpler instanceof if (a instanceof SumOfFourthDeviations) { ((SumOfFourthDeviations) a).combine((SumOfFourthDeviations) b); } else if (a instanceof SumOfCubedDeviations) { ((SumOfCubedDeviations) a).combine((SumOfCubedDeviations) b); } else if (a instanceof SumOfSquaredDeviations) { ((SumOfSquaredDeviations) a).combine((SumOfSquaredDeviations) b); } else if (a != null) { a.combine(b); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy