Skip to content

Commit

Permalink
feat(corelib): Iterator::product (#7156)
Browse files Browse the repository at this point in the history
  • Loading branch information
MagisterDaIlis authored Jan 26, 2025
1 parent d3da51b commit 11b20fc
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 1 deletion.
2 changes: 1 addition & 1 deletion corelib/src/iter.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,4 @@
mod adapters;
mod traits;
pub use adapters::PeekableTrait;
pub use traits::{FromIterator, IntoIterator, Iterator};
pub use traits::{FromIterator, IntoIterator, Iterator, Product};
2 changes: 2 additions & 0 deletions corelib/src/iter/traits.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod accum;
mod collect;
mod iterator;
pub use accum::Product;
pub use collect::{FromIterator, IntoIterator};
pub use iterator::Iterator;
22 changes: 22 additions & 0 deletions corelib/src/iter/traits/accum.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// Trait to represent types that can be created by multiplying elements of an
/// iterator.
///
/// This trait is used to implement [`Iterator::product()`]. Types which implement
/// this trait can be generated by using the [`product()`] method on an iterator.
/// Like [`FromIterator`], this trait should rarely be called directly.
///
/// [`product()`]: Iterator::product
/// [`FromIterator`]: crate::iter::FromIterator
pub trait Product<A> {
/// Takes an iterator and generates `Self` from the elements by "summing up"
/// the items.
fn product<I, +Iterator<I>[Item: A], +Destruct<I>, +Destruct<A>>(iter: I) -> A;
}

impl ProductMultiplicativeTypesImpl<
A, +Mul<A>, impl OneA: core::num::traits::One<A>,
> of Product<A> {
fn product<I, +Iterator<I>[Item: A], +Destruct<I>, +Destruct<A>>(mut iter: I) -> A {
iter.fold(OneA::one(), |acc, x| acc * x)
}
}
26 changes: 26 additions & 0 deletions corelib/src/iter/traits/iterator.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::iter::adapters::{
Enumerate, Map, Peekable, Zip, enumerated_iterator, mapped_iterator, peekable_iterator,
zipped_iterator,
};
use crate::iter::traits::Product;

/// A trait for dealing with iterators.
///
Expand Down Expand Up @@ -445,4 +446,29 @@ pub trait Iterator<T> {
fn peekable(self: T) -> Peekable<T, Self::Item> {
peekable_iterator(self)
}

/// Iterates over the entire iterator, multiplying all the elements
///
/// An empty iterator returns the one value of the type.
///
/// # Panics
///
/// When calling `product()` and a primitive integer type is being returned, this
/// method will panic if the computation overflows.
///
/// # Examples
///
/// ```
/// fn factorial(n: u32) -> u32 {
/// (1..=n).into_iter().product()
/// }
/// assert_eq!(factorial(0), 1);
/// assert_eq!(factorial(1), 1);
/// assert_eq!(factorial(5), 120);
/// ```
fn product<+Destruct<T>, +Destruct<Self::Item>, +Product<Self::Item>>(
self: T,
) -> Self::Item {
Product::<Self::Item>::product::<T, Self>(self)
}
}
7 changes: 7 additions & 0 deletions corelib/src/test/iter_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,10 @@ fn test_iter_adapter_peekable() {
assert_eq!(iter.peek(), Option::None);
assert_eq!(iter.next(), Option::None);
}

#[test]
fn test_iter_accum_product() {
assert_eq!((1_usize..=0).into_iter().product(), 1);
assert_eq!((1_usize..=1).into_iter().product(), 1);
assert_eq!((1_usize..=5).into_iter().product(), 120);
}

0 comments on commit 11b20fc

Please sign in to comment.