# Path: finitediff/util.py
# def interpolate_ahead(x, y, n, direction="fw"):
#     if not np.all(np.diff(x) > 0):
#         raise ValueError("x not strictly monotonic.")
# 
#     if direction == "both":
#         y1, slc1 = interpolate_ahead(x, y, n, "fw")
#         y2, slc2 = interpolate_ahead(x, y, n, "bw")
#         y = np.zeros_like(x)
#         y[slc1] = y1
#         y[slc2] += y2
#         y[slc1.start : slc2.stop] /= 2
#         return y, slice(None, None)
#     elif direction == "fw":
#         forward = True
#     elif direction == "bw":
#         forward = False
#     else:
#         raise ValueError("Unknown direction: %s" % direction)
# 
#     rev = slice(None, None, 1) if forward else slice(None, None, -1)
#     values = []
#     for idx, (xv, yv) in enumerate(zip(x[rev][n:], y[rev][n:])):
#         _x = np.ascontiguousarray(x[rev][idx : idx + n], dtype=np.float64)
#         _y = np.ascontiguousarray(y[rev][idx : idx + n], dtype=np.float64)
#         _v = np.array([xv])
#         values.append(
#             interpolate_by_finite_diff(_x, _y, _v, maxorder=0, ntail=n, nhead=0)
#         )
#     return np.array(values[rev]).squeeze(), slice(n, None) if forward else slice(
#         None, -n
#     )


import numpy as np
from ..util import interpolate_ahead
        ystart, ystop = 0, 0
        for yslc in yslices:
            ystop += yslc.stop - yslc.start
            nextresults[yslc] = newresults[ystart:ystop]
            nexty[yslc] = newy[ystart:ystop]
            ystart = ystop

        return nextgrid, nextresults, nexty

    results = cb(grid)
    y = np.array(
        results if metric is None else [metric(r) for r in results], dtype=np.float64
    )

    for na in grid_additions:
        if extremum_refinement:
            extremum_cb, extremum_n, predicate_cb = extremum_refinement
            argext = extremum_cb(y)
            if predicate_cb(y, argext):
                additions = np.zeros(grid.size - 1, dtype=int)
                if argext > 0:  # left of
                    additions[argext - 1] = extremum_n
                elif argext < grid.size - 1:  # right of
                    additions[argext] = extremum_n
                grid, results, y = add_to(additions, grid, results, y)

        additions = np.zeros(grid.size - 1, dtype=int)
        done = True if atol is not None or rtol is not None else False
        slcs, errs = [], []
        for direction in ("fw", "bw"):

# Path: finitediff/util.py
# def interpolate_ahead(x, y, n, direction="fw"):
#     if not np.all(np.diff(x) > 0):
#         raise ValueError("x not strictly monotonic.")
# 
#     if direction == "both":
#         y1, slc1 = interpolate_ahead(x, y, n, "fw")
#         y2, slc2 = interpolate_ahead(x, y, n, "bw")
#         y = np.zeros_like(x)
#         y[slc1] = y1
#         y[slc2] += y2
#         y[slc1.start : slc2.stop] /= 2
#         return y, slice(None, None)
#     elif direction == "fw":
#         forward = True
#     elif direction == "bw":
#         forward = False
#     else:
#         raise ValueError("Unknown direction: %s" % direction)
# 
#     rev = slice(None, None, 1) if forward else slice(None, None, -1)
#     values = []
#     for idx, (xv, yv) in enumerate(zip(x[rev][n:], y[rev][n:])):
#         _x = np.ascontiguousarray(x[rev][idx : idx + n], dtype=np.float64)
#         _y = np.ascontiguousarray(y[rev][idx : idx + n], dtype=np.float64)
#         _v = np.array([xv])
#         values.append(
#             interpolate_by_finite_diff(_x, _y, _v, maxorder=0, ntail=n, nhead=0)
#         )
#     return np.array(values[rev]).squeeze(), slice(n, None) if forward else slice(
#         None, -n
#     )


# Path: finitediff/grid/refine.py
import numpy as np
from ..util import interpolate_ahead

        ystart, ystop = 0, 0
        for yslc in yslices:
            ystop += yslc.stop - yslc.start
            nextresults[yslc] = newresults[ystart:ystop]
            nexty[yslc] = newy[ystart:ystop]
            ystart = ystop

        return nextgrid, nextresults, nexty

    results = cb(grid)
    y = np.array(
        results if metric is None else [metric(r) for r in results], dtype=np.float64
    )

    for na in grid_additions:
        if extremum_refinement:
            extremum_cb, extremum_n, predicate_cb = extremum_refinement
            argext = extremum_cb(y)
            if predicate_cb(y, argext):
                additions = np.zeros(grid.size - 1, dtype=int)
                if argext > 0:  # left of
                    additions[argext - 1] = extremum_n
                elif argext < grid.size - 1:  # right of
                    additions[argext] = extremum_n
                grid, results, y = add_to(additions, grid, results, y)

        additions = np.zeros(grid.size - 1, dtype=int)
        done = True if atol is not None or rtol is not None else False
        slcs, errs = [], []
        for direction in ("fw", "bw"):

            est, slc = interpolate_ahead(grid, y, ntrail, direction)