@Override
    public void add(long item, long count) {
        if (count < 0) {
            // Negative values are not implemented in the regular version, and do not
            // play nicely with this algorithm anyway
            throw new IllegalArgumentException("Negative increments not implemented");
        }
        int[] buckets = new int[depth];
        for (int i = 0; i < depth; ++i) {
            buckets[i] = hash(item, i);
        }
        long min = table[0][buckets[0]];
        for (int i = 1; i < depth; ++i) {
            min = Math.min(min, table[i][buckets[i]]);
        }
        for (int i = 0; i < depth; ++i) {
            long newVal = Math.max(table[i][buckets[i]], min + count);
            table[i][buckets[i]] = newVal;
        }
        size += count;
    }
@Test
    public void testAccuracyStrings() {
        int seed = 7364181;
        Random r = new Random(seed);
        int numItems = 1000000;
        String[] xs = new String[numItems];
        int maxScale = 20;
        for (int i = 0; i < xs.length; i++) {
            int scale = r.nextInt(maxScale);
            xs[i] = RandomStringUtils.random(scale);
        }

        double epsOfTotalCount = 0.0001;
        double confidence = 0.99;

        ConservativeAddSketch sketch = new ConservativeAddSketch(epsOfTotalCount, confidence, seed);
        IFrequency baseSketch = new CountMinSketch(epsOfTotalCount, confidence, seed);
        for (String x : xs) {
            sketch.add(x, 1);
            baseSketch.add(x, 1);
        }

        Map<String, Long> actualFreq = new HashMap<String, Long>(numItems / 10);
        for (String x : xs) {
            Long val = actualFreq.get(x);
            if (val == null) {
                actualFreq.put(x, 1L);
            } else {
                actualFreq.put(x, val + 1L);
            }
        }

        int numErrors = 0;
        int betterNumbers = 0;
        long totalDelta = 0;
        int okayError = (int) (numItems * epsOfTotalCount) + 1;
        long totalError = 0;
        for (Map.Entry<String, Long> entry : actualFreq.entrySet()) {
            String key = entry.getKey();
            Long value = entry.getValue();
            long error = sketch.estimateCount(key) - value;
            totalError += error;
            if (error > okayError) {
                numErrors++;
            }
            long delta = baseSketch.estimateCount(key) - sketch.estimateCount(key);
            if (delta > 0) {
                totalDelta += delta;
                betterNumbers++;
            }
        }
        long usedValues = actualFreq.size();
        double pCorrect = 1 - 1.0 * numErrors / usedValues;
        System.out.println("Confidence : " + pCorrect + "   Errors : " + numErrors + "  Error margin : " + okayError);
        System.out.println("Total error : " + totalError + "  Average error : " + totalError / usedValues);
        System.out.println("Beat base for : " + 100 * betterNumbers / usedValues + " percent of values" +
                           " with a total delta of " + totalDelta);
        assertTrue("Confidence not reached: required " + confidence + ", reached " + pCorrect, pCorrect > confidence);
    }