rhai_sci/integration_and_differentiation.rs
1use rhai::plugin::*;
2
3#[export_module]
4pub mod int_and_diff {
5 use crate::if_list_convert_to_vec_float_and_do;
6 use rhai::{Array, Dynamic, EvalAltResult, Position, FLOAT};
7
8 /// Returns the approximate integral of the curve defined by `y` and `x` using the trapezoidal method.
9 /// ```typescript
10 /// let y = [1.0, 1.5, 2.0];
11 /// let x = [1.0, 2.0, 3.0];
12 /// let A = trapz(x, y);
13 /// assert_eq(A, 3.0);
14 /// ```
15 /// ```typescript
16 /// let y = [1, 2, 3];
17 /// let x = [1, 2, 3];
18 /// let A = trapz(x, y);
19 /// assert_eq(A, 4.0);
20 /// ```
21 #[rhai_fn(name = "trapz", return_raw)]
22 pub fn trapz(x: Array, y: Array) -> Result<Dynamic, Box<EvalAltResult>> {
23 if x.len() != y.len() {
24 Err(EvalAltResult::ErrorArithmetic(
25 "The arrays must have the same length".to_string(),
26 Position::NONE,
27 )
28 .into())
29 } else {
30 if_list_convert_to_vec_float_and_do(&mut y.clone(), |yf| {
31 if_list_convert_to_vec_float_and_do(&mut x.clone(), |xf| {
32 let mut trapsum = 0.0;
33 for i in 1..x.len() {
34 trapsum += (yf[i] + yf[i - 1]) * (xf[i] - xf[i - 1]) / 2.0;
35 }
36 Ok(Dynamic::from_float(trapsum))
37 })
38 })
39 }
40 }
41
42 /// Returns the approximate integral of the curve defined by `y` using the trapezoidal method.
43 /// Assumes that x-values have unit spacing.
44 /// ```typescript
45 /// let y = [1.0, 1.5, 2.0];
46 /// let A = trapz(y);
47 /// assert_eq(A, 3.0);
48 /// ```
49 /// ```typescript
50 /// let y = [1, 2, 3];
51 /// let A = trapz(y);
52 /// assert_eq(A, 4.0);
53 /// ```
54 #[rhai_fn(name = "trapz", return_raw, pure)]
55 pub fn trapz_unit(arr: &mut Array) -> Result<Dynamic, Box<EvalAltResult>> {
56 if_list_convert_to_vec_float_and_do(arr, |y| {
57 let mut trapsum = 0.0 as FLOAT;
58 for i in 1..y.len() {
59 trapsum += (y[i] + y[i - 1]) / 2.0;
60 }
61 Ok(Dynamic::from_float(trapsum))
62 })
63 }
64
65 /// Returns the difference between successive elements of a 1-D array.
66 /// ```typescript
67 /// let arr = [2, 5, 1, 7, 8];
68 /// let d = diff(arr);
69 /// assert_eq(d, [3, -4, 6, 1]);
70 /// ```
71 #[rhai_fn(name = "diff", return_raw, pure)]
72 pub fn diff(arr: &mut Array) -> Result<Array, Box<EvalAltResult>> {
73 crate::if_list_do_int_or_do_float(
74 arr,
75 |arr| {
76 let mut new_arr = vec![];
77 for idx in 1..arr.len() {
78 new_arr.push(Dynamic::from_int(
79 arr[idx].as_int().unwrap() - arr[idx - 1].as_int().unwrap(),
80 ));
81 }
82 Ok(new_arr)
83 },
84 |arr| {
85 let mut new_arr = vec![];
86 for idx in 1..arr.len() {
87 new_arr.push(Dynamic::from_float(
88 arr[idx].as_float().unwrap() - arr[idx - 1].as_float().unwrap(),
89 ));
90 }
91 Ok(new_arr)
92 },
93 )
94 }
95}