binius_math/
line.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use binius_field::PackedField;
4
5/// Extrapolates lines through a pair of packed fields at a packed vector of points.
6///
7/// Given two points (0, x0) and (1, x1), this function evaluates the line through these
8/// points at parameter z using the formula: x0 + (x1 - x0) * z
9///
10/// # Properties
11/// - When z = 0, returns x0
12/// - When z = 1, returns x1
13/// - The function is linear in z
14/// - Operates on packed field elements for SIMD efficiency
15///
16/// # Arguments
17/// * `x0` - The y-coordinate at z = 0
18/// * `x1` - The y-coordinate at z = 1
19/// * `z` - The evaluation point(s)
20///
21/// # Returns
22/// The interpolated/extrapolated value(s) at point(s) z
23#[inline]
24pub fn extrapolate_line_packed<P>(x0: P, x1: P, z: P) -> P
25where
26	P: PackedField,
27{
28	x0 + (x1 - x0) * z
29}
30
31#[cfg(test)]
32mod tests {
33	use binius_field::{Field, PackedField, Random};
34	use rand::prelude::*;
35
36	use super::*;
37	use crate::test_utils::{B128, Packed128b};
38
39	type P = Packed128b;
40	type F = B128;
41
42	#[test]
43	fn test_extrapolate_line_packed_boundary_values() {
44		let mut rng = StdRng::seed_from_u64(0);
45
46		// Test with scalar field
47		let x0 = F::random(&mut rng);
48		let x1 = F::random(&mut rng);
49		let zero = F::ZERO;
50		let one = F::ONE;
51
52		// When z = 0, should return x0
53		assert_eq!(extrapolate_line_packed(x0, x1, zero), x0);
54
55		// When z = 1, should return x1
56		assert_eq!(extrapolate_line_packed(x0, x1, one), x1);
57
58		// Test with packed field
59		let x0_packed = P::random(&mut rng);
60		let x1_packed = P::random(&mut rng);
61		let zero_packed = P::zero();
62		let one_packed = P::one();
63
64		// When z = 0, should return x0
65		assert_eq!(extrapolate_line_packed(x0_packed, x1_packed, zero_packed), x0_packed);
66
67		// When z = 1, should return x1
68		assert_eq!(extrapolate_line_packed(x0_packed, x1_packed, one_packed), x1_packed);
69	}
70
71	#[test]
72	fn test_extrapolate_line_packed_linearity() {
73		let mut rng = StdRng::seed_from_u64(0);
74
75		// Generate random points and values
76		let x0 = F::random(&mut rng);
77		let x1 = F::random(&mut rng);
78		let z0 = F::random(&mut rng);
79		let z1 = F::random(&mut rng);
80		let alpha = F::random(&mut rng);
81
82		// Test linearity property: f(αz0 + (1-α)z1) = αf(z0) + (1-α)f(z1)
83		let z_combined = alpha * z0 + (F::ONE - alpha) * z1;
84
85		let f_z0 = extrapolate_line_packed(x0, x1, z0);
86		let f_z1 = extrapolate_line_packed(x0, x1, z1);
87		let f_combined = extrapolate_line_packed(x0, x1, z_combined);
88
89		let expected = alpha * f_z0 + (F::ONE - alpha) * f_z1;
90
91		assert_eq!(f_combined, expected);
92	}
93}