use super::super::Q;
use crate::{
integer::Z,
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,
},
};
use flint_sys::fmpq::{fmpq_mul, fmpq_mul_fmpz, fmpq_mul_si, fmpq_mul_ui};
use std::ops::{Mul, MulAssign};
impl MulAssign<&Q> for Q {
fn mul_assign(&mut self, other: &Self) {
unsafe { fmpq_mul(&mut self.value, &self.value, &other.value) };
}
}
impl MulAssign<&Z> for Q {
fn mul_assign(&mut self, other: &Z) {
unsafe { fmpq_mul_fmpz(&mut self.value, &self.value, &other.value) };
}
}
impl MulAssign<i64> for Q {
fn mul_assign(&mut self, other: i64) {
unsafe { fmpq_mul_si(&mut self.value, &self.value, other) };
}
}
impl MulAssign<u64> for Q {
fn mul_assign(&mut self, other: u64) {
unsafe { fmpq_mul_ui(&mut self.value, &self.value, other) };
}
}
impl MulAssign<f64> for Q {
fn mul_assign(&mut self, other: f64) {
let other = Q::from(other);
unsafe { fmpq_mul(&mut self.value, &self.value, &other.value) };
}
}
arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, Q, Q);
arithmetic_assign_trait_borrowed_to_owned!(MulAssign, mul_assign, Q, Z);
arithmetic_assign_between_types!(MulAssign, mul_assign, Q, i64, i32 i16 i8);
arithmetic_assign_between_types!(MulAssign, mul_assign, Q, u64, u32 u16 u8);
arithmetic_assign_between_types!(MulAssign, mul_assign, Q, f64, f32);
impl Mul for &Q {
type Output = Q;
fn mul(self, other: Self) -> Self::Output {
let mut out = Q::default();
unsafe {
fmpq_mul(&mut out.value, &self.value, &other.value);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, Q, Q, Q);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Q, Q, Q);
arithmetic_between_types!(Mul, mul, Q, Q, i64 i32 i16 i8 u64 u32 u16 u8 f32 f64);
impl Mul<&Z> for &Q {
type Output = Q;
fn mul(self, other: &Z) -> Self::Output {
let mut out = Q::default();
unsafe {
fmpq_mul_fmpz(&mut out.value, &self.value, &other.value);
}
out
}
}
arithmetic_trait_borrowed_to_owned!(Mul, mul, Q, Z, Q);
arithmetic_trait_mixed_borrowed_owned!(Mul, mul, Q, Z, Q);
#[cfg(test)]
mod test_mul_assign {
use crate::{integer::Z, rational::Q};
#[test]
fn correct_small() {
let mut a = Q::MINUS_ONE;
let b = Q::MINUS_ONE;
let c = Q::ZERO;
let d = Q::from((-1, 2));
a *= &b;
assert_eq!(1, a);
a *= &b;
assert_eq!(-1, a);
a *= &d;
assert_eq!(Q::from((1, 2)), a);
a *= &c;
assert_eq!(0, a);
}
#[test]
fn correct_large() {
let mut a: Q = Q::from((2, u64::MAX));
let b = Q::from(u64::MAX);
a *= b;
assert_eq!(a, Q::from(2));
}
#[test]
fn availability() {
let mut a = Q::from((1, 2));
let b = Q::from((4, 5));
let c = Z::ONE;
a *= &b;
a *= b;
a *= &c;
a *= c;
a *= 0.5_f64;
a *= 0.5_f32;
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 {
use super::Q;
use std::str::FromStr;
#[test]
fn mul() {
let a: Q = Q::from(2);
let b: Q = Q::from((42, 2));
let c: Q = a * b;
assert_eq!(c, Q::from(42));
}
#[test]
fn mul_borrow() {
let a: Q = Q::from(2);
let b: Q = Q::from((42, 2));
let c: Q = &a * &b;
assert_eq!(c, Q::from(42));
}
#[test]
fn mul_first_borrowed() {
let a: Q = Q::from(4);
let b: Q = Q::from((42, 10));
let c: Q = &a * b;
assert_eq!(c, Q::from((168, 10)));
}
#[test]
fn mul_second_borrowed() {
let a: Q = Q::from(2);
let b: Q = Q::from((42, 2));
let c: Q = a * &b;
assert_eq!(c, Q::from(42));
}
#[test]
fn mul_large() {
let a: Q = Q::from(i64::MAX);
let b: Q = Q::from(2);
let c: Q = Q::from((1, i32::MAX));
let d: Q = Q::from((1, u32::MAX));
let e: Q = &a * &b;
let f: Q = c * d;
assert_eq!(e, Q::from(u64::MAX - 1));
assert_eq!(
f,
Q::from_str(&format!(
"1/{}",
u64::from(u32::MAX) * u64::from((u32::MAX - 1) / 2)
))
.unwrap()
);
}
}
#[cfg(test)]
mod test_mul_between_q_and_z {
use crate::integer::Z;
use crate::rational::Q;
#[test]
fn mul() {
let a: Q = Q::from((5, 7));
let b: Z = Z::from(4);
let c: Q = a * b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_borrow() {
let a: Q = Q::from((5, 7));
let b: Z = Z::from(4);
let c: Q = &a * &b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_first_borrowed() {
let a: Q = Q::from((5, 7));
let b: Z = Z::from(4);
let c: Q = &a * b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_second_borrowed() {
let a: Q = Q::from((5, 7));
let b: Z = Z::from(4);
let c: Q = a * &b;
assert_eq!(c, Q::from((20, 7)));
}
#[test]
fn mul_large_numbers() {
let a: Q = Q::from((u64::MAX, 2));
let b: Q = Q::from((1, u64::MAX));
let c: Z = Z::from(u64::MAX);
let d: Q = a * &c;
let e: Q = b * c;
assert_eq!(d, Q::from(u64::MAX) * Q::from((u64::MAX, 2)));
assert_eq!(e, Q::from((1, u64::MAX)) * Q::from(u64::MAX));
}
}
#[cfg(test)]
mod test_mul_between_types {
use crate::rational::Q;
#[test]
#[allow(clippy::op_ref)]
fn mul() {
let a: Q = Q::from(42);
let b: u64 = 1;
let c: u32 = 1;
let d: u16 = 1;
let e: u8 = 1;
let f: i64 = 1;
let g: i32 = 1;
let h: i16 = 1;
let i: i8 = 1;
let j: f32 = 0.3;
let k: f64 = 0.3;
let _: Q = &a * &b;
let _: Q = &a * &c;
let _: Q = &a * &d;
let _: Q = &a * &e;
let _: Q = &a * &f;
let _: Q = &a * &g;
let _: Q = &a * &h;
let _: Q = &a * &i;
let _: Q = &a * &j;
let _: Q = &a * &k;
let _: Q = &b * &a;
let _: Q = &c * &a;
let _: Q = &d * &a;
let _: Q = &e * &a;
let _: Q = &f * &a;
let _: Q = &g * &a;
let _: Q = &h * &a;
let _: Q = &i * &a;
let _: Q = &j * &a;
let _: Q = &k * &a;
let _: Q = &a * b;
let _: Q = &a * c;
let _: Q = &a * d;
let _: Q = &a * e;
let _: Q = &a * f;
let _: Q = &a * g;
let _: Q = &a * h;
let _: Q = &a * i;
let _: Q = &a * j;
let _: Q = &a * k;
let _: Q = &b * Q::from(42);
let _: Q = &c * Q::from(42);
let _: Q = &d * Q::from(42);
let _: Q = &e * Q::from(42);
let _: Q = &f * Q::from(42);
let _: Q = &g * Q::from(42);
let _: Q = &h * Q::from(42);
let _: Q = &i * Q::from(42);
let _: Q = &j * Q::from(42);
let _: Q = &k * Q::from(42);
let _: Q = Q::from(42) * &b;
let _: Q = Q::from(42) * &c;
let _: Q = Q::from(42) * &d;
let _: Q = Q::from(42) * &e;
let _: Q = Q::from(42) * &f;
let _: Q = Q::from(42) * &g;
let _: Q = Q::from(42) * &h;
let _: Q = Q::from(42) * &i;
let _: Q = Q::from(42) * &j;
let _: Q = Q::from(42) * &k;
let _: Q = b * &a;
let _: Q = c * &a;
let _: Q = d * &a;
let _: Q = e * &a;
let _: Q = f * &a;
let _: Q = g * &a;
let _: Q = h * &a;
let _: Q = i * &a;
let _: Q = j * &a;
let _: Q = k * &a;
let _: Q = Q::from(42) * b;
let _: Q = Q::from(42) * c;
let _: Q = Q::from(42) * d;
let _: Q = Q::from(42) * e;
let _: Q = Q::from(42) * f;
let _: Q = Q::from(42) * g;
let _: Q = Q::from(42) * h;
let _: Q = Q::from(42) * i;
let _: Q = Q::from(42) * j;
let _: Q = Q::from(42) * k;
let _: Q = b * Q::from(42);
let _: Q = c * Q::from(42);
let _: Q = d * Q::from(42);
let _: Q = e * Q::from(42);
let _: Q = f * Q::from(42);
let _: Q = g * Q::from(42);
let _: Q = h * Q::from(42);
let _: Q = i * Q::from(42);
let _: Q = j * Q::from(42);
let _: Q = k * Q::from(42);
}
}