1use std::collections::HashMap;
2
3use qudit_core::ComplexScalar;
4use serde::Deserialize;
5use serde::Serialize;
6
7use crate::expressions::Constant;
8use crate::expressions::Expression;
9use crate::qgl::Expression as CiscExpression;
10use crate::qgl::parse_scalar;
11
12#[derive(Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
13pub struct ComplexExpression {
14 pub real: Expression,
15 pub imag: Expression,
16}
17
18impl ComplexExpression {
19 pub fn from_string(input: impl AsRef<str>) -> Self {
20 ComplexExpression::new(
21 parse_scalar(input.as_ref()).unwrap_or_else(|e| panic!("Invalid input string: {e}")),
22 )
23 }
24
25 pub fn from_real_64(input: f64) -> Self {
26 ComplexExpression {
27 real: Expression::from_float_64(input),
28 imag: Expression::zero(),
29 }
30 }
31
32 pub fn from_real_32(input: f32) -> Self {
33 ComplexExpression {
34 real: Expression::from_float_32(input),
35 imag: Expression::zero(),
36 }
37 }
38
39 pub fn new(cisc_expr: CiscExpression) -> Self {
40 match cisc_expr {
41 CiscExpression::Number(num) => ComplexExpression {
42 real: Expression::Constant(
43 Constant::from_float(num.parse::<f64>().unwrap()).unwrap(),
44 ),
45 imag: Expression::zero(),
46 },
47 CiscExpression::Variable(var) => {
48 if var == "i" {
49 ComplexExpression {
50 real: Expression::zero(),
51 imag: Expression::one(),
52 }
53 } else if var == "π" || var == "pi" {
54 ComplexExpression {
55 real: Expression::Pi,
56 imag: Expression::zero(),
57 }
58 } else {
59 ComplexExpression {
60 real: Expression::Variable(var),
61 imag: Expression::zero(),
62 }
63 }
64 }
65 CiscExpression::Unary { op, expr } => {
66 let risc_expr = ComplexExpression::new(*expr);
67 match op {
68 '~' => ComplexExpression {
69 real: Expression::Neg(Box::new(risc_expr.real)),
70 imag: Expression::Neg(Box::new(risc_expr.imag)),
71 },
72 _ => panic!("Invalid unary operator: {}", op),
73 }
74 }
75 CiscExpression::Binary { op, lhs, rhs } => {
76 let risc_lhs = ComplexExpression::new(*lhs);
77 let risc_rhs = ComplexExpression::new(*rhs);
78 match op {
79 '+' => risc_lhs + risc_rhs,
80 '-' => risc_lhs - risc_rhs,
81 '*' => risc_lhs * risc_rhs,
82 '/' => risc_lhs / risc_rhs,
83 '^' => {
84 if risc_lhs.is_e() {
85 assert!(
89 risc_rhs.real.is_zero(),
90 "Exponential power must be imaginary",
91 );
92 ComplexExpression {
93 real: Expression::Cos(Box::new(risc_rhs.imag.clone())),
94 imag: Expression::Sin(Box::new(risc_rhs.imag)),
95 }
96 } else {
97 assert!(risc_lhs.is_real(), "Power base must be real");
98 assert!(risc_rhs.is_real(), "Power exponent must be real");
99 ComplexExpression {
100 real: Expression::Pow(
101 Box::new(risc_lhs.real),
102 Box::new(risc_rhs.real),
103 ),
104 imag: Expression::zero(),
105 }
106 }
107 }
108 _ => panic!("Invalid binary operator: {}", op),
109 }
110 }
111 CiscExpression::Call { fn_name, args } => match fn_name.as_str() {
112 "sqrt" => {
113 let risc_arg = ComplexExpression::new(args[0].clone());
114 assert!(args.len() == 1, "sqrt function takes exactly one argument");
115 assert!(
116 risc_arg.is_real(),
117 "sqrt function is only supported for real numbers"
118 );
119 ComplexExpression {
120 real: Expression::Sqrt(Box::new(risc_arg.real)),
121 imag: Expression::zero(),
122 }
123 }
124 "sin" => {
125 let risc_arg = ComplexExpression::new(args[0].clone());
126 assert!(args.len() == 1, "sin function takes exactly one argument");
127 assert!(
128 risc_arg.is_real(),
129 "sin function is only supported for real numbers"
130 );
131 ComplexExpression {
132 real: Expression::Sin(Box::new(risc_arg.real)),
133 imag: Expression::zero(),
134 }
135 }
136 "cos" => {
137 let risc_arg = ComplexExpression::new(args[0].clone());
138 assert!(args.len() == 1, "cos function takes exactly one argument");
139 assert!(
140 risc_arg.is_real(),
141 "cos function is only supported for real numbers"
142 );
143 ComplexExpression {
144 real: Expression::Cos(Box::new(risc_arg.real)),
145 imag: Expression::zero(),
146 }
147 }
148 "tan" => {
149 let risc_arg = ComplexExpression::new(args[0].clone());
150 assert!(args.len() == 1, "tan function takes exactly one argument");
151 assert!(
152 risc_arg.is_real(),
153 "tan function is only supported for real numbers"
154 );
155 ComplexExpression {
156 real: Expression::Div(
157 Box::new(Expression::Sin(Box::new(risc_arg.real.clone()))),
158 Box::new(Expression::Cos(Box::new(risc_arg.real))),
159 ),
160 imag: Expression::zero(),
161 }
162 }
163 "csc" => {
164 let risc_arg = ComplexExpression::new(args[0].clone());
165 assert!(args.len() == 1, "csc function takes exactly one argument");
166 assert!(
167 risc_arg.is_real(),
168 "csc function is only supported for real numbers"
169 );
170 ComplexExpression {
171 real: Expression::Div(
172 Box::new(Expression::one()),
173 Box::new(Expression::Sin(Box::new(risc_arg.real))),
174 ),
175 imag: Expression::zero(),
176 }
177 }
178 "sec" => {
179 let risc_arg = ComplexExpression::new(args[0].clone());
180 assert!(args.len() == 1, "sec function takes exactly one argument");
181 assert!(
182 risc_arg.is_real(),
183 "sec function is only supported for real numbers"
184 );
185 ComplexExpression {
186 real: Expression::Div(
187 Box::new(Expression::one()),
188 Box::new(Expression::Cos(Box::new(risc_arg.real))),
189 ),
190 imag: Expression::zero(),
191 }
192 }
193 "cot" => {
194 let risc_arg = ComplexExpression::new(args[0].clone());
195 assert!(args.len() == 1, "cot function takes exactly one argument");
196 assert!(
197 risc_arg.is_real(),
198 "cot function is only supported for real numbers"
199 );
200 ComplexExpression {
201 real: Expression::Div(
202 Box::new(Expression::Cos(Box::new(risc_arg.real.clone()))),
203 Box::new(Expression::Sin(Box::new(risc_arg.real))),
204 ),
205 imag: Expression::zero(),
206 }
207 }
208 _ => panic!("Invalid function name: {}", fn_name),
209 },
210 _ => panic!("Unexpected expression during complex conversion"),
211 }
212 }
213
214 pub fn one() -> Self {
215 ComplexExpression {
216 real: Expression::one(),
217 imag: Expression::zero(),
218 }
219 }
220
221 pub fn zero() -> Self {
222 ComplexExpression {
223 real: Expression::zero(),
224 imag: Expression::zero(),
225 }
226 }
227
228 pub fn i() -> Self {
229 ComplexExpression {
230 real: Expression::zero(),
231 imag: Expression::one(),
232 }
233 }
234
235 pub fn pi() -> Self {
236 ComplexExpression {
237 real: Expression::Pi,
238 imag: Expression::zero(),
239 }
240 }
241
242 pub fn is_real(&self) -> bool {
243 self.imag.is_zero()
244 }
245
246 pub fn is_imag(&self) -> bool {
247 self.real.is_zero() && !self.imag.is_zero()
248 }
249
250 pub fn is_cplx(&self) -> bool {
251 !self.real.is_zero() && !self.imag.is_zero()
252 }
253
254 pub fn is_real_fast(&self) -> bool {
255 self.imag.is_zero_fast()
256 }
257
258 pub fn is_imag_fast(&self) -> bool {
259 self.real.is_zero_fast() && !self.imag.is_zero_fast()
260 }
261
262 pub fn is_cplx_fast(&self) -> bool {
263 !self.real.is_zero_fast() && !self.imag.is_zero_fast()
264 }
265
266 pub fn is_e(&self) -> bool {
267 match &self.real {
268 Expression::Variable(var) => var == "e",
269 _ => false,
270 }
271 }
272
273 pub fn is_zero(&self) -> bool {
274 self.real.is_zero() && self.imag.is_zero()
275 }
276
277 pub fn is_one(&self) -> bool {
278 self.real.is_one() && self.imag.is_zero()
279 }
280
281 pub fn is_zero_fast(&self) -> bool {
282 self.real.is_zero_fast() && self.imag.is_zero_fast()
283 }
284
285 pub fn is_one_fast(&self) -> bool {
286 self.real.is_one_fast() && self.imag.is_zero_fast()
287 }
288
289 pub fn eval<C: ComplexScalar>(&self, args: &HashMap<&str, C::R>) -> C {
290 C::new(self.real.eval(args), self.imag.eval(args))
291 }
292
293 pub fn map_var_names(&self, var_map: &HashMap<String, String>) -> Self {
294 ComplexExpression {
295 real: self.real.map_var_names(var_map),
296 imag: self.imag.map_var_names(var_map),
297 }
298 }
299
300 pub fn conjugate(&self) -> Self {
301 ComplexExpression {
302 real: self.real.clone(),
303 imag: Expression::Neg(Box::new(self.imag.clone())),
304 }
305 }
306
307 pub fn conjugate_in_place(&mut self) {
308 self.imag = Expression::Neg(Box::new(self.imag.clone()));
309 }
310
311 pub fn differentiate(&self, wrt: &str) -> Self {
312 ComplexExpression {
313 real: self.real.differentiate(wrt),
314 imag: self.imag.differentiate(wrt),
315 }
316 }
317
318 pub fn simplify(&self) -> Self {
319 ComplexExpression {
320 real: self.real.simplify(),
321 imag: self.imag.simplify(),
322 }
323 }
324
325 pub fn get_ancestors(&self, variable: &str) -> Vec<Expression> {
326 let mut ancestors = self.real.get_ancestors(variable);
327 let im_ancestors = self.imag.get_ancestors(variable);
328 if ancestors.is_empty() {
329 return im_ancestors;
330 }
331 if !im_ancestors.is_empty() {
332 ancestors.retain(|x| im_ancestors.contains(x));
333 }
334 ancestors
335 }
336
337 pub fn substitute<S: AsRef<Expression>, T: AsRef<Expression>>(
338 &self,
339 original: S,
340 substitution: T,
341 ) -> Self {
342 ComplexExpression {
344 real: self
345 .real
346 .substitute(original.as_ref(), substitution.as_ref()),
347 imag: self
348 .imag
349 .substitute(original.as_ref(), substitution.as_ref()),
350 }
351 }
352
353 pub fn rename_variable<S: AsRef<str>, T: AsRef<str>>(&self, original: S, new: T) -> Self {
354 ComplexExpression {
355 real: self.real.rename_variable(original.as_ref(), new.as_ref()),
356 imag: self.imag.rename_variable(original.as_ref(), new.as_ref()),
357 }
358 }
359
360 pub fn get_unique_variables(&self) -> Vec<String> {
361 let mut real = self.real.get_unique_variables();
362 for i in self.imag.get_unique_variables().into_iter() {
363 if !real.contains(&i) {
364 real.push(i)
365 }
366 }
367 real
368 }
369
370 pub fn is_parameterized(&self) -> bool {
371 self.real.is_parameterized() || self.imag.is_parameterized()
372 }
373}
374
375impl std::ops::Mul<ComplexExpression> for ComplexExpression {
376 type Output = Self;
377
378 fn mul(self, rhs: Self) -> Self {
379 &self * &rhs
380 }
381}
382
383impl std::ops::Mul<&ComplexExpression> for ComplexExpression {
384 type Output = ComplexExpression;
385
386 fn mul(self, rhs: &ComplexExpression) -> ComplexExpression {
387 &self * rhs
388 }
389}
390
391impl std::ops::Mul<ComplexExpression> for &ComplexExpression {
392 type Output = ComplexExpression;
393
394 fn mul(self, rhs: ComplexExpression) -> ComplexExpression {
395 self * &rhs
396 }
397}
398
399impl std::ops::Mul<&ComplexExpression> for &ComplexExpression {
400 type Output = ComplexExpression;
401
402 fn mul(self, rhs: &ComplexExpression) -> ComplexExpression {
403 ComplexExpression {
404 real: &self.real * &rhs.real - &self.imag * &rhs.imag,
405 imag: &self.real * &rhs.imag + &self.imag * &rhs.real,
406 }
407 }
408}
409
410impl std::ops::Add<ComplexExpression> for ComplexExpression {
411 type Output = Self;
412
413 fn add(self, rhs: Self) -> Self {
414 &self + &rhs
415 }
416}
417
418impl std::ops::Add<&ComplexExpression> for ComplexExpression {
419 type Output = ComplexExpression;
420
421 fn add(self, rhs: &ComplexExpression) -> ComplexExpression {
422 &self + rhs
423 }
424}
425
426impl std::ops::Add<ComplexExpression> for &ComplexExpression {
427 type Output = ComplexExpression;
428
429 fn add(self, rhs: ComplexExpression) -> ComplexExpression {
430 self + &rhs
431 }
432}
433
434impl std::ops::Add<&ComplexExpression> for &ComplexExpression {
435 type Output = ComplexExpression;
436
437 fn add(self, rhs: &ComplexExpression) -> ComplexExpression {
438 ComplexExpression {
439 real: &self.real + &rhs.real,
440 imag: &self.imag + &rhs.imag,
441 }
442 }
443}
444
445impl std::ops::Sub<ComplexExpression> for ComplexExpression {
446 type Output = Self;
447
448 fn sub(self, rhs: Self) -> Self {
449 &self - &rhs
450 }
451}
452
453impl std::ops::Sub<&ComplexExpression> for ComplexExpression {
454 type Output = ComplexExpression;
455
456 fn sub(self, rhs: &ComplexExpression) -> ComplexExpression {
457 &self - rhs
458 }
459}
460
461impl std::ops::Sub<ComplexExpression> for &ComplexExpression {
462 type Output = ComplexExpression;
463
464 fn sub(self, rhs: ComplexExpression) -> ComplexExpression {
465 self - &rhs
466 }
467}
468
469impl std::ops::Sub<&ComplexExpression> for &ComplexExpression {
470 type Output = ComplexExpression;
471
472 fn sub(self, rhs: &ComplexExpression) -> ComplexExpression {
473 ComplexExpression {
474 real: &self.real - &rhs.real,
475 imag: &self.imag - &rhs.imag,
476 }
477 }
478}
479
480impl std::ops::Neg for ComplexExpression {
481 type Output = Self;
482
483 fn neg(self) -> Self {
484 -&self
485 }
486}
487
488impl std::ops::Neg for &ComplexExpression {
489 type Output = ComplexExpression;
490
491 fn neg(self) -> ComplexExpression {
492 ComplexExpression {
493 real: -&self.real,
494 imag: -&self.imag,
495 }
496 }
497}
498
499impl std::ops::Div<ComplexExpression> for ComplexExpression {
500 type Output = Self;
501
502 fn div(self, rhs: Self) -> Self {
503 &self / &rhs
504 }
505}
506
507impl std::ops::Div<&ComplexExpression> for ComplexExpression {
508 type Output = ComplexExpression;
509
510 fn div(self, rhs: &ComplexExpression) -> ComplexExpression {
511 &self / rhs
512 }
513}
514
515impl std::ops::Div<ComplexExpression> for &ComplexExpression {
516 type Output = ComplexExpression;
517
518 fn div(self, rhs: ComplexExpression) -> ComplexExpression {
519 self / &rhs
520 }
521}
522
523impl std::ops::Div<&ComplexExpression> for &ComplexExpression {
524 type Output = ComplexExpression;
525
526 fn div(self, rhs: &ComplexExpression) -> ComplexExpression {
527 let dem = &rhs.real * &rhs.real + &rhs.imag * &rhs.imag;
528 ComplexExpression {
529 real: (&self.real * &rhs.real + &self.imag * &rhs.imag) / &dem,
530 imag: (&self.imag * &rhs.real - &self.real * &rhs.imag) / &dem,
531 }
532 }
533}
534
535impl std::ops::AddAssign for ComplexExpression {
536 fn add_assign(&mut self, rhs: Self) {
537 *self = &*self + &rhs;
538 }
539}
540
541impl std::ops::AddAssign<&ComplexExpression> for ComplexExpression {
542 fn add_assign(&mut self, rhs: &Self) {
543 *self = &*self + rhs;
544 }
545}
546
547impl std::ops::SubAssign for ComplexExpression {
548 fn sub_assign(&mut self, rhs: Self) {
549 *self = &*self - &rhs;
550 }
551}
552
553impl std::ops::SubAssign<&ComplexExpression> for ComplexExpression {
554 fn sub_assign(&mut self, rhs: &Self) {
555 *self = &*self - rhs;
556 }
557}
558
559impl std::ops::MulAssign for ComplexExpression {
560 fn mul_assign(&mut self, rhs: Self) {
561 *self = &*self * &rhs;
562 }
563}
564
565impl std::ops::MulAssign<&ComplexExpression> for ComplexExpression {
566 fn mul_assign(&mut self, rhs: &Self) {
567 *self = &*self * rhs;
568 }
569}
570
571impl std::ops::DivAssign for ComplexExpression {
572 fn div_assign(&mut self, rhs: Self) {
573 *self = &*self / &rhs;
574 }
575}
576
577impl std::ops::DivAssign<&ComplexExpression> for ComplexExpression {
578 fn div_assign(&mut self, rhs: &Self) {
579 *self = &*self / rhs;
580 }
581}
582
583impl std::fmt::Debug for ComplexExpression {
584 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
585 f.debug_struct("ComplexExpression")
586 .field("real", &self.real)
587 .field("imag", &self.imag)
588 .finish()
589 }
590}
591
592impl<C: ComplexScalar> From<C> for ComplexExpression {
593 fn from(value: C) -> Self {
594 ComplexExpression {
595 real: value.re().into(),
596 imag: value.im().into(),
597 }
598 }
599}