Skip to content

Commit

Permalink
Merge pull request #127 from PyO3/release0.9
Browse files Browse the repository at this point in the history
Bump version to 0.9.0
  • Loading branch information
kngwyu committed May 14, 2020
2 parents e8b3ced + e6deb3f commit fb703b7
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 109 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Changelog
- v0.9.0
- Update PyO3 to 0.10.0

- v0.8.0
- Update PyO3 to 0.9.0
- Fix SliceBox initialization
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "numpy"
version = "0.8.0"
version = "0.9.0"
authors = ["Toshiki Teramura <[email protected]>", "Yuji Kanagawa <[email protected]>"]
description = "Rust binding of NumPy C-API"
documentation = "https://rust-numpy.github.io/rust-numpy/numpy"
Expand All @@ -15,7 +15,7 @@ libc = "0.2"
num-complex = "0.2"
num-traits = "0.2"
ndarray = ">=0.13"
pyo3 = "0.9.0"
pyo3 = "0.10.1"

[features]
# In default setting, python version is automatically detected
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ using [setuptools-rust](https://github.com/PyO3/setuptools-rust).
name = "numpy-test"

[dependencies]
pyo3 = "0.9.0"
numpy = "0.8.0"
pyo3 = "0.10.1"
numpy = "0.9.0"
```

```rust
use numpy::{PyArray1, get_array_module};
use pyo3::prelude::{ObjectProtocol, PyResult, Python};
use pyo3::prelude::{PyResult, Python};
use pyo3::types::PyDict;

fn main() -> Result<(), ()> {
Expand Down Expand Up @@ -98,7 +98,7 @@ name = "rust_ext"
crate-type = ["cdylib"]

[dependencies]
numpy = "0.8.0"
numpy = "0.9.0"
ndarray = "0.13"

[dependencies.pyo3]
Expand Down
2 changes: 1 addition & 1 deletion examples/linalg/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ ndarray = ">= 0.13"
ndarray-linalg = { version = "0.12", features = ["openblas"] }

[dependencies.pyo3]
version = "0.9.0"
version = "0.10.1"
features = ["extension-module"]
2 changes: 1 addition & 1 deletion examples/simple-extension/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ numpy = { path = "../.." }
ndarray = ">= 0.12"

[dependencies.pyo3]
version = "0.9.0"
version = "0.10.1"
features = ["extension-module"]
57 changes: 27 additions & 30 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@ use ndarray::*;
use num_traits::AsPrimitive;
use pyo3::{ffi, prelude::*, type_object, types::PyAny};
use pyo3::{AsPyPointer, PyDowncastError, PyNativeType};
use std::iter::ExactSizeIterator;
use std::marker::PhantomData;
use std::mem;
use std::os::raw::c_int;
use std::ptr;
use std::{iter::ExactSizeIterator, marker::PhantomData};
use std::{mem, os::raw::c_int, ptr, slice};

use crate::convert::{IntoPyArray, NpyIndex, ToNpyDims, ToPyArray};
use crate::error::{ErrorKind, IntoPyResult};
use crate::slice_box::SliceBox;
use crate::types::{NpyDataType, TypeNum};

/// A safe, static-typed interface for
/// [NumPy ndarray](https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html).
/// [NumPy ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html).
///
/// # Memory location
///
Expand Down Expand Up @@ -77,7 +74,7 @@ use crate::types::{NpyDataType, TypeNum};
/// );
/// # }
/// ```
pub struct PyArray<T, D>(PyObject, PhantomData<T>, PhantomData<D>);
pub struct PyArray<T, D>(PyAny, PhantomData<T>, PhantomData<D>);

/// one-dimensional array
pub type PyArray1<T> = PyArray<T, Ix1>;
Expand Down Expand Up @@ -113,7 +110,7 @@ pyobject_native_type_convert!(

pyobject_native_type_named!(PyArray<T, D>, T, D);

impl<'a, T, D> ::std::convert::From<&'a PyArray<T, D>> for &'a PyAny {
impl<'a, T, D> std::convert::From<&'a PyArray<T, D>> for &'a PyAny {
fn from(ob: &'a PyArray<T, D>) -> Self {
unsafe { &*(ob as *const PyArray<T, D> as *const PyAny) }
}
Expand All @@ -139,8 +136,8 @@ impl<'a, T: TypeNum, D: Dimension> FromPyObject<'a> for &'a PyArray<T, D> {
}

impl<T, D> IntoPy<PyObject> for PyArray<T, D> {
fn into_py(self, _py: Python<'_>) -> PyObject {
self.0
fn into_py(self, py: Python<'_>) -> PyObject {
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}

Expand Down Expand Up @@ -226,7 +223,7 @@ impl<T, D> PyArray<T, D> {

/// Returns the number of dimensions in the array.
///
/// Same as [numpy.ndarray.ndim](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.ndim.html)
/// Same as [numpy.ndarray.ndim](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.ndim.html)
///
/// # Example
/// ```
Expand All @@ -237,15 +234,15 @@ impl<T, D> PyArray<T, D> {
/// assert_eq!(arr.ndim(), 3);
/// # }
/// ```
// C API: https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_NDIM
// C API: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_NDIM
pub fn ndim(&self) -> usize {
let ptr = self.as_array_ptr();
unsafe { (*ptr).nd as usize }
}

/// Returns a slice which contains how many bytes you need to jump to the next row.
///
/// Same as [numpy.ndarray.strides](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.strides.html)
/// Same as [numpy.ndarray.strides](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html)
/// # Example
/// ```
/// # fn main() {
Expand All @@ -255,19 +252,19 @@ impl<T, D> PyArray<T, D> {
/// assert_eq!(arr.strides(), &[240, 48, 8]);
/// # }
/// ```
// C API: https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_STRIDES
// C API: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_STRIDES
pub fn strides(&self) -> &[isize] {
let n = self.ndim();
let ptr = self.as_array_ptr();
unsafe {
let p = (*ptr).strides;
::std::slice::from_raw_parts(p, n)
slice::from_raw_parts(p, n)
}
}

/// Returns a slice which contains dimmensions of the array.
///
/// Same as [numpy.ndarray.shape](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.shape.html)
/// Same as [numpy.ndarray.shape](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.shape.html)
/// # Example
/// ```
/// # fn main() {
Expand All @@ -277,13 +274,13 @@ impl<T, D> PyArray<T, D> {
/// assert_eq!(arr.shape(), &[4, 5, 6]);
/// # }
/// ```
// C API: https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_DIMS
// C API: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_DIMS
pub fn shape(&self) -> &[usize] {
let n = self.ndim();
let ptr = self.as_array_ptr();
unsafe {
let p = (*ptr).dimensions as *mut usize;
::std::slice::from_raw_parts(p, n)
slice::from_raw_parts(p, n)
}
}

Expand Down Expand Up @@ -314,7 +311,7 @@ impl<T, D> PyArray<T, D> {
let ptr = self.as_array_ptr();
unsafe {
let p = (*ptr).strides;
::std::slice::from_raw_parts(p as *const _, n)
slice::from_raw_parts(p as *const _, n)
}
}
}
Expand Down Expand Up @@ -371,11 +368,11 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
dims.ndim_cint(),
dims.as_dims_ptr(),
T::typenum_default(),
strides as *mut _, // strides
ptr::null_mut(), // data
0, // itemsize
flag, // flag
::std::ptr::null_mut(), //obj
strides as *mut _, // strides
ptr::null_mut(), // data
0, // itemsize
flag, // flag
ptr::null_mut(), //obj
);
Self::from_owned_ptr(py, ptr)
}
Expand Down Expand Up @@ -404,7 +401,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
data_ptr as _, // data
mem::size_of::<T>() as i32, // itemsize
0, // flag
::std::ptr::null_mut(), //obj
ptr::null_mut(), //obj
);
PY_ARRAY_API.PyArray_SetBaseObject(ptr as *mut npyffi::PyArrayObject, cell as _);
Self::from_owned_ptr(py, ptr)
Expand All @@ -415,7 +412,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
/// If `is_fortran` is true, then
/// a fortran order array is created, otherwise a C-order array is created.
///
/// See also [PyArray_Zeros](https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_Zeros)
/// See also [PyArray_Zeros](https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Zeros)
///
/// # Example
/// ```
Expand Down Expand Up @@ -469,7 +466,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
if !self.is_contiguous() {
Err(ErrorKind::NotContiguous)
} else {
Ok(unsafe { ::std::slice::from_raw_parts(self.data(), self.len()) })
Ok(unsafe { slice::from_raw_parts(self.data(), self.len()) })
}
}

Expand All @@ -479,7 +476,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
if !self.is_contiguous() {
Err(ErrorKind::NotContiguous)
} else {
Ok(unsafe { ::std::slice::from_raw_parts_mut(self.data(), self.len()) })
Ok(unsafe { slice::from_raw_parts_mut(self.data(), self.len()) })
}
}

Expand Down Expand Up @@ -1037,9 +1034,9 @@ impl<T: TypeNum, D> PyArray<T, D> {

impl<T: TypeNum + AsPrimitive<f64>> PyArray<T, Ix1> {
/// Return evenly spaced values within a given interval.
/// Same as [numpy.arange](https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html).
/// Same as [numpy.arange](https://numpy.org/doc/stable/reference/generated/numpy.arange.html).
///
/// See also [PyArray_Arange](https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_Arange).
/// See also [PyArray_Arange](https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Arange).
///
/// # Example
/// ```
Expand Down
3 changes: 1 addition & 2 deletions src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
use ndarray::{ArrayBase, Data, Dimension, IntoDimension, Ix1, OwnedRepr};
use pyo3::Python;

use std::mem;
use std::os::raw::c_int;
use std::{mem, os::raw::c_int};

use super::*;
use crate::npyffi::npy_intp;
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! `rust-numpy` provides Rust interfaces for [NumPy C APIs](https://docs.scipy.org/doc/numpy/reference/c-api.html),
//! especially for [ndarray](https://www.numpy.org/devdocs/reference/arrays.ndarray.html) class.
//! `rust-numpy` provides Rust interfaces for [NumPy C APIs](https://numpy.org/doc/stable/reference/c-api),
//! especially for [ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html) class.
//!
//! It uses [pyo3](https://github.com/PyO3/pyo3) for rust bindings to cpython, and uses
//! [ndarray](https://github.com/bluss/ndarray) for rust side matrix library.
Expand Down
54 changes: 27 additions & 27 deletions src/npyffi/array.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
//! Low-Level binding for [Array API](https://docs.scipy.org/doc/numpy/reference/c-api.array.html)
//! Low-Level binding for [Array API](https://numpy.org/doc/stable/reference/c-api/array.html)
use libc::FILE;
use pyo3::ffi::{self, PyObject, PyTypeObject};
use std::ops::Deref;
use std::os::raw::*;
use std::ptr;
use std::sync::Once;
use std::{cell::Cell, ptr, sync::Once};

use crate::npyffi::*;

pub(crate) const MOD_NAME: &str = "numpy.core.multiarray";
const CAPSULE_NAME: &str = "_ARRAY_API";

/// A global variable which stores a ['capsule'](https://docs.python.org/3/c-api/capsule.html)
/// pointer to [Numpy Array API](https://docs.scipy.org/doc/numpy/reference/c-api.array.html).
/// pointer to [Numpy Array API](https://numpy.org/doc/stable/reference/c-api/array.html).
///
/// You can acceess raw c APIs via this variable and its Deref implementation.
///
Expand All @@ -31,35 +29,33 @@ const CAPSULE_NAME: &str = "_ARRAY_API";
/// assert_eq!(array.as_slice().unwrap(), &[2, 3, 4])
/// # }
/// ```
pub static PY_ARRAY_API: PyArrayAPI = PyArrayAPI {
__private_field: (),
};
pub static PY_ARRAY_API: PyArrayAPI = PyArrayAPI::new();

/// See [PY_ARRAY_API] for more.
pub struct PyArrayAPI {
__private_field: (),
once: Once,
api: Cell<*const *const c_void>,
}

impl Deref for PyArrayAPI {
type Target = PyArrayAPI_Inner;
fn deref(&self) -> &Self::Target {
static INIT_API: Once = Once::new();
static mut ARRAY_API_CACHE: PyArrayAPI_Inner = PyArrayAPI_Inner(ptr::null());
unsafe {
if ARRAY_API_CACHE.0.is_null() {
let api = get_numpy_api(MOD_NAME, CAPSULE_NAME);
INIT_API.call_once(move || {
ARRAY_API_CACHE = PyArrayAPI_Inner(api);
});
}
&ARRAY_API_CACHE
impl PyArrayAPI {
const fn new() -> Self {
Self {
once: Once::new(),
api: Cell::new(ptr::null_mut()),
}
}
fn get(&self, offset: isize) -> *const *const c_void {
if self.api.get().is_null() {
let api = get_numpy_api(MOD_NAME, CAPSULE_NAME);
self.once.call_once(|| self.api.set(api));
}
unsafe { self.api.get().offset(offset) }
}
}

#[allow(non_camel_case_types)]
pub struct PyArrayAPI_Inner(*const *const c_void);
unsafe impl Sync for PyArrayAPI {}

impl PyArrayAPI_Inner {
impl PyArrayAPI {
impl_api![0; PyArray_GetNDArrayCVersion() -> c_uint];
impl_api![40; PyArray_SetNumericOps(dict: *mut PyObject) -> c_int];
impl_api![41; PyArray_GetNumericOps() -> *mut PyObject];
Expand Down Expand Up @@ -322,13 +318,15 @@ impl PyArrayAPI_Inner {
/// Define PyTypeObject related to Array API
macro_rules! impl_array_type {
($(($offset:expr, $tname:ident)),*) => {
/// All type objects that numpy has.
#[allow(non_camel_case_types)]
#[repr(i32)]
pub enum ArrayType { $($tname),* }
impl PyArrayAPI_Inner {
impl PyArrayAPI {
/// Get the pointer of the type object that `self` refers.
pub unsafe fn get_type_object(&self, ty: ArrayType) -> *mut PyTypeObject {
match ty {
$( ArrayType::$tname => *(self.0.offset($offset)) as *mut PyTypeObject ),*
$( ArrayType::$tname => *(self.get($offset)) as *mut PyTypeObject ),*
}
}
}
Expand Down Expand Up @@ -377,11 +375,13 @@ impl_array_type!(
(39, PyVoidArrType_Type)
);

/// Checks that `op` is an instance of `PyArray` or not.
#[allow(non_snake_case)]
pub unsafe fn PyArray_Check(op: *mut PyObject) -> c_int {
ffi::PyObject_TypeCheck(op, PY_ARRAY_API.get_type_object(ArrayType::PyArray_Type))
}

/// Checks that `op` is an exact instance of `PyArray` or not.
#[allow(non_snake_case)]
pub unsafe fn PyArray_CheckExact(op: *mut PyObject) -> c_int {
(ffi::Py_TYPE(op) == PY_ARRAY_API.get_type_object(ArrayType::PyArray_Type)) as c_int
Expand Down
Loading

0 comments on commit fb703b7

Please sign in to comment.