qfall_math/rational/poly_over_q/arithmetic/
mul.rs1use super::super::PolyOverQ;
12use crate::{
13 integer::PolyOverZ,
14 macros::arithmetics::{
15 arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
16 arithmetic_trait_mixed_borrowed_owned, arithmetic_trait_reverse,
17 },
18};
19use flint_sys::fmpq_poly::fmpq_poly_mul;
20use std::ops::{Mul, MulAssign};
21
22impl MulAssign<&PolyOverQ> for PolyOverQ {
23 fn mul_assign(&mut self, other: &Self) {
48 unsafe { fmpq_poly_mul(&mut self.poly, &self.poly, &other.poly) };
49 }
50}
51impl MulAssign<&PolyOverZ> for PolyOverQ {
52 fn mul_assign(&mut self, other: &PolyOverZ) {
54 let other = PolyOverQ::from(other);
55
56 self.mul_assign(other);
57 }
58}
59
60arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolyOverQ, PolyOverQ);
61arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolyOverQ, PolyOverZ);
62
63impl Mul for &PolyOverQ {
64 type Output = PolyOverQ;
65 fn mul(self, other: Self) -> Self::Output {
87 let mut out = PolyOverQ::default();
88 unsafe {
89 fmpq_poly_mul(&mut out.poly, &self.poly, &other.poly);
90 }
91 out
92 }
93}
94
95arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverQ, PolyOverQ, PolyOverQ);
96arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverQ, PolyOverQ, PolyOverQ);
97
98impl Mul<&PolyOverZ> for &PolyOverQ {
99 type Output = PolyOverQ;
100 fn mul(self, other: &PolyOverZ) -> Self::Output {
120 let mut out = PolyOverQ::default();
121 unsafe {
122 fmpq_poly_mul(&mut out.poly, &self.poly, &PolyOverQ::from(other).poly);
123 }
124 out
125 }
126}
127
128arithmetic_trait_reverse!(Mul, mul, PolyOverZ, PolyOverQ, PolyOverQ);
129
130arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverQ, PolyOverZ, PolyOverQ);
131arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverZ, PolyOverQ, PolyOverQ);
132arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverQ, PolyOverZ, PolyOverQ);
133arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverZ, PolyOverQ, PolyOverQ);
134
135#[cfg(test)]
136mod test_mul_assign {
137 use super::PolyOverQ;
138 use crate::integer::PolyOverZ;
139 use std::str::FromStr;
140
141 #[test]
143 fn correct_small() {
144 let mut a = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
145 let b = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
146
147 a *= b;
148
149 assert_eq!(
150 a,
151 PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
152 );
153 }
154
155 #[test]
157 fn correct_large() {
158 let mut a = PolyOverQ::from_str(&format!("2 {} {}", 2, i64::MIN)).unwrap();
159 let b = PolyOverQ::from_str(&format!(
160 "2 {}/{} {}/{}",
161 u32::MAX,
162 u128::MAX,
163 i64::MAX,
164 u128::MAX
165 ))
166 .unwrap();
167
168 a *= b;
169
170 assert_eq!(
171 a,
172 PolyOverQ::from_str(&format!(
173 "3 {}/{} {}/{} {}/{}",
174 2_u128 * u128::from(u32::MAX),
175 u128::MAX,
176 2_i128 * i128::from(i64::MAX) + i128::from(u32::MAX) * i128::from(i64::MIN),
177 u128::MAX,
178 i128::from(i64::MAX) * i128::from(i64::MIN),
179 u128::MAX
180 ))
181 .unwrap()
182 );
183 }
184
185 #[test]
187 fn availability() {
188 let mut a = PolyOverQ::from_str("3 1 2 -3").unwrap();
189 let b = PolyOverQ::from_str("3 -1 -2 3").unwrap();
190 let c = PolyOverZ::from_str("4 2 -1 2 3").unwrap();
191
192 a *= &b;
193 a *= b;
194 a *= &c;
195 a *= c;
196 }
197}
198
199#[cfg(test)]
200mod test_mul {
201 use super::PolyOverQ;
202 use std::str::FromStr;
203
204 #[test]
206 fn mul() {
207 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
208 let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
209 let c: PolyOverQ = a * b;
210 assert_eq!(
211 c,
212 PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
213 );
214 }
215
216 #[test]
218 fn mul_borrow() {
219 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
220 let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
221 let c: PolyOverQ = &a * &b;
222 assert_eq!(
223 c,
224 PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
225 );
226 }
227
228 #[test]
230 fn mul_first_borrowed() {
231 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
232 let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
233 let c: PolyOverQ = &a * b;
234 assert_eq!(
235 c,
236 PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
237 );
238 }
239
240 #[test]
242 fn mul_second_borrowed() {
243 let a: PolyOverQ = PolyOverQ::from_str("3 1/7 2/7 -3/7").unwrap();
244 let b: PolyOverQ = PolyOverQ::from_str("5 1/11 2/11 5/11 1/11 2/11").unwrap();
245 let c: PolyOverQ = a * &b;
246 assert_eq!(
247 c,
248 PolyOverQ::from_str("7 1/77 4/77 6/77 5/77 -11/77 1/77 -6/77").unwrap()
249 );
250 }
251
252 #[test]
254 fn mul_constant() {
255 let a: PolyOverQ = PolyOverQ::from_str("3 1/11 1/2 -7/3").unwrap();
256 let b: PolyOverQ = PolyOverQ::from_str("1 4/7").unwrap();
257 let c: PolyOverQ = a * b;
258 assert_eq!(c, PolyOverQ::from_str("3 4/77 2/7 -4/3").unwrap());
259 }
260
261 #[test]
263 fn mul_zero() {
264 let a: PolyOverQ = PolyOverQ::from_str("3 1/18 2/7 -3/10").unwrap();
265 let b: PolyOverQ = PolyOverQ::default();
266 let c: PolyOverQ = a * b;
267 assert_eq!(c, PolyOverQ::default());
268 }
269
270 #[test]
272 fn mul_large_numbers() {
273 let a: PolyOverQ = PolyOverQ::from_str(&format!("2 {} {}", 2, i64::MIN)).unwrap();
274 let b: PolyOverQ = PolyOverQ::from_str(&format!(
275 "2 {}/{} {}/{}",
276 u32::MAX,
277 u128::MAX,
278 i64::MAX,
279 u128::MAX
280 ))
281 .unwrap();
282 let c: PolyOverQ = a * b;
283
284 assert_eq!(
285 c,
286 PolyOverQ::from_str(&format!(
287 "3 {}/{} {}/{} {}/{}",
288 2_u128 * u128::from(u32::MAX),
289 u128::MAX,
290 2_i128 * i128::from(i64::MAX) + i128::from(u32::MAX) * i128::from(i64::MIN),
291 u128::MAX,
292 i128::from(i64::MAX) * i128::from(i64::MIN),
293 u128::MAX
294 ))
295 .unwrap()
296 );
297 }
298}
299
300#[cfg(test)]
301mod test_mul_poly_over_z {
302 use super::PolyOverQ;
303 use crate::integer::PolyOverZ;
304 use std::str::FromStr;
305
306 #[test]
308 fn borrowed_correctness() {
309 let poly_1 = PolyOverQ::from_str(&format!("1 1/{}", i64::MAX)).unwrap();
310 let poly_2 = PolyOverZ::from_str("2 1 2").unwrap();
311 let poly_cmp = PolyOverQ::from_str(&format!("2 1/{} 2/{}", i64::MAX, i64::MAX)).unwrap();
312
313 let poly_1 = &poly_1 * &poly_2;
314
315 assert_eq!(poly_cmp, poly_1);
316 }
317
318 #[test]
320 fn availability() {
321 let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
322 let z = PolyOverZ::from(2);
323
324 _ = poly.clone() * z.clone();
325 _ = z.clone() * poly.clone();
326 _ = &poly * &z;
327 _ = &z * &poly;
328 _ = &poly * z.clone();
329 _ = z.clone() * &poly;
330 _ = &z * poly.clone();
331 _ = poly.clone() * &z;
332 }
333}