127 lines
2.9 KiB
Rust
127 lines
2.9 KiB
Rust
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)
|
|
}
|
|
}
|