docs: public static double[] jaccard(final Sketch sketchA, final Sketch sketchB) {
      //Corner case checks
      if ((sketchA == null) || (sketchB == null)) { return ZEROS.clone(); }
      if (sketchA == sketchB) { return ONES.clone(); }
      if (sketchA.isEmpty() && sketchB.isEmpty()) { return ONES.clone(); }
      if (sketchA.isEmpty() || sketchB.isEmpty()) { return ZEROS.clone(); }
  
      final int countA = sketchA.getRetainedEntries();
      final int countB = sketchB.getRetainedEntries();
  
      //Create the Union
      final int minK = 1 << MIN_LG_NOM_LONGS;
      final int maxK = 1 << MAX_LG_NOM_LONGS;
      final int newK = max(min(ceilingPowerOf2(countA + countB), maxK), minK);
      final Union union =
          SetOperation.builder().setNominalEntries(newK).buildUnion();
      union.update(sketchA);
      union.update(sketchB);
      final Sketch unionAB = union.getResult();
      final long thetaLongUAB = unionAB.getThetaLong();
      final long thetaLongA = sketchA.getThetaLong();
      final long thetaLongB = sketchB.getThetaLong();
      final int countUAB = unionAB.getRetainedEntries();
  
      //Check for identical data
      if ((countUAB == countA) && (countUAB == countB)
          && (thetaLongUAB == thetaLongA) && (thetaLongUAB == thetaLongB)) {
        return ONES.clone();
      }
  
      //Create the Intersection
      final Intersection inter = SetOperation.builder().buildIntersection();
      inter.update(sketchA);
      inter.update(sketchB);
      inter.update(unionAB); //ensures that intersection is a subset of the union
      final Sketch interABU = inter.getResult(true, null);
  
      final double lb = getLowerBoundForBoverA(unionAB, interABU);
      final double est = getEstimateOfBoverA(unionAB, interABU);
      final double ub = getUpperBoundForBoverA(unionAB, interABU);
      return new double[] {lb, est, ub};
    }