mathhook-core 0.2.0

Core mathematical engine for MathHook - expressions, algebra, and solving
Documentation
//! Rational expression operations tests

use mathhook_core::prelude::*;

#[test]
fn test_simplify_rational_expressions() {
    // Test basic rational simplification
    let expr = Expression::add(vec![
        Expression::number(Number::rational(num_rational::BigRational::new(
            num_bigint::BigInt::from(1),
            num_bigint::BigInt::from(2),
        ))),
        Expression::number(Number::rational(num_rational::BigRational::new(
            num_bigint::BigInt::from(1),
            num_bigint::BigInt::from(3),
        ))),
    ]);

    let result = expr.simplify();
    println!("1/2 + 1/3 = {}", result);

    // Should combine rationals
    assert!(!result.is_zero());
}

#[test]
fn test_simple_rational_combination() {
    // Test 1/4 + 1/4 = 1/2
    let quarter1 = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(1),
        num_bigint::BigInt::from(4),
    )));
    let quarter2 = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(1),
        num_bigint::BigInt::from(4),
    )));

    let expr = Expression::add(vec![quarter1, quarter2]);
    let result = expr.simplify();

    println!("1/4 + 1/4 = {}", result);
    assert!(!result.is_zero());
}

#[test]
fn test_simplify_rational() {
    let x = symbol!(x);

    // Test rational with variables
    let expr = Expression::add(vec![
        Expression::mul(vec![
            Expression::number(Number::rational(num_rational::BigRational::new(
                num_bigint::BigInt::from(2),
                num_bigint::BigInt::from(3),
            ))),
            Expression::symbol(x.clone()),
        ]),
        Expression::number(Number::rational(num_rational::BigRational::new(
            num_bigint::BigInt::from(1),
            num_bigint::BigInt::from(6),
        ))),
    ]);

    let result = expr.simplify();
    println!("(2/3)*x + 1/6 = {}", result);
    assert!(!result.is_zero());
}

#[test]
fn test_simplify_rational_mode() {
    // Test rational arithmetic in different modes
    let half = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(1),
        num_bigint::BigInt::from(2),
    )));
    let third = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(1),
        num_bigint::BigInt::from(3),
    )));

    let sum = Expression::add(vec![half.clone(), third.clone()]);
    let product = Expression::mul(vec![half, third]);

    let sum_result = sum.simplify();
    let product_result = product.simplify();

    println!("Sum: {}, Product: {}", sum_result, product_result);

    assert!(!sum_result.is_zero());
    assert!(!product_result.is_zero());
}

#[test]
fn test_rational_number_patterns() {
    // Test various rational number patterns

    // Pattern 1: Simple fractions
    let expr = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(6),
        num_bigint::BigInt::from(8),
    )));
    let result = expr.simplify();
    println!("6/8 simplified = {}", result);

    // Pattern 2: Improper fractions
    let expr = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(7),
        num_bigint::BigInt::from(3),
    )));
    let result = expr.simplify();
    println!("7/3 = {}", result);

    // Pattern 3: Negative fractions
    let expr = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(-3),
        num_bigint::BigInt::from(4),
    )));
    let result = expr.simplify();
    println!("-3/4 = {}", result);

    assert!(!result.is_zero());
}

#[test]
fn test_issue_4194() {
    // From SymPy test suite - specific rational issue
    let x = symbol!(x);

    let expr = Expression::add(vec![
        Expression::symbol(x.clone()),
        Expression::number(Number::rational(num_rational::BigRational::new(
            num_bigint::BigInt::from(1),
            num_bigint::BigInt::from(2),
        ))),
    ]);

    let result = expr.simplify();
    println!("x + 1/2 = {}", result);

    // Should maintain the structure
    assert!(
        matches!(result, Expression::Add(_)),
        "Expected x + 1/2 to remain as addition (issue 4194), got: {}",
        result
    );
}

