import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;

public abstract class Equations {

    public static double pValue(Integer w, Integer w_a, Integer w_b, double w_ab_d) {
        int w_ab = (int) w_ab_d;
        double pv = 0.0;
        Integer maxOverlap = w_a >= w_b ? w_b : w_a;
        for(int i = w_ab; i <= maxOverlap; i++){
            pv += probPairedByChance(w, i, w_a, w_b);
        }
        return pv;
    }

    private static double probPairedByChance(Integer w, Integer w_a, Integer w_b, Integer w_ab){
        BigInteger numer1 = choose(w, w_ab);
        BigInteger numer2 = choose(w - w_ab, w_a - w_ab);
        BigInteger numer3 = choose(w - w_a, w_b - w_ab);
        BigInteger numer = numer1.multiply(numer2.multiply(numer3));
        BigInteger denom = choose(w, w_a).multiply(choose(w, w_b));
        BigDecimal numer_d = new BigDecimal(numer);
        BigDecimal denom_d = new BigDecimal(denom);
        BigDecimal prob = numer_d.divide(denom_d, MathContext.DECIMAL64);
        return prob.doubleValue();
    }

    /*
     * This works because nC(k+1) = nCk * (n-k)/(k+1)
     * Since nC0 = 1, can start there and generate all the rest.
     */
     public static BigInteger choose(final int N, final int K) {
         BigInteger nCk = BigInteger.ONE;
         for (int k = 0; k < K; k++) {
             nCk = nCk.multiply(BigInteger.valueOf(N-k))
                 .divide(BigInteger.valueOf(k+1));
         }
         return nCk;
     }
}
