@UdafFactory(description = "Compute sample standard deviation of column with type Double.",
      aggregateSchema = "STRUCT<SUM double, COUNT bigint, M2 double>")
  public static TableUdaf<Double, Struct, Double> stdDevDouble() {
    return getStdDevImplementation(
        0.0,
        STRUCT_DOUBLE,
        (agg, newValue) -> newValue + agg.getFloat64(SUM),
        (agg, newValue) -> newValue * (agg.getInt64(COUNT) + 1) - (agg.getFloat64(SUM) + newValue),
        (agg1, agg2) ->
            agg1.getFloat64(SUM) / agg1.getInt64(COUNT)
                - agg2.getFloat64(SUM) / agg2.getInt64(COUNT),
        (agg1, agg2) -> agg1.getFloat64(SUM) + agg2.getFloat64(SUM),
        (agg, valueToRemove) -> agg.getFloat64(SUM) - valueToRemove);
  }
@Test
  public void shouldMergeDoubles() {
    final TableUdaf<Double, Struct, Double> udaf = stdDevDouble();

    Struct left = udaf.initialize();
    final Double[] leftValues = new Double[] {5.5, 8.4, 10.9};
    for (final Double thisValue : leftValues) {
      left = udaf.aggregate(thisValue, left);
    }

    Struct right = udaf.initialize();
    final Double[] rightValues = new Double[] {6.3, 7.2, 9.7};
    for (final Double thisValue : rightValues) {
      right = udaf.aggregate(thisValue, right);
    }

    final Struct merged = udaf.merge(left, right);

    assertThat(merged.getInt64(COUNT), equalTo(6L));
    assertThat(merged.getFloat64(SUM), equalTo(48.0));
    assertThat(merged.getFloat64(M2), equalTo(21.240000000000006));

    final double standardDev = udaf.map(merged);
    assertThat(standardDev, equalTo(4.248000000000001));
  }