use num_rational::Rational64;
#[derive(Debug, Clone, PartialEq)]
pub struct Operand {
pub kind: OperandKind,
pub raw: String,
}
#[derive(Debug, Clone, PartialEq)]
pub enum OperandKind {
Number(f64),
Fraction(Rational64),
RowRef(usize),
ColRef(usize),
Variable(String),
}
impl Operand {
pub fn number(n: f64, raw: impl Into<String>) -> Self {
Operand {
kind: OperandKind::Number(n),
raw: raw.into(),
}
}
pub fn fraction(num: i64, den: i64, raw: impl Into<String>) -> Self {
Operand {
kind: OperandKind::Fraction(Rational64::new(num, den)),
raw: raw.into(),
}
}
pub fn row_ref(idx: usize, raw: impl Into<String>) -> Self {
Operand {
kind: OperandKind::RowRef(idx),
raw: raw.into(),
}
}
pub fn col_ref(idx: usize, raw: impl Into<String>) -> Self {
Operand {
kind: OperandKind::ColRef(idx),
raw: raw.into(),
}
}
pub fn variable(name: impl Into<String>) -> Self {
let name = name.into();
Operand {
kind: OperandKind::Variable(name.clone()),
raw: name,
}
}
pub fn to_f64(&self) -> f64 {
match &self.kind {
OperandKind::Number(n) => *n,
OperandKind::Fraction(r) => *r.numer() as f64 / *r.denom() as f64,
OperandKind::RowRef(_) | OperandKind::ColRef(_) | OperandKind::Variable(_) => 1.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Operator {
Add,
Subtract,
Multiply,
Replace,
}
impl std::fmt::Display for Operator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Operator::Add => write!(f, "+"),
Operator::Subtract => write!(f, "-"),
Operator::Multiply => write!(f, "x"),
Operator::Replace => write!(f, "<"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct RowOperation {
pub target: usize,
pub operator: Operator,
pub operands: Vec<Operand>,
}
impl RowOperation {
pub fn first_operand(&self) -> Option<&Operand> {
self.operands.first()
}
pub fn source_row(&self) -> Option<usize> {
self.operands.iter().find_map(|op| match &op.kind {
OperandKind::RowRef(idx) => Some(*idx),
_ => None,
})
}
pub fn source_col(&self) -> Option<usize> {
self.operands.iter().find_map(|op| match &op.kind {
OperandKind::ColRef(idx) => Some(*idx),
_ => None,
})
}
}