// Path: src/main/java/ro/hasna/ts/math/util/TimeSeriesPrecision.java
// public class TimeSeriesPrecision {
//     public static final double EPSILON = FastMath.pow(2, -30);
// 
//     /**
//      * Private constructor.
//      */
//     private TimeSeriesPrecision() {
//     }
// }


import org.apache.commons.math3.exception.NumberIsTooSmallException;
import org.apache.commons.math3.util.Precision;
import ro.hasna.ts.math.util.TimeSeriesPrecision;
        this.minScalingFactor = minScalingFactor;

        if (maxScalingFactor < minScalingFactor) {
            throw new NumberIsTooSmallException(maxScalingFactor, minScalingFactor, true);
        }
        this.maxScalingFactor = maxScalingFactor;

        if (steps < 1) {
            throw new NumberIsTooSmallException(steps, 1, true);
        }
        this.steps = steps;

        this.distance = distance;
    }

    @Override
    public double compute(double[] a, double[] b) {
        return compute(a, b, Double.POSITIVE_INFINITY);
    }

    @Override
    public double compute(double[] a, double[] b, double cutOffValue) {
        double min = Double.POSITIVE_INFINITY;
        double[] aux = new double[a.length];
        if (steps == 1) {
            double scalingFactor = (minScalingFactor + maxScalingFactor) / 2;
            return computeDistance(a, b, aux, scalingFactor, cutOffValue);
        }

        double interval = (maxScalingFactor - minScalingFactor) / (steps - 1);
// Path: src/main/java/ro/hasna/ts/math/util/TimeSeriesPrecision.java
// public class TimeSeriesPrecision {
//     public static final double EPSILON = FastMath.pow(2, -30);
// 
//     /**
//      * Private constructor.
//      */
//     private TimeSeriesPrecision() {
//     }
// }


// Path: src/main/java/ro/hasna/ts/math/ml/distance/UniformScalingDistance.java
import org.apache.commons.math3.exception.NumberIsTooSmallException;
import org.apache.commons.math3.util.Precision;
import ro.hasna.ts.math.util.TimeSeriesPrecision;

        this.minScalingFactor = minScalingFactor;

        if (maxScalingFactor < minScalingFactor) {
            throw new NumberIsTooSmallException(maxScalingFactor, minScalingFactor, true);
        }
        this.maxScalingFactor = maxScalingFactor;

        if (steps < 1) {
            throw new NumberIsTooSmallException(steps, 1, true);
        }
        this.steps = steps;

        this.distance = distance;
    }

    @Override
    public double compute(double[] a, double[] b) {
        return compute(a, b, Double.POSITIVE_INFINITY);
    }

    @Override
    public double compute(double[] a, double[] b, double cutOffValue) {
        double min = Double.POSITIVE_INFINITY;
        double[] aux = new double[a.length];
        if (steps == 1) {
            double scalingFactor = (minScalingFactor + maxScalingFactor) / 2;
            return computeDistance(a, b, aux, scalingFactor, cutOffValue);
        }

        double interval = (maxScalingFactor - minScalingFactor) / (steps - 1);
        if (Precision.equals(interval, 0.0, TimeSeriesPrecision.EPSILON)) {