Skip to content

Commit

Permalink
migrate IntoPyArray and ToPyArray
Browse files Browse the repository at this point in the history
  • Loading branch information
Icxolu committed Mar 25, 2024
1 parent c2a3c39 commit 2817305
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 123 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ numpy = "0.20"

```rust
use numpy::ndarray::{ArrayD, ArrayViewD, ArrayViewMutD};
use numpy::{IntoPyArray, PyArrayDyn, PyReadonlyArrayDyn};
use pyo3::{pymodule, types::PyModule, PyResult, Python};
use numpy::{IntoPyArray, PyArrayDyn, PyReadonlyArrayDyn, PyArrayMethods};
use pyo3::{pymodule, types::PyModule, PyResult, Python, Bound};

#[pymodule]
fn rust_ext<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
fn rust_ext<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> {
// example using immutable borrows producing a new array
fn axpy(a: f64, x: ArrayViewD<'_, f64>, y: ArrayViewD<'_, f64>) -> ArrayD<f64> {
a * &x + &y
Expand All @@ -67,17 +67,17 @@ fn rust_ext<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
a: f64,
x: PyReadonlyArrayDyn<'py, f64>,
y: PyReadonlyArrayDyn<'py, f64>,
) -> &'py PyArrayDyn<f64> {
) -> Bound<'py, PyArrayDyn<f64>> {
let x = x.as_array();
let y = y.as_array();
let z = axpy(a, x, y);
z.into_pyarray(py)
z.into_pyarray_bound(py)
}

// wrapper of `mult`
#[pyfn(m)]
#[pyo3(name = "mult")]
fn mult_py<'py>(a: f64, x: &'py PyArrayDyn<f64>) {
fn mult_py<'py>(a: f64, x: &Bound<'py, PyArrayDyn<f64>>) {
let x = unsafe { x.as_array_mut() };
mult(a, x);
}
Expand Down
11 changes: 7 additions & 4 deletions examples/linalg/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use ndarray_linalg::solve::Inverse;
use numpy::{IntoPyArray, PyArray2, PyReadonlyArray2};
use pyo3::{exceptions::PyRuntimeError, pymodule, types::PyModule, PyResult, Python};
use pyo3::{exceptions::PyRuntimeError, pymodule, types::PyModule, Bound, PyResult, Python};

#[pymodule]
fn rust_linalg<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
fn rust_linalg<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> {
#[pyfn(m)]
fn inv<'py>(py: Python<'py>, x: PyReadonlyArray2<'py, f64>) -> PyResult<&'py PyArray2<f64>> {
fn inv<'py>(
py: Python<'py>,
x: PyReadonlyArray2<'py, f64>,
) -> PyResult<Bound<'py, PyArray2<f64>>> {
let x = x.as_array();
let y = x
.inv()
.map_err(|e| PyRuntimeError::new_err(e.to_string()))?;
Ok(y.into_pyarray(py))
Ok(y.into_pyarray_bound(py))
}
Ok(())
}
8 changes: 4 additions & 4 deletions examples/parallel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ extern crate blas_src;

use numpy::ndarray::Zip;
use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1, PyReadonlyArray2};
use pyo3::{pymodule, types::PyModule, PyResult, Python};
use pyo3::{pymodule, types::PyModule, Bound, PyResult, Python};

#[pymodule]
fn rust_parallel<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
fn rust_parallel<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> {
#[pyfn(m)]
fn rows_dot<'py>(
py: Python<'py>,
x: PyReadonlyArray2<'py, f64>,
y: PyReadonlyArray1<'py, f64>,
) -> &'py PyArray1<f64> {
) -> Bound<'py, PyArray1<f64>> {
let x = x.as_array();
let y = y.as_array();
let z = Zip::from(x.rows()).par_map_collect(|row| row.dot(&y));
z.into_pyarray(py)
z.into_pyarray_bound(py)
}
Ok(())
}
26 changes: 13 additions & 13 deletions examples/simple/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ use pyo3::{
exceptions::PyIndexError,
pymodule,
types::{PyDict, PyModule},
FromPyObject, PyAny, PyObject, PyResult, Python,
Bound, FromPyObject, PyAny, PyObject, PyResult, Python,
};

#[pymodule]
fn rust_ext<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
fn rust_ext<'py>(m: &Bound<'py, PyModule>) -> PyResult<()> {
// example using generic PyObject
fn head(x: ArrayViewD<'_, PyObject>) -> PyResult<PyObject> {
x.get(0)
Expand Down Expand Up @@ -60,11 +60,11 @@ fn rust_ext<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
a: f64,
x: PyReadonlyArrayDyn<'py, f64>,
y: PyReadonlyArrayDyn<'py, f64>,
) -> &'py PyArrayDyn<f64> {
) -> Bound<'py, PyArrayDyn<f64>> {
let x = x.as_array();
let y = y.as_array();
let z = axpy(a, x, y);
z.into_pyarray(py)
z.into_pyarray_bound(py)
}

// wrapper of `mult`
Expand All @@ -81,8 +81,8 @@ fn rust_ext<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
fn conj_py<'py>(
py: Python<'py>,
x: PyReadonlyArrayDyn<'py, Complex64>,
) -> &'py PyArrayDyn<Complex64> {
conj(x.as_array()).into_pyarray(py)
) -> Bound<'py, PyArrayDyn<Complex64>> {
conj(x.as_array()).into_pyarray_bound(py)
}

// example of how to extract an array from a dictionary
Expand Down Expand Up @@ -125,28 +125,28 @@ fn rust_ext<'py>(_py: Python<'py>, m: &'py PyModule) -> PyResult<()> {
fn polymorphic_add<'py>(
x: SupportedArray<'py>,
y: SupportedArray<'py>,
) -> PyResult<&'py PyAny> {
) -> PyResult<Bound<'py, PyAny>> {
match (x, y) {
(SupportedArray::F64(x), SupportedArray::F64(y)) => Ok(generic_add(
x.readonly().as_array(),
y.readonly().as_array(),
)
.into_pyarray(x.py())
.into()),
.into_pyarray_bound(x.py())
.into_any()),
(SupportedArray::I64(x), SupportedArray::I64(y)) => Ok(generic_add(
x.readonly().as_array(),
y.readonly().as_array(),
)
.into_pyarray(x.py())
.into()),
.into_pyarray_bound(x.py())
.into_any()),
(SupportedArray::F64(x), SupportedArray::I64(y))
| (SupportedArray::I64(y), SupportedArray::F64(x)) => {
let y = y.cast::<f64>(false)?;

Ok(
generic_add(x.readonly().as_array(), y.readonly().as_array())
.into_pyarray(x.py())
.into(),
.into_pyarray_bound(x.py())
.into_any(),
)
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
where
S: Data<Elem = T>,
{
ToPyArray::to_pyarray(arr, py)
ToPyArray::to_pyarray_bound(arr, py).into_gil_ref()
}

/// Get an immutable borrow of the NumPy array
Expand Down Expand Up @@ -1103,7 +1103,7 @@ impl<T: Element> PyArray<T, Ix1> {
/// ```
#[inline(always)]
pub fn from_vec<'py>(py: Python<'py>, vec: Vec<T>) -> &'py Self {
vec.into_pyarray(py)
vec.into_pyarray_bound(py).into_gil_ref()
}

