#![cfg(not(target_arch = "wasm32"))]
#![allow(clippy::field_reassign_with_default)]
mod common;
use common::approx_eq_default;
use ries_rs::eval::{evaluate, evaluate_with_constants, EvalError};
use ries_rs::expr::Expression;
use ries_rs::profile::UserConstant;
#[test]
fn test_basic_evaluation() {
let expr = Expression::parse("32+").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!(approx_eq_default(result.value, 5.0));
assert!(approx_eq_default(result.derivative, 0.0));
}
#[test]
fn test_variable_evaluation() {
let expr = Expression::parse("x").unwrap();
let result = evaluate(&expr, 3.5).unwrap();
assert!(approx_eq_default(result.value, 3.5));
assert!(approx_eq_default(result.derivative, 1.0));
}
#[test]
fn test_x_squared() {
let expr = Expression::parse("xs").unwrap();
let result = evaluate(&expr, 3.0).unwrap();
assert!(approx_eq_default(result.value, 9.0));
assert!(approx_eq_default(result.derivative, 6.0)); }
#[test]
fn test_sqrt_pi() {
let expr = Expression::parse("pq").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!(approx_eq_default(result.value, std::f64::consts::PI.sqrt()));
}
#[test]
fn test_exponential() {
let expr = Expression::parse("xE").unwrap();
let result = evaluate(&expr, 1.0).unwrap();
assert!(approx_eq_default(result.value, std::f64::consts::E));
assert!(approx_eq_default(result.derivative, std::f64::consts::E));
}
#[test]
fn test_complex_expression() {
let expr = Expression::parse("xs2x*+1+").unwrap();
let result = evaluate(&expr, 3.0).unwrap();
assert!(approx_eq_default(result.value, 16.0)); assert!(approx_eq_default(result.derivative, 8.0)); }
#[test]
fn test_division_by_zero() {
let expr = Expression::parse("1x/").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::DivisionByZero)));
}
#[test]
fn test_sqrt_negative() {
let expr = Expression::parse("1nq").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::SqrtDomain)));
}
#[test]
fn test_log_domain() {
let expr = Expression::parse("1nl").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::LogDomain)));
}
#[test]
fn test_user_constant() {
let user_constants: Vec<UserConstant> = vec![];
let expr = Expression::parse("32+").unwrap();
let result = evaluate_with_constants(&expr, 0.0, &user_constants).unwrap();
assert!(approx_eq_default(result.value, 5.0));
}
#[test]
fn test_missing_user_constant_is_error() {
let mut expr = Expression::new();
expr.push(ries_rs::symbol::Symbol::UserConstant0);
let result = evaluate_with_constants(&expr, 0.0, &[]);
assert!(matches!(result, Err(EvalError::MissingUserConstant(0))));
}
#[test]
fn test_lambert_w() {
let expr = Expression::parse("1W").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!((result.value - 0.5671432904).abs() < 1e-9);
let expr = Expression::parse("eW").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!(approx_eq_default(result.value, 1.0));
}
#[test]
fn test_root_odd_of_negative() {
let expr = Expression::parse("38nv").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!(approx_eq_default(result.value, -2.0));
}
#[test]
fn test_root_even_of_negative() {
let expr = Expression::parse("28nv").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::SqrtDomain)));
}
#[test]
fn test_root_non_integer_index_of_negative() {
let expr = Expression::parse("e8nv").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::SqrtDomain)));
let expr = Expression::parse("p8nv").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::SqrtDomain)));
let expr = Expression::parse("f8nv").unwrap();
let result = evaluate(&expr, 0.0);
assert!(matches!(result, Err(EvalError::SqrtDomain)));
}
#[test]
fn test_root_fifth_of_negative() {
let expr = Expression::parse("51nv").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!(approx_eq_default(result.value, -1.0));
}
#[test]
fn test_root_positive_radicand_non_integer() {
let expr = Expression::parse("p8v").unwrap();
let result = evaluate(&expr, 0.0).unwrap();
assert!(result.value > 0.0 && result.value.is_finite());
}
#[test]
fn test_pow_derivative_negative_base_integer_exponent_is_finite() {
let expr = Expression::parse("2nx^").unwrap();
let result = evaluate(&expr, 2.0).unwrap();
assert_eq!(result.value, 4.0); assert!(
result.derivative.is_finite(),
"derivative of (-2)^x must be finite (not NaN), got {}",
result.derivative
);
}