quantrs2_symengine_pure/scirs2_bridge/
complex.rs1use scirs2_core::Complex64;
7
8use crate::error::{SymEngineError, SymEngineResult};
9use crate::expr::Expression;
10
11pub fn to_complex64(expr: &Expression) -> SymEngineResult<Complex64> {
16 if let Some(re) = expr.to_f64() {
18 return Ok(Complex64::new(re, 0.0));
19 }
20
21 Err(SymEngineError::eval(
25 "Cannot convert symbolic expression to Complex64 - try evaluating with specific values",
26 ))
27}
28
29pub fn from_complex64(c: Complex64) -> Expression {
33 Expression::from_complex64(c)
34}
35
36pub fn eval_complex(
49 expr: &Expression,
50 values: &std::collections::HashMap<String, Complex64>,
51) -> SymEngineResult<Complex64> {
52 crate::eval::evaluate_complex_with_complex_values(expr, values)
53}
54
55pub mod complex_ops {
57 use super::*;
58
59 pub fn complex(re: f64, im: f64) -> Expression {
61 Expression::from_complex64(Complex64::new(re, im))
62 }
63
64 pub fn imag(b: f64) -> Expression {
66 Expression::float_unchecked(b) * Expression::i()
67 }
68
69 pub fn polar(r: f64, theta: f64) -> Expression {
71 let c = Complex64::from_polar(r, theta);
72 Expression::from_complex64(c)
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_from_complex64_real() {
82 let c = Complex64::new(2.5, 0.0);
83 let expr = from_complex64(c);
84 assert!(expr.is_number());
85 }
86
87 #[test]
88 fn test_from_complex64_pure_imag() {
89 let c = Complex64::new(0.0, 2.0);
90 let expr = from_complex64(c);
91 assert!(!expr.is_symbol());
93 }
94
95 #[test]
96 fn test_from_complex64_general() {
97 let c = Complex64::new(3.0, 4.0);
98 let expr = from_complex64(c);
99 assert!(!expr.is_symbol());
101 }
102
103 #[test]
104 fn test_complex_ops() {
105 use complex_ops::*;
106
107 let c = complex(1.0, 2.0);
108 let i = imag(3.0);
109 let p = polar(1.0, std::f64::consts::FRAC_PI_2);
110
111 assert!(!c.is_symbol());
112 assert!(!i.is_symbol());
113 assert!(!p.is_symbol());
114 }
115
116 #[test]
121 fn test_eval_complex_pure_real() {
122 let expr = Expression::float_unchecked(7.0);
124 let values = std::collections::HashMap::new();
125 let result = eval_complex(&expr, &values).expect("should evaluate pure real");
126 assert!((result.re - 7.0).abs() < 1e-10);
127 assert!(result.im.abs() < 1e-10);
128 }
129
130 #[test]
131 fn test_eval_complex_real_plus_imag() {
132 let two = Expression::float_unchecked(2.0);
134 let three = Expression::float_unchecked(3.0);
135 let i = Expression::i();
136 let expr = two + three * i;
137
138 let values = std::collections::HashMap::new();
139 let result = eval_complex(&expr, &values).expect("should evaluate 2+3i");
140 assert!((result.re - 2.0).abs() < 1e-10);
141 assert!((result.im - 3.0).abs() < 1e-10);
142 }
143
144 #[test]
145 fn test_eval_complex_with_complex_var() {
146 let z = Expression::symbol("z");
148 let mut values = std::collections::HashMap::new();
149 values.insert("z".to_string(), Complex64::new(1.0, 2.0));
150
151 let result = eval_complex(&z, &values).expect("should evaluate complex variable");
152 assert!((result.re - 1.0).abs() < 1e-10);
153 assert!((result.im - 2.0).abs() < 1e-10);
154 }
155
156 #[test]
157 fn test_eval_complex_pure_imaginary() {
158 let five = Expression::float_unchecked(5.0);
160 let i = Expression::i();
161 let expr = five * i;
162
163 let values = std::collections::HashMap::new();
164 let result = eval_complex(&expr, &values).expect("should evaluate pure imaginary");
165 assert!(result.re.abs() < 1e-10);
166 assert!((result.im - 5.0).abs() < 1e-10);
167 }
168
169 #[test]
170 fn test_eval_complex_i_squared() {
171 let i1 = Expression::i();
173 let i2 = Expression::i();
174 let expr = i1 * i2;
175
176 let values = std::collections::HashMap::new();
177 let result = eval_complex(&expr, &values).expect("I*I should be -1");
178 assert!((result.re - (-1.0)).abs() < 1e-10);
179 assert!(result.im.abs() < 1e-10);
180 }
181}