Issue 1:
Describe your issue.

Using RegularGridInterpolator on a read-only 2D array with dtype numpy.float64 raises ValueError: buffer source is read-only. Of course, read-write access shouldn't be required to interpolate.

It works for 2D arrays with dtype numpy.int64. Code/output is not shown, but it works both for int64 and float64 in the 3D case.

The numpy array is made read-only using the writeable flag from ndarray.flags. From the numpy docs:

Only the WRITEBACKIFCOPY, WRITEABLE, and ALIGNED flags can be changed by the user, via direct assignment to the attribute or dictionary entry, or by calling ndarray.setflags.

WRITEABLE (W)

The data area can be written to. Setting this to False locks the data, making it read-only. A view (slice, etc.) inherits WRITEABLE from its base array at creation time, but a view of a writeable array may be subsequently locked while the base array remains writeable. (The opposite is not true, in that a view of a locked array may not be made writeable. However, currently, locking a base object does not lock any views that already reference it, so under that circumstance it is possible to alter the contents of a locked array via a previously created writeable view onto it.) Attempting to change a non-writeable array raises a RuntimeError exception.

This may be related to the new fast path in v1.10.0 for 2D interpolation in RegularGridInterpolator (#17291), although I don't understand how.

Reproducing Code Example

import numpy
import scipy.interpolate

a = numpy.array(
[
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 1, 1, 1, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 0, 0],
]
)

z = numpy.copy(a)
z.flags.writeable = False
print(z.dtype)
print(z)
interpolator = scipy.interpolate.RegularGridInterpolator(
(numpy.linspace(0, 5, num=5), numpy.linspace(0, 5, num=5)),
z,
method="linear",
)

print("Interpolation on read-only int array:", interpolator([0.5, 0.5]), ": OK.")
print()

z = numpy.copy(a)
z = z.astype(float, casting="safe")
z.flags.writeable = False
print(z.dtype)
print(z)

interpolator = scipy.interpolate.RegularGridInterpolator(
(numpy.linspace(0, 5, num=5), numpy.linspace(0, 5, num=5)),
z,
method="linear",
)

print("Interpolation on read-only float array:", interpolator([0.5, 0.5]), ": crashes.")

Error message

dtype: int64
[[0 0 0 0 0]
[0 1 1 1 0]
[0 1 1 1 0]
[0 1 1 1 0]
[0 0 0 0 0]]
Interpolation on read-only int array: [0.16] : OK.

dtype: float64
[[0. 0. 0. 0. 0.]
[0. 1. 1. 1. 0.]
[0. 1. 1. 1. 0.]
[0. 1. 1. 1. 0.]
[0. 0. 0. 0. 0.]]
Traceback (most recent call last):
File "/home/vleduc/python/newdev/rtdata/_test_bug_scipy.py", line 39, in <module>
print("Interpolation on read-only float array:", interpolator([0.5, 0.5]), ": crashes.")
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/vleduc/python/venvs/rtdata-py311/lib/python3.11/site-packages/scipy/interpolate/_rgi.py", line 336, in __call__
result = evaluate_linear_2d(self.values,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "_rgi_cython.pyx", line 19, in scipy.interpolate._rgi_cython.evaluate_linear_2d
File "stringsource", line 660, in View.MemoryView.memoryview_cwrapper
File "stringsource", line 350, in View.MemoryView.memoryview.__cinit__
ValueError: buffer source array is read-only

SciPy/NumPy/Python version information

1.10.0 1.24.1 sys.version_info(major=3, minor=11, micro=1, releaselevel='final', serial=0)

Issue 2:
Describe your issue.

Using a slightly modified version of the example from the documentation

import numpy
from scipy.interpolate import interpn

def value_func_3d(x, y, z):
return 2 * x + 3 * y - z

x = numpy.linspace(0, 4, 5)
y = numpy.linspace(0, 5, 6)
z = numpy.linspace(0, 6, 7)
points = (x, y, z)
values = value_func_3d(*numpy.meshgrid(*points, indexing='ij'))
point = numpy.array([2.21, 3.12, 1.15])
print(interpn(points, values, point))
for ax in points:
ax.flags.writeable = False
print(interpn(points, values, point))

Fails with

...
return find_indices(self.grid, xi)
File "_rgi_cython.pyx", line 95, in scipy.interpolate._rgi_cython.find_indices
File "stringsource", line 660, in View.MemoryView.memoryview_cwrapper
File "stringsource", line 350, in View.MemoryView.memoryview.__cinit__
ValueError: buffer source array is read-only

A more minimal example is:

import numpy
from scipy.interpolate import _rgi

grid = (numpy.array([0, 1], dtype='f8'), )
xi = numpy.array([[0.5, 0.5], ])
grid[0].flags.writeable = False
print(_rgi.find_indices(grid, xi))

This may be related to #17172 and may have been introduced with the cython code in #17291

Adding a const to this line appear to fix the problem locally:

scipy/scipy/interpolate/_rgi_cython.pyx

Line 79
in
7b858b7

double[::1] grid_i

Reproducing Code Example

import numpy
from scipy.interpolate import _rgi

grid = (numpy.array([0, 1], dtype='f8'), )
xi = numpy.array([[0.5, 0.5], ])
grid[0].flags.writeable = False
print(_rgi.find_indices(grid, xi))

Error message

File "_rgi_cython.pyx", line 95, in scipy.interpolate._rgi_cython.find_indices
File "stringsource", line 660, in View.MemoryView.memoryview_cwrapper
File "stringsource", line 350, in View.MemoryView.memoryview.__cinit__
ValueError: buffer source array is read-only

SciPy/NumPy/Python version information

1.11.0.dev0+0.057cf5c 1.24.1 sys.version_info(major=3, minor=10, micro=6, releaselevel='final', serial=0)