@@ -19,6 +19,7 @@ use pyo3::{
19
19
Python , ToPyObject ,
20
20
} ;
21
21
22
+ use crate :: cold;
22
23
use crate :: convert:: { ArrayExt , IntoPyArray , NpyIndex , ToNpyDims , ToPyArray } ;
23
24
use crate :: dtype:: { Element , PyArrayDescr } ;
24
25
use crate :: error:: { DimensionalityError , FromVecError , NotContiguousError , TypeError } ;
@@ -954,14 +955,8 @@ impl<T: Element> PyArray<T, Ix1> {
954
955
pub fn from_slice < ' py > ( py : Python < ' py > , slice : & [ T ] ) -> & ' py Self {
955
956
unsafe {
956
957
let array = PyArray :: new ( py, [ slice. len ( ) ] , false ) ;
957
- if T :: IS_COPY {
958
- ptr:: copy_nonoverlapping ( slice. as_ptr ( ) , array. data ( ) , slice. len ( ) ) ;
959
- } else {
960
- let data_ptr = array. data ( ) ;
961
- for ( i, item) in slice. iter ( ) . enumerate ( ) {
962
- data_ptr. add ( i) . write ( item. clone ( ) ) ;
963
- }
964
- }
958
+ let mut data_ptr = array. data ( ) ;
959
+ clone_elements ( slice, & mut data_ptr) ;
965
960
array
966
961
}
967
962
}
@@ -978,6 +973,7 @@ impl<T: Element> PyArray<T, Ix1> {
978
973
/// assert_eq!(pyarray.readonly().as_slice().unwrap(), &[1, 2, 3, 4, 5]);
979
974
/// });
980
975
/// ```
976
+ #[ inline( always) ]
981
977
pub fn from_vec < ' py > ( py : Python < ' py > , vec : Vec < T > ) -> & ' py Self {
982
978
vec. into_pyarray ( py)
983
979
}
@@ -988,34 +984,45 @@ impl<T: Element> PyArray<T, Ix1> {
988
984
/// # Example
989
985
/// ```
990
986
/// use numpy::PyArray;
991
- /// use std::collections::BTreeSet ;
992
- /// let vec = vec![1, 2, 3, 4, 5];
993
- /// pyo3:: Python::with_gil(|py| {
994
- /// let pyarray = PyArray::from_exact_iter(py, vec.iter ().map(|&x| x ));
987
+ /// use pyo3::Python ;
988
+ ///
989
+ /// Python::with_gil(|py| {
990
+ /// let pyarray = PyArray::from_exact_iter(py, [1, 2, 3, 4, 5].into_iter ().copied( ));
995
991
/// assert_eq!(pyarray.readonly().as_slice().unwrap(), &[1, 2, 3, 4, 5]);
996
992
/// });
997
993
/// ```
998
- pub fn from_exact_iter ( py : Python < ' _ > , iter : impl ExactSizeIterator < Item = T > ) -> & Self {
999
- let data = iter. collect :: < Box < [ _ ] > > ( ) ;
1000
- data. into_pyarray ( py)
994
+ #[ deprecated(
995
+ note = "`from_exact_iter` is deprecated as it does not provide any benefit over `from_iter`."
996
+ ) ]
997
+ #[ inline( always) ]
998
+ pub fn from_exact_iter < I > ( py : Python < ' _ > , iter : I ) -> & Self
999
+ where
1000
+ I : IntoIterator < Item = T > ,
1001
+ I :: IntoIter : ExactSizeIterator ,
1002
+ {
1003
+ Self :: from_iter ( py, iter)
1001
1004
}
1002
1005
1003
- /// Construct one-dimension PyArray from a type which implements
1004
- /// [`IntoIterator`](https://doc.rust-lang.org/std/iter/trait.IntoIterator.html).
1006
+ /// Construct one-dimension PyArray from a type which implements [`IntoIterator`].
1005
1007
///
1006
- /// If no reliable [`size_hint`](https://doc.rust-lang.org/std/iter/trait. Iterator.html#method. size_hint) is available,
1008
+ /// If no reliable [`size_hint`][ Iterator:: size_hint] is available,
1007
1009
/// this method can allocate memory multiple time, which can hurt performance.
1008
1010
///
1009
1011
/// # Example
1012
+ ///
1010
1013
/// ```
1011
1014
/// use numpy::PyArray;
1012
- /// let set: std::collections::BTreeSet<u32> = [4, 3, 2, 5, 1].into_iter().cloned().collect();
1013
- /// pyo3::Python::with_gil(|py| {
1014
- /// let pyarray = PyArray::from_iter(py, set);
1015
- /// assert_eq!(pyarray.readonly().as_slice().unwrap(), &[1, 2, 3, 4, 5]);
1015
+ /// use pyo3::Python;
1016
+ ///
1017
+ /// Python::with_gil(|py| {
1018
+ /// let pyarray = PyArray::from_iter(py, "abcde".chars().map(u32::from));
1019
+ /// assert_eq!(pyarray.readonly().as_slice().unwrap(), &[97, 98, 99, 100, 101]);
1016
1020
/// });
1017
1021
/// ```
1018
- pub fn from_iter ( py : Python < ' _ > , iter : impl IntoIterator < Item = T > ) -> & Self {
1022
+ pub fn from_iter < I > ( py : Python < ' _ > , iter : I ) -> & Self
1023
+ where
1024
+ I : IntoIterator < Item = T > ,
1025
+ {
1019
1026
let data = iter. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
1020
1027
data. into_pyarray ( py)
1021
1028
}
@@ -1095,19 +1102,18 @@ impl<T: Element> PyArray<T, Ix2> {
1095
1102
/// });
1096
1103
/// ```
1097
1104
pub fn from_vec2 < ' py > ( py : Python < ' py > , v : & [ Vec < T > ] ) -> Result < & ' py Self , FromVecError > {
1098
- let last_len = v. last ( ) . map_or ( 0 , |v| v. len ( ) ) ;
1099
- for v in v {
1100
- if v. len ( ) != last_len {
1101
- return Err ( FromVecError :: new ( v. len ( ) , last_len) ) ;
1102
- }
1103
- }
1104
- let dims = [ v. len ( ) , last_len] ;
1105
+ let len2 = v. first ( ) . map_or ( 0 , |v| v. len ( ) ) ;
1106
+ let dims = [ v. len ( ) , len2] ;
1107
+ // SAFETY: The result of `Self::new` is always safe to drop.
1105
1108
unsafe {
1106
1109
let array = Self :: new ( py, dims, false ) ;
1107
- for ( y, vy) in v. iter ( ) . enumerate ( ) {
1108
- for ( x, vyx) in vy. iter ( ) . enumerate ( ) {
1109
- array. uget_raw ( [ y, x] ) . write ( vyx. clone ( ) ) ;
1110
+ let mut data_ptr = array. data ( ) ;
1111
+ for v in v {
1112
+ if v. len ( ) != len2 {
1113
+ cold ( ) ;
1114
+ return Err ( FromVecError :: new ( v. len ( ) , len2) ) ;
1110
1115
}
1116
+ clone_elements ( v, & mut data_ptr) ;
1111
1117
}
1112
1118
Ok ( array)
1113
1119
}
@@ -1135,28 +1141,24 @@ impl<T: Element> PyArray<T, Ix3> {
1135
1141
/// });
1136
1142
/// ```
1137
1143
pub fn from_vec3 < ' py > ( py : Python < ' py > , v : & [ Vec < Vec < T > > ] ) -> Result < & ' py Self , FromVecError > {
1138
- let len2 = v. last ( ) . map_or ( 0 , |v| v. len ( ) ) ;
1139
- for v in v {
1140
- if v. len ( ) != len2 {
1141
- return Err ( FromVecError :: new ( v. len ( ) , len2) ) ;
1142
- }
1143
- }
1144
- let len3 = v. last ( ) . map_or ( 0 , |v| v. last ( ) . map_or ( 0 , |v| v. len ( ) ) ) ;
1145
- for v in v {
1146
- for v in v {
1147
- if v. len ( ) != len3 {
1148
- return Err ( FromVecError :: new ( v. len ( ) , len3) ) ;
1149
- }
1150
- }
1151
- }
1144
+ let len2 = v. first ( ) . map_or ( 0 , |v| v. len ( ) ) ;
1145
+ let len3 = v. first ( ) . map_or ( 0 , |v| v. first ( ) . map_or ( 0 , |v| v. len ( ) ) ) ;
1152
1146
let dims = [ v. len ( ) , len2, len3] ;
1147
+ // SAFETY: The result of `Self::new` is always safe to drop.
1153
1148
unsafe {
1154
1149
let array = Self :: new ( py, dims, false ) ;
1155
- for ( z, vz) in v. iter ( ) . enumerate ( ) {
1156
- for ( y, vzy) in vz. iter ( ) . enumerate ( ) {
1157
- for ( x, vzyx) in vzy. iter ( ) . enumerate ( ) {
1158
- array. uget_raw ( [ z, y, x] ) . write ( vzyx. clone ( ) ) ;
1150
+ let mut data_ptr = array. data ( ) ;
1151
+ for v in v {
1152
+ if v. len ( ) != len2 {
1153
+ cold ( ) ;
1154
+ return Err ( FromVecError :: new ( v. len ( ) , len2) ) ;
1155
+ }
1156
+ for v in v {
1157
+ if v. len ( ) != len3 {
1158
+ cold ( ) ;
1159
+ return Err ( FromVecError :: new ( v. len ( ) , len3) ) ;
1159
1160
}
1161
+ clone_elements ( v, & mut data_ptr) ;
1160
1162
}
1161
1163
}
1162
1164
Ok ( array)
@@ -1298,6 +1300,18 @@ impl<T: Element + AsPrimitive<f64>> PyArray<T, Ix1> {
1298
1300
}
1299
1301
}
1300
1302
1303
+ unsafe fn clone_elements < T : Element > ( elems : & [ T ] , data_ptr : & mut * mut T ) {
1304
+ if T :: IS_COPY {
1305
+ ptr:: copy_nonoverlapping ( elems. as_ptr ( ) , * data_ptr, elems. len ( ) ) ;
1306
+ * data_ptr = data_ptr. add ( elems. len ( ) ) ;
1307
+ } else {
1308
+ for elem in elems {
1309
+ data_ptr. write ( elem. clone ( ) ) ;
1310
+ * data_ptr = data_ptr. add ( 1 ) ;
1311
+ }
1312
+ }
1313
+ }
1314
+
1301
1315
#[ cfg( test) ]
1302
1316
mod tests {
1303
1317
use super :: * ;
0 commit comments