-
Notifications
You must be signed in to change notification settings - Fork 4
/
problem_2_3_correctness_of_horners_rule.rs
63 lines (51 loc) · 1.5 KB
/
problem_2_3_correctness_of_horners_rule.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
use std::ops::{Add, Mul};
// 1 y = 0
// 2 for i = n downto 0
// 3 y = a_i + x ⋅ y
pub fn polynomial<T: Default>(a: &[T], x: &T) -> T
where
for<'a> &'a T: Add<Output = T> + Mul<Output = T>,
{
let mut y: T = T::default();
for a_i in a.iter().rev() {
y = a_i + &(x * &y);
}
y
}
pub fn polynomial_naive<T: Default + Clone>(a: &[T], x: &T) -> T
where
for<'a> &'a T: Add<Output = T> + Mul<Output = T>,
{
let mut y: T = T::default();
for (i, a_i) in a.iter().enumerate() {
let mut p = a_i.clone();
for _ in 0..i {
p = &p * x;
}
y = &y + &p;
}
y
}
#[cfg(test)]
mod tests {
fn run_polynomial_test(f: fn(&[f64], &f64) -> f64) {
approx::assert_ulps_eq!(f(&[], &0.0), 0.0);
approx::assert_ulps_eq!(f(&[], &1.0), 0.0);
approx::assert_ulps_eq!(f(&[1.0], &0.0), 1.0);
approx::assert_ulps_eq!(f(&[1.0], &1.0), 1.0);
approx::assert_ulps_eq!(f(&[1.0, 2.0], &0.0), 1.0);
approx::assert_ulps_eq!(f(&[1.0, 2.0], &1.0), 3.0);
approx::assert_ulps_eq!(f(&[1.0, 2.0], &2.0), 5.0);
approx::assert_ulps_eq!(f(&[1.0, 2.0, 3.0], &0.0), 1.0);
approx::assert_ulps_eq!(f(&[1.0, 2.0, 3.0], &1.0), 6.0);
approx::assert_ulps_eq!(f(&[1.0, 2.0, 3.0], &2.0), 17.0);
}
#[test]
fn test_polynomial() {
run_polynomial_test(super::polynomial);
}
#[test]
fn test_polynomial_naive() {
run_polynomial_test(super::polynomial_naive);
}
}