use num_complex::Complex;
use serde::Deserialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BuiltinSymbol(pub u32);
impl<'de> serde::Deserialize<'de> for BuiltinSymbol {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let id: u32 = u32::deserialize(deserializer)?;
Ok(BuiltinSymbol(id))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize)]
pub enum Slot {
Param(usize),
Const(usize),
Temp(usize),
Out(usize),
Static(usize),
Arg(usize),
}
#[derive(Debug, Clone, Deserialize)]
pub enum Instruction {
Add(Slot, Vec<Slot>, usize),
Mul(Slot, Vec<Slot>, usize),
Pow(Slot, Slot, i64, bool),
Powf(Slot, Slot, Slot, bool),
Fun(Slot, BuiltinSymbol, Slot, bool),
ExternalFun(Slot, String, Vec<Slot>),
Assign(Slot, Slot),
IfElse(Slot, usize),
Goto(usize),
Label(usize),
Join(Slot, Slot, Slot, Slot),
}
#[derive(Debug, Clone, Deserialize)]
pub enum Value {
Single(f64),
}
impl Value {
fn value(&self) -> f64 {
let Value::Single(x) = self;
*x
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct Rational {
pub numerator: Value,
pub denominator: Value,
}
impl Rational {
fn value(&self) -> f64 {
self.numerator.value() / self.denominator.value()
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct ComplexRational {
pub re: Rational,
pub im: Rational,
}
impl ComplexRational {
fn value(&self) -> Complex<f64> {
Complex::new(self.re.value(), self.im.value())
}
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum ConstType {
Complex(ComplexRational),
Single(f64),
}
impl ConstType {
pub fn value(&self) -> Complex<f64> {
match self {
ConstType::Single(x) => Complex::new(*x, 0.0),
ConstType::Complex(x) => x.value(),
}
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct SymbolicaModel(pub Vec<Instruction>, pub usize, pub Vec<ConstType>);