oscirs/
vector.rs

1//! Useful functions and implementations for standard vectors
2
3use crate::{
4    ApplyFunction,
5    Result
6};
7use crate::err::SciError;
8
9impl<T> ApplyFunction<T> for Vec<T> {
10    fn apply_fn(&self, fn_to_apply: Box<dyn Fn(&T) -> T>) -> Self {
11        self.into_iter()
12            .map(|x| fn_to_apply(x))
13            .collect::<Vec<T>>()
14    }
15}
16
17/// Discrete trapezoidal integration of dep with respect to ind
18/// 
19/// Assumes sorted inputs
20pub fn integrate(ind: &Vec<f32>, dep: &Vec<f32>) -> Result<Vec<f32>> {
21    if ind.len() != dep.len() {
22        return Err(Box::new(SciError::VectorLengthsError))
23    }
24
25    let mut output_vec: Vec<f32> = Vec::with_capacity(ind.len());
26    output_vec.push(0.0);
27
28    for idx in 1..ind.len() {
29        output_vec.push(output_vec[idx - 1] + 0.5 * (dep[idx] + dep[idx - 1]) * (ind[idx] - ind[idx -1]));
30    }
31
32    Ok(output_vec)
33}
34
35/// Estimate value of dependent at input extrapolated from ind and dep
36/// 
37/// Assumes sorted inputs
38pub fn linterp(ind: &Vec<f32>, dep: &Vec<f32>, input: f32) -> Result<f32> {
39    if ind.len() != dep.len() {
40        return Err(Box::new(SciError::VectorLengthsError))
41    }
42
43    if ind[0] > input || input > ind[ind.len() - 1] {
44        return Err(Box::new(SciError::RangeError))
45    }
46
47    let mut idx: usize = 0;
48    while ind[idx] < input { idx += 1 }
49
50    let less_idx: usize = idx - 1;
51
52    let d_ind: f32 = ind[idx] - ind[less_idx];
53    let d_dep: f32 = dep[idx] - dep[less_idx];
54
55    let guess_dep: f32 = dep[less_idx] + (d_dep / d_ind) * (input - ind[less_idx]);
56
57    Ok(guess_dep)
58}