|
58 | 58 | type Item = A;
|
59 | 59 | type Dim = D;
|
60 | 60 | fn into_pyarray<'py>(self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
|
61 |
| - let strides = npy_strides(&self); |
| 61 | + let strides = NpyStrides::from_array(&self); |
62 | 62 | let dim = self.raw_dim();
|
63 | 63 | let boxed = self.into_raw_vec().into_boxed_slice();
|
64 | 64 | unsafe { PyArray::from_boxed_slice(py, dim, strides.as_ptr(), boxed) }
|
@@ -102,26 +102,55 @@ where
|
102 | 102 | type Dim = D;
|
103 | 103 | fn to_pyarray<'py>(&self, py: Python<'py>) -> &'py PyArray<Self::Item, Self::Dim> {
|
104 | 104 | let len = self.len();
|
105 |
| - let mut strides = npy_strides(self); |
| 105 | + let strides = NpyStrides::from_array(self); |
106 | 106 | unsafe {
|
107 |
| - let array = PyArray::new_(py, self.raw_dim(), strides.as_mut_ptr() as *mut npy_intp, 0); |
| 107 | + let array = PyArray::new_(py, self.raw_dim(), strides.as_ptr(), 0); |
108 | 108 | array.copy_ptr(self.as_ptr(), len);
|
109 | 109 | array
|
110 | 110 | }
|
111 | 111 | }
|
112 | 112 | }
|
113 | 113 |
|
114 |
| -fn npy_strides<S, D, A>(array: &ArrayBase<S, D>) -> Vec<npyffi::npy_intp> |
115 |
| -where |
116 |
| - S: Data<Elem = A>, |
117 |
| - D: Dimension, |
118 |
| - A: TypeNum, |
119 |
| -{ |
120 |
| - array |
121 |
| - .strides() |
122 |
| - .into_iter() |
123 |
| - .map(|n| n * mem::size_of::<A>() as npyffi::npy_intp) |
124 |
| - .collect() |
| 114 | +/// Numpy strides with short array optimization |
| 115 | +enum NpyStrides { |
| 116 | + Short([npyffi::npy_intp; 8]), |
| 117 | + Long(Vec<npyffi::npy_intp>), |
| 118 | +} |
| 119 | + |
| 120 | +impl NpyStrides { |
| 121 | + fn as_ptr(&self) -> *const npy_intp { |
| 122 | + match self { |
| 123 | + NpyStrides::Short(inner) => inner.as_ptr(), |
| 124 | + NpyStrides::Long(inner) => inner.as_ptr(), |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + fn from_array<A, S, D>(array: &ArrayBase<S, D>) -> Self |
| 129 | + where |
| 130 | + S: Data<Elem = A>, |
| 131 | + D: Dimension, |
| 132 | + A: TypeNum, |
| 133 | + { |
| 134 | + Self::from_strides(array.strides(), mem::size_of::<A>()) |
| 135 | + } |
| 136 | + fn from_strides(strides: &[isize], type_size: usize) -> Self { |
| 137 | + let len = strides.len(); |
| 138 | + let type_size = type_size as npyffi::npy_intp; |
| 139 | + if len <= 8 { |
| 140 | + let mut res = [0; 8]; |
| 141 | + for i in 0..len { |
| 142 | + res[i] = strides[i] as npyffi::npy_intp * type_size; |
| 143 | + } |
| 144 | + NpyStrides::Short(res) |
| 145 | + } else { |
| 146 | + NpyStrides::Long( |
| 147 | + strides |
| 148 | + .into_iter() |
| 149 | + .map(|&n| n as npyffi::npy_intp * type_size) |
| 150 | + .collect(), |
| 151 | + ) |
| 152 | + } |
| 153 | + } |
125 | 154 | }
|
126 | 155 |
|
127 | 156 | /// Utility trait to specify the dimention of array
|
|
0 commit comments