protected int forEach()

in accord-core/src/main/java/accord/utils/CheckpointIntervalArray.java [132:219]


    protected <P1, P2, P3, P4> int forEach(int start, int end, int floor, Key startBound, int cmpStartBoundWithEnd,
                                           IndexedQuadConsumer<P1, P2, P3, P4> forEachScanOrCheckpoint, IndexedRangeQuadConsumer<P1, P2, P3, P4> forEachRange,
                                           P1 p1, P2 p2, P3 p3, P4 p4, int minIndex)
    {
        if (start < minIndex) start = minIndex;

        // find the checkpoint array, so we know how far to step back
        int checkpoint = Arrays.binarySearch(lowerBounds, floor);
        if (checkpoint < 0) checkpoint = -2 - checkpoint;
        if (checkpoint < 0) return end;

        int headerBaseIndex = (checkpoint / 4) * 5;
        int headerSubIndex = checkpoint & 3;
        int headerListIndex = headerBaseIndex + 1 + headerSubIndex;

        int scanDistance = (headers[headerBaseIndex] >>> (8 * headerSubIndex)) & 0xff;
        int checkpointStart = headers[headerListIndex];
        int checkpointEnd = headers[headerListIndex + (headerSubIndex + 5)/4]; // skip the next header

        if (scanDistance == MAX_SCAN_DISTANCE)
        {
            scanDistance = -checkpointLists[checkpointStart++];
            Invariants.require(scanDistance >= MAX_SCAN_DISTANCE);
        }

        // NOTE: we visit in approximately ascending order, and this is a requirement for correctness of RangeDeps builders
        //       Only the checkpoint is visited in uncertain order, but it is visited entirely, before the scan matches
        //       and the range matches
        int minScanIndex = Math.max(floor - scanDistance, minIndex);
        var c = accessor.keyComparator();
        for (int i = checkpointStart; i < checkpointEnd ; ++i)
        {
            int ri = checkpointLists[i];
            if (ri < 0)
            {
                int subStart, subEnd;
                if ((ri & BIT30) != 0)
                {
                    subStart = ri & 0xfffff;
                    subEnd = subStart + ((ri >>> 20) & 0x1ff);
                }
                else if ((ri & BIT29) != 0)
                {
                    subStart = ri & 0x1fffffff;
                    subEnd = Integer.MAX_VALUE;
                }
                else
                {
                    int length = ri & 0x1fffffff;
                    subStart = checkpointLists[++i];
                    subEnd = subStart + length;
                }

                for (int j = subStart ; j < subEnd ; ++j)
                {
                    ri = checkpointLists[j];
                    if (ri < 0)
                        continue;

                    if (c.compare(accessor.end(ranges, ri), startBound) <= cmpStartBoundWithEnd)
                        break;

                    if (ri >= minIndex && ri < minScanIndex)
                        forEachScanOrCheckpoint.accept(p1, p2, p3, p4, ri);
                }
            }
            else
            {
                // if startBound is key, we cannot be equal to it;
                // if startBound is a Range start, we also cannot be equal to it due to the requirement that
                // endInclusive() != startInclusive(), so equality really means inequality
                if (c.compare(accessor.end(ranges, ri), startBound) <= cmpStartBoundWithEnd)
                    break;

                if (ri >= minIndex && ri < minScanIndex)
                    forEachScanOrCheckpoint.accept(p1, p2, p3, p4, ri);
            }
        }

        for (int i = minScanIndex; i < floor ; ++i)
        {
            if (c.compare(accessor.end(ranges, i), startBound) > cmpStartBoundWithEnd)
                forEachScanOrCheckpoint.accept(p1, p2, p3, p4, i);
        }

        forEachRange.accept(p1, p2, p3, p4, start, end);
        return end;
    }