code: private static double logLikelihood(double a, double b, 
                                          double c, double d) {
          // Table set up as:
          //  a   b
          //  c   d
          double col1sum = a + c;
          double col2sum = b + d;
          double row1sum = a + b;
          double row2sum = c + d;
          double sum = row1sum + row2sum;
          
          // Calculate the expected values for a, b, c, d
          double aExp = (row1sum / sum) * col1sum;
          double bExp = (row1sum / sum) * col2sum;
          double cExp = (row2sum / sum) * col1sum;
          double dExp = (row2sum / sum) * col2sum;
  
          // log(0) = Infinity, which messes up the calcuation.  Therefore, check
          // whether the value is zero before calculating its contribution.
          double aVal = (a == 0) ? 0 : a * Math.log(a / aExp);
          double bVal = (b == 0) ? 0 : b * Math.log(b / bExp);
          double cVal = (c == 0) ? 0 : c * Math.log(c / cExp);
          double dVal = (d == 0) ? 0 : d * Math.log(d / dExp);
  
          return 2 * (aVal + bVal + cVal + dVal);            
      }
docs: Returns the log-likelihood of the contingency table made up of the four
  values.