public void train(CharSequence cSeq, Classification classification, double count) {
        if (count == 0.0) return;
        String cat = classification.bestCategory();
        int catIndex = getIndex(cat);

        // throw if underflow
        if (mCaseCounts[catIndex] < -count) {
            String msg = "Decrement caused negative token count."
                    + "Revert to previous state."
                    + " cSeq=" + cSeq
                + " classification=" + cat
                    + " count=" + count;
            throw new IllegalArgumentException(msg);
        }

        mCaseCounts[catIndex] += count;
        mTotalCaseCount += count;

        ObjectToCounterMap<String> tokenCountMap = tokenCountMap(cSeq);
        double lengthMultiplier = lengthMultiplier(tokenCountMap);

        double lengthNormCount = lengthMultiplier * count;

        char[] cs = Strings.toCharArray(cSeq);
        Tokenizer tokenizer = mTokenizerFactory.tokenizer(cs,0,cs.length);
        int pos = 0;
        for (String token : tokenizer) {
            double[] tokenCounts = mTokenToCountsMap.get(token);

            // cleanup underflow and throw
            if (lengthNormCount < 0 && ((tokenCounts == null)
                              || (tokenCounts[catIndex] < -lengthNormCount))) {

                // first two are unnormed
                mCaseCounts[catIndex] -= count;
                mTotalCaseCount -= count;

                Tokenizer tokenizer2 = mTokenizerFactory.tokenizer(cs,0,cs.length);
                int fixPos = 0;
                for (String token2 : tokenizer2) {
                    if (fixPos >= pos) break;
                    ++fixPos;
                    double[] tokenCounts2 = mTokenToCountsMap.get(token2);
                    tokenCounts2[catIndex] -= lengthNormCount;
                    mTotalCountsPerCategory[catIndex] -= lengthNormCount;
                }
                String msg = "Decrement caused negative token count."
                    + "Revert to previous state."
                    + " cSeq=" + cSeq
                    + " classification=" + cat
                    + " count=" + count;
                throw new IllegalArgumentException(msg);
            }

            ++pos;
            if (tokenCounts == null) {
                tokenCounts = new double[mCategories.length];
                mTokenToCountsMap.put(token,tokenCounts);
            }
            tokenCounts[catIndex] += lengthNormCount;;
            mTotalCountsPerCategory[catIndex] += lengthNormCount;
        }
    }