aboutsummaryrefslogblamecommitdiff
path: root/src/utils.rs
blob: 0fc4328aefed2c960ce08bc96cefb63e3e8d1c14 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
                
                                        
 
                      






                             
                                        





                                                      







                                                             
                     
 


                                     




                                                                    















                                                                            


                                                                    

























                                                                    




                                                            







                                                          

                                                                                     
 
use std::ops::*;
use std::fmt::{Debug, Formatter, Error};

#[derive(Copy, Clone)]
pub struct Rational
{
    n: i64,
    d: i64
}

fn gcd(a: i64, b: i64) -> i64
{match b { 0 => a, _ => gcd(b, a % b) }}

impl Default for Rational
{
    fn default() -> Rational { Rational::from_int(0) }
}

impl Debug for Rational
{
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>
    {
        f.write_fmt(format_args!("{}/{}", self.n, self.d))
    }
}

impl Add for Rational
{
    type Output = Self;

    fn add(self, other: Self) -> Self
    {
        let c = gcd(self.d, other.d);
        Rational{n: self.n * (other.d / c) + other.n * (self.d / c),
                 d: self.d / c * other.d}.reduced()
    }
}

impl AddAssign for Rational
{
    fn add_assign(&mut self, other: Self)
    {
        let c = gcd(self.d, other.d);
        *self = Rational{n: self.n * (other.d / c) + other.n * (self.d / c),
                         d: self.d / c * other.d}.reduced()
    }
}

impl Mul for Rational
{
    type Output = Self;
    fn mul(self, other: Self) -> Self
    {
        Rational{n: self.n * other.n, d: self.d * other.d}.reduced()
    }
}

impl Div for Rational
{
    type Output = Self;
    fn div(self, other: Self) -> Self
    {
        Rational{n: self.n * other.d, d: self.d * other.n}.reduced()
    }
}

impl From<u32> for Rational
{
    fn from(v: u32) -> Self { Rational::from_int(v as i64) }
}

impl From<u16> for Rational
{
    fn from(v: u16) -> Self { Rational::from_int(v as i64) }
}

impl From<u8> for Rational
{
    fn from(v: u8) -> Self { Rational::from_int(v as i64) }
}

impl From<Rational> for f64
{
    fn from(v: Rational) -> Self { v.n as f64 / v.d as f64 }
}

impl Rational
{
    fn from_int(v: i64) -> Rational {Rational{n: v, d: 1}}
    fn reduced(self) -> Rational
    {
        let c = gcd(self.n, self.d);
        Rational{n: self.n / c, d: self.d / c}
    }
    pub fn as_int_trunc(self) -> i64 {self.n / self.d}
    pub fn as_int_round(self) -> i64 {(self.n as f64 / self.d as f64).round() as i64}
}