@@ -19,6 +19,7 @@ use pyo3::{
1919 Python , ToPyObject ,
2020} ;
2121
22+ use crate :: cold;
2223use crate :: convert:: { ArrayExt , IntoPyArray , NpyIndex , ToNpyDims , ToPyArray } ;
2324use crate :: dtype:: { Element , PyArrayDescr } ;
2425use crate :: error:: { DimensionalityError , FromVecError , NotContiguousError , TypeError } ;
@@ -954,14 +955,8 @@ impl<T: Element> PyArray<T, Ix1> {
954955 pub fn from_slice < ' py > ( py : Python < ' py > , slice : & [ T ] ) -> & ' py Self {
955956 unsafe {
956957 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) ;
965960 array
966961 }
967962 }
@@ -978,6 +973,7 @@ impl<T: Element> PyArray<T, Ix1> {
978973 /// assert_eq!(pyarray.readonly().as_slice().unwrap(), &[1, 2, 3, 4, 5]);
979974 /// });
980975 /// ```
976+ #[ inline( always) ]
981977 pub fn from_vec < ' py > ( py : Python < ' py > , vec : Vec < T > ) -> & ' py Self {
982978 vec. into_pyarray ( py)
983979 }
@@ -988,34 +984,45 @@ impl<T: Element> PyArray<T, Ix1> {
988984 /// # Example
989985 /// ```
990986 /// 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( ));
995991 /// assert_eq!(pyarray.readonly().as_slice().unwrap(), &[1, 2, 3, 4, 5]);
996992 /// });
997993 /// ```
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)
10011004 }
10021005
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`].
10051007 ///
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,
10071009 /// this method can allocate memory multiple time, which can hurt performance.
10081010 ///
10091011 /// # Example
1012+ ///
10101013 /// ```
10111014 /// 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]);
10161020 /// });
10171021 /// ```
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+ {
10191026 let data = iter. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
10201027 data. into_pyarray ( py)
10211028 }
@@ -1095,19 +1102,18 @@ impl<T: Element> PyArray<T, Ix2> {
10951102 /// });
10961103 /// ```
10971104 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.
11051108 unsafe {
11061109 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) ) ;
11101115 }
1116+ clone_elements ( v, & mut data_ptr) ;
11111117 }
11121118 Ok ( array)
11131119 }
@@ -1135,28 +1141,24 @@ impl<T: Element> PyArray<T, Ix3> {
11351141 /// });
11361142 /// ```
11371143 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 ( ) ) ) ;
11521146 let dims = [ v. len ( ) , len2, len3] ;
1147+ // SAFETY: The result of `Self::new` is always safe to drop.
11531148 unsafe {
11541149 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) ) ;
11591160 }
1161+ clone_elements ( v, & mut data_ptr) ;
11601162 }
11611163 }
11621164 Ok ( array)
@@ -1298,6 +1300,18 @@ impl<T: Element + AsPrimitive<f64>> PyArray<T, Ix1> {
12981300 }
12991301}
13001302
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+
13011315#[ cfg( test) ]
13021316mod tests {
13031317 use super :: * ;
0 commit comments