def _shift_arr_retain(M, dir, n):
    """
    Shift an array along one of the eight (inter)cardinal directions.
    Pixels padded to the edges of the axes retain the value from the
    original array.

    Parameters
    ----------
    M : ndarray
        Input array.

    dir : int
        Direction along to shift the array, ranging from 0 (north) to 7
        (northwest).

    n : int
        Number of pixels to be shifted.

    Returns
    -------
    S : ndarray
        Shifted array.
    """
    S = M.copy()

    if dir == 0:  # north
        S[:-n - 1, :] = M[1 + n:, :]
    elif dir == 1:  # northeast
        S[:-n - 1, 1 + n:] = M[1 + n:, :-n - 1]
    elif dir == 2:  # east
        S[:, 1 + n:] = M[:, :-n - 1]
    elif dir == 3:  # southeast
        S[1 + n:, 1 + n:] = M[:-n - 1, :-n - 1]
    elif dir == 4:  # south
        S[1 + n:, :] = M[:-n - 1, :]
    elif dir == 5:  # southwest
        S[1 + n:, :-n - 1] = M[:-n - 1, 1 + n:]
    elif dir == 6:  # west
        S[:, :-n - 1] = M[:, 1 + n:]
    elif dir == 7:  # northwest
        S[:-n - 1, :-n - 1] = M[1 + n:, 1 + n:]

    return S