44//! [NpySingleIter](./struct.NpySingleIter.html) and
55//! [NpyMultiIter](./struct.NpyMultiIter.html).
66use crate :: array:: { PyArray , PyArrayDyn } ;
7- use crate :: error:: NpyIterInstantiationError ;
87use crate :: npyffi:: {
98 array:: PY_ARRAY_API ,
109 npy_intp, npy_uint32,
@@ -163,7 +162,7 @@ pub struct NpySingleIterBuilder<'py, T, I: IterMode> {
163162}
164163
165164impl < ' py , T : Element > NpySingleIterBuilder < ' py , T , Readonly > {
166- /// Make a new builder for a readonly iterator.
165+ /// Makes a new builder for a readonly iterator.
167166 pub fn readonly < D : ndarray:: Dimension > ( array : PyReadonlyArray < ' py , T , D > ) -> Self {
168167 let ( array, was_writable) = array. destruct ( ) ;
169168 Self {
@@ -176,7 +175,7 @@ impl<'py, T: Element> NpySingleIterBuilder<'py, T, Readonly> {
176175}
177176
178177impl < ' py , T : Element > NpySingleIterBuilder < ' py , T , ReadWrite > {
179- /// Make a new builder for a writable iterator.
178+ /// Makes a new builder for a writable iterator.
180179 pub fn readwrite < D : ndarray:: Dimension > ( array : & ' py PyArray < T , D > ) -> Self {
181180 Self {
182181 flags : NPY_ITER_READWRITE ,
@@ -188,13 +187,13 @@ impl<'py, T: Element> NpySingleIterBuilder<'py, T, ReadWrite> {
188187}
189188
190189impl < ' py , T : Element , I : IterMode > NpySingleIterBuilder < ' py , T , I > {
191- /// Set a flag to this builder, returning `self`.
190+ /// Sets a flag to this builder, returning `self`.
192191 pub fn set ( mut self , flag : NpyIterFlag ) -> Self {
193192 self . flags |= flag. to_c_enum ( ) ;
194193 self
195194 }
196195
197- /// Create an iterator from this builder.
196+ /// Creates an iterator from this builder.
198197 pub fn build ( self ) -> PyResult < NpySingleIter < ' py , T , I > > {
199198 let array_ptr = self . array . as_array_ptr ( ) ;
200199 let iter_ptr = unsafe {
@@ -216,11 +215,50 @@ impl<'py, T: Element, I: IterMode> NpySingleIterBuilder<'py, T, I> {
216215 }
217216}
218217
219- /// An iterator over a single array.
218+ /// An iterator over a single array, construced by
219+ /// [NpySingleIterBuilder](./struct.NpySingleIterBuilder.html).
220+ /// This iterator iterates all elements in the array as `&mut T` (in case `readwrite` is used)
221+ /// or `&T` (in case `readonly` is used).
220222///
221223/// # Example
222224///
225+ /// You can use
226+ /// [`NpySingleIterBuilder::readwrite`](./struct.NpySingleIterBuilder.html#method.readwrite)
227+ /// to get a mutable iterator.
223228///
229+ /// ```
230+ /// use numpy::NpySingleIterBuilder;
231+ /// let gil = pyo3::Python::acquire_gil();
232+ /// let py = gil.python();
233+ /// let array = numpy::PyArray::arange(py, 0, 10, 1);
234+ /// let iter = NpySingleIterBuilder::readwrite(array).build().unwrap();
235+ /// for (i, elem) in iter.enumerate() {
236+ /// assert_eq!(*elem, i as i64);
237+ /// *elem = *elem * 2; // elements are mutable
238+ /// }
239+ /// ```
240+ /// Or, as a shorthand, `PyArray::iter` can be also used.
241+ /// ```
242+ /// # use numpy::NpySingleIterBuilder;
243+ /// # let gil = pyo3::Python::acquire_gil();
244+ /// # let py = gil.python();
245+ /// # let array = numpy::PyArray::arange(py, 0, 10, 1);
246+ /// for (i, elem) in array.iter().unwrap().enumerate() {
247+ /// assert_eq!(*elem, i as i64);
248+ /// *elem = *elem * 2; // elements are mutable
249+ /// }
250+ /// ```
251+ /// On the other hand, immutable iterator requires [readonly array](../struct.PyReadonlyArray.html).
252+ /// ```
253+ /// use numpy::NpySingleIterBuilder;
254+ /// let gil = pyo3::Python::acquire_gil();
255+ /// let py = gil.python();
256+ /// let array = numpy::PyArray::arange(py, 0, 1, 10);
257+ /// let iter = NpySingleIterBuilder::readonly(array.readonly()).build().unwrap();
258+ /// for (i, elem) in iter.enumerate() {
259+ /// assert_eq!(*elem, i as i64);
260+ /// }
261+ /// ```
224262pub struct NpySingleIter < ' py , T , I > {
225263 iterator : ptr:: NonNull < NpyIter > ,
226264 iternext : unsafe extern "C" fn ( * mut NpyIter ) -> c_int ,
@@ -242,7 +280,7 @@ impl<'py, T, I> NpySingleIter<'py, T, I> {
242280 let mut iterator = match ptr:: NonNull :: new ( iterator) {
243281 Some ( iter) => iter,
244282 None => {
245- return Err ( NpyIterInstantiationError . into ( ) ) ;
283+ return Err ( PyErr :: fetch ( py ) ) ;
246284 }
247285 } ;
248286
@@ -257,7 +295,7 @@ impl<'py, T, I> NpySingleIter<'py, T, I> {
257295
258296 if dataptr. is_null ( ) {
259297 unsafe { PY_ARRAY_API . NpyIter_Deallocate ( iterator. as_mut ( ) ) } ;
260- return Err ( NpyIterInstantiationError . into ( ) ) ;
298+ return Err ( PyErr :: fetch ( py ) ) ;
261299 }
262300
263301 let iter_size = unsafe { PY_ARRAY_API . NpyIter_GetIterSize ( iterator. as_mut ( ) ) } ;
@@ -368,7 +406,7 @@ impl<'py, T: Element, S: MultiIterMode> NpyMultiIterBuilder<'py, T, S> {
368406 }
369407 }
370408
371- /// Add a writable array to the resulting iterator.
409+ /// Adds a writable array to the resulting iterator.
372410 pub fn add_readwrite < D : ndarray:: Dimension > (
373411 mut self ,
374412 array : & ' py PyArray < T , D > ,
@@ -385,7 +423,7 @@ impl<'py, T: Element, S: MultiIterMode> NpyMultiIterBuilder<'py, T, S> {
385423}
386424
387425impl < ' py , T : Element , S : MultiIterModeWithManyArrays > NpyMultiIterBuilder < ' py , T , S > {
388- /// Create an iterator from this builder.
426+ /// Creates an iterator from this builder.
389427 pub fn build ( self ) -> PyResult < NpyMultiIter < ' py , T , S > > {
390428 let Self {
391429 flags,
@@ -419,7 +457,34 @@ impl<'py, T: Element, S: MultiIterModeWithManyArrays> NpyMultiIterBuilder<'py, T
419457 }
420458}
421459
422- /// Multi iterator
460+ /// An iterator over multiple arrays, construced by
461+ /// [NpyMultiIterBuilder](./struct.NpyMultiIterBuilder.html).
462+ /// You can add
463+ /// [`NpyMultiIterBuilder::add_readwrite`](./struct.NpyMultiIterBuilder.html#method.add_readwrite)
464+ /// for adding a mutable component to the iterator, and
465+ /// [`NpyMultiIterBuilder::add_readonly`](./struct.NpyMultiIterBuilder.html#method.add_readonly)
466+ /// for adding a immutable one.
467+ ///
468+ /// # Example
469+ ///
470+ /// ```
471+ /// use numpy::NpyMultiIterBuilder;
472+ /// let gil = pyo3::Python::acquire_gil();
473+ /// let py = gil.python();
474+ /// let array1 = numpy::PyArray::arange(py, 0, 10, 1);
475+ /// let array2 = numpy::PyArray::arange(py, 10, 20, 1);
476+ /// let array3 = numpy::PyArray::arange(py, 10, 30, 2);
477+ /// let iter = NpyMultiIterBuilder::new()
478+ /// .add_readonly(array1.readonly())
479+ /// .add_readwrite(array2)
480+ /// .add_readonly(array3.readonly())
481+ /// .build()
482+ /// .unwrap();
483+ /// for (i, j, k) in iter {
484+ /// assert_eq!(*i + *j, *k);
485+ /// *j += *i + *k; // The third element is only mutable.
486+ /// }
487+ /// ```
423488pub struct NpyMultiIter < ' py , T , S : MultiIterModeWithManyArrays > {
424489 iterator : ptr:: NonNull < NpyIter > ,
425490 iternext : unsafe extern "C" fn ( * mut NpyIter ) -> c_int ,
@@ -442,7 +507,7 @@ impl<'py, T, S: MultiIterModeWithManyArrays> NpyMultiIter<'py, T, S> {
442507 let mut iterator = match ptr:: NonNull :: new ( iterator) {
443508 Some ( ptr) => ptr,
444509 None => {
445- return Err ( NpyIterInstantiationError . into ( ) ) ;
510+ return Err ( PyErr :: fetch ( py ) ) ;
446511 }
447512 } ;
448513
@@ -457,7 +522,7 @@ impl<'py, T, S: MultiIterModeWithManyArrays> NpyMultiIter<'py, T, S> {
457522
458523 if dataptr. is_null ( ) {
459524 unsafe { PY_ARRAY_API . NpyIter_Deallocate ( iterator. as_mut ( ) ) } ;
460- return Err ( NpyIterInstantiationError . into ( ) ) ;
525+ return Err ( PyErr :: fetch ( py ) ) ;
461526 }
462527
463528 let iter_size = unsafe { PY_ARRAY_API . NpyIter_GetIterSize ( iterator. as_mut ( ) ) } ;
0 commit comments