quantrs2_symengine_pure/scirs2_bridge/
complex.rs

1//! Complex number integration with SciRS2.
2//!
3//! This module provides conversion between symbolic expressions and
4//! SciRS2's Complex64 type.
5
6use scirs2_core::Complex64;
7
8use crate::error::{SymEngineError, SymEngineResult};
9use crate::expr::Expression;
10
11/// Convert a symbolic expression to a Complex64 if possible.
12///
13/// # Errors
14/// Returns an error if the expression cannot be evaluated to a complex number.
15pub fn to_complex64(expr: &Expression) -> SymEngineResult<Complex64> {
16    // First try to evaluate as real
17    if let Some(re) = expr.to_f64() {
18        return Ok(Complex64::new(re, 0.0));
19    }
20
21    // Check if it's a pure imaginary (i * value)
22    // This is a simplified check - full implementation would parse the expression tree
23
24    Err(SymEngineError::eval(
25        "Cannot convert symbolic expression to Complex64 - try evaluating with specific values",
26    ))
27}
28
29/// Create an expression from a Complex64.
30///
31/// Returns a simplified expression when possible (e.g., real for pure real numbers).
32pub fn from_complex64(c: Complex64) -> Expression {
33    Expression::from_complex64(c)
34}
35
36/// Evaluate a symbolic expression to a Complex64 with given variable values.
37///
38/// # Arguments
39/// * `expr` - The expression to evaluate
40/// * `values` - Map of variable names to complex values
41///
42/// # Errors
43/// Returns an error if evaluation fails.
44pub fn eval_complex(
45    expr: &Expression,
46    values: &std::collections::HashMap<String, Complex64>,
47) -> SymEngineResult<Complex64> {
48    // For now, only support real evaluation
49    // TODO: Implement full complex evaluation
50
51    let real_values: std::collections::HashMap<String, f64> = values
52        .iter()
53        .filter(|(_, v)| v.im.abs() < 1e-15)
54        .map(|(k, v)| (k.clone(), v.re))
55        .collect();
56
57    if real_values.len() != values.len() {
58        return Err(SymEngineError::not_impl(
59            "Complex variable evaluation not yet implemented",
60        ));
61    }
62
63    let result = expr.eval(&real_values)?;
64    Ok(Complex64::new(result, 0.0))
65}
66
67/// Create complex arithmetic expressions.
68pub mod complex_ops {
69    use super::*;
70
71    /// Create a complex number expression a + bi
72    pub fn complex(re: f64, im: f64) -> Expression {
73        Expression::from_complex64(Complex64::new(re, im))
74    }
75
76    /// Create a pure imaginary number i*b
77    pub fn imag(b: f64) -> Expression {
78        Expression::float_unchecked(b) * Expression::i()
79    }
80
81    /// Polar form: r * e^(iθ)
82    pub fn polar(r: f64, theta: f64) -> Expression {
83        let c = Complex64::from_polar(r, theta);
84        Expression::from_complex64(c)
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_from_complex64_real() {
94        let c = Complex64::new(2.5, 0.0);
95        let expr = from_complex64(c);
96        assert!(expr.is_number());
97    }
98
99    #[test]
100    fn test_from_complex64_pure_imag() {
101        let c = Complex64::new(0.0, 2.0);
102        let expr = from_complex64(c);
103        // Should be 2 * I
104        assert!(!expr.is_symbol());
105    }
106
107    #[test]
108    fn test_from_complex64_general() {
109        let c = Complex64::new(3.0, 4.0);
110        let expr = from_complex64(c);
111        // Should be 3 + 4*I
112        assert!(!expr.is_symbol());
113    }
114
115    #[test]
116    fn test_complex_ops() {
117        use complex_ops::*;
118
119        let c = complex(1.0, 2.0);
120        let i = imag(3.0);
121        let p = polar(1.0, std::f64::consts::FRAC_PI_2);
122
123        assert!(!c.is_symbol());
124        assert!(!i.is_symbol());
125        assert!(!p.is_symbol());
126    }
127}