private void makePartitions(FeatureRange range, long fromVal, long toVal, long stepSize, int arity, boolean isNeg) {
        int fromRemainder = (int) (fromVal % arity);
        int toRemainder = (int) (toVal % arity);
        long nextFromVal = fromVal - fromRemainder;
        long nextToVal = toVal - toRemainder;
        if (nextFromVal == nextToVal) {
            addPartitions(range, nextFromVal, stepSize, fromRemainder, toRemainder, isNeg);
        } else {
            if (fromRemainder > 0) {
                addPartitions(range, nextFromVal, stepSize, fromRemainder, arity, isNeg);
                fromVal = nextFromVal + arity;
            }
            addPartitions(range, nextToVal, stepSize, 0, toRemainder, isNeg);
            makePartitions(range, fromVal / arity, toVal / arity, stepSize * arity, arity, isNeg);
        }
    }
Partitions all the feature ranges according to the arity and bounds
set in the PredicateOptions, and updates the ranges with a set of
partitions and edge partitions.
This is required to be able to store a range in the PredicateIndex.

@author Magnar Nedland
@author bjorncs
predicate-search-core/src/main/java/com/yahoo/search/predicate/optimization/ComplexNodeTransformer.java