Compare commits
3 changed files with 112 additions and 61 deletions
|
|
@ -83,41 +83,111 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
|
||||||
return Err(Error::MissingArgument(node.clone()));
|
return Err(Error::MissingArgument(node.clone()));
|
||||||
};
|
};
|
||||||
|
|
||||||
function.apply_to(n);
|
function.for_float()(n);
|
||||||
|
|
||||||
nodes.remove(start + index);
|
nodes.remove(start + index);
|
||||||
end -= 1;
|
end -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! collapse_operator {
|
while let Some(operator) = nodes[start..end]
|
||||||
($operator:expr) => {
|
.iter()
|
||||||
while let Some(index) = nodes[start..end]
|
.position(|n| *n == Node::Operator(Operator::Exp))
|
||||||
.iter()
|
{
|
||||||
.position(|n| *n == Node::Operator($operator))
|
let lhs = match nodes.remove(start + operator - 1) {
|
||||||
{
|
Node::Number(n) => n,
|
||||||
let lhs = match nodes.remove(start + index - 1) {
|
n => return Err(Error::InvalidOperand(n)),
|
||||||
Node::Number(n) => n,
|
|
||||||
n => return Err(Error::InvalidOperand(n)),
|
|
||||||
};
|
|
||||||
end -= 1;
|
|
||||||
match nodes.get_mut(start + index) {
|
|
||||||
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + index)),
|
|
||||||
|
|
||||||
Some(Node::Number(n)) => $operator.apply_to(n, lhs),
|
|
||||||
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
|
||||||
};
|
|
||||||
|
|
||||||
nodes.remove(start + index - 1);
|
|
||||||
end -= 1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
end -= 1;
|
||||||
|
match nodes.get_mut(start + operator) {
|
||||||
|
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
|
||||||
|
|
||||||
|
Some(Node::Number(n)) => n.pow_from(lhs),
|
||||||
|
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.remove(start + operator - 1);
|
||||||
|
end -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_operator!(Operator::Exp);
|
while let Some(operator) = nodes[start..end]
|
||||||
collapse_operator!(Operator::Div);
|
.iter()
|
||||||
collapse_operator!(Operator::Mult);
|
.position(|n| *n == Node::Operator(Operator::Div))
|
||||||
collapse_operator!(Operator::Minus);
|
{
|
||||||
collapse_operator!(Operator::Plus);
|
let lhs = match nodes.remove(start + operator - 1) {
|
||||||
|
Node::Number(n) => n,
|
||||||
|
n => return Err(Error::InvalidOperand(n)),
|
||||||
|
};
|
||||||
|
end -= 1;
|
||||||
|
match nodes.get_mut(start + operator) {
|
||||||
|
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
|
||||||
|
|
||||||
|
Some(Node::Number(n)) => n.div_from(lhs),
|
||||||
|
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.remove(start + operator - 1);
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some(operator) = nodes[start..end]
|
||||||
|
.iter()
|
||||||
|
.position(|n| *n == Node::Operator(Operator::Mult))
|
||||||
|
{
|
||||||
|
let lhs = match nodes.remove(start + operator - 1) {
|
||||||
|
Node::Number(n) => n,
|
||||||
|
n => return Err(Error::InvalidOperand(n)),
|
||||||
|
};
|
||||||
|
end -= 1;
|
||||||
|
match nodes.get_mut(start + operator) {
|
||||||
|
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
|
||||||
|
|
||||||
|
Some(Node::Number(n)) => n.mul_from(lhs),
|
||||||
|
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.remove(start + operator - 1);
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some(operator) = nodes[start..end]
|
||||||
|
.iter()
|
||||||
|
.position(|n| *n == Node::Operator(Operator::Minus))
|
||||||
|
{
|
||||||
|
let lhs = match nodes.remove(start + operator - 1) {
|
||||||
|
Node::Number(n) => n,
|
||||||
|
n => return Err(Error::InvalidOperand(n)),
|
||||||
|
};
|
||||||
|
end -= 1;
|
||||||
|
match nodes.get_mut(start + operator) {
|
||||||
|
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
|
||||||
|
|
||||||
|
Some(Node::Number(n)) => n.sub_from(lhs),
|
||||||
|
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.remove(start + operator - 1);
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while let Some(operator) = nodes[start..end]
|
||||||
|
.iter()
|
||||||
|
.position(|n| *n == Node::Operator(Operator::Plus))
|
||||||
|
{
|
||||||
|
let lhs = match nodes.remove(start + operator - 1) {
|
||||||
|
Node::Number(n) => n,
|
||||||
|
n => return Err(Error::InvalidOperand(n)),
|
||||||
|
};
|
||||||
|
end -= 1;
|
||||||
|
match nodes.get_mut(start + operator) {
|
||||||
|
None => return Err(Error::OutOfBounds(Nodes(nodes.clone()), start + operator)),
|
||||||
|
|
||||||
|
Some(Node::Number(n)) => n.add_from(lhs),
|
||||||
|
Some(n) => return Err(Error::InvalidOperand(n.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.remove(start + operator - 1);
|
||||||
|
end -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
if nodes.len() > 1 {
|
if nodes.len() > 1 {
|
||||||
nodes.remove(end);
|
nodes.remove(end);
|
||||||
|
|
@ -127,32 +197,21 @@ fn collapse_toplevel(nodes: &mut Vec<Node>, mut end: usize) -> Result<(), Error>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Operator {
|
|
||||||
fn apply_to(&self, rhs: &mut Float, lhs: Float) {
|
|
||||||
match self {
|
|
||||||
Self::Plus => Float::add_from(rhs, lhs),
|
|
||||||
Self::Minus => Float::sub_from(rhs, lhs),
|
|
||||||
Self::Mult => Float::mul_from(rhs, lhs),
|
|
||||||
Self::Div => Float::div_from(rhs, lhs),
|
|
||||||
Self::Exp => Float::pow_from(rhs, lhs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Function {
|
impl Function {
|
||||||
fn apply_to(&self, n: &mut Float) {
|
fn for_float(&self) -> impl FnMut(&mut Float) {
|
||||||
match self {
|
match self {
|
||||||
Self::Sqrt => Float::sqrt_mut(n),
|
Function::Sqrt => Float::sqrt_mut,
|
||||||
|
|
||||||
Self::Ln => Float::ln_mut(n),
|
Function::Ln => Float::ln_mut,
|
||||||
|
|
||||||
Self::Sine => Float::sin_mut(n),
|
Function::Sine => Float::sin_mut,
|
||||||
Self::ArcSine => Float::asin_mut(n),
|
Function::ArcSine => Float::asin_mut,
|
||||||
Self::Cosine => Float::cos_mut(n),
|
Function::Cosine => Float::cos_mut,
|
||||||
Self::ArcCosine => Float::acos_mut(n),
|
Function::ArcCosine => Float::acos_mut,
|
||||||
Self::Tangent => Float::tan_mut(n),
|
Function::Tangent => Float::tan_mut,
|
||||||
Self::ArcTangent => Float::atan_mut(n),
|
Function::ArcTangent => Float::atan_mut,
|
||||||
Self::Secant => Float::sec_mut(n),
|
Function::Secant => Float::sec_mut,
|
||||||
Self::CoSecant => Float::csc_mut(n),
|
Function::CoSecant => Float::csc_mut,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
use core::f64;
|
use core::f64;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rug::{
|
use rug::{Float, float::ParseFloatError};
|
||||||
Float,
|
|
||||||
float::{self, ParseFloatError},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::nodes::{Function, Node, Nodes, Operator};
|
use crate::nodes::{Function, Node, Nodes, Operator};
|
||||||
|
|
||||||
|
|
@ -13,7 +10,7 @@ impl Node {
|
||||||
Ok(match s {
|
Ok(match s {
|
||||||
"c" => Self::from(299_792_458),
|
"c" => Self::from(299_792_458),
|
||||||
"A" => Self::from(6.02214076e23),
|
"A" => Self::from(6.02214076e23),
|
||||||
"pi" | "π" => Self::from(float::Constant::Pi),
|
"pi" | "π" => Self::from(f64::consts::PI),
|
||||||
// Planck's constant, in J*s (joule-seconds)
|
// Planck's constant, in J*s (joule-seconds)
|
||||||
"h" => Self::from(6.62607015e-34),
|
"h" => Self::from(6.62607015e-34),
|
||||||
"e" => Self::from(f64::consts::E),
|
"e" => Self::from(f64::consts::E),
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,3 @@ fn constant_implicit_mult() {
|
||||||
assert_eq!(eval("2pi"), 6.283185307179586);
|
assert_eq!(eval("2pi"), 6.283185307179586);
|
||||||
assert_eq!(eval("pi2"), 6.283185307179586);
|
assert_eq!(eval("pi2"), 6.283185307179586);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn pi_precision() {
|
|
||||||
assert_eq!(eval("sin(pi)"), 0.)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue