use scirs2_core::Complex64;
use crate::error::{SymEngineError, SymEngineResult};
use crate::expr::Expression;
pub fn to_complex64(expr: &Expression) -> SymEngineResult<Complex64> {
if let Some(re) = expr.to_f64() {
return Ok(Complex64::new(re, 0.0));
}
Err(SymEngineError::eval(
"Cannot convert symbolic expression to Complex64 - try evaluating with specific values",
))
}
pub fn from_complex64(c: Complex64) -> Expression {
Expression::from_complex64(c)
}
pub fn eval_complex(
expr: &Expression,
values: &std::collections::HashMap<String, Complex64>,
) -> SymEngineResult<Complex64> {
crate::eval::evaluate_complex_with_complex_values(expr, values)
}
pub mod complex_ops {
use super::*;
pub fn complex(re: f64, im: f64) -> Expression {
Expression::from_complex64(Complex64::new(re, im))
}
pub fn imag(b: f64) -> Expression {
Expression::float_unchecked(b) * Expression::i()
}
pub fn polar(r: f64, theta: f64) -> Expression {
let c = Complex64::from_polar(r, theta);
Expression::from_complex64(c)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_complex64_real() {
let c = Complex64::new(2.5, 0.0);
let expr = from_complex64(c);
assert!(expr.is_number());
}
#[test]
fn test_from_complex64_pure_imag() {
let c = Complex64::new(0.0, 2.0);
let expr = from_complex64(c);
assert!(!expr.is_symbol());
}
#[test]
fn test_from_complex64_general() {
let c = Complex64::new(3.0, 4.0);
let expr = from_complex64(c);
assert!(!expr.is_symbol());
}
#[test]
fn test_complex_ops() {
use complex_ops::*;
let c = complex(1.0, 2.0);
let i = imag(3.0);
let p = polar(1.0, std::f64::consts::FRAC_PI_2);
assert!(!c.is_symbol());
assert!(!i.is_symbol());
assert!(!p.is_symbol());
}
#[test]
fn test_eval_complex_pure_real() {
let expr = Expression::float_unchecked(7.0);
let values = std::collections::HashMap::new();
let result = eval_complex(&expr, &values).expect("should evaluate pure real");
assert!((result.re - 7.0).abs() < 1e-10);
assert!(result.im.abs() < 1e-10);
}
#[test]
fn test_eval_complex_real_plus_imag() {
let two = Expression::float_unchecked(2.0);
let three = Expression::float_unchecked(3.0);
let i = Expression::i();
let expr = two + three * i;
let values = std::collections::HashMap::new();
let result = eval_complex(&expr, &values).expect("should evaluate 2+3i");
assert!((result.re - 2.0).abs() < 1e-10);
assert!((result.im - 3.0).abs() < 1e-10);
}
#[test]
fn test_eval_complex_with_complex_var() {
let z = Expression::symbol("z");
let mut values = std::collections::HashMap::new();
values.insert("z".to_string(), Complex64::new(1.0, 2.0));
let result = eval_complex(&z, &values).expect("should evaluate complex variable");
assert!((result.re - 1.0).abs() < 1e-10);
assert!((result.im - 2.0).abs() < 1e-10);
}
#[test]
fn test_eval_complex_pure_imaginary() {
let five = Expression::float_unchecked(5.0);
let i = Expression::i();
let expr = five * i;
let values = std::collections::HashMap::new();
let result = eval_complex(&expr, &values).expect("should evaluate pure imaginary");
assert!(result.re.abs() < 1e-10);
assert!((result.im - 5.0).abs() < 1e-10);
}
#[test]
fn test_eval_complex_i_squared() {
let i1 = Expression::i();
let i2 = Expression::i();
let expr = i1 * i2;
let values = std::collections::HashMap::new();
let result = eval_complex(&expr, &values).expect("I*I should be -1");
assert!((result.re - (-1.0)).abs() < 1e-10);
assert!(result.im.abs() < 1e-10);
}
}