use super::super::Z;
use crate::{
integer_mod_q::Zq,
macros::arithmetics::{
arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
arithmetic_trait_mixed_borrowed_owned,
},
rational::Q,
};
use flint_sys::{
fmpq::fmpq_mul_fmpz,
fmpz::{fmpz, fmpz_mul, fmpz_mul_si, fmpz_mul_ui},
fmpz_mod::fmpz_mod_mul_fmpz,
};
use std::ops::{Mul, MulAssign};
impl MulAssign<&Z> for Z {
fn mul_assign(&mut self, other: &Self) {
unsafe { fmpz_mul(&mut self.value, &self.value, &other.value) };
}
}
impl MulAssign<i64> for Z {
fn mul_assign(&mut self, other: i64) {
unsafe { fmpz_mul_si(&mut self.value, &self.value, other) };
}
}
impl MulAssign<u64> for Z {
fn mul_assign(&mut self, other: u64) {
unsafe { fmpz_mul_ui(&mut self.value, &self.value, other) };
}
}
arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, Z, Z);
arithmetic_assign_between_types!(MulAssign, mul_assign, Z, i64, i32 i16 i8);
arithmetic_assign_between_types!(MulAssign, mul_assign, Z, u64, u32 u16 u8);
impl Mul for &Z {
type Output = Z;
fn mul(self, other: Self) -> Self::Output {
let mut out = Z::default();
unsafe {
fmpz_mul(&mut out.value, &self.value, &other.value);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, Z, Z);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, Z, Z);
arithmetic_between_types!(Mul, mul, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
impl Mul<&Q> for &Z {
type Output = Q;
fn mul(self, other: &Q) -> Self::Output {
let mut out = Q::default();
unsafe {
fmpq_mul_fmpz(&mut out.value, &other.value, &self.value);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, Q, Q);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, Q, Q);
arithmetic_between_types!(Mul, mul, Z, Q, f32 f64);
impl Mul<&Zq> for &Z {
type Output = Zq;
fn mul(self, other: &Zq) -> Self::Output {
let mut out = fmpz(0);
unsafe {
fmpz_mod_mul_fmpz(
&mut out,
&other.value.value,
&self.value,
other.modulus.get_fmpz_mod_ctx_struct(),
);
}
Zq {
modulus: other.modulus.clone(),
value: Z { value: out },
}
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, Z, Zq, Zq);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Z, Zq, Zq);
#[cfg(test)]
mod test_mul_assign {
use crate::integer::Z;
#[test]
fn correct_small() {
let mut a: Z = Z::MINUS_ONE;
let b = Z::MINUS_ONE;
let c = Z::ZERO;
a *= &b;
assert_eq!(1, a);
a *= &b;
assert_eq!(-1, a);
a *= &c;
assert_eq!(0, a);
a *= &c;
}
#[test]
fn correct_large() {
let mut a: Z = Z::from(i64::MIN);
let mut b = Z::from(u64::MAX);
a *= Z::MINUS_ONE;
assert_eq!(-1 * Z::from(i64::MIN), a);
b *= Z::MINUS_ONE;
assert_eq!(-1 * Z::from(u64::MAX), b);
}
#[test]
fn availability() {
let mut a: Z = Z::from(42);
let b: Z = Z::from(1);
a *= &b;
a *= b;
a *= 1_u8;
a *= 1_u16;
a *= 1_u32;
a *= 1_u64;
a *= 1_i8;
a *= 1_i16;
a *= 1_i32;
a *= 1_i64;
}
}
#[cfg(test)]
mod test_mul_between_types {
use crate::integer::Z;
#[test]
#[allow(clippy::op_ref)]
fn mul() {
let a: Z = Z::from(42);
let b: u64 = 5;
let c: u32 = 5;
let d: u16 = 5;
let e: u8 = 5;
let f: i64 = 5;
let g: i32 = 5;
let h: i16 = 5;
let i: i8 = 5;
let _: Z = &a * &b;
let _: Z = &a * &c;
let _: Z = &a * &d;
let _: Z = &a * &e;
let _: Z = &a * &f;
let _: Z = &a * &g;
let _: Z = &a * &h;
let _: Z = &a * &i;
let _: Z = &b * &a;
let _: Z = &c * &a;
let _: Z = &d * &a;
let _: Z = &e * &a;
let _: Z = &f * &a;
let _: Z = &g * &a;
let _: Z = &h * &a;
let _: Z = &i * &a;
let _: Z = &a * b;
let _: Z = &a * c;
let _: Z = &a * d;
let _: Z = &a * e;
let _: Z = &a * f;
let _: Z = &a * g;
let _: Z = &a * h;
let _: Z = &a * i;
let _: Z = &b * Z::from(42);
let _: Z = &c * Z::from(42);
let _: Z = &d * Z::from(42);
let _: Z = &e * Z::from(42);
let _: Z = &f * Z::from(42);
let _: Z = &g * Z::from(42);
let _: Z = &h * Z::from(42);
let _: Z = &i * Z::from(42);
let _: Z = Z::from(42) * &b;
let _: Z = Z::from(42) * &c;
let _: Z = Z::from(42) * &d;
let _: Z = Z::from(42) * &e;
let _: Z = Z::from(42) * &f;
let _: Z = Z::from(42) * &g;
let _: Z = Z::from(42) * &h;
let _: Z = Z::from(42) * &i;
let _: Z = b * &a;
let _: Z = c * &a;
let _: Z = d * &a;
let _: Z = e * &a;
let _: Z = f * &a;
let _: Z = g * &a;
let _: Z = h * &a;
let _: Z = i * &a;
let _: Z = Z::from(42) * b;
let _: Z = Z::from(42) * c;
let _: Z = Z::from(42) * d;
let _: Z = Z::from(42) * e;
let _: Z = Z::from(42) * f;
let _: Z = Z::from(42) * g;
let _: Z = Z::from(42) * h;
let _: Z = Z::from(42) * i;
let _: Z = b * Z::from(42);
let _: Z = c * Z::from(42);
let _: Z = d * Z::from(42);
let _: Z = e * Z::from(42);
let _: Z = f * Z::from(42);
let _: Z = g * Z::from(42);
let _: Z = h * Z::from(42);
let _: Z = i * Z::from(42);
}
}
#[cfg(test)]
mod test_mul {
use super::Z;
#[test]
fn mul() {
let a: Z = Z::from(42);
let b: Z = Z::from(4);
let c: Z = a * b;
assert_eq!(c, Z::from(168));
}
#[test]
fn mul_borrow() {
let a: Z = Z::from(42);
let b: Z = Z::from(4);
let c: Z = &a * &b;
assert_eq!(c, Z::from(168));
}
#[test]
fn mul_first_borrowed() {
let a: Z = Z::from(42);
let b: Z = Z::from(4);
let c: Z = &a * b;
assert_eq!(c, Z::from(168));
}
#[test]
fn mul_second_borrowed() {
let a: Z = Z::from(42);
let b: Z = Z::from(4);
let c: Z = a * &b;
assert_eq!(c, Z::from(168));
}
#[test]
fn mul_large_numbers() {
let a: Z = Z::from(i64::MAX);
let b: Z = Z::from(2);
let c: Z = Z::from(i32::MIN);
let d: Z = Z::from(i32::MAX);
let e: Z = a * b;
let f: Z = c * d;
assert_eq!(e, Z::from(u64::MAX - 1));
assert_eq!(f, Z::from(i64::from(i32::MAX) * i64::from(i32::MIN)));
}
}
#[cfg(test)]
mod test_mul_between_z_and_zq {
use super::Z;
use crate::integer_mod_q::Zq;
#[test]
fn mul() {
let a: Z = Z::from(9);
let b: Zq = Zq::from((4, 11));
let c: Zq = a * b;
assert_eq!(c, Zq::from((3, 11)));
}
#[test]
fn mul_borrow() {
let a: Z = Z::from(9);
let b: Zq = Zq::from((4, 11));
let c: Zq = &a * &b;
assert_eq!(c, Zq::from((3, 11)));
}
#[test]
fn mul_first_borrowed() {
let a: Z = Z::from(9);
let b: Zq = Zq::from((4, 11));
let c: Zq = &a * b;
assert_eq!(c, Zq::from((3, 11)));
}
#[test]
fn mul_second_borrowed() {
let a: Z = Z::from(9);
let b: Zq = Zq::from((4, 11));
let c: Zq = a * &b;
assert_eq!(c, Zq::from((3, 11)));
}
#[test]
fn mul_large_numbers() {
let a: Z = Z::from(u64::MAX);
let b: Zq = Zq::from((i64::MAX, u64::MAX - 58));
let c: Zq = Zq::from((i64::MAX - 1, i64::MAX));
let d: Zq = &a * b;
let e: Zq = a * c;
assert_eq!(
d,
Zq::from(((u64::MAX - 1) / 2, u64::MAX - 58)) * Zq::from((u64::MAX, u64::MAX - 58))
);
assert_eq!(e, Zq::from((u64::MAX, i64::MAX)) * Zq::from((-1, i64::MAX)));
}
}
#[cfg(test)]
mod test_mul_between_z_and_q {
use super::Z;
use crate::rational::Q;
#[test]
fn availability() {
let a: Z = Z::from(42);
let b: Q = Q::from((5, 7));
let _: Q = &a * &b;
let _: Q = &a * b.clone();
let _: Q = a.clone() * &b;
let _: Q = a.clone() * b;
let _: Q = &a * 0.5_f32;
let _: Q = &a * 0.5_f64;
let _: Q = a.clone() * 0.5_f32;
let _: Q = a.clone() * 0.5_f64;
let _: Q = 0.5_f32 * &a;
let _: Q = 0.5_f64 * &a;
let _: Q = 0.5_f32 * a.clone();
let _: Q = 0.5_f64 * a.clone();
}
#[test]
fn mul() {
let a: Z = Z::from(4);
let b: Q = Q::from((5, 7));
let c: Q = a * b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_borrow() {
let a: Z = Z::from(4);
let b: Q = Q::from((5, 7));
let c: Q = &a * &b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_first_borrowed() {
let a: Z = Z::from(4);
let b: Q = Q::from((5, 7));
let c: Q = &a * b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_second_borrowed() {
let a: Z = Z::from(4);
let b: Q = Q::from((5, 7));
let c: Q = a * &b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_large_numbers() {
let a: Z = Z::from(u64::MAX);
let b: Q = Q::from((1, u64::MAX));
let c: Q = Q::from((u64::MAX, 2));
let d: Q = &a * b;
let e: Q = a * c;
assert_eq!(d, Q::from((1, u64::MAX)) * Q::from(u64::MAX));
assert_eq!(e, Q::from(u64::MAX) * Q::from((u64::MAX, 2)));
}
}