use super::*;
mod comprehensive_functions {
use super::*;
#[test]
fn test_trig_functions() {
let expr = parse("sin(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "sin");
assert_eq!(args.len(), 1);
}
_ => panic!("Expected function"),
}
let expr = parse("cos(2*pi)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "cos");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Binary { .. }));
}
_ => panic!("Expected function"),
}
let expr = parse("tan(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => {
assert_eq!(name, "tan");
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_inverse_trig_functions() {
let expr = parse("asin(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "arcsin"),
_ => panic!("Expected function"),
}
let expr = parse("acos(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "arccos"),
_ => panic!("Expected function"),
}
let expr = parse("atan(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "arctan"),
_ => panic!("Expected function"),
}
let expr = parse("arcsin(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "arcsin"),
_ => panic!("Expected function"),
}
let expr = parse("arccos(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "arccos"),
_ => panic!("Expected function"),
}
let expr = parse("arctan(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "arctan"),
_ => panic!("Expected function"),
}
let expr = parse("atan2(y, x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "atan2");
assert_eq!(args.len(), 2);
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_function_name_aliases() {
let expr = parse("sign(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "sgn");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
let expr = parse("log2(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "lg");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
let expr = parse("sgn(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "sgn"),
_ => panic!("Expected function"),
}
}
#[test]
fn test_additional_math_functions() {
let expr = parse("cbrt(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "cbrt");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
let expr = parse("round(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "round");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
let expr = parse("pow(x, y)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "pow");
assert_eq!(args.len(), 2);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
assert!(matches!(args[1].kind, ExprKind::Variable(ref v) if v == "y"));
}
_ => panic!("Expected function"),
}
let expr = parse("atan2(y, x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "atan2");
assert_eq!(args.len(), 2);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "y"));
assert!(matches!(args[1].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_hyperbolic_functions() {
let expr = parse("sinh(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "sinh"),
_ => panic!("Expected function"),
}
let expr = parse("cosh(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "cosh"),
_ => panic!("Expected function"),
}
let expr = parse("tanh(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "tanh"),
_ => panic!("Expected function"),
}
}
#[test]
fn test_logarithmic_functions() {
let expr = parse("log(2, 8)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "log");
assert_eq!(args.len(), 2);
}
_ => panic!("Expected function"),
}
let expr = parse("ln(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "ln");
assert_eq!(args.len(), 1);
}
_ => panic!("Expected function"),
}
let expr = parse("exp(-x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "exp");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Unary { .. }));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_other_functions() {
let expr = parse("sqrt(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "sqrt"),
_ => panic!("Expected function"),
}
let expr = parse("abs(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "abs"),
_ => panic!("Expected function"),
}
let expr = parse("floor(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "floor"),
_ => panic!("Expected function"),
}
let expr = parse("ceil(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "ceil"),
_ => panic!("Expected function"),
}
let expr = parse("sgn(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "sgn"),
_ => panic!("Expected function"),
}
}
#[test]
fn test_multi_argument_functions() {
let expr = parse("max(a, b)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "max");
assert_eq!(args.len(), 2);
}
_ => panic!("Expected function"),
}
let expr = parse("min(a, b, c)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "min");
assert_eq!(args.len(), 3);
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_deeply_nested_functions() {
let expr = parse("sin(cos(x))").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "sin");
assert_eq!(args.len(), 1);
match &args[0].kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "cos");
assert_eq!(args.len(), 1);
}
_ => panic!("Expected nested function"),
}
}
_ => panic!("Expected function"),
}
let expr = parse("max(min(a, b), c)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "max");
assert_eq!(args.len(), 2);
match &args[0].kind {
ExprKind::Function { name, .. } => assert_eq!(name, "min"),
_ => panic!("Expected nested function"),
}
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_functions_with_complex_expressions() {
let expr = parse("sin(x + y)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "sin");
assert_eq!(args.len(), 1);
assert!(matches!(
args[0].kind,
ExprKind::Binary {
op: BinaryOp::Add,
..
}
));
}
_ => panic!("Expected function"),
}
let expr = parse("log(2, x^2 + 1)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "log");
assert_eq!(args.len(), 2);
assert!(matches!(args[0].kind, ExprKind::Integer(2)));
assert!(matches!(
args[1].kind,
ExprKind::Binary {
op: BinaryOp::Add,
..
}
));
}
_ => panic!("Expected function"),
}
let expr = parse("sqrt(x^2 + y^2)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "sqrt");
assert_eq!(args.len(), 1);
assert!(matches!(
args[0].kind,
ExprKind::Binary {
op: BinaryOp::Add,
..
}
));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_custom_function_names() {
let expr = parse("myFunc(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "myFunc");
assert_eq!(args.len(), 1);
}
_ => panic!("Expected function"),
}
let expr = parse("customFunction(a, b, c)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "customFunction");
assert_eq!(args.len(), 3);
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_function_in_complex_expression() {
let expr = parse("2 * sin(x) + cos(y)").unwrap();
match &expr.kind {
ExprKind::Binary {
op: BinaryOp::Add,
left,
right,
} => {
match &left.kind {
ExprKind::Binary {
op: BinaryOp::Mul, ..
} => {}
_ => panic!("Expected multiplication on left"),
}
match &right.kind {
ExprKind::Function { name, .. } => assert_eq!(name, "cos"),
_ => panic!("Expected function on right"),
}
}
_ => panic!("Expected binary addition"),
}
let expr = parse("pow(x, 2)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "pow");
assert_eq!(args.len(), 2);
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_nested_parentheses() {
let expr = parse("((2 + 3) * (4 + 5))").unwrap();
assert!(matches!(expr.kind, ExprKind::Binary { .. }));
}
#[test]
fn test_multiple_unary_operators() {
let expr = parse("--5").unwrap();
match &expr.kind {
ExprKind::Unary {
op: UnaryOp::Neg,
operand,
} => {
assert!(matches!(
operand.kind,
ExprKind::Unary {
op: UnaryOp::Neg,
..
}
));
}
_ => panic!("Expected negation"),
}
}
#[test]
fn test_log_two_args() {
let expr = parse("log(x, 2)").unwrap();
assert_eq!(
expr.kind,
ExprKind::Function {
name: "log".to_string(),
args: vec![
ExprKind::Variable("x".to_string()).into(),
ExprKind::Integer(2).into(),
],
}
);
}
#[test]
fn test_log_numeric_args() {
let expr = parse("log(8, 2)").unwrap();
assert_eq!(
expr.kind,
ExprKind::Function {
name: "log".to_string(),
args: vec![Expression::integer(8), Expression::integer(2)],
}
);
}
#[test]
fn test_trunc() {
let expr = parse("trunc(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "trunc");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_trunc_nested() {
let expr = parse("trunc(sin(x))").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "trunc");
assert_eq!(args.len(), 1);
assert!(
matches!(args[0].kind, ExprKind::Function { ref name, .. } if name == "sin")
);
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_clamp() {
let expr = parse("clamp(x, 0, 1)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "clamp");
assert_eq!(args.len(), 3);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
assert!(matches!(args[1].kind, ExprKind::Integer(0)));
assert!(matches!(args[2].kind, ExprKind::Integer(1)));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_clamp_complex_first_arg() {
let expr = parse("clamp(x^2, -1, 1)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "clamp");
assert_eq!(args.len(), 3);
assert!(matches!(
args[0].kind,
ExprKind::Binary {
op: BinaryOp::Pow,
..
}
));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_lerp() {
let expr = parse("lerp(a, b, t)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "lerp");
assert_eq!(args.len(), 3);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "a"));
assert!(matches!(args[1].kind, ExprKind::Variable(ref v) if v == "b"));
assert!(matches!(args[2].kind, ExprKind::Variable(ref v) if v == "t"));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_lerp_numeric_bounds() {
let expr = parse("lerp(0, 1, t)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "lerp");
assert_eq!(args.len(), 3);
assert!(matches!(args[0].kind, ExprKind::Integer(0)));
assert!(matches!(args[1].kind, ExprKind::Integer(1)));
assert!(matches!(args[2].kind, ExprKind::Variable(ref v) if v == "t"));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_rad() {
let expr = parse("rad(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "rad");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_deg() {
let expr = parse("deg(x)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "deg");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Variable(ref v) if v == "x"));
}
_ => panic!("Expected function"),
}
}
#[test]
fn test_rad_deg_with_pi() {
let expr = parse("rad(180)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "rad");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Integer(180)));
}
_ => panic!("Expected function"),
}
let expr = parse("deg(pi)").unwrap();
match &expr.kind {
ExprKind::Function { name, args } => {
assert_eq!(name, "deg");
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Constant(MathConstant::Pi)));
}
_ => panic!("Expected function"),
}
}
}