/*
 * Copyright 2015-16, Yahoo! Inc.
 * Licensed under the terms of the Apache License 2.0. See LICENSE file at the project root for terms.
 */

package com.yahoo.sketches;

import com.yahoo.sketches.theta.Sketch;

/**
 * This class is used to compute the bounds on the estimate of the ratio <i>B / A</i>, where:
 * <ul>
 * <li><i>A</i> is a Theta Sketch of unique identifiers.</li>
 * <li><i>B</i> is a Theta Sketch of a subset <i>B</i> of <i>A</i> obtained by an intersection
 * with a Theta Sketch <i>C</i>.</li>
 * </ul>
 * The theta of A cannot be greater than the theta of B.
 * 
 * @author Kevin Lang
 */
public final class BoundsOnRatiosInThetaSketchedSets {
  
  private BoundsOnRatiosInThetaSketchedSets() {}
  
  /**
   * Gets the approximate lower bound for B over A based on a 95% confidence interval
   * @param sketchA the sketch A
   * @param sketchB the sketch B
   * @return the approximate lower bound for B over A
   */
  public static double getLowerBoundForBoverA(Sketch sketchA, Sketch sketchB) {
    double thetaA = sketchA.getTheta();
    double thetaB = sketchB.getTheta();
    checkThetas(thetaA, thetaB);
    
    int countB = sketchB.getRetainedEntries(true);
    int countA = (thetaB == thetaA) ? sketchA.getRetainedEntries(true) 
        : sketchA.getCountLessThanTheta(thetaB);
    
    if (countA <= 0) return 0;
    
    return BoundsOnRatiosInSampledSets.getLowerBoundForBoverA(countA, countB, thetaB);
  }
  
  /**
   * Gets the approximate upper bound for B over A based on a 95% confidence interval
   * @param sketchA the sketch A
   * @param sketchB the sketch B
   * @return the approximate upper bound for B over A
   */
  public static double getUpperBoundForBoverA(Sketch sketchA, Sketch sketchB) {
    double thetaA = sketchA.getTheta();
    double thetaB = sketchB.getTheta();
    checkThetas(thetaA, thetaB);

    int countB = sketchB.getRetainedEntries(true);
    int countA = (thetaB == thetaA) ? sketchA.getRetainedEntries(true) 
        : sketchA.getCountLessThanTheta(thetaB);
    
    if (countA <= 0) return 1.0;
    
    return BoundsOnRatiosInSampledSets.getUpperBoundForBoverA(countA, countB, thetaB);
  }
  
  /**
   * Gets the estimate for B over A
   * @param sketchA the sketch A
   * @param sketchB the sketch B
   * @return the estimate for B over A
   */
  public static double getEstimateOfBoverA(Sketch sketchA, Sketch sketchB) {
    double thetaA = sketchA.getTheta();
    double thetaB = sketchB.getTheta();
    checkThetas(thetaA, thetaB);

    int countB = sketchB.getRetainedEntries(true);
    int countA = (thetaB == thetaA) ? sketchA.getRetainedEntries(true) 
        : sketchA.getCountLessThanTheta(thetaB);
    
    if (countA <= 0) return 0.5;
    
    return (double) countB / (double) countA;
  }
  
  static void checkThetas(double thetaA, double thetaB) {
    if (thetaB > thetaA) {
      throw new SketchesArgumentException("ThetaB cannot be > ThetaA.");
    }
  }
}

@@ -355,26 +355,30 @@
  of 
-unique identifiers
+population %3Ci%3EPopA%3C/i%3E
 .%3C/l
@@ -421,25 +421,54 @@
  of 
-a subset
+population
  %3Ci%3E
+Pop
 B%3C/i%3E
+ that is a proper subset
  of 
@@ -475,16 +475,21 @@
 %3Ci%3EA%3C/i%3E
+, %0A *
  obtaine
@@ -512,40 +512,516 @@
 tion
-%0A * with a Theta Sketch %3Ci%3EC
+ of %3Ci%3EA%3C/i%3E with some other Theta Sketch %3Ci%3EC%3C/i%3E, %0A * which acts like a predicate or selection clause.%3C/li%3E%0A * %3Cli%3EThe estimate of the ratio %3Ci%3EPopB/PopA%3C/i%3E is%0A * BoundsOnRatiosInThetaSketchedSets.getEstimateOfBoverA(%3Ci%3EA, B%3C/i%3E).%3C/li%3E%0A * %3Cli%3EThe Upper Bound estimate on the ratio PopB/PopA is %0A * BoundsOnRatiosInThetaSketchedSets.getUpperBoundForBoverA(%3Ci%3EA, B%3C/i%3E).%3C/li%3E%0A * %3Cli%3EThe Lower Bound estimate on the ratio PopB/PopA is %0A * BoundsOnRatiosInThetaSketchedSets.getLowerBoundForBoverA(%3Ci%3EA, B
 %3C/i%3E
+)
 .%3C/l
@@ -1034,16 +1034,22 @@
 %3C/ul%3E%0A *
+ Note:
  The the
@@ -1054,17 +1054,24 @@
 heta of 
-A
+%3Ci%3EA%3C/i%3E
  cannot 
@@ -1103,36 +1103,265 @@
  of 
-B.%0A * %0A * @author Kevin Lang
+%3Ci%3EB%3C/i%3E. %0A * If %3Ci%3EB%3C/i%3E is formed as an intersection of %3Ci%3EA%3C/i%3E and some other set %3Ci%3EC%3C/i%3E, %0A * then the theta of %3Ci%3EB%3C/i%3E is guaranteed to be less than or equal to the theta of %3Ci%3EB%3C/i%3E.%0A * %0A * @version 0.5.1%0A * @author Kevin Lang%0A * @author Lee Rhodes
 %0A */

Update javadocs