hecate-symrs 0.2.4

A pure rust symbolic computation library! Inspired by sympy.
Documentation
use std::cmp::Ordering;

use crate::{Expr, KnownExpr, Rational};

pub fn compare<A: Expr + ?Sized, B: Expr + ?Sized>(a: &A, b: &B) -> Option<Ordering> {
    if a.get_ref() == b.get_ref() {
        return Some(Ordering::Equal);
    }

    match (a.known_expr(), b.known_expr()) {
        (KnownExpr::Integer(i1), KnownExpr::Integer(i2)) => Some(i1.cmp(&i2)),
        (KnownExpr::Rational(r1), KnownExpr::Rational(r2)) => Some(r1.cmp(&r2)),
        (KnownExpr::Integer(i1), KnownExpr::Rational(r2)) => {
            let r1: Rational = i1.into();
            Some(r1.cmp(&r2))
        }
        (KnownExpr::Rational(r1), KnownExpr::Integer(i2)) => {
            let r2: Rational = i2.into();
            Some(r1.cmp(&r2))
        }
        _ => None,
    }
}

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

    #[test]
    fn test_compare() {
        let x = symbol!("x");
        assert_eq!(compare(x, x), Some(Ordering::Equal))
    }
    #[test]
    fn test_compare_ints() {
        let int1 = int!(3);
        let int2 = int!(5);
        assert_eq!(compare(int1, int2), Some(Ordering::Less));
        assert_eq!(compare(int2, int1), Some(Ordering::Greater));
        assert_eq!(compare(int1, int1), Some(Ordering::Equal));
    }

    #[test]
    fn test_compare_rationals() {
        let rat1 = rational!(1, 3);
        let rat2 = rational!(2, 3);
        assert_eq!(compare(rat1, rat2), Some(Ordering::Less));
        assert_eq!(compare(rat2, rat1), Some(Ordering::Greater));
        assert_eq!(compare(rat1, rat1), Some(Ordering::Equal));
    }

    #[test]
    fn test_compare_int_and_rational() {
        let int = int!(2);
        let rat = rational!(2, 1);
        assert_eq!(compare(int, rat), Some(Ordering::Equal));
        assert_eq!(compare(rat, int), Some(Ordering::Equal));

        let rat_less = rational!(1, 1);
        assert_eq!(compare(int, rat_less), Some(Ordering::Greater));
        assert_eq!(compare(rat_less, int), Some(Ordering::Less));
    }

    #[test]
    fn test_compare_unknown_expressions() {
        let x = symbol!("x");
        let y = symbol!("y");
        assert_eq!(compare(x, y), None);
        assert_eq!(compare(y, x), None);
    }
}