Comparison { @SuppressWarnings("WeakerAccess") public static double llr(double[][] count) { if (count.length == 0) { throw new IllegalArgumentException("Must have some data in llr"); } int columns = count[0].length; int rows = count.length; double[] rowSums = new double[rows]; double[] colSums = new double[columns]; double totalCount = 0; double h = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { double k = count[i][j]; rowSums[i] += k; colSums[j] += k; if (k < 0) { throw new IllegalArgumentException(String.format("Illegal negative count (%.5f) at %d,%d", k, i, j)); } if (k > 0) { h += k * Math.log(k); totalCount += k; } } } double normalizer = totalCount * Math.log(totalCount); h -= normalizer; double hr = 0; for (int i = 0; i < rows; i++) { if (rowSums[i] > 0) { hr += rowSums[i] * Math.log(rowSums[i]); } } hr -= normalizer; double hc = 0; for (int j = 0; j < columns; j++) { if (colSums[j] > 0) { hc += colSums[j] * Math.log(colSums[j]); } } hc -= normalizer; return 2 * (h - hr - hc); }  @SuppressWarnings("WeakerAccess") static double compareChi2(TDigest dist1, TDigest dist2, double[] qCuts); @SuppressWarnings("WeakerAccess") static double compareChi2(Histogram dist1, Histogram dist2); @SuppressWarnings("WeakerAccess") static double llr(double[][] count); static double ks(TDigest d1, TDigest d2);  }
@Test public void llr() { double[][] count = new double[2][2]; count[0][0] = 1; count[1][1] = 1; assertEquals(2.77, Comparison.llr(count), 0.01); count[0][0] = 3; count[0][1] = 1; count[1][0] = 1; count[1][1] = 3; assertEquals(2.09, Comparison.llr(count), 0.01); count[1][1] = 5; assertEquals(3.55, Comparison.llr(count), 0.01); }