use super::*;
#[test]
fn test_explicit_mathrm_e() {
let expr = parse_latex(r"\mathrm{e}").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::E));
}
#[test]
fn test_explicit_mathrm_i() {
let expr = parse_latex(r"\mathrm{i}").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::I));
}
#[test]
fn test_imath() {
let expr = parse_latex(r"\imath").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::I));
}
#[test]
fn test_jmath() {
let expr = parse_latex(r"\jmath").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::I));
}
#[test]
fn test_bare_e_is_constant() {
let expr = parse_latex("e").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::E));
}
#[test]
fn test_bare_i_is_constant() {
let expr = parse_latex("i").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::I));
}
#[test]
fn test_e_in_expression() {
let expr = parse_latex("e + 1").unwrap();
match &expr.kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Add);
assert_eq!(**left, Expression::constant(MathConstant::E));
assert_eq!(**right, Expression::integer(1));
}
_ => panic!("Expected binary expression"),
}
}
#[test]
fn test_i_in_expression() {
let expr = parse_latex("2 * i").unwrap();
match &expr.kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Mul);
assert_eq!(**left, Expression::integer(2));
assert_eq!(**right, Expression::constant(MathConstant::I));
}
_ => panic!("Expected binary expression"),
}
}
#[test]
fn test_sum_bound_i() {
let expr = parse_latex(r"\sum_{i=1}^{n} i").unwrap();
match &expr.kind {
ExprKind::Sum {
index,
lower,
upper,
body,
} => {
assert_eq!(index, "i");
assert_eq!(**lower, Expression::integer(1));
assert_eq!(**upper, Expression::variable("n".to_string()));
assert_eq!(**body, Expression::variable("i".to_string()));
}
_ => panic!("Expected Sum variant"),
}
}
#[test]
fn test_prod_bound_e() {
let expr = parse_latex(r"\prod_{e=1}^{n} e").unwrap();
match &expr.kind {
ExprKind::Product {
index,
lower,
upper,
body,
} => {
assert_eq!(index, "e");
assert_eq!(**lower, Expression::integer(1));
assert_eq!(**upper, Expression::variable("n".to_string()));
assert_eq!(**body, Expression::variable("e".to_string()));
}
_ => panic!("Expected Product variant"),
}
}
#[test]
fn test_sum_with_e_and_i() {
let expr = parse_latex(r"\sum_{i=1}^{n} e").unwrap();
match &expr.kind {
ExprKind::Sum { index, body, .. } => {
assert_eq!(index, "i");
assert_eq!(**body, Expression::constant(MathConstant::E));
}
_ => panic!("Expected Sum variant"),
}
}
#[test]
fn test_sum_bound_i_in_multiplication() {
let expr = parse_latex(r"\sum_{i=1}^{n} 2 * i").unwrap();
match &expr.kind {
ExprKind::Sum { body, .. } => {
match &body.kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Mul);
assert_eq!(**left, Expression::integer(2));
assert_eq!(**right, Expression::variable("i".to_string()));
}
_ => panic!("Expected multiplication in body"),
}
}
_ => panic!("Expected Sum variant"),
}
}
#[test]
fn test_e_power_is_exp() {
let expr = parse_latex("e^x").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "exp");
assert_eq!(args.len(), 1);
assert_eq!(args[0], Expression::variable("x".to_string()));
}
_ => panic!("Expected Function variant"),
}
}
#[test]
fn test_e_power_braced() {
let expr = parse_latex("e^{x+1}").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "exp");
assert_eq!(args.len(), 1);
match &args[0].kind {
ExprKind::Binary { op, .. } => {
assert_eq!(*op, BinaryOp::Add);
}
_ => panic!("Expected binary expression in exp argument"),
}
}
_ => panic!("Expected Function variant"),
}
}
#[test]
fn test_exp_and_e_power_equal() {
let expr1 = parse_latex(r"\exp{x}").unwrap();
let expr2 = parse_latex("e^x").unwrap();
assert_eq!(expr1, expr2);
}
#[test]
fn test_explicit_mathrm_e_power() {
let expr = parse_latex(r"\mathrm{e}^x").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "exp");
assert_eq!(args.len(), 1);
assert_eq!(args[0], Expression::variable("x".to_string()));
}
_ => panic!("Expected Function variant"),
}
}
#[test]
fn test_euler_formula() {
let expr = parse_latex(r"e^{i \pi}").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "exp");
assert_eq!(args.len(), 1);
match &args[0].kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Mul);
assert_eq!(**left, Expression::constant(MathConstant::I));
assert_eq!(**right, Expression::constant(MathConstant::Pi));
}
_ => panic!("Expected multiplication in exp argument"),
}
}
_ => panic!("Expected Function variant"),
}
}
#[test]
fn test_e_without_power() {
let expr = parse_latex("e + 1").unwrap();
match &expr.kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Add);
assert_eq!(**left, Expression::constant(MathConstant::E));
assert_eq!(**right, Expression::integer(1));
}
_ => panic!("Expected binary expression"),
}
}
#[test]
fn test_subscript_e_is_variable() {
let expr = parse_latex("x_e").unwrap();
assert_eq!(expr, Expression::variable("x_e".to_string()));
}
#[test]
fn test_subscript_i_is_variable() {
let expr = parse_latex("x_i").unwrap();
assert_eq!(expr, Expression::variable("x_i".to_string()));
}
#[test]
fn test_other_letters_are_variables() {
assert_eq!(
parse_latex("a").unwrap(),
Expression::variable("a".to_string())
);
assert_eq!(
parse_latex("b").unwrap(),
Expression::variable("b".to_string())
);
assert_eq!(
parse_latex("x").unwrap(),
Expression::variable("x".to_string())
);
assert_eq!(
parse_latex("y").unwrap(),
Expression::variable("y".to_string())
);
}
#[test]
fn test_complex_number_pattern() {
let expr = parse_latex("a + b * i").unwrap();
match &expr.kind {
ExprKind::Binary {
op: BinaryOp::Add,
left,
right,
} => {
assert_eq!(**left, Expression::variable("a".to_string()));
match &right.kind {
ExprKind::Binary {
op: BinaryOp::Mul,
left: ref b,
right: ref i,
} => {
assert_eq!(**b, Expression::variable("b".to_string()));
assert_eq!(**i, Expression::constant(MathConstant::I));
}
_ => panic!("Expected multiplication"),
}
}
_ => panic!("Expected addition"),
}
}
#[test]
fn test_nested_sum_scope() {
let expr = parse_latex(r"\sum_{i=1}^{n} \sum_{j=1}^{m} i * j").unwrap();
match &expr.kind {
ExprKind::Sum {
body: outer_body, ..
} => {
match &outer_body.kind {
ExprKind::Sum {
body: inner_body, ..
} => {
match &inner_body.kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Mul);
assert_eq!(**left, Expression::variable("i".to_string()));
assert_eq!(**right, Expression::variable("j".to_string()));
}
_ => panic!("Expected binary multiplication"),
}
}
_ => panic!("Expected inner Sum"),
}
}
_ => panic!("Expected outer Sum"),
}
}
#[test]
fn test_mathrm_other_letter() {
let result = parse_latex(r"\mathrm{a}");
assert!(result.is_err() || matches!(result, Ok(_)));
}
#[test]
fn test_neg_infty_is_neg_infinity() {
let expr = parse_latex(r"-\infty").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::NegInfinity));
}
#[test]
fn test_neg_infty_in_limit() {
let expr = parse_latex(r"\lim_{x \to -\infty} f(x)").unwrap();
match &expr.kind {
ExprKind::Limit { to, .. } => {
assert_eq!(**to, Expression::constant(MathConstant::NegInfinity));
}
_ => panic!("Expected Limit variant"),
}
}
#[test]
fn test_neg_infty_in_integral_bound() {
let expr = parse_latex(r"\int_{-\infty}^{\infty} x dx").unwrap();
match &expr.kind {
ExprKind::Integral { bounds, .. } => {
let bounds = bounds.as_ref().expect("Expected definite integral bounds");
assert_eq!(
*bounds.lower,
Expression::constant(MathConstant::NegInfinity)
);
assert_eq!(*bounds.upper, Expression::constant(MathConstant::Infinity));
}
_ => panic!("Expected Integral variant"),
}
}
#[test]
fn test_positive_infty_unchanged() {
let expr = parse_latex(r"\infty").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::Infinity));
}
#[test]
fn test_tokenize_mathrm_e() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\mathrm{e}").unwrap();
assert!(matches!(tokens[0].0, LatexToken::ExplicitConstant('e')));
}
#[test]
fn test_tokenize_mathrm_i() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\mathrm{i}").unwrap();
assert!(matches!(tokens[0].0, LatexToken::ExplicitConstant('i')));
}
#[test]
fn test_tokenize_imath() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\imath").unwrap();
assert!(matches!(tokens[0].0, LatexToken::ExplicitConstant('i')));
}
#[test]
fn test_tokenize_jmath() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\jmath").unwrap();
assert!(matches!(tokens[0].0, LatexToken::ExplicitConstant('i')));
}
#[test]
fn test_text_nan_uppercase() {
let expr = parse_latex(r"\text{NaN}").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::NaN));
}
#[test]
fn test_text_nan_lowercase() {
let expr = parse_latex(r"\text{nan}").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::NaN));
}
#[test]
fn test_mathrm_nan_uppercase() {
let expr = parse_latex(r"\mathrm{NaN}").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::NaN));
}
#[test]
fn test_mathrm_nan_lowercase() {
let expr = parse_latex(r"\mathrm{nan}").unwrap();
assert_eq!(expr, Expression::constant(MathConstant::NaN));
}
#[test]
fn test_nan_in_expression() {
let expr = parse_latex(r"x + \text{NaN}").unwrap();
match &expr.kind {
ExprKind::Binary { op, left, right } => {
assert_eq!(*op, BinaryOp::Add);
assert_eq!(**left, Expression::variable("x".to_string()));
assert_eq!(**right, Expression::constant(MathConstant::NaN));
}
_ => panic!("Expected binary expression"),
}
}
#[test]
fn test_tokenize_text_nan() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\text{NaN}").unwrap();
assert!(matches!(tokens[0].0, LatexToken::NaNConstant));
}
#[test]
fn test_tokenize_text_nan_lowercase() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\text{nan}").unwrap();
assert!(matches!(tokens[0].0, LatexToken::NaNConstant));
}
#[test]
fn test_tokenize_mathrm_nan() {
use crate::parser::latex_tokenizer::{tokenize_latex, LatexToken};
let tokens = tokenize_latex(r"\mathrm{NaN}").unwrap();
assert!(matches!(tokens[0].0, LatexToken::NaNConstant));
}
#[test]
fn test_nan_to_latex_roundtrip() {
use crate::latex::ToLatex;
let expr = Expression::constant(MathConstant::NaN);
let latex = expr.to_latex();
assert_eq!(latex, r"\text{NaN}");
let reparsed = parse_latex(&latex).unwrap();
assert_eq!(reparsed, expr);
}
#[test]
fn test_nan_display() {
let expr = Expression::constant(MathConstant::NaN);
assert_eq!(format!("{}", expr), "NaN");
}
#[test]
fn test_nan_ne_infinity() {
assert_ne!(MathConstant::NaN, MathConstant::Infinity);
assert_ne!(MathConstant::NaN, MathConstant::NegInfinity);
}