use mathhook_core::algebra::solvers::{linear::LinearSolver, EquationSolver, SolverResult};
use mathhook_core::core::{Expression, Number};
use mathhook_core::symbol;
use num_bigint::BigInt;
#[test]
fn test_fraction_already_simplified() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::add(vec![
Expression::mul(vec![Expression::integer(2), Expression::symbol(x.clone())]),
Expression::integer(-3),
]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Rational(r)) = solution {
assert_eq!(r.numer(), &BigInt::from(3));
assert_eq!(r.denom(), &BigInt::from(2));
} else {
panic!("Expected rational number, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}
#[test]
fn test_fraction_needs_simplification() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::add(vec![
Expression::mul(vec![Expression::integer(4), Expression::symbol(x.clone())]),
Expression::integer(-6),
]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Rational(r)) = solution {
assert_eq!(r.numer(), &BigInt::from(3));
assert_eq!(r.denom(), &BigInt::from(2));
} else {
panic!("Expected rational number, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}
#[test]
fn test_integer_solution_not_fraction() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::add(vec![
Expression::mul(vec![Expression::integer(5), Expression::symbol(x.clone())]),
Expression::integer(-10),
]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Integer(i)) = solution {
assert_eq!(i, 2);
} else {
panic!("Expected integer number, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}
#[test]
fn test_large_fraction_simplification() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::add(vec![
Expression::mul(vec![Expression::integer(12), Expression::symbol(x.clone())]),
Expression::integer(-18),
]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Rational(r)) = solution {
assert_eq!(r.numer(), &BigInt::from(3));
assert_eq!(r.denom(), &BigInt::from(2));
} else {
panic!("Expected rational number, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}
#[test]
fn test_negative_fraction_simplification() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::add(vec![
Expression::mul(vec![Expression::integer(-4), Expression::symbol(x.clone())]),
Expression::integer(-6),
]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Rational(r)) = solution {
assert_eq!(r.numer(), &BigInt::from(-3));
assert_eq!(r.denom(), &BigInt::from(2));
} else {
panic!("Expected rational number, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}
#[test]
fn test_coprime_numerator_denominator() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::add(vec![
Expression::mul(vec![Expression::integer(7), Expression::symbol(x.clone())]),
Expression::integer(-11),
]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Rational(r)) = solution {
assert_eq!(r.numer(), &BigInt::from(11));
assert_eq!(r.denom(), &BigInt::from(7));
} else {
panic!("Expected rational number, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}
#[test]
fn test_zero_solution_as_integer() {
let solver = LinearSolver::new_fast();
let x = symbol!(x);
let equation = Expression::mul(vec![Expression::integer(5), Expression::symbol(x.clone())]);
match solver.solve(&equation, &x) {
SolverResult::Single(solution) => {
if let Expression::Number(Number::Integer(i)) = solution {
assert_eq!(i, 0);
} else {
panic!("Expected integer zero, got: {:?}", solution);
}
}
_ => panic!("Expected single solution"),
}
}