-
Notifications
You must be signed in to change notification settings - Fork 18
/
lagrange_interpolation.rs
80 lines (71 loc) · 1.97 KB
/
lagrange_interpolation.rs
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
pub fn lagrange_interpolation<T>(xs: &[T], ys: &[T], one: T, zero: T) -> Vec<T>
where
T: Clone
+ Copy
+ std::ops::Sub<Output = T>
+ std::ops::Mul<Output = T>
+ std::ops::Div<Output = T>
+ std::ops::AddAssign
+ std::ops::SubAssign
+ std::ops::MulAssign,
{
let n = xs.len();
let mut all_c = vec![zero; n + 1];
all_c[0] = one;
for &x in xs.iter() {
let mut next = vec![zero; n + 1];
next[1..(n + 1)].clone_from_slice(&all_c[..n]);
for j in 0..n {
next[j] -= x * all_c[j];
}
all_c = next;
}
let mut c = vec![zero; n];
for i in 0..n {
let mut qi = one;
for j in 0..n {
if i == j {
continue;
}
qi *= xs[i] - xs[j];
}
let ri = ys[i] / qi;
let mut tmp_c = all_c.clone();
for j in (0..n).rev() {
c[j] += ri * tmp_c[j + 1];
let next_c = tmp_c[j + 1] * xs[i];
tmp_c[j] += next_c;
}
}
c
}
#[cfg(test)]
mod tests {
use super::*;
use crate::math::mod_int::mod_int::{set_mod_int, ModInt};
use rand::{thread_rng, Rng};
const MOD: i64 = 1_000_000_007;
#[test]
fn test_lagrange_interpolation() {
set_mod_int(MOD);
let mut rng = thread_rng();
let n = 500;
for _ in 0..10 {
let mut xs = vec![];
let mut ys = vec![];
for _ in 0..n {
xs.push(ModInt::from(rng.gen_range(0, MOD)));
ys.push(ModInt::from(rng.gen_range(0, MOD)));
}
let c = lagrange_interpolation(&xs, &ys, ModInt::from(1), ModInt::from(0));
for i in 0..n {
let mut y = ModInt::from(0);
let x = xs[i];
for i in 0..n {
y += x.pow(i as i64) * c[i];
}
assert_eq!(y.value(), ys[i].value());
}
}
}
}