193 lines
4.9 KiB
Rust
193 lines
4.9 KiB
Rust
use std::ops;
|
|
|
|
//TODO slow ? check Stein's algorithm (binaryGCD)
|
|
fn gcd(a: i128, b: i128) -> i128 {
|
|
if b == 0 {
|
|
a
|
|
} else {
|
|
gcd(b, a % b)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
|
pub struct Rational {
|
|
numerator: i128,
|
|
denominator: i128,
|
|
}
|
|
|
|
impl Rational {
|
|
pub fn new(numerator: i128, denominator: i128) -> Self {
|
|
Self {
|
|
numerator,
|
|
denominator,
|
|
}
|
|
}
|
|
|
|
pub fn reduce(&self) -> Self {
|
|
let gcd = gcd(self.numerator, self.denominator);
|
|
Rational::new(self.numerator / gcd, self.denominator / gcd)
|
|
}
|
|
|
|
pub fn inverse(&self) -> Self {
|
|
Rational::new(self.denominator, self.numerator)
|
|
}
|
|
|
|
pub fn left_shift(&self) -> Self {
|
|
Rational::new(self.numerator, self.denominator * 10)
|
|
}
|
|
|
|
pub fn simplify(lhs: Rational, rhs: Rational) -> Self {
|
|
let res = Rational::new(lhs.numerator * rhs.denominator, lhs.denominator * rhs.numerator);
|
|
res.reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Add<Rational> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn add(self, rhs: Rational) -> Rational {
|
|
Rational::new(self.numerator * rhs.denominator + rhs.numerator * self.denominator, self.denominator * rhs.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Add<i128> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn add(self, rhs: i128) -> Rational {
|
|
Rational::new(self.numerator + rhs * self.denominator, self.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Add<Rational> for i128 {
|
|
type Output = Rational;
|
|
|
|
fn add(self, rhs: Rational) -> Rational {
|
|
Rational::new(self * rhs.denominator + rhs.numerator, rhs.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Sub<Rational> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn sub(self, rhs: Rational) -> Rational {
|
|
Rational::new(self.numerator * rhs.denominator - rhs.numerator * self.denominator, self.denominator * rhs.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Sub<i128> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn sub(self, rhs: i128) -> Rational {
|
|
Rational::new(self.numerator - rhs * self.denominator, self.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Sub<Rational> for i128 {
|
|
type Output = Rational;
|
|
|
|
fn sub(self, rhs: Rational) -> Rational {
|
|
Rational::new(self * rhs.denominator - rhs.numerator, rhs.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Mul<Rational> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn mul(self, rhs: Rational) -> Rational {
|
|
Rational::new(self.numerator * rhs.numerator, self.denominator * rhs.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Mul<i128> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn mul(self, rhs: i128) -> Rational {
|
|
Rational::new(self.numerator * rhs, self.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Mul<Rational> for i128 {
|
|
type Output = Rational;
|
|
|
|
fn mul(self, rhs: Rational) -> Rational {
|
|
Rational::new(self * rhs.numerator, rhs.denominator).reduce()
|
|
}
|
|
}
|
|
|
|
impl ops::Div<Rational> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn div(self, rhs: Rational) -> Rational {
|
|
self * rhs.inverse()
|
|
}
|
|
}
|
|
|
|
impl ops::Div<i128> for Rational {
|
|
type Output = Rational;
|
|
|
|
fn div(self, rhs: i128) -> Rational {
|
|
let rhs_inverse = Rational::new(1, rhs);
|
|
self * rhs_inverse
|
|
}
|
|
}
|
|
|
|
impl ops::Div<Rational> for i128 {
|
|
type Output = Rational;
|
|
|
|
fn div(self, rhs: Rational) -> Rational {
|
|
self * rhs.inverse()
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
|
pub struct GaussianRational {
|
|
real: Rational,
|
|
imaginary: Rational,
|
|
}
|
|
|
|
impl GaussianRational {
|
|
pub fn new(real: Rational, imaginary: Rational) -> Self {
|
|
Self {
|
|
real,
|
|
imaginary,
|
|
}
|
|
}
|
|
|
|
pub fn conjugate(&self) -> Self {
|
|
GaussianRational::new(self.real, -1 * self.imaginary)
|
|
}
|
|
}
|
|
|
|
impl ops::Add<GaussianRational> for GaussianRational {
|
|
type Output = GaussianRational;
|
|
|
|
fn add(self, rhs: GaussianRational) -> GaussianRational {
|
|
GaussianRational::new(self.real + rhs.real, self.imaginary + rhs.imaginary)
|
|
}
|
|
}
|
|
|
|
impl ops::Sub<GaussianRational> for GaussianRational {
|
|
type Output = GaussianRational;
|
|
|
|
fn sub(self, rhs: GaussianRational) -> GaussianRational {
|
|
GaussianRational::new(self.real - rhs.real, self.imaginary - rhs.imaginary)
|
|
}
|
|
}
|
|
|
|
impl ops::Mul<GaussianRational> for GaussianRational {
|
|
type Output = GaussianRational;
|
|
|
|
fn mul(self, rhs: GaussianRational) -> GaussianRational {
|
|
GaussianRational::new(self.real * rhs.real - self.imaginary * rhs.imaginary, self.real * rhs.imaginary + self.imaginary * rhs.real)
|
|
}
|
|
}
|
|
|
|
impl ops::Div<GaussianRational> for GaussianRational {
|
|
type Output = GaussianRational;
|
|
|
|
fn div(self, rhs: GaussianRational) -> GaussianRational {
|
|
let cd_squared = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary;
|
|
GaussianRational::new(Rational::simplify(self.real * rhs.real + self.imaginary * rhs.imaginary, cd_squared), Rational::simplify(self.imaginary * rhs.real - self.real * rhs.imaginary, cd_squared))
|
|
}
|
|
}
|