feat(maths::evaluator): ast evaluation v1
This commit is contained in:
parent
06a998666f
commit
b92bdf74ee
|
@ -3,9 +3,9 @@ use std::process;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
let _equation = computorv1::parse(&args[1]).unwrap_or_else(|e| {
|
let equation = computorv1::parse(&args[1]).unwrap_or_else(|e| {
|
||||||
println!("Error during parsing: {e}");
|
println!("Error during parsing: {e}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
});
|
});
|
||||||
//computorv1::solve(equation);
|
let evaluated = computorv1::maths::evaluator::evaluate(equation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::ops;
|
use std::ops;
|
||||||
|
|
||||||
|
pub mod evaluator;
|
||||||
|
|
||||||
//TODO slow ? check Stein's algorithm (binaryGCD)
|
//TODO slow ? check Stein's algorithm (binaryGCD)
|
||||||
fn gcd(a: i128, b: i128) -> i128 {
|
fn gcd(a: i128, b: i128) -> i128 {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
use super::*;
|
||||||
|
use crate::parser::Token;
|
||||||
|
use crate::Node;
|
||||||
|
|
||||||
|
fn zero() -> GaussianRational {
|
||||||
|
GaussianRational::new(Rational::new(0, 1), Rational::new(0, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn one() -> GaussianRational {
|
||||||
|
GaussianRational::new(Rational::new(1, 1), Rational::new(0, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
let mut len = lhs.len();
|
||||||
|
if rhs.len() > len {
|
||||||
|
len = rhs.len();
|
||||||
|
}
|
||||||
|
for _ in 0..len {
|
||||||
|
res.push(zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, gr) in lhs.iter().enumerate() {
|
||||||
|
res[i] = res[i] + *gr;
|
||||||
|
}
|
||||||
|
for (i, gr) in rhs.iter().enumerate() {
|
||||||
|
res[i] = res[i] + *gr;
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sub(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
let mut len = lhs.len();
|
||||||
|
if rhs.len() > len {
|
||||||
|
len = rhs.len();
|
||||||
|
}
|
||||||
|
for _ in 0..len {
|
||||||
|
res.push(zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, gr) in lhs.iter().enumerate() {
|
||||||
|
res[i] = res[i] + *gr;
|
||||||
|
}
|
||||||
|
for (i, gr) in rhs.iter().enumerate() {
|
||||||
|
res[i] = res[i] - *gr;
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mul(lhs: Vec<GaussianRational>, rhs: &Vec<GaussianRational>) -> Vec<GaussianRational> {
|
||||||
|
println!("\nIci ca multiplie {:?} et {:?}", lhs, rhs);
|
||||||
|
let len = lhs.len() + rhs.len() - 1;
|
||||||
|
let mut res = Vec::new();
|
||||||
|
for _ in 0..len {
|
||||||
|
res.push(zero());
|
||||||
|
}
|
||||||
|
for (i, lhs) in lhs.iter().enumerate() {
|
||||||
|
for (j, rhs) in rhs.iter().enumerate() {
|
||||||
|
res[i + j] = res[i + j] + *lhs * *rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exp(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> {
|
||||||
|
if rhs.len() != 1 {
|
||||||
|
panic!("Eh t'y es fou mon gate puissance d'inconnu !");
|
||||||
|
}
|
||||||
|
if rhs[0].imaginary.numerator != 0 {
|
||||||
|
panic!("Diablerie une puissance complexe !");
|
||||||
|
}
|
||||||
|
if rhs[0].real.denominator != 1 {
|
||||||
|
panic!("MON DIEU UNE PUISSANCE DE RATIONNEL");
|
||||||
|
}
|
||||||
|
let mut res = Vec::new();
|
||||||
|
let pow = rhs[0].real.numerator;
|
||||||
|
res.push(one());
|
||||||
|
for _ in 0..pow {
|
||||||
|
res = mul(res, &lhs);
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_div(lhs: &Vec<GaussianRational>, rhs: &Vec<GaussianRational>) -> bool {
|
||||||
|
for i in 0..(rhs.len() - 1) {
|
||||||
|
if rhs[i] != zero() || lhs[i] != zero() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn div(lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> {
|
||||||
|
if rhs.len() > lhs.len() {
|
||||||
|
panic!("faut pas diviser par plus grande puissance d'inconnu que sois meme :$");
|
||||||
|
}
|
||||||
|
if !check_div(&lhs, &rhs) {
|
||||||
|
panic!("Moi je sais pas faire heing");
|
||||||
|
}
|
||||||
|
|
||||||
|
let denominator = *rhs.last().unwrap();
|
||||||
|
let len = lhs.len() - rhs.len() + 1;
|
||||||
|
let mut res = Vec::new();
|
||||||
|
for _ in 0..len {
|
||||||
|
res.push(zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in (rhs.len() - 1)..lhs.len() {
|
||||||
|
let res_i = i - (rhs.len() - 1);
|
||||||
|
res[res_i] = lhs[i] / denominator;
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate(operator: Token, lhs: Vec<GaussianRational>, rhs: Vec<GaussianRational>) -> Vec<GaussianRational> {
|
||||||
|
match operator {
|
||||||
|
Token::Addition() => add(lhs, rhs),
|
||||||
|
Token::Substraction() => sub(lhs, rhs),
|
||||||
|
Token::Multiplication() => mul(lhs, &rhs),
|
||||||
|
Token::Division() => div(lhs, rhs),
|
||||||
|
Token::Exponentiation() => exp(lhs, rhs),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn evaluate(ast: Node) -> Vec<GaussianRational> {
|
||||||
|
match ast {
|
||||||
|
Node::Internal { operator, lhs, rhs } => calculate(operator, evaluate(*lhs), evaluate(*rhs)),
|
||||||
|
Node::Leaf(value) => value,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue