qfall_math/integer/poly_over_z/arithmetic/
mul_scalar.rs1use super::super::PolyOverZ;
12use crate::integer::Z;
13use crate::integer_mod_q::{PolyOverZq, Zq};
14use crate::macros::arithmetics::{
15 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
16 arithmetic_trait_borrowed_to_owned, arithmetic_trait_mixed_borrowed_owned,
17 arithmetic_trait_reverse,
18};
19use crate::macros::for_others::implement_for_others;
20use crate::rational::{PolyOverQ, Q};
21use flint_sys::fmpq_poly::fmpq_poly_scalar_mul_fmpq;
22use flint_sys::fmpz_mod_poly::fmpz_mod_poly_scalar_mul_fmpz;
23use flint_sys::fmpz_poly::{
24 fmpz_poly_scalar_mul_fmpz, fmpz_poly_scalar_mul_si, fmpz_poly_scalar_mul_ui,
25};
26use std::ops::{Mul, MulAssign};
27
28impl Mul<&Z> for &PolyOverZ {
29 type Output = PolyOverZ;
30 fn mul(self, scalar: &Z) -> Self::Output {
51 let mut out = PolyOverZ::default();
52 unsafe {
53 fmpz_poly_scalar_mul_fmpz(&mut out.poly, &self.poly, &scalar.value);
54 }
55 out
56 }
57}
58
59arithmetic_trait_reverse!(Mul, mul, Z, PolyOverZ, PolyOverZ);
60
61arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverZ, Z, PolyOverZ);
62arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, PolyOverZ, PolyOverZ);
63arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverZ, Z, PolyOverZ);
64arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, PolyOverZ, PolyOverZ);
65
66implement_for_others!(Z, PolyOverZ, PolyOverZ, Mul Scalar for i8 i16 i32 i64 u8 u16 u32 u64);
67
68impl Mul<&Zq> for &PolyOverZ {
69 type Output = PolyOverZq;
70 fn mul(self, scalar: &Zq) -> PolyOverZq {
91 let mut out = PolyOverZq::from(&scalar.modulus);
92 unsafe {
93 fmpz_mod_poly_scalar_mul_fmpz(
94 &mut out.poly,
95 &PolyOverZq::from((self, &scalar.modulus)).poly,
96 &scalar.value.value,
97 out.modulus.get_fmpz_mod_ctx_struct(),
98 )
99 }
100 out
101 }
102}
103
104arithmetic_trait_reverse!(Mul, mul, Zq, PolyOverZ, PolyOverZq);
105
106arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverZ, Zq, PolyOverZq);
107arithmetic_trait_borrowed_to_owned!(Mul, mul, Zq, PolyOverZ, PolyOverZq);
108arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverZ, Zq, PolyOverZq);
109arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Zq, PolyOverZ, PolyOverZq);
110
111impl Mul<&Q> for &PolyOverZ {
112 type Output = PolyOverQ;
113 fn mul(self, scalar: &Q) -> PolyOverQ {
134 let mut out = PolyOverQ::default();
135 unsafe {
136 fmpq_poly_scalar_mul_fmpq(&mut out.poly, &PolyOverQ::from(self).poly, &scalar.value);
137 }
138 out
139 }
140}
141
142arithmetic_trait_reverse!(Mul, mul, Q, PolyOverZ, PolyOverQ);
143
144arithmetic_trait_borrowed_to_owned!(Mul, mul, PolyOverZ, Q, PolyOverQ);
145arithmetic_trait_borrowed_to_owned!(Mul, mul, Q, PolyOverZ, PolyOverQ);
146arithmetic_trait_mixed_borrowed_owned!(Mul, mul, PolyOverZ, Q, PolyOverQ);
147arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Q, PolyOverZ, PolyOverQ);
148
149implement_for_others!(Q, PolyOverZ, PolyOverQ, Mul Scalar for f32 f64);
150
151impl MulAssign<&Z> for PolyOverZ {
152 fn mul_assign(&mut self, scalar: &Z) {
174 unsafe { fmpz_poly_scalar_mul_fmpz(&mut self.poly, &self.poly, &scalar.value) };
175 }
176}
177
178impl MulAssign<i64> for PolyOverZ {
179 fn mul_assign(&mut self, scalar: i64) {
181 unsafe { fmpz_poly_scalar_mul_si(&mut self.poly, &self.poly, scalar) };
182 }
183}
184
185impl MulAssign<u64> for PolyOverZ {
186 fn mul_assign(&mut self, scalar: u64) {
188 unsafe { fmpz_poly_scalar_mul_ui(&mut self.poly, &self.poly, scalar) };
189 }
190}
191
192arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, PolyOverZ, Z);
193arithmetic_assign_between_types!(MulAssign, mul_assign, PolyOverZ, i64, i32 i16 i8);
194arithmetic_assign_between_types!(MulAssign, mul_assign, PolyOverZ, u64, u32 u16 u8);
195
196#[cfg(test)]
197mod test_mul_z {
198 use super::PolyOverZ;
199 use crate::integer::Z;
200 use std::str::FromStr;
201
202 #[test]
204 fn borrowed_correctness() {
205 let poly_1 = PolyOverZ::from_str(&format!("3 1 2 {}", i64::MAX)).unwrap();
206 let poly_2 = poly_1.clone();
207 let poly_3 = PolyOverZ::from_str(&format!("3 2 4 {}", (i64::MAX as u64) * 2)).unwrap();
208 let integer = Z::from(2);
209
210 let poly_1 = &poly_1 * &integer;
211 let poly_2 = &integer * &poly_2;
212
213 assert_eq!(poly_3, poly_1);
214 assert_eq!(poly_3, poly_2);
215 }
216
217 #[test]
219 fn availability() {
220 let poly = PolyOverZ::from_str("3 1 2 3").unwrap();
221 let z = Z::from(2);
222
223 _ = poly.clone() * z.clone();
224 _ = poly.clone() * 2i8;
225 _ = poly.clone() * 2u8;
226 _ = poly.clone() * 2i16;
227 _ = poly.clone() * 2u16;
228 _ = poly.clone() * 2i32;
229 _ = poly.clone() * 2u32;
230 _ = poly.clone() * 2i64;
231 _ = poly.clone() * 2u64;
232
233 _ = z.clone() * poly.clone();
234 _ = 2i8 * poly.clone();
235 _ = 2u64 * poly.clone();
236
237 _ = &poly * &z;
238 _ = &z * &poly;
239 _ = &poly * z.clone();
240 _ = z.clone() * &poly;
241 _ = poly.clone() * &z;
242 _ = &z * poly.clone();
243 _ = &poly * 2i8;
244 _ = 2i8 * &poly;
245 }
246}
247
248#[cfg(test)]
249mod test_mul_zq {
250 use super::PolyOverZ;
251 use crate::integer_mod_q::{PolyOverZq, Zq};
252 use std::str::FromStr;
253
254 #[test]
256 fn borrowed_correctness() {
257 let poly_1 = PolyOverZ::from_str(&format!("3 1 2 {}", i64::MAX)).unwrap();
258 let poly_2 = poly_1.clone();
259 let poly_3 = PolyOverZq::from_str(&format!(
260 "3 2 4 {} mod {}",
261 (i64::MAX as u64) * 2,
262 u64::MAX
263 ))
264 .unwrap();
265 let integer = Zq::from((2, u64::MAX));
266
267 let poly_1 = &poly_1 * &integer;
268 let poly_2 = &integer * &poly_2;
269
270 assert_eq!(poly_3, poly_1);
271 assert_eq!(poly_3, poly_2);
272 }
273
274 #[test]
276 fn availability() {
277 let poly = PolyOverZ::from_str("3 1 2 3").unwrap();
278 let z = Zq::from((2, 17));
279
280 _ = poly.clone() * z.clone();
281 _ = z.clone() * poly.clone();
282 _ = &poly * &z;
283 _ = &z * &poly;
284 _ = &poly * z.clone();
285 _ = z.clone() * &poly;
286 _ = &z * poly.clone();
287 _ = poly.clone() * &z;
288 }
289}
290
291#[cfg(test)]
292mod test_mul_assign {
293 use crate::integer::{PolyOverZ, Z};
294 use std::str::FromStr;
295
296 #[test]
298 fn correct_small() {
299 let mut a = PolyOverZ::from_str("3 1 2 -3").unwrap();
300 let b = Z::from(2);
301 let c = Z::ZERO;
302
303 a *= &b;
304 assert_eq!(PolyOverZ::from_str("3 2 4 -6").unwrap(), a);
305 a *= &c;
306 assert_eq!(PolyOverZ::from(0), a);
307 }
308
309 #[test]
311 fn correct_large() {
312 let mut a = PolyOverZ::from_str("2 2 -1").unwrap();
313 let b = i32::MAX;
314 let cmp = PolyOverZ::from_str(&format!(
315 "2 {} {}",
316 i32::MAX as i64 * 2,
317 -(i32::MAX as i64)
318 ))
319 .unwrap();
320
321 a *= b;
322
323 assert_eq!(cmp, a);
324 }
325
326 #[test]
328 fn availability() {
329 let mut a = PolyOverZ::from_str("3 1 2 -3").unwrap();
330 let b = Z::from(2);
331
332 a *= &b;
333 a *= b;
334 a *= 1_u8;
335 a *= 1_u16;
336 a *= 1_u32;
337 a *= 1_u64;
338 a *= 1_i8;
339 a *= 1_i16;
340 a *= 1_i32;
341 a *= 1_i64;
342 }
343}
344
345#[cfg(test)]
346mod test_mul_q {
347 use super::PolyOverZ;
348 use crate::rational::{PolyOverQ, Q};
349 use std::str::FromStr;
350
351 #[test]
353 fn borrowed_correctness() {
354 let poly_1 = PolyOverZ::from_str(&format!("3 1 2 {}", (i64::MAX as u64) * 2)).unwrap();
355 let poly_2 = poly_1.clone();
356 let poly_3 = PolyOverQ::from_str(&format!("3 1/2 1 {}", i64::MAX)).unwrap();
357 let rational = Q::from((1, 2));
358
359 let poly_1 = &poly_1 * &rational;
360 let poly_2 = &rational * &poly_2;
361
362 assert_eq!(poly_3, poly_1);
363 assert_eq!(poly_3, poly_2);
364 }
365
366 #[test]
368 fn availability() {
369 let poly = PolyOverZ::from_str("3 1 2 3").unwrap();
370 let q = Q::from((1, 2));
371
372 _ = poly.clone() * q.clone();
373 _ = q.clone() * poly.clone();
374 _ = &poly * &q;
375 _ = &q * &poly;
376 _ = &poly * q.clone();
377 _ = q.clone() * &poly;
378 _ = &q * poly.clone();
379 _ = poly.clone() * &q;
380 _ = &poly * 1.0f32;
381 _ = &poly * 1.0f64;
382 }
383}