diff --git a/src/main.rs b/src/main.rs index 535d588..3167c4d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,9 @@ use std::process; fn main() { let args: Vec = 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}"); process::exit(1); }); - //computorv1::solve(equation); + let evaluated = computorv1::maths::evaluator::evaluate(equation); } diff --git a/src/maths.rs b/src/maths.rs index c537270..58015dd 100644 --- a/src/maths.rs +++ b/src/maths.rs @@ -1,5 +1,7 @@ use std::ops; +pub mod evaluator; + //TODO slow ? check Stein's algorithm (binaryGCD) fn gcd(a: i128, b: i128) -> i128 { if b == 0 { diff --git a/src/maths/evaluator.rs b/src/maths/evaluator.rs new file mode 100644 index 0000000..be6ffdb --- /dev/null +++ b/src/maths/evaluator.rs @@ -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, rhs: Vec) -> Vec { + 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, rhs: Vec) -> Vec { + 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, rhs: &Vec) -> Vec { + 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, rhs: Vec) -> Vec { + 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, rhs: &Vec) -> bool { + for i in 0..(rhs.len() - 1) { + if rhs[i] != zero() || lhs[i] != zero() { + return false + } + } + true +} + +fn div(lhs: Vec, rhs: Vec) -> Vec { + 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, rhs: Vec) -> Vec { + 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 { + match ast { + Node::Internal { operator, lhs, rhs } => calculate(operator, evaluate(*lhs), evaluate(*rhs)), + Node::Leaf(value) => value, + } +} \ No newline at end of file