use super::Q;
use flint_sys::fmpq::{fmpq_abs, fmpq_inv, fmpq_is_one, fmpq_is_zero};
impl Q {
pub fn abs(mut self) -> Self {
unsafe {
fmpq_abs(&mut self.value, &self.value);
}
self
}
pub fn inverse(&self) -> Option<Q> {
if self == &Q::ZERO {
return None;
}
let mut out = Q::ZERO;
unsafe { fmpq_inv(&mut out.value, &self.value) };
Some(out)
}
pub fn is_zero(&self) -> bool {
1 == unsafe { fmpq_is_zero(&self.value) }
}
pub fn is_one(&self) -> bool {
1 == unsafe { fmpq_is_one(&self.value) }
}
}
#[cfg(test)]
mod test_abs {
use super::Q;
#[test]
fn small_values() {
let pos = Q::ONE;
let zero = Q::ZERO;
let neg = Q::from(-15);
assert_eq!(Q::ONE, pos.abs());
assert_eq!(Q::ZERO, zero.abs());
assert_eq!(Q::from(15), neg.abs());
}
#[test]
fn large_values() {
let pos = Q::from(i64::MAX);
let neg = Q::from((1, i64::MIN));
assert_eq!(Q::from(i64::MAX), pos.abs());
assert_eq!(Q::from((-1, i64::MIN)), neg.abs());
}
}
#[cfg(test)]
mod test_inv {
use super::Q;
#[test]
fn small_values() {
let val_0 = Q::from(4);
let val_1 = Q::from((2, -7));
let inv_0 = val_0.inverse().unwrap();
let inv_1 = val_1.inverse().unwrap();
assert_eq!(Q::from((1, 4)), inv_0);
assert_eq!(Q::from((-7, 2)), inv_1);
}
#[test]
fn large_values() {
let val_0 = Q::from((1, i64::MAX));
let val_1 = Q::from(i64::MIN);
let inv_0 = val_0.inverse().unwrap();
let inv_1 = val_1.inverse().unwrap();
assert_eq!(Q::from(i64::MAX), inv_0);
assert_eq!(Q::from((1, i64::MIN)), inv_1);
}
#[test]
fn inv_zero_none() {
let zero = Q::ZERO;
let inv_zero = zero.inverse();
assert!(inv_zero.is_none());
}
}
#[cfg(test)]
mod test_is_zero {
use super::Q;
use std::str::FromStr;
#[test]
fn zero_detection() {
let zero = Q::ZERO;
assert!(zero.is_zero());
}
#[test]
fn zero_rejection() {
let small = Q::from(2);
let large = Q::from_str(&format!("{}", (u128::MAX - 1) / 2 + 1)).unwrap();
assert!(!small.is_zero());
assert!(!large.is_zero());
}
}
#[cfg(test)]
mod test_is_one {
use super::Q;
use std::str::FromStr;
#[test]
fn one_detection() {
let one = Q::ONE;
assert!(one.is_one());
}
#[test]
fn one_rejection() {
let small = Q::from(2);
let large = Q::from_str(&format!("1/{}", (u128::MAX - 1) / 2 + 2)).unwrap();
assert!(!small.is_one());
assert!(!large.is_one());
}
}