exact-float 0.1.1

Do your calculations with exact floating point numbers
#![feature(float_extras)]
extern crate num;

use num::integer::Integer;
use num::{BigInt, One, abs};
use num::cast::ToPrimitive;
use num::bigint::ToBigInt;
use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Neg};

fn reduce(a: &BigInt, b: &BigInt) -> (BigInt, BigInt) {
    let gcd = a.gcd(&b);
    (a / gcd.clone(), b / gcd)
}

pub trait ExactFloatNumber {
    fn from_integer(self) -> ExactFloat;
}

impl ExactFloatNumber for ExactFloat {
    fn from_integer(self) -> ExactFloat {self}
}

impl ExactFloatNumber for u8 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for u16 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for u32 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for u64 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for i8 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for i16 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for i32 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for i64 {
    fn from_integer(self) -> ExactFloat {ExactFloat::from_bigint(self.to_bigint().unwrap())}
}

impl ExactFloatNumber for f32 {
    fn from_integer(self) -> ExactFloat {
        let (mantissa, exponent, sign) = self.integer_decode();
        let (numerator, denominator) = if exponent > 0 {
            (mantissa * 2u64.pow(exponent as u32), 1)
        }
        else {
            (mantissa, 2u64.pow((-exponent) as u32))
        };
        ExactFloat {
            numerator: (numerator * sign as u64).to_bigint().unwrap(),
            denominator: denominator.to_bigint().unwrap()
        }
    }
}

impl ExactFloatNumber for f64 {
    fn from_integer(self) -> ExactFloat {
        let (mantissa, exponent, sign) = self.integer_decode();
        println!("{:?}, {:?}", mantissa, exponent);
        let (numerator, denominator) = if exponent > 0 {
            (mantissa * 2u64.pow(exponent as u32), 1)
        }
        else {
            (mantissa, 2u64.pow((-exponent) as u32))
        };
        ExactFloat {
            numerator: (numerator * sign as u64).to_bigint().unwrap(),
            denominator: denominator.to_bigint().unwrap()
        }
    }
}


#[derive(Clone, Debug)]
pub struct ExactFloat {
    pub numerator: BigInt,
    pub denominator: BigInt
}

impl ExactFloat {
    pub fn new<T: ExactFloatNumber>(x: T) -> ExactFloat {
        x.from_integer()
    }
    fn from_bigint(a: BigInt) -> ExactFloat {
        ExactFloat {
            numerator: a,
            denominator: One::one()
        }
    }
    pub fn pre_calculate(&mut self) {
        let (numerator, denominator) = reduce(&self.numerator, &self.denominator);
        self.numerator = numerator;
        self.denominator = denominator;
    }
    pub fn calculate(&self) -> Option<f64> {
        let (numerator, denominator) = reduce(&self.numerator, &self.denominator);
        match (numerator.to_f64(), denominator.to_f64()) {
            (Some(numerator), Some(denominator)) => Some(numerator / denominator),
            _ => None
        }
    }
    pub fn abs(&self) -> ExactFloat {
        ExactFloat {
            numerator: abs(self.numerator.clone()),
            denominator: abs(self.denominator.clone())
        }
    }
}

impl<T: ExactFloatNumber> Add<T> for ExactFloat {
    type Output = ExactFloat;

    fn add(self, other: T) -> ExactFloat {
        let as_exact_float = other.from_integer();
        ExactFloat {
            numerator: &as_exact_float.denominator * self.numerator + &self.denominator * as_exact_float.numerator,
            denominator: self.denominator * as_exact_float.denominator
        }
    }
}

impl<T: ExactFloatNumber> AddAssign<T> for ExactFloat {
    fn add_assign(&mut self, other: T) {
        let as_exact_float = other.from_integer();
        self.numerator = &as_exact_float.denominator * &self.numerator + &self.denominator * as_exact_float.numerator;
        self.denominator = &self.denominator * as_exact_float.denominator;
    }
}

impl<T: ExactFloatNumber> Sub<T> for ExactFloat {
    type Output = ExactFloat;

    fn sub(self, other: T) -> ExactFloat {
        let as_exact_float = other.from_integer();
        ExactFloat {
            numerator: &as_exact_float.denominator * self.numerator - &self.denominator * as_exact_float.numerator,
            denominator: &self.denominator * &as_exact_float.denominator
        }
    }
}

impl<T: ExactFloatNumber> SubAssign<T> for ExactFloat {
    fn sub_assign(&mut self, other: T) {
        let as_exact_float = other.from_integer();
        self.numerator = &as_exact_float.denominator * &self.numerator - &self.denominator * as_exact_float.numerator;
        self.denominator = &self.denominator * &as_exact_float.denominator;
    }
}

impl<T: ExactFloatNumber> Mul<T> for ExactFloat {
    type Output = ExactFloat;

    fn mul(self, other: T) -> ExactFloat {
        let as_exact_float = other.from_integer();
        ExactFloat {
            numerator: self.numerator * as_exact_float.numerator,
            denominator: self.denominator * as_exact_float.denominator
        }
    }
}

impl<T: ExactFloatNumber> MulAssign<T> for ExactFloat {
    fn mul_assign(&mut self, other: T) {
        let as_exact_float = other.from_integer();
        self.numerator = &self.numerator * as_exact_float.numerator;
        self.denominator = &self.denominator * as_exact_float.denominator;
    }
}

impl<T: ExactFloatNumber> Div<T> for ExactFloat {
    type Output = ExactFloat;

    fn div(self, other: T) -> ExactFloat {
        let as_exact_float = other.from_integer();
        ExactFloat {
            numerator: self.numerator * as_exact_float.denominator,
            denominator: self.denominator * as_exact_float.numerator
        }
    }
}

impl<T: ExactFloatNumber> DivAssign<T> for ExactFloat {
    fn div_assign(&mut self, other: T) {
        let as_exact_float = other.from_integer();
        self.numerator = &self.numerator * as_exact_float.denominator;
        self.denominator = &self.denominator * as_exact_float.numerator;
    }
}

impl Neg for ExactFloat {
    type Output = ExactFloat;

    fn neg(self) -> ExactFloat {
        ExactFloat {
            numerator: -self.numerator,
            denominator: self.denominator
        }
    }
}