qfall_math/rational/poly_over_q/
dot_product.rs1use crate::error::MathError;
12use crate::rational::{PolyOverQ, Q};
13use flint_sys::fmpq::{fmpq_add, fmpq_mul};
14use flint_sys::fmpq_poly::fmpq_poly_get_coeff_fmpq;
15
16impl PolyOverQ {
17 pub fn dot_product(&self, other: &Self) -> Result<Q, MathError> {
37 let self_degree = self.get_degree();
38 let other_degree = other.get_degree();
39
40 let mut smaller_degree = self_degree;
41 if smaller_degree > other_degree {
42 smaller_degree = other_degree;
43 }
44
45 let mut result = Q::default();
47 let mut temp = Q::default();
48 for i in 0..=smaller_degree {
49 unsafe {
51 let mut coefficient_1 = Q::default();
52 let mut coefficient_2 = Q::default();
53 fmpq_poly_get_coeff_fmpq(&mut coefficient_1.value, &self.poly, i);
54 fmpq_poly_get_coeff_fmpq(&mut coefficient_2.value, &other.poly, i);
55
56 fmpq_mul(&mut temp.value, &coefficient_1.value, &coefficient_2.value);
57
58 fmpq_add(&mut result.value, &result.value, &temp.value)
59 }
60 }
61
62 Ok(result)
63 }
64}
65
66#[cfg(test)]
67mod test_dot_product {
68 use crate::rational::{PolyOverQ, Q};
69 use std::str::FromStr;
70
71 #[test]
73 fn dot_product_correct() {
74 let poly_1 = PolyOverQ::from_str("2 1/2 1").unwrap();
75 let poly_2 = PolyOverQ::from_str("2 3 4/2").unwrap();
76
77 let cmp = Q::from((7, 2));
78 let dot_prod = poly_1.dot_product(&poly_2).unwrap();
79
80 assert_eq!(dot_prod, cmp);
81 }
82
83 #[test]
85 fn large_numbers() {
86 let poly_1 = PolyOverQ::from_str("3 6 2 2").unwrap();
87 let poly_2 = PolyOverQ::from_str(&format!("3 1 2 {}", i64::MAX / 3)).unwrap();
88
89 let cmp = Q::from(10 + 2 * (i64::MAX / 3));
90 let dot_prod = poly_1.dot_product(&poly_2).unwrap();
91
92 assert_eq!(dot_prod, cmp);
93 }
94
95 #[test]
98 fn different_lengths_work() {
99 let poly_1 = PolyOverQ::from_str("3 1 2 3/7").unwrap();
100 let poly_2 = PolyOverQ::from_str("2 3 4").unwrap();
101
102 let cmp = Q::from(11);
103 let dot_prod = poly_1.dot_product(&poly_2).unwrap();
104
105 assert_eq!(dot_prod, cmp);
106 }
107
108 #[test]
111 fn zero_length_works() {
112 let poly_1 = PolyOverQ::from_str("3 1 2/11 3").unwrap();
113 let poly_2 = PolyOverQ::from_str("0").unwrap();
114
115 let cmp = Q::ZERO;
116 let dot_prod = poly_1.dot_product(&poly_2).unwrap();
117
118 assert_eq!(dot_prod, cmp);
119 }
120}