135 lines
3.5 KiB
Rust
135 lines
3.5 KiB
Rust
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,
|
|
}
|
|
} |