/// Construct a one-dimensional array from an [`Iterator`].
Expand All @@ -1127,7 +1127,7 @@ impl<T: Element> PyArray<T, Ix1> {
I: IntoIterator<Item = T>,
{
let data = iter.into_iter().collect::<Vec<_>>();
data.into_pyarray(py)
data.into_pyarray_bound(py).into_gil_ref()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/array_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ where
let array = Array1::from(vec)
.into_dimensionality()
.expect("D being compatible to Ix1")
.into_pyarray(py)
.into_pyarray_bound(py)
.readonly();
return Ok(Self(array, PhantomData));
}
Expand Down
82 changes: 44 additions & 38 deletions src/borrow/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,18 +477,20 @@ mod tests {
#[test]
fn with_base_object() {
Python::with_gil(|py| {
let array = Array::<f64, _>::zeros((1, 2, 3)).into_pyarray(py);
let array = Array::<f64, _>::zeros((1, 2, 3)).into_pyarray_bound(py);

let base = unsafe { (*array.as_array_ptr()).base };
assert!(!base.is_null());

let base_address = base_address(py, array.as_array_ptr());
assert_ne!(base_address, array as *const _ as *mut c_void);
assert_eq!(base_address, base as *mut c_void);
assert_ne!(base_address, array.as_ptr().cast());
assert_eq!(base_address, base.cast::<c_void>());

let data_range = data_range(array.as_array_ptr());
assert_eq!(data_range.0, array.data() as *mut c_char);
assert_eq!(data_range.1, unsafe { array.data().add(6) } as *mut c_char);
assert_eq!(data_range.0, array.data().cast::<c_char>());
assert_eq!(data_range.1, unsafe {
array.data().add(6).cast::<c_char>()
});
});
}

Expand Down Expand Up @@ -524,33 +526,35 @@ mod tests {
#[test]
fn view_with_base_object() {
Python::with_gil(|py| {
let array = Array::<f64, _>::zeros((1, 2, 3)).into_pyarray(py);
let array = Array::<f64, _>::zeros((1, 2, 3)).into_pyarray_bound(py);

let locals = [("array", array)].into_py_dict(py);
let locals = [("array", &array)].into_py_dict_bound(py);
let view = py
.eval("array[:,:,0]", None, Some(locals))
.eval_bound("array[:,:,0]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();
assert_ne!(
view as *const _ as *mut c_void,
array as *const _ as *mut c_void
view.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>(),
);

let base = unsafe { (*view.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base.cast::<c_void>(), array.as_ptr().cast::<c_void>());

let base = unsafe { (*array.as_array_ptr()).base };
assert!(!base.is_null());

let base_address = base_address(py, view.as_array_ptr());
assert_ne!(base_address, view as *const _ as *mut c_void);
assert_ne!(base_address, array as *const _ as *mut c_void);
assert_eq!(base_address, base as *mut c_void);
assert_ne!(base_address, view.as_ptr().cast::<c_void>());
assert_ne!(base_address, array.as_ptr().cast::<c_void>());
assert_eq!(base_address, base.cast::<c_void>());

let data_range = data_range(view.as_array_ptr());
assert_eq!(data_range.0, array.data() as *mut c_char);
assert_eq!(data_range.1, unsafe { array.data().add(4) } as *mut c_char);
assert_eq!(data_range.0, array.data().cast::<c_char>());
assert_eq!(data_range.1, unsafe {
array.data().add(4).cast::<c_char>()
});
});
}

Expand Down Expand Up @@ -605,52 +609,54 @@ mod tests {
#[test]
fn view_of_view_with_base_object() {
Python::with_gil(|py| {
let array = Array::<f64, _>::zeros((1, 2, 3)).into_pyarray(py);
let array = Array::<f64, _>::zeros((1, 2, 3)).into_pyarray_bound(py);

let locals = [("array", array)].into_py_dict(py);
let locals = [("array", &array)].into_py_dict_bound(py);
let view1 = py
.eval("array[:,:,0]", None, Some(locals))
.eval_bound("array[:,:,0]", None, Some(&locals))
.unwrap()
.downcast::<PyArray2<f64>>()
.downcast_into::<PyArray2<f64>>()
.unwrap();
assert_ne!(
view1 as *const _ as *mut c_void,
array as *const _ as *mut c_void
view1.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>(),
);

let locals = [("view1", view1)].into_py_dict(py);
let locals = [("view1", &view1)].into_py_dict_bound(py);
let view2 = py
.eval("view1[:,0]", None, Some(locals))
.eval_bound("view1[:,0]", None, Some(&locals))
.unwrap()
.downcast::<PyArray1<f64>>()
.downcast_into::<PyArray1<f64>>()
.unwrap();
assert_ne!(
view2 as *const _ as *mut c_void,
array as *const _ as *mut c_void
view2.as_ptr().cast::<c_void>(),
array.as_ptr().cast::<c_void>(),
);
assert_ne!(
view2 as *const _ as *mut c_void,
view1 as *const _ as *mut c_void
view2.as_ptr().cast::<c_void>(),
view1.as_ptr().cast::<c_void>(),
);

let base = unsafe { (*view2.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base.cast::<c_void>(), array.as_ptr().cast::<c_void>());

let base = unsafe { (*view1.as_array_ptr()).base };
assert_eq!(base as *mut c_void, array as *const _ as *mut c_void);
assert_eq!(base.cast::<c_void>(), array.as_ptr().cast::<c_void>());

let base = unsafe { (*array.as_array_ptr()).base };
assert!(!base.is_null());

let base_address = base_address(py, view2.as_array_ptr());
assert_ne!(base_address, view2 as *const _ as *mut c_void);
assert_ne!(base_address, view1 as *const _ as *mut c_void);
assert_ne!(base_address, array as *const _ as *mut c_void);
assert_eq!(base_address, base as *mut c_void);
assert_ne!(base_address, view2.as_ptr().cast::<c_void>());
assert_ne!(base_address, view1.as_ptr().cast::<c_void>());
assert_ne!(base_address, array.as_ptr().cast::<c_void>());
assert_eq!(base_address, base.cast::<c_void>());

let data_range = data_range(view2.as_array_ptr());
assert_eq!(data_range.0, array.data() as *mut c_char);
assert_eq!(data_range.1, unsafe { array.data().add(1) } as *mut c_char);
assert_eq!(data_range.0, array.data().cast::<c_char>());
assert_eq!(data_range.1, unsafe {
array.data().add(1).cast::<c_char>()
});
});
}

Expand Down
Loading

0 comments on commit 2817305

Please sign in to comment.