1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use rhai::plugin::*;
#[export_module]
pub mod cum_functions {
use crate::{if_list_convert_to_vec_float_and_do, if_list_do};
use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT, INT};
fn accumulate<G>(arr: &mut Array, mut f: G) -> Result<Array, Box<EvalAltResult>>
where
G: FnMut(&mut Array) -> Dynamic,
{
if_list_do(arr, |arr| {
let mut new_arr: Array = vec![];
let n = arr.len() as INT;
for i in 0..n {
new_arr.push(f(&mut arr.get(0_usize..=(i as usize)).unwrap().to_vec()))
}
Ok(new_arr)
})
}
/// Returns an array representing the cumulative product of a 1-D array.
/// ```typescript
/// let arr = [1, 2, 3, 4, 5];
/// let c = cumprod(arr);
/// assert_eq(c, [1, 2, 6, 24, 120]);
/// ```
#[rhai_fn(name = "cumprod", return_raw, pure)]
pub fn cumprod(arr: &mut Array) -> Result<Array, Box<EvalAltResult>> {
accumulate(arr, |x| crate::stats::prod(x).unwrap())
}
/// Returns an array representing the cumulative maximum of a 1-D array.
/// ```typescript
/// let arr = [1, 4, 5, 3, 9, 8];
/// let c = cummax(arr);
/// assert_eq(c, [1, 4, 5, 5, 9, 9]);
/// ```
#[rhai_fn(name = "cummax", return_raw, pure)]
pub fn cummax(arr: &mut Array) -> Result<Array, Box<EvalAltResult>> {
accumulate(arr, |x| crate::stats::array_max(x).unwrap())
}
/// Returns an array representing the cumulative minimum of a 1-D array.
/// ```typescript
/// let arr = [8, 9, 3, 5, 4, 1];
/// let c = cummin(arr);
/// assert_eq(c, [8, 8, 3, 3, 3, 1]);
/// ```
#[rhai_fn(name = "cummin", return_raw, pure)]
pub fn cummin(arr: &mut Array) -> Result<Array, Box<EvalAltResult>> {
accumulate(arr, |x| crate::stats::array_min(x).unwrap())
}
/// Returns an array representing the cumulative product of a 1-D array.
/// ```typescript
/// let arr = [1.1, 2.5, 3.4];
/// let c = cumsum(arr);
/// assert_eq(c, [1.1, 3.6, 7.0]);
/// ```
#[rhai_fn(name = "cumsum", return_raw, pure)]
pub fn cumsum(arr: &mut Array) -> Result<Array, Box<EvalAltResult>> {
accumulate(arr, |x| crate::stats::sum(x).unwrap())
}
/// Returns the cumulative approximate integral of the curve defined by Y and x using the trapezoidal method.
/// ```typescript
/// let y = [1, 2, 3];
/// let x = [1, 2, 3];
/// let c = cumtrapz(x, y);
/// assert_eq(c, [0.0, 1.5, 4.0]);
/// ```
#[rhai_fn(name = "cumtrapz", return_raw)]
pub fn cumtrapz(x: Array, y: Array) -> Result<Array, Box<EvalAltResult>> {
if x.len() != y.len() {
Err(EvalAltResult::ErrorArithmetic(
"The arrays must have the same length".to_string(),
Position::NONE,
)
.into())
} else {
if_list_convert_to_vec_float_and_do(&mut y.clone(), |yf| {
if_list_convert_to_vec_float_and_do(&mut x.clone(), |xf| {
let mut trapsum = 0.0;
let mut cumtrapsum = vec![Dynamic::FLOAT_ZERO];
for i in 1..x.len() {
trapsum += (yf[i] + yf[i - 1]) * (xf[i] - xf[i - 1]) / 2.0;
cumtrapsum.push(Dynamic::from_float(trapsum));
}
Ok(cumtrapsum)
})
})
}
}
/// Returns the cumulative approximate integral of the curve defined by Y and x using the
/// trapezoidal method. Assumes unit spacing in the x direction.
/// ```typescript
/// let y = [1, 2, 3];
/// let c = cumtrapz(y);
/// assert_eq(c, [0.0, 1.5, 4.0]);
/// ```
#[rhai_fn(name = "cumtrapz", return_raw, pure)]
pub fn cumtrapz_unit(y: &mut Array) -> Result<Array, Box<EvalAltResult>> {
if_list_convert_to_vec_float_and_do(y, |yf| {
let mut trapsum = 0.0 as FLOAT;
let mut cumtrapsum = vec![Dynamic::FLOAT_ZERO];
for i in 1..yf.len() {
trapsum += (yf[i] + yf[i - 1]) / 2.0;
cumtrapsum.push(Dynamic::from_float(trapsum));
}
Ok(cumtrapsum)
})
}
}