| use crate::ast::{BinaryOp, UnaryOp}; |
| use num_complex::ComplexFloat; |
| use std::f64::consts::PI; |
|
|
| pub type Complex = num_complex::Complex<f64>; |
|
|
| #[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<f64> { |
| match self { |
| Self::Number(Number::Real(val)) => Some(*val), |
| _ => None, |
| } |
| } |
| } |
|
|
| impl From<f64> 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) |
| } |
| } |
|
|