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

org.meeuw.math.statistics.StatisticalDoubleImpl Maven / Gradle / Ivy

/*
 *  Copyright 2022 Michiel Meeuwissen
 *
 *    Licensed 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
 *
 *        https://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.meeuw.math.statistics;

import lombok.Getter;

import java.math.BigDecimal;
import java.util.OptionalDouble;
import java.util.function.DoubleConsumer;

import org.meeuw.math.*;
import org.meeuw.math.exceptions.DivisionByZeroException;
import org.meeuw.math.exceptions.IllegalLogarithmException;
import org.meeuw.math.uncertainnumbers.UncertainNumber;
import org.meeuw.math.uncertainnumbers.field.*;

/**
 * Represents a set of measured values. The value represents the average value.
 * {@link #toString} present the current value, but only the relevant digits. The standard
 * deviation {@link #getStandardDeviation} is used to determine what digits are relevant.
 *
 * @author Michiel Meeuwissen
 */

public class StatisticalDoubleImpl
    extends AbstractStatisticalDouble
    implements UncertainReal, StatisticalDouble, DoubleConsumer {

    @Getter
    private double sum = 0;
    @Getter
    private double sumOfSquares = 0;

    @Getter
    private double min = Double.MAX_VALUE;
    @Getter
    private double max = -1 * Double.MAX_VALUE;

    public StatisticalDoubleImpl() {

    }

    protected StatisticalDoubleImpl(double sum, double sumOfSquares, int count) {
        super(count);
        this.sum = sum;
        this.sumOfSquares = sumOfSquares;
    }

    @Override
    public boolean isExact() {
        return min == max &&  doubleUncertainty() == EXACT;
    }

    @Override
    public StatisticalDoubleImpl copy() {
        StatisticalDoubleImpl m = new StatisticalDoubleImpl(sum, sumOfSquares, count);
        m.max = max;
        m.min = min;
        return m;
    }

    /**
     * Enters new value(s).
     * @param ds doubles to add
     * @return this
     */
    public StatisticalDoubleImpl enter(double... ds) {
        for (double d : ds) {
            sum += d;
            sumOfSquares += d * d;
            count++;
            max = Math.max(max, d);
            min = Math.min(min, d);
        }
        return this;
    }

    /**
     * Assuming that the measurement m is from the same set, add it to the already existing
     * statistics.
     * See also {@link StatisticalDoubleImpl#plus(UncertainReal)} which is something entirely different.
     */
    @Override
    public StatisticalDoubleImpl enter(StatisticalDoubleImpl m) {
        sum += m.sum;
        sumOfSquares += m.sumOfSquares;
        count += m.count;
        max = Math.max(max, m.max);
        min = Math.max(min, m.min);
        return this;
    }


    @Override
    public StatisticalDoubleImpl multiply(double d) {
        sum *= d;
        sumOfSquares *= d * d;
        max = DoubleUtils.round(max * d);
        min = DoubleUtils.round(min * d);
        return this;
    }

    @Override
    public OptionalDouble optionalDoubleMean() {
        if (count == 0) {
            return OptionalDouble.empty();
        } else {
            return OptionalDouble.of(sum / count);
        }
    }

    @Override
    public UncertainRealField getStructure() {
        return UncertainRealField.INSTANCE;
    }

    @Override
    public UncertainReal exp() {
        double value = Math.exp(getValue());
        return new UncertainDoubleElement(value, getUncertainty()); /// todo);
    }

    @Override
    @NonAlgebraic(reason = NonAlgebraic.Reason.ELEMENTS, value="Can't be taken of negative values")
    public UncertainReal ln()  throws IllegalLogarithmException {
        UncertainNumber value = operations().ln(getValue());
        return new UncertainDoubleElement(value.getValue(), value.getUncertainty());
    }


    @Override
    public UncertainDoubleElement reciprocal() {
        if (getValue() == 0d) {
            throw new DivisionByZeroException("Division by zero");
        }
        double value = 1d / getValue();
        return new UncertainDoubleElement(value, value * getFractionalUncertainty() + DoubleUtils.uncertaintyForDouble(value));
    }

    @Override
    public BigDecimal bigDecimalValue() {
        return BigDecimal.valueOf(getMean());
    }

    @Override
    public double doubleStandardDeviation() {
        double mean = getMean();
        if (count < 2) {
            return Double.NaN;
        }
        return Math.sqrt(sumOfSquares / count - mean * mean);
    }

    @Override
    public StatisticalDoubleImpl plus(double summand) {
        return
            new StatisticalDoubleImpl(
                sum + summand * count,
                sumOfSquares + summand * summand * count + 2 * sum * summand, count);
    }

    @Override
    public void accept(double value) {
        enter(value);
    }

    @Override
    public void reset() {
        super.reset();
        sum = 0;
        sumOfSquares = 0;
        max = Double.MIN_VALUE;
        min = Double.MAX_VALUE;
    }

    @Override
    public StatisticalDoubleImpl abs() {
        if (isPositive()) {
            return this;
        } else {
            return new StatisticalDoubleImpl(-1 * sum, sumOfSquares, count);
        }
    }


}







© 2015 - 2025 Weber Informatics LLC | Privacy Policy