public long cardinality()
    {
        // The initial guess of 1 may seem awful, but this converges quickly, and starting small returns better results for small cardinalities.
        // This generally takes <= 40 iterations, even for cardinalities as large as 10^33.
        double guess = 1;
        double changeInGuess = Double.POSITIVE_INFINITY;
        int iterations = 0;
        while (Math.abs(changeInGuess) > 0.1 && iterations < MAX_ESTIMATION_ITERATIONS) {
            changeInGuess = -logLikelihoodFirstDerivative(guess) / logLikelihoodSecondDerivative(guess);
            guess += changeInGuess;
            iterations += 1;
        }
        return Math.max(0, Math.round(guess));
    }
@Test
    public void testSimulatedCardinalityEstimates()
    {
        // Instead of creating sketches by adding items, we simulate them for fast testing of huge cardinalities.
        // For reference, 10^33 is one decillion.
        // The goal here is to test general functionality and numerical stability.
        int[] magnitudes = {6, 9, 12, 15, 18, 21, 24, 27, 30, 33};
        double[] epsilons = {4, SfmSketch.NON_PRIVATE_EPSILON};
        for (int mag : magnitudes) {
            int n = (int) Math.pow(10, mag);
            for (double eps : epsilons) {
                SfmSketch sketch = createSketchWithTargetCardinality(4096, 24, eps, n);
                assertEquals(sketch.cardinality(), n, n * 0.1);
            }
        }
    }