use oxinum_core::{OxiNum, OxiSigned, Pow, Sign};
use oxinum_int::native::{BigInt, BigUint};
use super::rational::BigRational;
impl OxiNum for BigRational {
#[inline]
fn is_zero(&self) -> bool {
BigRational::is_zero(self)
}
#[inline]
fn is_one(&self) -> bool {
BigRational::is_one(self)
}
}
impl OxiSigned for BigRational {
#[inline]
fn signum(&self) -> Sign {
self.num.signum()
}
#[inline]
fn abs(&self) -> Self {
BigRational::abs(self)
}
}
fn bigint_pow(base: &BigInt, exp: u32) -> BigInt {
if exp == 0 {
return BigInt::one();
}
let mag_pow = base.magnitude().pow(exp);
if base.sign() == Sign::Negative && exp % 2 == 1 {
BigInt::from_parts(Sign::Negative, mag_pow)
} else {
BigInt::from_parts(Sign::Positive, mag_pow)
}
}
fn rational_pow_u32(r: &BigRational, exp: u32) -> BigRational {
if exp == 0 {
return BigRational::one();
}
let num_pow: BigInt = bigint_pow(&r.num, exp);
let den_pow: BigUint = r.den.pow(exp);
BigRational::from_parts(num_pow, den_pow)
.expect("rational pow: denominator is always non-zero after exponentiation")
}
impl Pow<u32> for BigRational {
type Output = BigRational;
#[inline]
fn pow(&self, exp: u32) -> BigRational {
rational_pow_u32(self, exp)
}
}