// Path: fast-ftrl-proximal/src/main/java/io/scaledml/core/util/Util.java
// public class Util {
//     private final static HashFunction murmur = Hashing.murmur3_128(42);
// 
//     private final static HashFunction murmur32 = Hashing.murmur3_32(17);
//     public static final double EPSILON = 0.0000001;
// 
//     public static boolean doublesEqual(double d1, double d2, double precision) {
//         if (!Doubles.isFinite(d1) || !Doubles.isFinite(d2)) {
//             return false;
//         }
//         return Math.abs(d1 - d2) < precision;
//     }
// 
//     public static boolean doublesEqual(double d1, double d2) {
//         return doublesEqual(d1, d2, EPSILON);
//     }
// 
//     public static HashFunction murmur() {
//         return murmur;
//     }
// 
//     public static HashFunction murmur32() {
//         return murmur32;
//     }
// 
//     public static boolean doublesLess(double v1, double v2) {
//         return v1 < v2 - EPSILON;
//     }
// }


import com.clearspring.analytics.stream.quantile.TDigest;
import com.clearspring.analytics.util.Preconditions;
import io.scaledml.core.util.Util;
import it.unimi.dsi.fastutil.doubles.Double2DoubleMap;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleList;
import org.junit.Test;
import java.util.concurrent.ThreadLocalRandom;
import static org.junit.Assert.*;
            digest.add(ThreadLocalRandom.current().nextDouble());
        }
        NumericalFeaturesStatistics st = new NumericalFeaturesStatistics()
                .percentsHistogramStep(0.01);
        Binning binning = st.buildBinning(digest, 0.);
        assertEquals(0, binning.getInsertionPoint(0.));
        assertEquals(-1, binning.getInsertionPoint(-0.1));
        assertEquals(99, binning.getInsertionPoint(1.));
        assertEquals(99, binning.getInsertionPoint(Double.MAX_VALUE));
        int middleInsertion = binning.getInsertionPoint(0.5);
        assertTrue("middleInsertion is " + middleInsertion, middleInsertion > 45 && middleInsertion < 55);
        int quarterInsertion = binning.getInsertionPoint(0.25);
        assertTrue("quarterInsertion is " + quarterInsertion, quarterInsertion > 20 && quarterInsertion < 30);
        int thirdQuarterInsertion = binning.getInsertionPoint(0.75);
        assertTrue("thirdQuarterInsertion is " + thirdQuarterInsertion, thirdQuarterInsertion > 70 && thirdQuarterInsertion < 80);
    }

    @Test
    public void testBuildHistogram() {
        Binning binning = new Binning();
        for (int i = 0; i < 99; i++) {
            binning.addPercentile(ThreadLocalRandom.current().nextDouble());
        }
        binning.addPercentile(0.).finishBuild();
        NumericalFeaturesStatistics st = new NumericalFeaturesStatistics()
                .percentsHistogramStep(0.01);
        Double2DoubleMap histogram = st.buildHistogram(binning, 0, 1);
        assertEquals(102, histogram.size());
        double sum = histogram.values()
                .stream().mapToDouble(Double::doubleValue).sum();
// Path: fast-ftrl-proximal/src/main/java/io/scaledml/core/util/Util.java
// public class Util {
//     private final static HashFunction murmur = Hashing.murmur3_128(42);
// 
//     private final static HashFunction murmur32 = Hashing.murmur3_32(17);
//     public static final double EPSILON = 0.0000001;
// 
//     public static boolean doublesEqual(double d1, double d2, double precision) {
//         if (!Doubles.isFinite(d1) || !Doubles.isFinite(d2)) {
//             return false;
//         }
//         return Math.abs(d1 - d2) < precision;
//     }
// 
//     public static boolean doublesEqual(double d1, double d2) {
//         return doublesEqual(d1, d2, EPSILON);
//     }
// 
//     public static HashFunction murmur() {
//         return murmur;
//     }
// 
//     public static HashFunction murmur32() {
//         return murmur32;
//     }
// 
//     public static boolean doublesLess(double v1, double v2) {
//         return v1 < v2 - EPSILON;
//     }
// }


// Path: fast-ftrl-proximal/src/test/java/io/scaledml/features/NumericalFeaturesStatisticsTest.java
import com.clearspring.analytics.stream.quantile.TDigest;
import com.clearspring.analytics.util.Preconditions;
import io.scaledml.core.util.Util;
import it.unimi.dsi.fastutil.doubles.Double2DoubleMap;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleList;
import org.junit.Test;
import java.util.concurrent.ThreadLocalRandom;
import static org.junit.Assert.*;

            digest.add(ThreadLocalRandom.current().nextDouble());
        }
        NumericalFeaturesStatistics st = new NumericalFeaturesStatistics()
                .percentsHistogramStep(0.01);
        Binning binning = st.buildBinning(digest, 0.);
        assertEquals(0, binning.getInsertionPoint(0.));
        assertEquals(-1, binning.getInsertionPoint(-0.1));
        assertEquals(99, binning.getInsertionPoint(1.));
        assertEquals(99, binning.getInsertionPoint(Double.MAX_VALUE));
        int middleInsertion = binning.getInsertionPoint(0.5);
        assertTrue("middleInsertion is " + middleInsertion, middleInsertion > 45 && middleInsertion < 55);
        int quarterInsertion = binning.getInsertionPoint(0.25);
        assertTrue("quarterInsertion is " + quarterInsertion, quarterInsertion > 20 && quarterInsertion < 30);
        int thirdQuarterInsertion = binning.getInsertionPoint(0.75);
        assertTrue("thirdQuarterInsertion is " + thirdQuarterInsertion, thirdQuarterInsertion > 70 && thirdQuarterInsertion < 80);
    }

    @Test
    public void testBuildHistogram() {
        Binning binning = new Binning();
        for (int i = 0; i < 99; i++) {
            binning.addPercentile(ThreadLocalRandom.current().nextDouble());
        }
        binning.addPercentile(0.).finishBuild();
        NumericalFeaturesStatistics st = new NumericalFeaturesStatistics()
                .percentsHistogramStep(0.01);
        Double2DoubleMap histogram = st.buildHistogram(binning, 0, 1);
        assertEquals(102, histogram.size());
        double sum = histogram.values()
                .stream().mapToDouble(Double::doubleValue).sum();
        assertEquals(1., sum, Util.EPSILON);