ihateintegrals 0.1.2

A computer algebra library for solving integrals.
Documentation
use core::fmt;
use std::sync::Arc;

use serde_json::json;

use super::{EXPRESSION_INSTANCES, Expression, IExpression};


#[derive(PartialEq, Eq, Hash)]
pub struct Fraction {
    numerator: Expression,
    denominator: Expression,
}

impl Fraction {
    pub fn of(numerator: Expression, denominator: Expression) -> Expression {
        let id = get_id(&numerator, &denominator);

        let mut instances = EXPRESSION_INSTANCES.lock().unwrap();

        if let Some(result) = instances.get(&id) {
            return result.clone();
        }

        let result = Expression::Fraction(Arc::new(Fraction {
            numerator,
            denominator,
        }));

        instances.insert(id, result.clone());
        result
    }

    pub fn numerator(&self) -> Expression {
        self.numerator.clone()
    }

    pub fn denominator(&self) -> Expression {
        self.denominator.clone()
    }
}

fn get_id(n: &Expression, d: &Expression) -> String {
    format!("Fraction{}{}", n.as_stringable().id(), d.as_stringable().id())
}

impl IExpression for Fraction {
    fn to_unambigious_string(&self) -> String {
        format!("({})/({})", 
            self.numerator.as_stringable().to_unambigious_string(),
            self.denominator.as_stringable().to_unambigious_string())
    }

    fn id(&self) -> String {
        get_id(&self.numerator, &self.denominator)
    }

    fn to_json(&self) -> serde_json::Value {
        json!([
            "Divide",
            self.numerator.to_json(),
            self.denominator.to_json()
        ])
    }
}

impl fmt::Debug for Fraction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Fraction({:?}, {:?})", self.numerator, self.denominator)
    }
}

#[cfg(test)]
mod tests {
    use crate::expressions::Integer;
    use super::*;

    #[test]
    fn flywheel() {
        let a = Fraction::of(Integer::of(1), Integer::of(1));
        let b = Fraction::of(Integer::of(1), Integer::of(1));
        let c = Fraction::of(Integer::of(2), Integer::of(1));
        assert_eq!(a, b);
        assert_ne!(a, c);
    }
}