File size: 2,923 Bytes
2409829 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
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)
}
}
|