refactor: modify numbers inplace

this should improve performance

I also happened to fix the lack of detail in the explicit panics
This commit is contained in:
electria 2026-07-13 19:37:29 -07:00
commit 23d49fbb6a
Signed by: electria
SSH key fingerprint: SHA256:8LlB3ucPbBHqozqkhsNbaV5oG3SlzzqUj8FZDL6IPQs

View file

@ -4,7 +4,7 @@ use std::str::FromStr;
use rug::{ use rug::{
Float, Float,
float::ParseFloatError, float::ParseFloatError,
ops::{CompleteRound, Pow}, ops::{AddFrom, CompleteRound, DivFrom, MulFrom, PowFrom, SubFrom},
}; };
#[derive(Clone, Debug, thiserror::Error)] #[derive(Clone, Debug, thiserror::Error)]
@ -190,105 +190,90 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) {
.iter() .iter()
.position(|n| *n == Node::Operator(Operator::Exp)) .position(|n| *n == Node::Operator(Operator::Exp))
{ {
let lhs = match &nodes[start..end][operator - 1] { let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n, Node::Number(n) => n,
_ => panic!("operator is missing an operand"), n => panic!("operator has an invalid operand: {n:?}"),
}; };
let rhs = match &nodes[start..end][operator + 1] { end -= 1;
Node::Number(n) => n, match &mut nodes[start..end][operator] {
_ => panic!("operator is missing an operand"), Node::Number(n) => n.pow_from(lhs),
n => panic!("operator has an invalid operand: {n:?}"),
}; };
let number = lhs.pow(rhs).complete(PREC);
nodes.remove(start + operator - 1); nodes.remove(start + operator - 1);
nodes.remove(start + operator - 1); end -= 1;
end -= 2;
nodes[start + operator - 1] = Node::Number(number);
} }
while let Some(operator) = nodes[start..end] while let Some(operator) = nodes[start..end]
.iter() .iter()
.position(|n| *n == Node::Operator(Operator::Div)) .position(|n| *n == Node::Operator(Operator::Div))
{ {
let lhs = match &nodes[start..end][operator - 1] { let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n, Node::Number(n) => n,
_ => panic!("operator is missing an operand"), n => panic!("operator has an invalid operand: {n:?}"),
}; };
let rhs = match &nodes[start..end][operator + 1] { end -= 1;
Node::Number(n) => n, match &mut nodes[start..end][operator] {
_ => panic!("operator is missing an operand"), Node::Number(n) => n.div_from(lhs),
n => panic!("operator has an invalid operand: {n:?}"),
}; };
let number = (lhs / rhs).complete(PREC);
nodes.remove(start + operator - 1); nodes.remove(start + operator - 1);
nodes.remove(start + operator - 1); end -= 1;
end -= 2;
nodes[start + operator - 1] = Node::Number(number);
} }
while let Some(operator) = nodes[start..end] while let Some(operator) = nodes[start..end]
.iter() .iter()
.position(|n| *n == Node::Operator(Operator::Mult)) .position(|n| *n == Node::Operator(Operator::Mult))
{ {
let lhs = match &nodes[start..end][operator - 1] { let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n, Node::Number(n) => n,
_ => panic!("operator is missing an operand"), n => panic!("operator has an invalid operand: {n:?}"),
}; };
let rhs = match &nodes[start..end][operator + 1] { end -= 1;
Node::Number(n) => n, match &mut nodes[start..end][operator] {
_ => panic!("operator is missing an operand"), Node::Number(n) => n.mul_from(lhs),
n => panic!("operator has an invalid operand: {n:?}"),
}; };
let number = (lhs * rhs).complete(PREC);
nodes.remove(start + operator - 1); nodes.remove(start + operator - 1);
nodes.remove(start + operator - 1); end -= 1;
end -= 2;
nodes[start + operator - 1] = Node::Number(number);
} }
while let Some(operator) = nodes[start..end] while let Some(operator) = nodes[start..end]
.iter() .iter()
.position(|n| *n == Node::Operator(Operator::Plus)) .position(|n| *n == Node::Operator(Operator::Plus))
{ {
let lhs = match &nodes[start..end][operator - 1] { let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n, Node::Number(n) => n,
_ => panic!("operator is missing an operand"), n => panic!("operator has an invalid operand: {n:?}"),
}; };
let rhs = match &nodes[start..end][operator + 1] { end -= 1;
Node::Number(n) => n, match &mut nodes[start..end][operator] {
_ => panic!("operator is missing an operand"), Node::Number(n) => n.add_from(lhs),
n => panic!("operator has an invalid operand: {n:?}"),
}; };
let number = (lhs + rhs).complete(PREC);
nodes.remove(start + operator - 1); nodes.remove(start + operator - 1);
nodes.remove(start + operator - 1); end -= 1;
end -= 2;
nodes[start + operator - 1] = Node::Number(number);
} }
while let Some(operator) = nodes[start..end] while let Some(operator) = nodes[start..end]
.iter() .iter()
.position(|n| *n == Node::Operator(Operator::Minus)) .position(|n| *n == Node::Operator(Operator::Minus))
{ {
let lhs = match &nodes[start..end][operator - 1] { let lhs = match nodes.remove(start + operator - 1) {
Node::Number(n) => n, Node::Number(n) => n,
_ => panic!("operator is missing an operand"), n => panic!("operator has an invalid operand: {n:?}"),
}; };
let rhs = match &nodes[start..end][operator + 1] { end -= 1;
Node::Number(n) => n, match &mut nodes[start..end][operator] {
_ => panic!("operator is missing an operand"), Node::Number(n) => n.sub_from(lhs),
n => panic!("operator has an invalid operand: {n:?}"),
}; };
let number = (lhs - rhs).complete(PREC);
nodes.remove(start + operator - 1); nodes.remove(start + operator - 1);
nodes.remove(start + operator - 1); end -= 1;
end -= 2;
nodes[start + operator - 1] = Node::Number(number);
} }
if nodes.len() > 1 { if nodes.len() > 1 {