1use binius_field::{PackedField, field::FieldOps};
4
5#[inline]
15pub fn extrapolate_line<F: FieldOps>(x0: F, x1: F, z: F) -> F {
16 x0.clone() + (x1 - x0) * z
17}
18
19#[inline]
38pub fn extrapolate_line_packed<P>(x0: P, x1: P, z: P) -> P
39where
40 P: PackedField,
41{
42 x0 + (x1 - x0) * z
43}
44
45#[cfg(test)]
46mod tests {
47 use binius_field::{Field, Random, field::FieldOps};
48 use rand::prelude::*;
49
50 use super::*;
51 use crate::test_utils::{B128, Packed128b};
52
53 type P = Packed128b;
54 type F = B128;
55
56 #[test]
57 fn test_extrapolate_line_packed_boundary_values() {
58 let mut rng = StdRng::seed_from_u64(0);
59
60 let x0 = F::random(&mut rng);
62 let x1 = F::random(&mut rng);
63 let zero = F::ZERO;
64 let one = F::ONE;
65
66 assert_eq!(extrapolate_line_packed(x0, x1, zero), x0);
68
69 assert_eq!(extrapolate_line_packed(x0, x1, one), x1);
71
72 let x0_packed = P::random(&mut rng);
74 let x1_packed = P::random(&mut rng);
75 let zero_packed = P::zero();
76 let one_packed = P::one();
77
78 assert_eq!(extrapolate_line_packed(x0_packed, x1_packed, zero_packed), x0_packed);
80
81 assert_eq!(extrapolate_line_packed(x0_packed, x1_packed, one_packed), x1_packed);
83 }
84
85 #[test]
86 fn test_extrapolate_line_packed_linearity() {
87 let mut rng = StdRng::seed_from_u64(0);
88
89 let x0 = F::random(&mut rng);
91 let x1 = F::random(&mut rng);
92 let z0 = F::random(&mut rng);
93 let z1 = F::random(&mut rng);
94 let alpha = F::random(&mut rng);
95
96 let z_combined = alpha * z0 + (F::ONE - alpha) * z1;
98
99 let f_z0 = extrapolate_line_packed(x0, x1, z0);
100 let f_z1 = extrapolate_line_packed(x0, x1, z1);
101 let f_combined = extrapolate_line_packed(x0, x1, z_combined);
102
103 let expected = alpha * f_z0 + (F::ONE - alpha) * f_z1;
104
105 assert_eq!(f_combined, expected);
106 }
107}