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