use crate::ext::xmpq;
use crate::ops::{
AddFrom, DivFrom, MulFrom, NegAssign, Pow, PowAssign, SubFrom,
};
use crate::{Assign, Rational};
use std::i32;
use std::iter::{Product, Sum};
use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Shl, ShlAssign, Shr,
ShrAssign, Sub, SubAssign,
};
arith_unary! {
Rational;
xmpq::neg;
Neg { neg }
NegAssign { neg_assign }
NegIncomplete
}
arith_binary! {
Rational;
xmpq::add;
Add { add }
AddAssign { add_assign }
AddFrom { add_from }
AddIncomplete
}
arith_binary! {
Rational;
xmpq::sub;
Sub { sub }
SubAssign { sub_assign }
SubFrom { sub_from }
SubIncomplete
}
arith_binary! {
Rational;
xmpq::mul;
Mul { mul }
MulAssign { mul_assign }
MulFrom { mul_from }
MulIncomplete
}
arith_binary! {
Rational;
xmpq::div;
Div { div }
DivAssign { div_assign }
DivFrom { div_from }
DivIncomplete
}
arith_prim! {
Rational;
xmpq::lshift_i32;
Shl { shl }
ShlAssign { shl_assign }
i32;
ShlI32Incomplete
}
arith_prim! {
Rational;
xmpq::rshift_i32;
Shr { shr }
ShrAssign { shr_assign }
i32;
ShrI32Incomplete
}
arith_prim! {
Rational;
xmpq::pow_i32;
Pow { pow }
PowAssign { pow_assign }
i32;
PowI32Incomplete
}
arith_prim! {
Rational;
xmpq::mul_2exp;
Shl { shl }
ShlAssign { shl_assign }
u32;
ShlU32Incomplete
}
arith_prim! {
Rational;
xmpq::div_2exp;
Shr { shr }
ShrAssign { shr_assign }
u32;
ShrU32Incomplete
}
arith_prim! {
Rational;
xmpq::pow_u32;
Pow { pow }
PowAssign { pow_assign }
u32;
PowU32Incomplete
}
impl<T> Sum<T> for Rational
where
Rational: AddAssign<T>,
{
fn sum<I>(iter: I) -> Rational
where
I: Iterator<Item = T>,
{
let mut ret = Rational::new();
for i in iter {
ret.add_assign(i);
}
ret
}
}
impl<T> Product<T> for Rational
where
Rational: MulAssign<T>,
{
fn product<I>(iter: I) -> Rational
where
I: Iterator<Item = T>,
{
let mut ret = Rational::from(1);
for i in iter {
ret.mul_assign(i);
}
ret
}
}
#[cfg(test)]
mod tests {
use crate::ops::Pow;
use crate::Rational;
macro_rules! test_ref_op {
($first:expr, $second:expr) => {
assert_eq!(
Rational::from($first),
$second,
"({}) != ({})",
stringify!($first),
stringify!($second)
);
};
}
#[test]
fn check_ref_op() {
let lhs = Rational::from((-13, 27));
let rhs = Rational::from((15, 101));
let pu = 30_u32;
let pi = -15_i32;
test_ref_op!(-&lhs, -lhs.clone());
test_ref_op!(&lhs + &rhs, lhs.clone() + &rhs);
test_ref_op!(&lhs - &rhs, lhs.clone() - &rhs);
test_ref_op!(&lhs * &rhs, lhs.clone() * &rhs);
test_ref_op!(&lhs / &rhs, lhs.clone() / &rhs);
test_ref_op!(&lhs << pu, lhs.clone() << pu);
test_ref_op!(&lhs >> pu, lhs.clone() >> pu);
test_ref_op!((&lhs).pow(pu), lhs.clone().pow(pu));
test_ref_op!(&lhs << pi, lhs.clone() << pi);
test_ref_op!(&lhs >> pi, lhs.clone() >> pi);
test_ref_op!((&lhs).pow(pi), lhs.clone().pow(pi));
}
}