use crate::ast::{BinaryOp, UnaryOp}; use num_complex::ComplexFloat; use std::f64::consts::PI; pub type Complex = num_complex::Complex; #[derive(Debug, PartialEq, Clone, Copy)] pub enum Value { Number(Number), } impl Value { pub fn from_f64(x: f64) -> Self { Self::Number(Number::Real(x)) } pub fn as_real(&self) -> Option { match self { Self::Number(Number::Real(val)) => Some(*val), _ => None, } } } impl From for Value { fn from(x: f64) -> Self { Self::from_f64(x) } } impl core::fmt::Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Value::Number(num) => num.fmt(f), } } } #[derive(Debug, PartialEq, Clone, Copy)] pub enum Number { Real(f64), Complex(Complex), } impl std::fmt::Display for Number { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Number::Real(real) => real.fmt(f), Number::Complex(complex) => complex.fmt(f), } } } impl Number { pub fn binary_op(self, op: BinaryOp, other: Number) -> Number { match (self, other) { (Number::Real(lhs), Number::Real(rhs)) => { let result = match op { BinaryOp::Add => lhs + rhs, BinaryOp::Sub => lhs - rhs, BinaryOp::Mul => lhs * rhs, BinaryOp::Div => lhs / rhs, BinaryOp::Pow => lhs.powf(rhs), }; Number::Real(result) } (Number::Complex(lhs), Number::Complex(rhs)) => { let result = match op { BinaryOp::Add => lhs + rhs, BinaryOp::Sub => lhs - rhs, BinaryOp::Mul => lhs * rhs, BinaryOp::Div => lhs / rhs, BinaryOp::Pow => lhs.powc(rhs), }; Number::Complex(result) } (Number::Real(lhs), Number::Complex(rhs)) => { let lhs_complex = Complex::new(lhs, 0.0); let result = match op { BinaryOp::Add => lhs_complex + rhs, BinaryOp::Sub => lhs_complex - rhs, BinaryOp::Mul => lhs_complex * rhs, BinaryOp::Div => lhs_complex / rhs, BinaryOp::Pow => lhs_complex.powc(rhs), }; Number::Complex(result) } (Number::Complex(lhs), Number::Real(rhs)) => { let rhs_complex = Complex::new(rhs, 0.0); let result = match op { BinaryOp::Add => lhs + rhs_complex, BinaryOp::Sub => lhs - rhs_complex, BinaryOp::Mul => lhs * rhs_complex, BinaryOp::Div => lhs / rhs_complex, BinaryOp::Pow => lhs.powf(rhs), }; Number::Complex(result) } } } pub fn unary_op(self, op: UnaryOp) -> Number { match self { Number::Real(real) => match op { UnaryOp::Neg => Number::Real(-real), UnaryOp::Sqrt => Number::Real(real.sqrt()), UnaryOp::Fac => todo!("Implement factorial"), }, Number::Complex(complex) => match op { UnaryOp::Neg => Number::Complex(-complex), UnaryOp::Sqrt => Number::Complex(complex.sqrt()), UnaryOp::Fac => todo!("Implement factorial"), }, } } pub fn from_f64(x: f64) -> Self { Self::Real(x) } }