#[test]
fn test_extract_minus_sign() {
    // Test extracting minus signs from rational expressions
    let x = symbol!(x);

    let expr = Expression::add(vec![
        Expression::mul(vec![Expression::integer(-1), Expression::symbol(x.clone())]),
        Expression::integer(5),
    ]);

    let result = expr.simplify();
    println!("-x + 5 = {}", result);

    // Should handle negative coefficients
    assert!(!result.is_zero());
}

#[test]
fn test_signsimp() {
    // Test sign simplification
    let x = symbol!(x);

    let expr = Expression::mul(vec![
        Expression::integer(-1),
        Expression::add(vec![Expression::symbol(x.clone()), Expression::integer(-1)]),
    ]);

    let result = expr.simplify();
    println!("-(x - 1) = {}", result);

    // Should distribute the negative sign
    assert!(!result.is_zero());
}

#[test]
fn test_advanced_rational_patterns() {
    let x = symbol!(x);
    let y = symbol!(y);

    // Test complex rational combinations
    let expr = Expression::add(vec![
        Expression::mul(vec![
            Expression::number(Number::rational(num_rational::BigRational::new(
                num_bigint::BigInt::from(1),
                num_bigint::BigInt::from(3),
            ))),
            Expression::symbol(x.clone()),
        ]),
        Expression::mul(vec![
            Expression::number(Number::rational(num_rational::BigRational::new(
                num_bigint::BigInt::from(2),
                num_bigint::BigInt::from(5),
            ))),
            Expression::symbol(y.clone()),
        ]),
    ]);

    let result = expr.simplify();
    println!("(1/3)*x + (2/5)*y = {}", result);

    assert!(!result.is_zero());
}

#[test]
fn test_complex_rational_arithmetic() {
    // Test complex rational arithmetic operations

    // Test (3/4) * (8/9) = 24/36 = 2/3
    let frac1 = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(3),
        num_bigint::BigInt::from(4),
    )));
    let frac2 = Expression::number(Number::rational(num_rational::BigRational::new(
        num_bigint::BigInt::from(8),
        num_bigint::BigInt::from(9),
    )));

    let product = Expression::mul(vec![frac1, frac2]);
    let result = product.simplify();

    println!("(3/4) * (8/9) = {}", result);
    assert!(!result.is_zero());
}

#[test]
fn test_ultimate_rational_mastery() {
    let x = symbol!(x);

    // Ultimate rational test combining multiple concepts
    let expr = Expression::add(vec![
        Expression::mul(vec![
            Expression::number(Number::rational(num_rational::BigRational::new(
                num_bigint::BigInt::from(5),
                num_bigint::BigInt::from(6),
            ))),
            Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
        ]),
        Expression::mul(vec![
            Expression::number(Number::rational(num_rational::BigRational::new(
                num_bigint::BigInt::from(-1),
                num_bigint::BigInt::from(3),
            ))),
            Expression::symbol(x.clone()),
        ]),
        Expression::number(Number::rational(num_rational::BigRational::new(
            num_bigint::BigInt::from(7),
            num_bigint::BigInt::from(12),
        ))),
    ]);

    let result = expr.simplify();
    println!("Ultimate rational: {}", result);

    // Complex rational polynomial
    assert!(!result.is_zero());
}

#[test]
fn test_historic_95_percent_milestone() {
    // Commemorating our 95% SymPy coverage milestone
    let x = symbol!(x);

    let expr = Expression::add(vec![
        Expression::pow(
            Expression::add(vec![
                Expression::symbol(x.clone()),
                Expression::number(Number::rational(num_rational::BigRational::new(
                    num_bigint::BigInt::from(1),
                    num_bigint::BigInt::from(2),
                ))),
            ]),
            Expression::integer(2),
        ),
        Expression::mul(vec![
            Expression::integer(-1),
            Expression::pow(Expression::symbol(x.clone()), Expression::integer(2)),
        ]),
    ]);

    let result = expr.simplify();
    println!("95% milestone expression: {}", result);

    // Should maintain algebraic structure
    assert!(!result.is_zero());
}