public static MeanVarianceAccumulator merge(MeanVarianceAccumulator first, MeanVarianceAccumulator second) {
        double max = Math.max(first.max, second.max);
        double min = Math.min(first.min, second.min);

        long count = first.count + second.count;
        double mean = ((first.mean * first.count) + (second.mean * second.count)) / count;
        double delta = second.mean - first.mean;
        double countFraction = ((double) first.count) / count;
        double sumSquares = first.sumSquares + second.sumSquares + ((delta*delta) * (countFraction * second.count));

        return new MeanVarianceAccumulator(max,min,mean,sumSquares,count);
    }
@Test
    public void testMerge() {
        SplittableRandom rng = new SplittableRandom(Trainer.DEFAULT_SEED);

        double[] values = new double[4096];

        for (int i = 0; i < values.length; i++) {
            values[i] = rng.nextDouble();
        }

        double[] firstValues = new double[3072];
        double[] secondValues = new double[1024];

        System.arraycopy(values, 0, firstValues, 0, firstValues.length);
        System.arraycopy(values, 3072, secondValues, 0, secondValues.length);

        MeanVarianceAccumulator totalAccumulator = new MeanVarianceAccumulator(values);

        MeanVarianceAccumulator first = new MeanVarianceAccumulator(firstValues);
        MeanVarianceAccumulator second = new MeanVarianceAccumulator(secondValues);

        MeanVarianceAccumulator sum = MeanVarianceAccumulator.merge(first,second);

        Assertions.assertEquals(totalAccumulator.getMin(),sum.getMin(), DELTA);
        Assertions.assertEquals(totalAccumulator.getMax(),sum.getMax(), DELTA);
        Assertions.assertEquals(totalAccumulator.getMean(),sum.getMean(), DELTA);
        Assertions.assertEquals(totalAccumulator.getVariance(),sum.getVariance(), DELTA);
        Assertions.assertEquals(totalAccumulator.getCount(),sum.getCount());
    }