Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a Cairo implementations of cumprod() #251

Merged
merged 1 commit into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/numeric/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Several interpolation methods are supported as follow:

Return the cumulative sum of the elements ([see also](https://numpy.org/doc/stable/reference/generated/numpy.cumsum.html#numpy-cumsum)).

## [Cumprod](./src/cumprod.cairo)

Return the cumulative product of the elements ([see also](https://numpy.org/doc/stable/reference/generated/numpy.cumprod.html#numpy-cumprod)).

## [Diff](./src/diff.cairo)

Return the discrete difference of the elements ([see also](https://numpy.org/doc/stable/reference/generated/numpy.diff.html#numpy.diff)).
27 changes: 27 additions & 0 deletions src/numeric/src/cumprod.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//! The cumulative product of the elements.

/// Compute the cumulative product of a sequence.
/// # Arguments
/// * `sequence` - The sequence to operate.
/// # Returns
/// * `Array<T>` - The cumulative product of sequence.
fn cumprod<T, +Mul<T>, +Copy<T>, +Drop<T>,>(mut sequence: Span<T>) -> Array<T> {
// [Check] Inputs
assert(sequence.len() >= 1, 'Array must have at least 1 elt');

// [Compute] Interpolation
let mut array = array![];
let mut prev_value = *sequence.pop_front().unwrap();
array.append(prev_value);
loop {
match sequence.pop_front() {
Option::Some(current_value) => {
let prod = *current_value * prev_value;
array.append(prod);
prev_value = prod;
},
Option::None => { break; },
};
};
array
}
1 change: 1 addition & 0 deletions src/numeric/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod cumprod;
mod cumsum;
mod diff;
mod integers;
Expand Down
1 change: 1 addition & 0 deletions src/numeric/src/tests.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod cumprod_test;
mod cumsum_test;
mod diff_test;
mod integers_test;
Expand Down
19 changes: 19 additions & 0 deletions src/numeric/src/tests/cumprod_test.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use alexandria_numeric::cumprod::cumprod;

#[test]
#[available_gas(2000000)]
fn cumprod_test() {
let xs: Array<u64> = array![3, 5, 7];
let ys = cumprod(xs.span());
assert(*ys[0] == *xs[0], 'wrong value at index 0');
assert(*ys[1] == *xs[0] * *xs[1], 'wrong value at index 1');
assert(*ys[2] == *xs[0] * *xs[1] * *xs[2], 'wrong value at index 2');
}

#[test]
#[should_panic(expected: ('Array must have at least 1 elt',))]
#[available_gas(2000000)]
fn cumprod_test_revert_empty() {
let xs: Array<u64> = array![];
let ys = cumprod(xs.span());
}