public void expand(String key, long value, RangeHandler rangeHandler, EdgeHandler edgeHandler) {
        if (value < lowerBound || value > upperBound) {
            // Value outside bounds -> expand to nothing.
            return;
        }
        int maxLevels = value > 0 ? maxPositiveLevels : maxNegativeLevels;
        int sign = value > 0 ? 1 : -1;
        // Append key to feature string builder
        StringBuilder builder = new StringBuilder(128);
        builder.append(key).append('=');

        long levelSize = arity;
        long edgeInterval = (value / arity) * arity;
        edgeHandler.handleEdge(createEdgeFeatureHash(builder, edgeInterval), (int) Math.abs(value - edgeInterval));
        for (int i = 0; i < maxLevels; ++i) {
            long start = (value / levelSize) * levelSize;
            if (Math.abs(start) + levelSize - 1 < 0) {  // overflow
                break;
            }
            rangeHandler.handleRange(createRangeFeatureHash(builder, start, start + sign * (levelSize - 1)));
            levelSize *= arity;
            if (levelSize <= 0 && levelSize != Long.MIN_VALUE) {  //overflow
                break;
            }
        }
    }
@Test
    void requireThatSmallNegativeRangeIsExpandedInArity2() {
        PredicateRangeTermExpander expander = new PredicateRangeTermExpander(2);
        Iterator<String> expectedLabels = List.of(
                "key=-43-42",
                "key=-43-40",
                "key=-47-40",
                "key=-47-32",
                "key=-63-32",
                "key=-63-0",
                "key=-127-0",
                "key=-255-0",
                "key=-511-0",
                "key=-1023-0",
                "key=-2047-0",
                "key=-4095-0",
                "key=-8191-0",
                "key=-16383-0",
                "key=-32767-0",
                "key=-65535-0",
                "key=-131071-0",
                "key=-262143-0",
                "key=-524287-0",
                "key=-1048575-0",
                "key=-2097151-0",
                "key=-4194303-0",
                "key=-8388607-0",
                "key=-16777215-0",
                "key=-33554431-0",
                "key=-67108863-0",
                "key=-134217727-0",
                "key=-268435455-0",
                "key=-536870911-0",
                "key=-1073741823-0",
                "key=-2147483647-0",
                "key=-4294967295-0",
                "key=-8589934591-0",
                "key=-17179869183-0",
                "key=-34359738367-0",
                "key=-68719476735-0",
                "key=-137438953471-0",
                "key=-274877906943-0",
                "key=-549755813887-0",
                "key=-1099511627775-0",
                "key=-2199023255551-0",
                "key=-4398046511103-0",
                "key=-8796093022207-0",
                "key=-17592186044415-0",
                "key=-35184372088831-0",
                "key=-70368744177663-0",
                "key=-140737488355327-0",
                "key=-281474976710655-0",
                "key=-562949953421311-0",
                "key=-1125899906842623-0",
                "key=-2251799813685247-0",
                "key=-4503599627370495-0",
                "key=-9007199254740991-0",
                "key=-18014398509481983-0",
                "key=-36028797018963967-0",
                "key=-72057594037927935-0",
                "key=-144115188075855871-0",
                "key=-288230376151711743-0",
                "key=-576460752303423487-0",
                "key=-1152921504606846975-0",
                "key=-2305843009213693951-0",
                "key=-4611686018427387903-0",
                "key=-9223372036854775807-0").iterator();
        expander.expand("key", -42, range -> assertEquals(PredicateHash.hash64(expectedLabels.next()), range),
                (edge, value) -> {
                    assertEquals(PredicateHash.hash64("key=-42"), edge);
                    assertEquals(0, value);
                });
        assertFalse(expectedLabels.hasNext());
    }