feat(maths::evaluator): ast evaluation v1

This commit is contained in:
gbrochar 2023-08-06 14:05:28 +02:00
parent 06a998666f
commit b92bdf74ee
3 changed files with 139 additions and 2 deletions

View File

@ -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);
} }

View File

@ -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 {

135
src/maths/evaluator.rs Normal file
View File

@ -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,
}
}