rsl_interpolation/types/
linear.rs1use std::marker::PhantomData;
2
3use crate::Accelerator;
4use crate::InterpType;
5use crate::Interpolation;
6use crate::{DomainError, InterpolationError};
7
8use crate::{check_if_inbounds, check1d_data};
9
10const MIN_SIZE: usize = 2;
11
12#[doc(alias = "gsl_interp_linear")]
16pub struct Linear;
17
18impl<T> InterpType<T> for Linear
19where
20 T: crate::Num,
21{
22 type Interpolation = LinearInterp<T>;
23
24 fn build(&self, xa: &[T], ya: &[T]) -> Result<LinearInterp<T>, InterpolationError> {
39 check1d_data(xa, ya, MIN_SIZE)?;
40 Ok(LinearInterp {
41 _variable_type: PhantomData,
42 })
43 }
44
45 fn name(&self) -> &str {
46 "Linear"
47 }
48
49 fn min_size(&self) -> usize {
50 MIN_SIZE
51 }
52}
53
54pub struct LinearInterp<T> {
62 _variable_type: PhantomData<T>,
63}
64
65impl<T> Interpolation<T> for LinearInterp<T>
66where
67 T: crate::Num,
68{
69 fn eval(&self, xa: &[T], ya: &[T], x: T, acc: &mut Accelerator) -> Result<T, DomainError> {
70 check_if_inbounds(xa, x)?;
71 let index = acc.find(xa, x);
72
73 let xlo = xa[index];
74 let xhi = xa[index + 1];
75 let ylo = ya[index];
76 let yhi = ya[index + 1];
77
78 let dx = xhi - xlo;
79
80 debug_assert!(dx > T::zero());
81 Ok(ylo + (x - xlo) / dx * (yhi - ylo))
82 }
83
84 fn eval_deriv(
85 &self,
86 xa: &[T],
87 ya: &[T],
88 x: T,
89 acc: &mut Accelerator,
90 ) -> Result<T, DomainError> {
91 check_if_inbounds(xa, x)?;
92 let index = acc.find(xa, x);
93
94 let xlo = xa[index];
95 let xhi = xa[index + 1];
96 let ylo = ya[index];
97 let yhi = ya[index + 1];
98
99 let dx = xhi - xlo;
100 let dy = yhi - ylo;
101
102 debug_assert!(dx > T::zero());
103 Ok(dy / dx)
104 }
105
106 #[allow(unused_variables)]
108 fn eval_deriv2(
109 &self,
110 xa: &[T],
111 ya: &[T],
112 x: T,
113 acc: &mut Accelerator,
114 ) -> Result<T, DomainError> {
115 check_if_inbounds(xa, x)?;
116 Ok(T::zero())
117 }
118
119 fn eval_integ(
120 &self,
121 xa: &[T],
122 ya: &[T],
123 a: T,
124 b: T,
125 acc: &mut Accelerator,
126 ) -> Result<T, DomainError> {
127 check_if_inbounds(xa, a)?;
128 check_if_inbounds(xa, b)?;
129 let index_a = acc.find(xa, a);
130 let index_b = acc.find(xa, b);
131
132 let mut result = T::zero();
133
134 for i in index_a..=index_b {
135 let xlo = xa[i];
136 let xhi = xa[i + 1];
137 let ylo = ya[i];
138 let yhi = ya[i + 1];
139
140 let dx = xhi - xlo;
141 let d = (yhi - ylo) / dx;
142 let half = T::from(0.5).unwrap();
143
144 if dx.is_zero() {
145 continue;
146 }
147
148 if (i == index_a) | (i == index_b) {
149 let x1 = if i == index_a { a } else { xlo };
150 let x2 = if i == index_b { b } else { xhi };
151 result += (x2 - x1) * (ylo + half * d * ((x2 - xlo) + (x1 - xlo)));
152 } else {
153 result += half * dx * (ylo + yhi);
154 }
155 }
156 Ok(result)
157 }
158}