diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index b36fb21..96b204e 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -2,7 +2,6 @@ name: Rust on: push: - branches: [ "mistress" ] pull_request: branches: [ "mistress" ] diff --git a/CHANGELOG.md b/CHANGELOG.md index b4ed4bb..bf69d3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# Version 3.0.0 : Symbolic calculation! +Version 3.0.0, at last! (if you've seen the PR for it it's been sitting for more +than three weeks!) + +Symbolic computation was added you can compute expressions with symbols (such as +x,y,whatever) and more ! + # Version 2.13.2 : Bug fix Fix #43 diff --git a/Cargo.lock b/Cargo.lock index 760f1af..3f3b36e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,7 +221,7 @@ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "mini-calc" -version = "2.13.2" +version = "3.0.0" dependencies = [ "ansi_term", "atty", diff --git a/Cargo.toml b/Cargo.toml index c067829..66bdd89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mini-calc" -version = "2.13.2" +version = "3.0.0" license = "GPL-3.0-or-later" description = "A fully-featured minimalistic configurable rust calculator" homepage = "https://calc.nwa2coco.fr" diff --git a/Makefile b/Makefile index 2833d59..f9d7d19 100644 --- a/Makefile +++ b/Makefile @@ -6,3 +6,5 @@ release: cargo build --release test: cargo test +publish: + cargo publish diff --git a/src/configuration/loader.rs b/src/configuration/loader.rs index f5fd6e7..5417676 100644 --- a/src/configuration/loader.rs +++ b/src/configuration/loader.rs @@ -131,7 +131,7 @@ pub fn load_color(string: String) -> Color { pub fn replace_variable(str: String) -> String { str.replace("%author%", "Charlotte Thomas") - .replace("%version%", "v2.13.2") + .replace("%version%", "v3.0.0") .to_string() } diff --git a/src/exact_math/mod.rs b/src/exact_math/mod.rs index f149e73..aa6bec9 100644 --- a/src/exact_math/mod.rs +++ b/src/exact_math/mod.rs @@ -1 +1,2 @@ pub mod rationals; +pub mod symbolic; diff --git a/src/exact_math/rationals.rs b/src/exact_math/rationals.rs index b833463..61753dd 100644 --- a/src/exact_math/rationals.rs +++ b/src/exact_math/rationals.rs @@ -2,7 +2,7 @@ use std::{fmt::Display, ops}; use crate::utils::integer_utils::gcd; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct Rationals { pub under: i64, pub over: i64, @@ -32,6 +32,17 @@ impl Rationals { return self.over == 0; } + pub fn opposite(self) -> Self { + Rationals::new(self.under, -1 * self.over) + } + + pub fn invert(self) -> Result { + match self.over { + 0 => Err(Rationals::new(0, 1)), + _ => Ok(Rationals::new(self.over, self.under).reduce()), + } + } + pub fn reduce(self) -> Self { let minus; let i1; @@ -84,7 +95,7 @@ impl Rationals { impl Display for Rationals { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let fs = self.clone().reduce(); + let fs = self.reduce(); if fs.under == 1 { write!(f, "{}", fs.over) } else { diff --git a/src/exact_math/symbolic.rs b/src/exact_math/symbolic.rs new file mode 100644 index 0000000..5296d68 --- /dev/null +++ b/src/exact_math/symbolic.rs @@ -0,0 +1,121 @@ +use crate::parsing::ast::Parameters; +use crate::parsing::ast::Parameters::*; + +pub fn size(p: &Parameters) -> i32 { + match p { + Null + | Int(_) + | Str(_) + | Float(_) + | Identifier(_) + | PlusOperation + | MinusOperation + | MultiplicationOperation + | DivideOperation + | Assign + | ExpoOperation + | GreaterOperation + | GreaterOrEqualOperation + | LesserOperation + | LesserOrEqualOperation + | Equal + | Bool(_) + | Rational(_) + | OrOperation + | AndOperation + | Not + | Vector(_) + | InterpreterVector(_) => 0, + Plus(x, y) => 1 + size(x) + size(y), + Var(x, _, _) => 1 + size(x), + Mul(x, y) => 1 + size(x) + size(y), + Div(x, y) => 1 + size(x) + size(y), + } +} + +#[cfg(test)] +mod test { + + use crate::{ + exact_math::rationals::Rationals, + parsing::ast::{ + Ast, + Parameters::{self, *}, + }, + }; + + use super::size; + #[test] + fn test_leaf() { + let v = vec![ + Null, + Int(1), + Str("".to_string()), + Float(1.0), + Identifier("".to_string()), + PlusOperation, + MinusOperation, + MultiplicationOperation, + DivideOperation, + Assign, + ExpoOperation, + GreaterOperation, + GreaterOrEqualOperation, + LesserOperation, + LesserOrEqualOperation, + Equal, + Bool(false), + Rational(Rationals::new(10, 10)), + OrOperation, + AndOperation, + Not, + Vector(Box::from(vec![Ast::Nil])), + InterpreterVector(Box::from(vec![Null])), + ]; + + let should = vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ]; + + let _ = v + .into_iter() + .map(|f| size(&f)) + .zip(should) + .for_each(|(x, y)| assert_eq!(x, y)); + } + + #[test] + fn test_size() { + let should = 2; + let tree = Plus( + Box::from(Plus( + Box::from(Parameters::Int(1)), + Box::from(Parameters::Int(2)), + )), + Box::from(Parameters::Int(3)), + ); + let result = size(&tree); + assert_eq!(result, should); + } + #[test] + fn test_size_mul() { + let should = 2; + let tree = Mul( + Box::from(Plus( + Box::from(Parameters::Int(1)), + Box::from(Parameters::Int(2)), + )), + Box::from(Parameters::Int(3)), + ); + let result = size(&tree); + assert_eq!(result, should); + } + #[test] + fn test_size_var() { + let should = 1; + let tree = Var(Box::from(Parameters::Int(1)), 1, "s".to_string()); + let result = size(&tree); + assert_eq!(result, should); + } +} diff --git a/src/functions/add.rs b/src/functions/add.rs new file mode 100644 index 0000000..fedaaa9 --- /dev/null +++ b/src/functions/add.rs @@ -0,0 +1,538 @@ +use crate::exact_math::rationals::Rationals; +use crate::exact_math::symbolic::size; +use crate::functions::function::apply_operator; +use crate::functions::function::apply_operator_reverse; +use crate::parsing::ast::Parameters::*; +use crate::parsing::ast::*; +use std::collections::HashMap; + +use super::mult::mult; + +pub fn add(i: Parameters, i2: Parameters, ram: Option<&HashMap>) -> Parameters { + match (i, i2) { + (Null, Int(v)) => Int(v), + (Null, Float(f)) => Float(f), + (Null, InterpreterVector(vec)) => InterpreterVector(vec.clone()), + (InterpreterVector(vec), Null) => InterpreterVector(vec.clone()), + (Int(v), Null) => Int(v), + (Float(f), Null) => Float(f), + (Rational(s), Null) => Rational(s.clone()), + (Null, Rational(s)) => Rational(s.clone()), + (Rational(s), Rational(s2)) => Rational(s + s2), + (Rational(s), Int(i)) => Rational(s + Rationals::new(1, i)), + (Int(i), Rational(s)) => Rational(s + Rationals::new(1, i)), + (Rational(s), Float(f)) => Float(s.approx() + f), + (Float(f), Rational(s)) => Float(f + s.approx()), + (Int(v), Int(v2)) => Int(v + v2), + (Int(v), Float(f)) => Float((v as f64) + f), + (Float(v), Float(f)) => Float(v + f), + (Float(v), Int(i1)) => Float(v + (i1 as f64)), + (InterpreterVector(vec), InterpreterVector(vec2)) => { + let mut res = Vec::new(); + vec.into_iter() + .zip(vec2.into_iter()) + .map(|(x, y)| add(x.clone(), y.clone(), ram)) + .for_each(|s| res.push(s)); + InterpreterVector(Box::from(res)) + } + (Bool(_), Int(i)) => Int(i), + (Bool(_), Float(i)) => Float(i), + (Int(i), Bool(_)) => Int(i), + (Float(i), Bool(_)) => Float(i), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + None => { + if s != s2 { + Plus( + Box::from(Identifier(s.clone())), + Box::from(Identifier(s2.clone())), + ) + } else { + Var(Box::from(Int(2)), 1, s.clone()) + } + } + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, add), + }, + (Identifier(s), Int(i)) => match ram { + None => Plus(Box::from(Identifier(s.clone())), Box::from(Int(i))), + Some(_) => apply_operator(Identifier(s), Int(i), ram, add), + }, + (Null, Identifier(s)) => match ram { + None => Identifier(s.clone()), + Some(_) => apply_operator(Identifier(s), Null, ram, add), + }, + (Rational(r), Identifier(ss)) => match ram { + None => Plus(Box::from(Rational(r)), Box::from(Identifier(ss.clone()))), + Some(_) => apply_operator_reverse(Rational(r), Identifier(ss.clone()), ram, add), + }, + (Identifier(ss), Rational(r)) => match ram { + None => Plus(Box::from(Identifier(ss.clone())), Box::from(Rational(r))), + Some(_) => apply_operator(Identifier(ss), Rational(r), ram, add), + }, + (Identifier(s), Null) => match ram { + None => Identifier(s.clone()), + Some(_) => apply_operator(Identifier(s), Null, ram, add), + }, + (Int(i), Identifier(s)) => match ram { + None => Plus(Box::from(Identifier(s)), Box::from(Int(i.clone()))), + Some(_) => apply_operator(Identifier(s), Int(i), ram, add), + }, + (Identifier(s), Float(i)) => match ram { + None => Plus(Box::from(Identifier(s.clone())), Box::from(Float(i))), + Some(_) => apply_operator(Identifier(s), Float(i), ram, add), + }, + (Float(i), Identifier(s)) => match ram { + None => Plus(Box::from(Identifier(s.clone())), Box::from(Float(i))), + Some(_) => apply_operator(Identifier(s), Float(i), ram, add), + }, + (Identifier(s), InterpreterVector(vec)) => match ram { + None => Null, + Some(_) => apply_operator(Identifier(s), InterpreterVector(vec.clone()), ram, add), + }, + (InterpreterVector(vec), Identifier(s)) => match ram { + None => Null, + Some(_) => apply_operator(Identifier(s), InterpreterVector(vec.clone()), ram, add), + }, + (Bool(b), Identifier(s)) => match ram { + None => Null, + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, add), + }, + (Identifier(s), Bool(b)) => match ram { + None => Null, + Some(_) => apply_operator(Identifier(s), Bool(b), ram, add), + }, + (Plus(s1, s2), Plus(s3, s4)) => { + let first = Plus( + Box::from(add(*s1.clone(), *s3.clone(), ram)), + Box::from(add(*s2.clone(), *s4.clone(), ram)), + ); + let second = Plus( + Box::from(add(*s1.clone(), *s4.clone(), ram)), + Box::from(add(*s2.clone(), *s3.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + + if s1 > s2 { + second + } else { + first + } + } + (Plus(s1, s2), Identifier(s3)) => { + let first = Plus( + Box::from(add(*s1.clone(), Identifier(s3.clone()), ram)), + s2.clone(), + ); + let second = Plus( + s1.clone(), + Box::from(add(*s2.clone(), Identifier(s3.clone()), ram)), + ); + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Identifier(s3), Plus(s1, s2)) => { + let first = Plus( + Box::from(add(*s1.clone(), Identifier(s3.clone()), ram)), + s2.clone(), + ); + let second = Plus( + s1.clone(), + Box::from(add(*s2.clone(), Identifier(s3.clone()), ram)), + ); + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Int(i), Plus(s1, s2)) => { + let first = Plus(Box::from(add(*s1.clone(), Int(i), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(add(*s2.clone(), Int(i), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Int(i)) => { + let first = Plus(Box::from(add(*s1.clone(), Int(i), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(add(*s2.clone(), Int(i), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Float(f)) => { + let first = Plus(Box::from(add(*s1.clone(), Float(f), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(add(*s2.clone(), Float(f), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Float(f), Plus(s1, s2)) => { + let first = Plus(Box::from(add(*s1.clone(), Float(f), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(add(*s2.clone(), Float(f), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Rational(r)) => { + let first = Plus(Box::from(add(*s1.clone(), Rational(r), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(add(*s2.clone(), Rational(r), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Rational(r), Plus(s1, s2)) => { + let first = Plus(Box::from(add(*s1.clone(), Rational(r), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(add(*s2.clone(), Rational(r), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Var(x, y, z)) => { + let first = Plus( + Box::from(add(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + s2.clone(), + ); + let second = Plus( + s1.clone(), + Box::from(add(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Var(x, y, z), Plus(s1, s2)) => { + let first = Plus( + Box::from(add(Var(x.clone(), y, z.clone()), *s1.clone(), ram)), + s2.clone(), + ); + let second = Plus( + s1.clone(), + Box::from(add(Var(x.clone(), y, z.clone()), *s2.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Null) => Plus(s1.clone(), s2.clone()), + + (Null, Plus(s1, s2)) => Plus(s1.clone(), s2.clone()), + + (Mul(s1, s2), Mul(s3, s4)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Mul(s3.clone(), s4.clone())), + ), + + (Mul(s1, s2), Identifier(s)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ), + + (Identifier(s), Mul(s1, s2)) => Plus( + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + Box::from(Mul(s1.clone(), s2.clone())), + ), + + (Mul(s1, s2), Int(i)) => Plus(Box::from(Mul(s1.clone(), s2.clone())), Box::from(Int(i))), + + (Int(i), Mul(s1, s2)) => Plus(Box::from(Int(i)), Box::from(Mul(s1.clone(), s2.clone()))), + + (Mul(s1, s2), Float(f)) => { + Plus(Box::from(Mul(s1.clone(), s2.clone())), Box::from(Float(f))) + } + + (Float(f), Mul(s1, s2)) => { + Plus(Box::from(Float(f)), Box::from(Mul(s1.clone(), s2.clone()))) + } + + (Mul(s1, s2), Rational(r)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Rational(r)), + ), + + (Rational(r), Mul(s1, s2)) => Plus( + Box::from(Rational(r)), + Box::from(Mul(s1.clone(), s2.clone())), + ), + + (Var(x, y, z), Mul(s1, s2)) => Plus( + Box::from(Var(x.clone(), y, z.clone())), + Box::from(Mul(s1.clone(), s2.clone())), + ), + + (Mul(s1, s2), Var(x, y, z)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Var(x.clone(), y, z.clone())), + ), + + (Mul(s1, s2), Plus(s3, s4)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Plus(s3.clone(), s4.clone())), + ), + + (Plus(s3, s4), Mul(s1, s2)) => Plus( + Box::from(Plus(s3.clone(), s4.clone())), + Box::from(Mul(s1.clone(), s2.clone())), + ), + + (Null, Mul(s1, s2)) => Mul(s1.clone(), s2.clone()), + + (Mul(s1, s2), Null) => Mul(s1.clone(), s2.clone()), + + (Var(x, y, z), Var(x1, y1, z1)) => { + if z == z1 && y == y1 { + Var(Box::from(add(*x.clone(), *x1.clone(), ram)), y, z) + } else { + Plus( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var(x1.clone(), y1.clone(), z1.clone())), + ) + } + } + + (Var(x, y, z), Identifier(s)) => { + if z == s && y == 1 { + Var(Box::from(add(*x.clone(), Int(1), ram)), y, z) + } else { + Plus( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ) + } + } + + (Identifier(s), Var(x, y, z)) => { + if z == s && y == 1 { + Var(Box::from(add(*x.clone(), Int(1), ram)), y, z) + } else { + Plus( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ) + } + } + + (Int(i), Var(x, y, z)) => Plus(Box::from(Int(i)), Box::from(Var(x, y, z))), + + (Var(x, y, z), Int(i)) => Plus(Box::from(Var(x, y, z)), Box::from(Int(i))), + + (Float(f), Var(x, y, z)) => Plus(Box::from(Float(f)), Box::from(Var(x, y, z))), + + (Var(x, y, z), Float(f)) => Plus(Box::from(Var(x, y, z)), Box::from(Float(f))), + + (Rational(r), Var(x, y, z)) => Plus(Box::from(Rational(r)), Box::from(Var(x, y, z))), + + (Var(x, y, z), Rational(r)) => Plus(Box::from(Var(x, y, z)), Box::from(Rational(r))), + + (Var(x, y, z), Div(s1, s2)) => { + let first = Div( + Box::from(add( + mult(Var(x.clone(), y, z.clone()), *s2.clone(), ram), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Div(s1, s2), Var(x, y, z)) => { + let first = Div( + Box::from(add( + mult(Var(x.clone(), y, z.clone()), *s2.clone(), ram), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Mul(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(add( + mult(*s4.clone(), mult(*s1.clone(), *s2.clone(), ram), ram), + *s3.clone(), + ram, + )), + s4.clone(), + ); + first + } + + (Div(s1, s2), Mul(s3, s4)) => { + let first = Div( + Box::from(add( + mult(*s2.clone(), mult(*s3.clone(), *s4.clone(), ram), ram), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Div(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(add( + mult(*s1.clone(), *s4.clone(), ram), + mult(*s2.clone(), *s3.clone(), ram), + ram, + )), + Box::from(mult(*s2.clone(), *s4.clone(), ram)), + ); + first + } + + (Div(s1, s2), Identifier(s)) => { + let first = Div( + Box::from(add( + mult(*s2.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Identifier(s), Div(s1, s2)) => { + let first = Div( + Box::from(add( + mult(Var(Box::from(Int(1)), 1, s.clone()), *s1.clone(), ram), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Div(s1, s2), Int(i)) => { + let first = Div( + Box::from(add(mult(*s2.clone(), Int(i), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Int(i), Div(s1, s2)) => { + let first = Div( + Box::from(add(mult(Int(i), *s2.clone(), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Div(s1, s2), Float(f)) => { + let first = Div( + Box::from(add(mult(*s2.clone(), Float(f), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Float(f), Div(s1, s2)) => { + let first = Div( + Box::from(add(mult(Float(f), *s2.clone(), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Div(s1, s2), Rational(r)) => { + let first = Div( + Box::from(add(mult(*s2.clone(), Rational(r), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Rational(r), Div(s1, s2)) => { + let first = Div( + Box::from(add(mult(Rational(r), *s2.clone(), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Div(s1, s2), Plus(s3, s4)) => { + let first = Div( + Box::from(add( + *s1.clone(), + mult(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + ram, + )), + s2.clone(), + ); + first + } + + (Plus(s3, s4), Div(s1, s2)) => { + let first = Div( + Box::from(add( + mult(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + *s1.clone(), + ram, + )), + s1.clone(), + ); + first + } + + (Null, Div(s1, s2)) => Div(s1.clone(), s2.clone()), + + (Div(s1, s2), Null) => Div(s1.clone(), s2.clone()), + _ => Identifier("@Those two values are incompatible with the + operator".to_string()), + } +} diff --git a/src/functions/divide.rs b/src/functions/divide.rs new file mode 100644 index 0000000..742e742 --- /dev/null +++ b/src/functions/divide.rs @@ -0,0 +1,636 @@ +use crate::exact_math::rationals::Rationals; +use crate::exact_math::symbolic::size; +use crate::functions::function::apply_operator; +use crate::functions::function::apply_operator_reverse; +use crate::parsing::ast::Parameters::*; +use crate::parsing::ast::*; +use std::collections::HashMap; + +use super::add::add; +use super::mult::mult; + +pub fn divide( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(v)) => Int(v), + (Null, Float(f)) => Float(f), + (Int(v), Null) => Int(v), + (Float(f), Null) => Float(f), + (Int(v), Int(v2)) => Rational(Rationals::new(v2, v)), + (Int(v), Float(f)) => Float((v as f64) / f), + (Float(v), Float(f)) => Float(v / f), + (Float(v), Int(i1)) => Float(v / (i1 as f64)), + (Null, InterpreterVector(vec)) => InterpreterVector(vec.clone()), + (InterpreterVector(vec), Null) => InterpreterVector(vec.clone()), + + (Rational(s), Null) => Rational(Rationals::new(1, 1) / s), + (Null, Rational(s)) => Rational(Rationals::new(1, 1) / s), + (Rational(s), Rational(s2)) => Rational(s / s2), + + (Rational(s), Int(i)) => Rational(s / Rationals::new(1, i)), + (Int(i), Rational(s)) => Rational(Rationals::new(1, i) / s), + (Rational(s), Float(f)) => Float(s.approx() / f), + (Float(f), Rational(s)) => Float(f / s.approx()), + (Bool(_), Int(i)) => Int(i), + (Bool(_), Float(i)) => Float(i), + (Int(i), Bool(_)) => Int(i), + (Float(i), Bool(_)) => Float(i), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, divide), + None => divide( + Var(Box::from(Int(1)), 1, s.clone()), + Var(Box::from(Int(1)), 1, s2.clone()), + ram, + ), + }, + + (Rational(r), Identifier(ss)) => match ram { + Some(_) => apply_operator_reverse(Rational(r), Identifier(ss.clone()), ram, divide), + None => Div( + Box::from(Int(r.over)), + Box::from(Var(Box::from(Int(r.under)), 1, ss.clone())), + ), + }, + (Identifier(ss), Rational(r)) => match ram { + Some(_) => apply_operator(Identifier(ss), Rational(r), ram, divide), + None => match r.invert() { + Ok(r) => Var(Box::from(Rational(r)), 1, ss.clone()), + Err(_) => Null, + }, + }, + + (Identifier(s), Int(i)) => match ram { + None => Var(Box::new(Rational(Rationals::new(i, 1))), 1, s.clone()), + Some(_) => apply_operator(Identifier(s), Int(i), ram, divide), + }, + (Int(i), Identifier(s)) => match ram { + None => Div( + Box::from(Int(i)), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ), + Some(_) => { + let v = apply_operator(Identifier(s.clone()), Int(i), ram, divide); + match v { + Float(i) => Float(1.0 / i), + _ => divide(Int(i), Identifier(s.clone()), None), + } + } + }, + (Null, Identifier(s)) => match ram { + None => Div( + Box::new(Int(1)), + Box::new(Var(Box::new(Int(1)), 1, s.clone())), + ), + Some(_) => apply_operator(Identifier(s), Null, ram, divide), + }, + (Identifier(s), Null) => match ram { + None => Div( + Box::new(Int(1)), + Box::new(Var(Box::new(Int(1)), 1, s.clone())), + ), + Some(_) => apply_operator(Identifier(s), Null, ram, divide), + }, + (Identifier(s), Float(i)) => match ram { + None => Var( + Box::from(Rational(Rationals::rationalize(1.0 / i))), + 1, + s.clone(), + ), + Some(_) => apply_operator(Identifier(s), Float(i), ram, divide), + }, + (Float(i), Identifier(s)) => match ram { + None => Div( + Box::from(Int(Rationals::rationalize(i).over)), + Box::from(Var( + Box::from(Int(Rationals::rationalize(i).under)), + 1, + s.clone(), + )), + ), + Some(_) => { + let v = apply_operator(Identifier(s), Float(i), ram, divide); + match v { + Float(i) => Float(1.0 / i), + _ => Null, + } + } + }, + (Bool(b), Identifier(s)) => match ram { + None => Bool(b), + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, divide), + }, + (Identifier(s), Bool(b)) => match ram { + None => Bool(b), + Some(_) => apply_operator(Identifier(s), Bool(b), ram, divide), + }, + (Plus(s1, s2), Plus(s3, s4)) => { + let first = add( + divide(*s1.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + divide(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + ram, + ); + first + } + (Plus(s1, s2), Identifier(s3)) => { + let first = add( + divide(*s1.clone(), Var(Box::from(Int(1)), 1, s3.clone()), ram), + divide(*s2.clone(), Var(Box::from(Int(1)), 1, s3.clone()), ram), + ram, + ); + first + } + + (Identifier(s3), Plus(s1, s2)) => { + let first = Div( + Box::from(Var(Box::new(Int(1)), 1, s3.clone())), + Box::from(add(*s1.clone(), *s2.clone(), ram)), + ); + first + } + (Int(i), Plus(s1, s2)) => { + let first = Div( + Box::from(Int(i)), + Box::from(add(*s1.clone(), *s2.clone(), ram)), + ); + first + } + + (Plus(s1, s2), Int(i)) => { + let first = add( + divide(*s1.clone(), Int(i), ram), + divide(*s2.clone(), Int(i), ram), + ram, + ); + first + } + + (Float(f), Plus(s1, s2)) => { + let first = Div( + Box::from(Float(f)), + Box::from(add(*s1.clone(), *s2.clone(), ram)), + ); + first + } + + (Plus(s1, s2), Float(f)) => { + let first = add( + divide(*s1.clone(), Float(f), ram), + divide(*s2.clone(), Float(f), ram), + ram, + ); + first + } + (Rational(r), Plus(s1, s2)) => { + let first = Div( + Box::from(Rational(r)), + Box::from(add(*s1.clone(), *s2.clone(), ram)), + ); + first + } + + (Plus(s1, s2), Rational(r)) => { + let first = add( + divide(*s1.clone(), Rational(r), ram), + divide(*s2.clone(), Rational(r), ram), + ram, + ); + first + } + (Var(x, y, z), Plus(s1, s2)) => Div( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(add(*s1.clone(), *s2.clone(), ram)), + ), + + (Plus(s1, s2), Var(x, y, z)) => add( + divide(*s1.clone(), Var(x.clone(), y, z.clone()), ram), + divide(*s2.clone(), Var(x.clone(), y, z.clone()), ram), + ram, + ), + + (Null, Plus(s1, s2)) => add(*s1.clone(), *s2.clone(), ram), + + (Plus(s1, s2), Null) => add(*s1.clone(), *s2.clone(), ram), + + (Var(x, y, z), Mul(s1, s2)) => { + let first = mult( + divide(Var(x.clone(), y, z.clone()), *s1.clone(), ram), + divide(Int(1), *s2.clone(), ram), + ram, + ); + let second = mult( + divide(Int(1), *s1.clone(), ram), + divide(Var(x.clone(), y, z.clone()), *s2.clone(), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Var(x, y, z)) => { + let first = mult( + divide(*s1.clone(), Var(x.clone(), y, z.clone()), ram), + *s2.clone(), + ram, + ); + let second = mult( + *s1.clone(), + divide(*s2.clone(), Var(x.clone(), y, z.clone()), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Mul(s3, s4)) => { + let first = mult( + divide(*s1.clone(), mult(*s3.clone(), *s4.clone(), ram), ram), + *s2.clone(), + ram, + ); + let second = mult( + *s1.clone(), + divide(*s2.clone(), mult(*s3.clone(), *s4.clone(), ram), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Identifier(s)) => { + let first = mult( + divide(*s1.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram), + *s2.clone(), + ram, + ); + let second = mult( + *s1.clone(), + divide(*s2.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Identifier(s), Mul(s1, s2)) => { + let first = mult( + divide(Var(Box::from(Int(1)), 1, s.clone()), *s1.clone(), ram), + divide(Int(1), *s2.clone(), ram), + ram, + ); + let second = mult( + divide(Int(1), *s1.clone(), ram), + divide(Var(Box::from(Int(1)), 1, s.clone()), *s2.clone(), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Int(i)) => { + let first = mult(divide(*s1.clone(), Int(i), ram), *s2.clone(), ram); + let second = mult(*s1.clone(), divide(*s2.clone(), Int(i), ram), ram); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Int(i), Mul(s1, s2)) => { + let first = mult( + divide(Int(i), *s1.clone(), ram), + divide(Int(1), *s2.clone(), ram), + ram, + ); + let second = mult( + divide(Int(1), *s1.clone(), ram), + divide(Int(i), *s2.clone(), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Float(f)) => { + let first = mult(divide(*s1.clone(), Float(f), ram), *s2.clone(), ram); + let second = mult(*s1.clone(), divide(*s2.clone(), Float(f), ram), ram); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Float(f), Mul(s1, s2)) => { + let first = mult( + divide(Float(f), *s1.clone(), ram), + divide(Int(1), *s2.clone(), ram), + ram, + ); + let second = mult( + divide(Int(1), *s1.clone(), ram), + divide(Float(f), *s2.clone(), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Rational(r)) => { + let first = mult(divide(*s1.clone(), Rational(r), ram), *s2.clone(), ram); + let second = mult(*s1.clone(), divide(*s2.clone(), Rational(r), ram), ram); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Rational(r), Mul(s1, s2)) => { + let first = mult( + divide(Rational(r), *s1.clone(), ram), + divide(Int(1), *s2.clone(), ram), + ram, + ); + let second = mult( + divide(Int(1), *s1.clone(), ram), + divide(Rational(r), *s2.clone(), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Plus(s3, s4)) => { + let first = mult( + divide(*s1.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + divide(Int(1), *s2.clone(), ram), + ram, + ); + let second = mult( + divide(Int(1), *s1.clone(), ram), + divide(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + ram, + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Plus(s3, s4), Mul(s1, s2)) => { + let first = add( + divide(*s3.clone(), mult(*s1.clone(), *s2.clone(), ram), ram), + divide(*s4.clone(), mult(*s1.clone(), *s2.clone(), ram), ram), + ram, + ); + first + } + + (Null, Mul(s1, s2)) => mult(*s1.clone(), *s2.clone(), ram), + + (Mul(s1, s2), Null) => mult(*s1.clone(), *s2.clone(), ram), + + (Var(x, y, z), Var(x1, y1, z1)) => { + if z == z1 { + Var(Box::from(divide(*x.clone(), *x1.clone(), ram)), y - y1, z) + } else { + Div( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var( + Box::from(divide(Int(1), *x1.clone(), ram)), + y1.clone(), + z1.clone(), + )), + ) + } + } + + (Var(x, y, z), Identifier(s)) => { + if z == s { + Var(Box::from(x.clone()), y - 1, z) + } else { + Div( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ) + } + } + + (Identifier(s), Var(x, y, z)) => { + if z == s { + Var(Box::from(divide(Int(1), *x.clone(), ram)), 1 - y, z) + } else { + Div( + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + Box::from(Var( + Box::from(mult(Int(1), *x.clone(), ram)), + y.clone(), + z.clone(), + )), + ) + } + } + + (Int(i), Var(x, y, z)) => Var(Box::from(divide(Int(i), *x.clone(), ram)), -y, z.clone()), + + (Var(x, y, z), Int(i)) => Var(Box::from(divide(*x.clone(), Int(i), ram)), y, z.clone()), + + (Float(f), Var(x, y, z)) => { + Var(Box::from(divide(Float(f), *x.clone(), ram)), -y, z.clone()) + } + + (Var(x, y, z), Float(f)) => Var(Box::from(divide(*x.clone(), Float(f), ram)), y, z.clone()), + + (Rational(r), Var(x, y, z)) => Var( + Box::from(divide(Rational(r), *x.clone(), ram)), + -y, + z.clone(), + ), + + (Var(x, y, z), Rational(r)) => Var( + Box::from(divide(*x.clone(), Rational(r), ram)), + y, + z.clone(), + ), + + (Var(x, y, z), Div(s1, s2)) => { + let first = Div( + Box::from(mult(Var(x.clone(), y, z.clone()), *s2.clone(), ram)), + s1.clone(), + ); + first + } + + (Div(s1, s2), Var(x, y, z)) => { + let first = Div( + s1.clone(), + Box::from(mult(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ); + first + } + + (Mul(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(mult(*s4.clone(), mult(*s1.clone(), *s2.clone(), ram), ram)), + s3.clone(), + ); + first + } + + (Div(s1, s2), Mul(s3, s4)) => { + let first = Div( + s1.clone(), + Box::from(mult(*s2.clone(), mult(*s3.clone(), *s4.clone(), ram), ram)), + ); + first + } + + (Div(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(mult(*s1.clone(), *s4.clone(), ram)), + Box::from(mult(*s2.clone(), *s3.clone(), ram)), + ); + first + } + + (Div(s1, s2), Identifier(s)) => { + let first = Div( + s1.clone(), + Box::from(mult(*s2.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram)), + ); + first + } + + (Identifier(s), Div(s1, s2)) => { + let first = Div( + Box::from(mult(Var(Box::from(Int(1)), 1, s.clone()), *s2.clone(), ram)), + s1.clone(), + ); + first + } + + (Div(s1, s2), Int(i)) => { + let first = Div(s1.clone(), Box::from(mult(*s2.clone(), Int(i), ram))); + first + } + + (Int(i), Div(s1, s2)) => { + let first = Div(Box::from(mult(Int(i), *s2.clone(), ram)), s1.clone()); + first + } + + (Div(s1, s2), Float(f)) => { + let first = Div(s1.clone(), Box::from(mult(*s2.clone(), Float(f), ram))); + first + } + + (Float(f), Div(s1, s2)) => { + let first = Div(Box::from(mult(Float(f), *s2.clone(), ram)), s1.clone()); + first + } + + (Div(s1, s2), Rational(r)) => { + let first = Div( + Box::from(mult(*s1.clone(), Int(r.under), ram)), + Box::from(mult(*s2.clone(), Int(r.over), ram)), + ); + first + } + + (Rational(r), Div(s1, s2)) => { + let first = Div( + Box::from(mult(Int(r.under), *s2.clone(), ram)), + Box::from(mult(*s1.clone(), Int(r.over), ram)), + ); + first + } + + (Div(s1, s2), Plus(s3, s4)) => { + let first = Div( + Box::from(mult(*s1.clone(), add(*s3.clone(), *s4.clone(), ram), ram)), + s2.clone(), + ); + first + } + + (Plus(s3, s4), Div(s1, s2)) => { + let first = Div( + Box::from(mult(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram)), + s1.clone(), + ); + first + } + + (Null, Div(s1, s2)) => divide(*s2.clone(), *s1.clone(), ram), + + (Div(s1, s2), Null) => divide(*s2.clone(), *s1.clone(), ram), + _ => Identifier("@Those two values are incompatible with the / operator".to_string()), + } +} diff --git a/src/functions/expo.rs b/src/functions/expo.rs new file mode 100644 index 0000000..f2b3c4c --- /dev/null +++ b/src/functions/expo.rs @@ -0,0 +1,86 @@ +use crate::functions::function::apply_operator; +use crate::functions::function::apply_operator_reverse; +use crate::parsing::ast::Parameters; +use crate::parsing::ast::Parameters::*; +use std::collections::HashMap; + +pub fn expo( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(v)) => Int(v), + (Null, Float(f)) => Float(f), + (Int(v), Null) => Int(v), + (Float(f), Null) => Float(f), + (Int(v), Int(v2)) => Float((v as f64).powf(v2 as f64)), + (Int(v), Float(f)) => Float((v as f64).powf(f)), + (Float(v), Float(f)) => Float(v.powf(f)), + (Float(v), Int(i1)) => Float(v.powf(i1 as f64)), + + (Rational(s), Null) => Rational(s.clone()), + (Null, Rational(s)) => Rational(s.clone()), + (Rational(s), Rational(s2)) => Float(s.approx().powf(s2.approx())), + (Rational(s), Int(i)) => Float(s.approx().powf(i as f64)), + (Int(i), Rational(s)) => Float((i as f64).powf(s.approx())), + (Rational(s), Float(f)) => Float(s.approx().powf(f)), + (Float(f), Rational(s)) => Float(f.powf(s.approx())), + (Bool(_), Int(i)) => Int(i), + (Bool(_), Float(i)) => Float(i), + (Int(i), Bool(_)) => Int(i), + (Float(i), Bool(_)) => Float(i), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + None => Identifier(s), + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, expo), + }, + (Identifier(s), Int(i)) => match ram { + None => Int(i), + Some(_) => apply_operator(Identifier(s), Int(i), ram, expo), + }, + (Int(i), Identifier(s)) => match ram { + None => Int(i), + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, expo), + }, + (Identifier(s), Float(i)) => match ram { + None => Float(i), + Some(_) => apply_operator(Identifier(s), Float(i), ram, expo), + }, + + (Rational(s), Identifier(ss)) => match ram { + None => Rational(s), + Some(_) => { + apply_operator_reverse(Rational(s.clone()), Identifier(ss.clone()), ram, expo) + } + }, + (Identifier(ss), Rational(s)) => match ram { + None => Rational(s), + Some(_) => apply_operator(Identifier(ss), Rational(s), ram, expo), + }, + (Identifier(s), Null) => match ram { + None => Null, + Some(_) => apply_operator(Identifier(s), Null, ram, expo), + }, + (Null, Identifier(s)) => match ram { + None => Null, + Some(_) => apply_operator(Identifier(s), Null, ram, expo), + }, + (Float(i), Identifier(s)) => match ram { + None => Float(i), + Some(_) => apply_operator_reverse(Float(i), Identifier(s), ram, expo), + }, + (Bool(b), Identifier(s)) => match ram { + None => Bool(b), + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, expo), + }, + (Identifier(s), Bool(b)) => match ram { + None => Bool(b), + Some(_) => apply_operator(Identifier(s), Bool(b), ram, expo), + }, + + _ => Identifier("@Those two values are incompatible with the ^ operator".to_string()), + } +} diff --git a/src/functions/function.rs b/src/functions/function.rs new file mode 100644 index 0000000..c51daf0 --- /dev/null +++ b/src/functions/function.rs @@ -0,0 +1,666 @@ +use std::collections::HashMap; + +use crate::exact_math::rationals::Rationals; + +use crate::parsing::ast::Parameters; +use crate::parsing::ast::Parameters::*; + +pub fn apply_operator( + value: Parameters, + value2: Parameters, + ram: Option<&HashMap>, + f: fn(Parameters, Parameters, Option<&HashMap>) -> Parameters, +) -> Parameters { + let s = match value { + Identifier(ref s) => s, + _ => "", + }; + if s == "" { + return Null; + } + match ram { + None => f(value.clone(), value2.clone(), None), + Some(i_ram) => { + let values = i_ram.get(s); + match values { + None => f(value.clone(), value2.clone(), None), + Some(val) => f(val.clone(), value2.clone(), ram), + } + } + } +} + +pub fn apply_operator_reverse( + value: Parameters, + value2: Parameters, + ram: Option<&HashMap>, + f: fn(Parameters, Parameters, Option<&HashMap>) -> Parameters, +) -> Parameters { + let s = match value2 { + Identifier(ref s) => s, + _ => "", + }; + if s == "" { + return Null; + } + match ram { + None => f(value.clone(), value2.clone(), None), + Some(i_ram) => { + let val3 = i_ram.get(s); + match val3 { + None => f(value.clone(), value2.clone(), None), + Some(val) => f(value.clone(), val.clone(), ram), + } + } + } +} + +pub fn assign(s: Parameters, s2: Parameters) -> (String, Parameters) { + match s { + Identifier(s) => (s, s2), + _ => ("".to_string(), s2), + } +} + +pub fn greater( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(_)) => Bool(true), + (Null, Float(_)) => Bool(true), + (Int(_), Null) => Bool(true), + (Float(_), Null) => Bool(true), + (Int(v), Int(v2)) => Bool(v > v2), + (Int(v), Float(f)) => Bool((v as f64) > f), + (Float(v), Float(f)) => Bool(v > f), + (Float(v), Int(i1)) => Bool(v > (i1 as f64)), + (Rational(_), Null) => Bool(true), + (Null, Rational(_)) => Bool(true), + (Rational(s), Rational(s2)) => Bool(s > s2), + (Rational(s), Int(i)) => Bool(s > Rationals::new(1, i)), + (Int(i), Rational(s)) => Bool(Rationals::new(1, i) > s), + (Rational(s), Float(f)) => Bool(s.approx() > f), + (Float(f), Rational(s)) => Bool(f > s.approx()), + (Bool(b), Int(_)) => Bool(b), + (Bool(b), Float(_)) => Bool(b), + (Int(_), Bool(b)) => Bool(b), + (Float(_), Bool(b)) => Bool(b), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + None => Identifier(s), + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, greater), + }, + + (Rational(s), Identifier(ss)) => match ram { + None => Rational(s), + Some(_) => apply_operator_reverse(Rational(s), Identifier(ss.clone()), ram, greater), + }, + (Identifier(ss), Rational(s)) => match ram { + Some(_) => apply_operator(Identifier(ss), Rational(s), ram, greater), + None => Rational(s), + }, + (Identifier(s), Int(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Int(i), ram, greater), + None => Int(i), + }, + (Null, Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, greater), + None => Identifier(s), + }, + (Identifier(s), Null) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, greater), + None => Identifier(s), + }, + (Int(i), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, greater), + None => Int(i), + }, + (Identifier(s), Float(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Float(i), ram, greater), + None => Float(i), + }, + (Float(i), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Float(i), Identifier(s), ram, greater), + None => Float(i), + }, + (Bool(b), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, greater), + None => Bool(b), + }, + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, greater), + None => Bool(b), + }, + _ => Identifier("@Those two values are incompatible with the > operator".to_string()), + } +} + +pub fn lesser( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(_)) => Bool(false), + (Null, Float(_)) => Bool(false), + (Int(_), Null) => Bool(false), + (Float(_), Null) => Bool(false), + (Int(v), Int(v2)) => Bool(v < v2), + (Int(v), Float(f)) => Bool((v as f64) < f), + (Float(v), Float(f)) => Bool(v < f), + (Float(v), Int(i1)) => Bool(v < (i1 as f64)), + (Rational(_), Null) => Bool(true), + (Null, Rational(_)) => Bool(true), + (Rational(s), Rational(s2)) => Bool(s < s2), + (Rational(s), Int(i)) => Bool(s < Rationals::new(1, i)), + (Int(i), Rational(s)) => Bool(Rationals::new(1, i) < s), + (Rational(s), Float(f)) => Bool(s.approx() < f), + (Float(f), Rational(s)) => Bool(f < s.approx()), + (Bool(b), Int(_)) => Bool(b), + (Bool(b), Float(_)) => Bool(b), + (Int(_), Bool(b)) => Bool(b), + (Float(_), Bool(b)) => Bool(b), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + None => Identifier(s), + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, lesser), + }, + (Identifier(s), Int(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Int(i), ram, lesser), + None => Int(i), + }, + (Null, Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, lesser), + None => Identifier(s), + }, + (Rational(s), Identifier(ss)) => match ram { + Some(_) => apply_operator_reverse(Rational(s), Identifier(ss.clone()), ram, lesser), + None => Rational(s), + }, + (Identifier(ss), Rational(s)) => match ram { + Some(_) => apply_operator(Identifier(ss), Rational(s), ram, lesser), + None => Rational(s), + }, + (Identifier(s), Null) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, lesser), + None => Identifier(s), + }, + (Int(i), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, lesser), + None => Int(i), + }, + (Identifier(s), Float(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Float(i), ram, lesser), + None => Float(i), + }, + (Float(i), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Float(i), Identifier(s), ram, lesser), + None => Float(i), + }, + (Bool(b), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, lesser), + None => Bool(b), + }, + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, lesser), + None => Bool(b), + }, + _ => Identifier("@Those two values are incompatible with the < operator".to_string()), + } +} + +pub fn greater_or_equal( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(_)) => Bool(true), + (Null, Float(_)) => Bool(true), + (Int(_), Null) => Bool(true), + (Float(_), Null) => Bool(true), + (Int(v), Int(v2)) => Bool(v >= v2), + (Int(v), Float(f)) => Bool((v as f64) >= f), + (Float(v), Float(f)) => Bool(v >= f), + (Float(v), Int(i1)) => Bool(v >= (i1 as f64)), + (Bool(b), Int(_)) => Bool(b), + (Bool(b), Float(_)) => Bool(b), + (Int(_), Bool(b)) => Bool(b), + (Float(_), Bool(b)) => Bool(b), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b == b2), + + (Rational(_), Null) => Bool(true), + (Null, Rational(_)) => Bool(true), + (Rational(s), Rational(s2)) => Bool(s >= s2), + (Rational(s), Int(i)) => Bool(s >= Rationals::new(1, i)), + (Int(i), Rational(s)) => Bool(Rationals::new(1, i) >= s), + (Rational(s), Float(f)) => Bool(s.approx() >= f), + (Float(f), Rational(s)) => Bool(f >= s.approx()), + (Identifier(s), Identifier(s2)) => match ram { + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, greater_or_equal), + None => Identifier(s), + }, + (Identifier(s), Int(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Int(i), ram, greater_or_equal), + None => Int(i), + }, + (Null, Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, greater_or_equal), + None => Identifier(s), + }, + (Identifier(s), Null) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, greater_or_equal), + None => Identifier(s), + }, + (Rational(s), Identifier(ss)) => match ram { + Some(_) => { + apply_operator_reverse(Rational(s), Identifier(ss.clone()), ram, greater_or_equal) + } + None => Rational(s), + }, + (Identifier(ss), Rational(s)) => match ram { + None => Rational(s), + Some(_) => apply_operator(Identifier(ss), Rational(s), ram, greater_or_equal), + }, + (Int(i), Identifier(s)) => match ram { + None => Int(i), + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, greater_or_equal), + }, + (Identifier(s), Float(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Float(i), ram, greater_or_equal), + None => Float(i), + }, + (Float(i), Identifier(s)) => match ram { + None => Float(i), + Some(_) => apply_operator_reverse(Float(i), Identifier(s), ram, greater_or_equal), + }, + (Bool(b), Identifier(s)) => match ram { + None => Bool(b), + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, greater_or_equal), + }, + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, greater_or_equal), + None => Bool(b), + }, + _ => Identifier("@Those two values are incompatible with the >= operator".to_string()), + } +} + +pub fn lesser_or_equal( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(_)) => Bool(false), + (Null, Float(_)) => Bool(false), + (Int(_), Null) => Bool(false), + (Float(_), Null) => Bool(false), + (Int(v), Int(v2)) => Bool(v <= v2), + (Int(v), Float(f)) => Bool((v as f64) <= f), + (Float(v), Float(f)) => Bool(v <= f), + (Float(v), Int(i1)) => Bool(v <= (i1 as f64)), + (Bool(b), Int(_)) => Bool(b), + (Bool(b), Float(_)) => Bool(b), + (Int(_), Bool(b)) => Bool(b), + (Float(_), Bool(b)) => Bool(b), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b == b2), + + (Rational(_), Null) => Bool(true), + (Null, Rational(_)) => Bool(true), + (Rational(s), Rational(s2)) => Bool(s <= s2), + (Rational(s), Int(i)) => Bool(s <= Rationals::new(1, i)), + (Int(i), Rational(s)) => Bool(Rationals::new(1, i) <= s), + (Rational(s), Float(f)) => Bool(s.approx() <= f), + (Float(f), Rational(s)) => Bool(f <= s.approx()), + (Identifier(s), Identifier(s2)) => match ram { + None => Identifier(s), + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, lesser_or_equal), + }, + (Identifier(s), Int(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Int(i), ram, lesser_or_equal), + None => Int(i), + }, + (Rational(s), Identifier(ss)) => match ram { + Some(_) => { + apply_operator_reverse(Rational(s), Identifier(ss.clone()), ram, lesser_or_equal) + } + None => Rational(s), + }, + (Identifier(ss), Rational(s)) => match ram { + None => Rational(s), + Some(_) => apply_operator(Identifier(ss), Rational(s), ram, lesser_or_equal), + }, + (Null, Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, lesser_or_equal), + None => Identifier(s), + }, + (Identifier(s), Null) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, lesser_or_equal), + None => Identifier(s), + }, + (Int(i), Identifier(s)) => match ram { + None => Int(i), + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, lesser_or_equal), + }, + (Identifier(s), Float(i)) => match ram { + None => Float(i), + Some(_) => apply_operator(Identifier(s), Float(i), ram, lesser_or_equal), + }, + (Float(i), Identifier(s)) => match ram { + None => Float(i), + Some(_) => apply_operator_reverse(Float(i), Identifier(s), ram, lesser_or_equal), + }, + (Bool(b), Identifier(s)) => match ram { + None => Bool(b), + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, lesser_or_equal), + }, + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, lesser_or_equal), + None => Bool(b), + }, + _ => Identifier("@Those two values are incompatible with the <= operator".to_string()), + } +} + +pub fn equal( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(_)) => Bool(true), + (Null, Float(_)) => Bool(true), + (Int(_), Null) => Bool(true), + (Float(_), Null) => Bool(true), + (Int(v), Int(v2)) => Bool(v == v2), + (Int(v), Float(f)) => Bool((v as f64) == f), + (Float(v), Float(f)) => Bool(v == f), + (Float(v), Int(i1)) => Bool(v == (i1 as f64)), + (Bool(_), Int(_)) => Bool(false), + (Bool(_), Float(_)) => Bool(false), + (Int(_), Bool(_)) => Bool(false), + (Float(_), Bool(_)) => Bool(false), + (Bool(_), Null) => Bool(false), + (Null, Bool(_)) => Bool(false), + (Bool(b), Bool(b2)) => Bool(b == b2), + + (Rational(_), Null) => Bool(true), + (Null, Rational(_)) => Bool(true), + (Rational(s), Rational(s2)) => Bool(s == s2), + (Rational(s), Int(i)) => Bool(s == Rationals::new(1, i)), + (Int(i), Rational(s)) => Bool(Rationals::new(1, i) == s), + (Rational(s), Float(f)) => Bool(s.approx() == f), + (Float(f), Rational(s)) => Bool(f == s.approx()), + (Identifier(s), Identifier(s2)) => match ram { + None => Identifier(s), + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, equal), + }, + (Identifier(s), Int(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Int(i), ram, equal), + None => Int(i), + }, + (Null, Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, equal), + None => Identifier(s), + }, + (Identifier(s), Null) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, equal), + None => Identifier(s), + }, + (Int(i), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, equal), + None => Int(i), + }, + (Identifier(s), Float(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Float(i), ram, equal), + None => Float(i), + }, + (Float(i), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Float(i), Identifier(s), ram, equal), + None => Float(i), + }, + (Bool(b), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, equal), + None => Bool(b), + }, + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, equal), + None => Bool(b), + }, + + (Rational(s), Identifier(ss)) => match ram { + None => Rational(s), + Some(_) => apply_operator_reverse(Rational(s), Identifier(ss.clone()), ram, equal), + }, + (Identifier(ss), Rational(s)) => match ram { + Some(_) => apply_operator(Identifier(ss), Rational(s), ram, equal), + None => Rational(s), + }, + + _ => Identifier("@Those two values are incompatible with the == operator".to_string()), + } +} + +pub fn not( + i: Parameters, + _i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match i { + Bool(b) => Bool(!b), + Identifier(s) => match ram { + None => Bool(false), + Some(_) => apply_operator(Identifier(s), Null, ram, not), + }, + _ => Bool(false), + } +} + +pub fn and(i: Parameters, i2: Parameters, ram: Option<&HashMap>) -> Parameters { + match (i, i2) { + (Bool(b), Bool(b2)) => Bool(b && b2), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, and), + None => Bool(b), + }, + (Bool(b), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, and), + None => Bool(b), + }, + (Identifier(s), Identifier(s2)) => match ram { + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, and), + None => Bool(false), + }, + _ => Bool(false), + } +} + +pub fn or(i: Parameters, i2: Parameters, ram: Option<&HashMap>) -> Parameters { + match (i, i2) { + (Bool(b), Bool(b2)) => Bool(b || b2), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, or), + None => Bool(b), + }, + (Bool(b), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, or), + None => Bool(b), + }, + (Identifier(s), Identifier(s2)) => match ram { + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, or), + None => Bool(false), + }, + _ => Bool(false), + } +} + +#[cfg(test)] +mod test { + use crate::functions::add::add; + use crate::functions::divide::divide; + use crate::functions::minus::minus; + use crate::functions::mult::mult; + use crate::parsing::ast::Parameters::*; + + #[test] + pub fn test_add_null() { + let expected = Int(1); + let result = add(Int(1), Null, None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_add_simple() { + let expected = Int(2); + let result = add(Int(1), Int(1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_add_float() { + let expected = Float(2.1); + let result = add(Float(0.1), Float(2.0), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_add_int_float() { + let expected = Float(2.1); + let result = add(Int(2), Float(0.1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_add_float_int() { + let expected = Float(2.1); + let result = add(Float(0.1), Int(2), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_minus_null() { + let expected = Int(-1); + let result = minus(Int(1), Null, None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_minus_null_rev() { + let expected = Int(-1); + let result = minus(Null, Int(1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_minus_simple() { + let expected = Int(0); + let result = minus(Int(1), Int(1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_minus_float() { + let expected = Float(1.9); + let result = minus(Float(2.0), Float(0.1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_minus_int_float() { + let expected = Float(1.9); + let result = minus(Int(2), Float(0.1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_minus_float_int() { + let expected = Float(-1.9); + let result = minus(Float(0.1), Int(2), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_mult_null() { + let expected = Int(1); + let result = mult(Int(1), Null, None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_mult_simple() { + let expected = Int(2); + let result = mult(Int(1), Int(2), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_mult_float() { + let expected = Float(0.2); + let result = mult(Float(0.1), Float(2.0), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_mult_int_float() { + let expected = Float(0.2); + let result = mult(Int(2), Float(0.1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_mult_float_int() { + let expected = Float(0.2); + let result = mult(Float(0.1), Int(2), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_divide_null() { + let expected = Int(1); + let result = divide(Int(1), Null, None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_divide_simple() { + let expected = Rational(crate::exact_math::rationals::Rationals { under: 1, over: 1 }); + let result = divide(Int(1), Int(1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_divide_float() { + let expected = Float(0.05); + let result = divide(Float(0.1), Float(2.0), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_divide_int_float() { + let expected = Float(20.0); + let result = divide(Int(2), Float(0.1), None); + assert_eq!(result, expected); + } + + #[test] + pub fn test_divide_float_int() { + let expected = Float(0.05); + let result = divide(Float(0.1), Int(2), None); + assert_eq!(result, expected); + } +} diff --git a/src/functions/minus.rs b/src/functions/minus.rs new file mode 100644 index 0000000..e8fd64a --- /dev/null +++ b/src/functions/minus.rs @@ -0,0 +1,644 @@ +use crate::exact_math::rationals::Rationals; +use crate::exact_math::symbolic::size; +use crate::functions::function::apply_operator; +use crate::functions::function::apply_operator_reverse; +use crate::parsing::ast::Parameters; +use crate::parsing::ast::Parameters::*; +use std::collections::HashMap; + +use super::add::add; +use super::divide::divide; +use super::mult::mult; + +pub fn minus( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(v)) => Int(-v), + (Null, Float(f)) => Float(-f), + (Int(v), Null) => Int(-v), + (Float(f), Null) => Float(-f), + (Int(v), Int(v2)) => Int(v - v2), + + (Rational(s), Null) => Rational(Rationals::new(1, 0) - s), + + (Null, Rational(s)) => Rational(s.opposite()), + (Rational(s), Rational(s2)) => Rational(s - s2), + (Rational(s), Int(i)) => Rational(s - Rationals::new(1, i)), + (Int(i), Rational(s)) => Rational(Rationals::new(1, i) - s), + (Rational(s), Float(f)) => Float(s.approx() - f), + (Float(f), Rational(s)) => Float(f - s.approx()), + (InterpreterVector(vec), Null) => { + let mut res = Vec::new(); + vec.into_iter() + .map(|x| minus(Null, x.clone(), ram)) + .for_each(|z| res.push(z)); + InterpreterVector(Box::from(res)) + } + + (Null, InterpreterVector(vec)) => { + let mut res = Vec::new(); + vec.into_iter() + .map(|x| minus(Null, x.clone(), ram)) + .for_each(|z| res.push(z)); + InterpreterVector(Box::from(res)) + } + + (InterpreterVector(vec), InterpreterVector(vec2)) => { + let mut res = Vec::new(); + vec.into_iter() + .zip(vec2.into_iter()) + .map(|(x, y)| minus(x.clone(), y.clone(), ram)) + .for_each(|z| res.push(z)); + InterpreterVector(Box::from(res)) + } + (Int(v), Float(f)) => Float((v as f64) - f), + (Float(v), Float(f)) => Float(v - f), + (Float(v), Int(i1)) => Float(v - (i1 as f64)), + + (Bool(_), Int(i)) => Int(i), + (Bool(_), Float(i)) => Float(i), + (Int(i), Bool(_)) => Int(i), + (Float(i), Bool(_)) => Float(i), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + None => { + if s != s2 { + Plus( + Box::from(Var(Box::from(Int(1)), 1, s)), + Box::from(Var(Box::from(Int(-1)), 1, s2)), + ) + } else { + Int(0) + } + } + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, minus), + }, + (Identifier(s), Int(i)) => match ram { + None => Plus(Box::from(Identifier(s.clone())), Box::from(Int(-i))), + Some(_) => apply_operator_reverse(Int(i), Identifier(s), ram, minus), + }, + (Null, Identifier(s)) => match ram { + None => Var(Box::from(Int(-1)), 1, s), + Some(_) => apply_operator(Identifier(s), Null, ram, minus), + }, + (Identifier(s), Null) => match ram { + None => Var(Box::from(Int(-1)), 1, s), + Some(_) => apply_operator_reverse(Identifier(s), Null, ram, minus), + }, + (Rational(r), Identifier(ss)) => match ram { + None => Plus( + Box::from(Rational(r)), + Box::from(Var(Box::from(Int(-1)), 1, ss)), + ), + Some(_) => apply_operator_reverse(Rational(r), Identifier(ss.clone()), ram, minus), + }, + (Identifier(ss), Rational(r)) => match ram { + None => Plus( + Box::from(Var(Box::from(Int(1)), 1, ss)), + Box::from(Rational(r.opposite())), + ), + Some(_) => apply_operator(Identifier(ss), Rational(r), ram, minus), + }, + (Int(i), Identifier(s)) => match ram { + None => Plus(Box::from(Int(i)), Box::from(Var(Box::from(Int(-1)), 1, s))), + Some(_) => { + let v = apply_operator(Identifier(s), Int(i), ram, minus); + match v { + Int(i) => Int(-i), + p => minus(Int(0), p, None), + } + } + }, + (Identifier(s), Float(i)) => match ram { + None => Plus( + Box::from(Var(Box::from(Int(1)), 1, s)), + Box::from(Float(-i)), + ), + Some(_) => apply_operator(Identifier(s), Float(i), ram, minus), + }, + (Float(i), Identifier(s)) => match ram { + None => Plus( + Box::from(Float(i)), + Box::from(Var(Box::from(Int(-1)), 1, s)), + ), + Some(_) => { + let v = apply_operator(Identifier(s), Float(i), ram, minus); + match v { + Float(i) => Float(-i), + _ => Null, + } + } + }, + + (InterpreterVector(vec), Identifier(s)) => match ram { + None => InterpreterVector(vec.clone()), + Some(_) => { + apply_operator_reverse(InterpreterVector(vec.clone()), Identifier(s), ram, minus) + } + }, + (Identifier(s), InterpreterVector(vec)) => match ram { + None => InterpreterVector(vec.clone()), + Some(_) => apply_operator(Identifier(s), InterpreterVector(vec.clone()), ram, minus), + }, + (Bool(b), Identifier(s)) => match ram { + None => Bool(b), + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, minus), + }, + (Identifier(s), Bool(b)) => match ram { + None => Bool(b), + Some(_) => apply_operator(Identifier(s), Bool(b), ram, minus), + }, + (Plus(s1, s2), Plus(s3, s4)) => { + let first = Plus( + Box::from(minus(*s1.clone(), *s3.clone(), ram)), + Box::from(minus(*s2.clone(), *s4.clone(), ram)), + ); + let second = Plus( + Box::from(minus(*s1.clone(), *s4.clone(), ram)), + Box::from(minus(*s2.clone(), *s3.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + + if s1 > s2 { + second + } else { + first + } + } + (Plus(s1, s2), Identifier(s3)) => { + let first = Plus( + Box::from(minus(*s1.clone(), Identifier(s3.clone()), ram)), + s2.clone(), + ); + let second = Plus( + s1.clone(), + Box::from(minus(*s2.clone(), Identifier(s3.clone()), ram)), + ); + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Identifier(s3), Plus(s1, s2)) => { + let first = Plus( + Box::from(minus(Identifier(s3.clone()), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ); + let second = Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Identifier(s3.clone()), *s2.clone(), ram)), + ); + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Int(i), Plus(s1, s2)) => { + let first = Plus( + Box::from(minus(Int(i), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ); + let second = Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Int(i), *s2.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Int(i)) => { + let first = Plus(Box::from(minus(*s1.clone(), Int(i), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(minus(*s2.clone(), Int(i), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Float(f)) => { + let first = Plus(Box::from(minus(*s1.clone(), Float(f), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(minus(*s2.clone(), Float(f), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Float(f), Plus(s1, s2)) => { + let first = Plus( + Box::from(minus(Float(f), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ); + let second = Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Float(f), *s2.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Rational(r)) => { + let first = Plus(Box::from(minus(*s1.clone(), Rational(r), ram)), s2.clone()); + let second = Plus(s1.clone(), Box::from(minus(*s2.clone(), Rational(r), ram))); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Rational(r), Plus(s1, s2)) => { + let first = Plus( + Box::from(minus(Rational(r), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ); + let second = Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Rational(r), *s2.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Plus(s1, s2), Var(x, y, z)) => { + let first = Plus( + Box::from(minus(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + s2.clone(), + ); + let second = Plus( + s1.clone(), + Box::from(minus(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + if s1 > s2 { + second + } else { + first + } + } + + (Var(x, y, z), Plus(s1, s2)) => { + let first = Plus( + Box::from(minus(Var(x.clone(), y, z.clone()), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ); + let second = Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Var(x.clone(), y, z.clone()), *s2.clone(), ram)), + ); + + let (s1, s2) = (size(&first), size(&second)); + + if s1 > s2 { + second + } else { + first + } + } + + (Null, Plus(s1, s2)) => Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ), + + (Plus(s1, s2), Null) => Plus( + Box::from(minus(Int(0), *s1.clone(), ram)), + Box::from(minus(Int(0), *s2.clone(), ram)), + ), + + (Mul(s1, s2), Mul(s3, s4)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Mul(Box::from(minus(Int(0), *s3.clone(), ram)), s4.clone())), + ), + + (Mul(s1, s2), Identifier(s)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Var(Box::from(Int(-1)), 1, s.clone())), + ), + + (Identifier(s), Mul(s1, s2)) => Plus( + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + Box::from(Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone())), + ), + + (Mul(s1, s2), Int(i)) => Plus(Box::from(Mul(s1.clone(), s2.clone())), Box::from(Int(-i))), + + (Int(i), Mul(s1, s2)) => Plus( + Box::from(Int(i)), + Box::from(Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone())), + ), + + (Mul(s1, s2), Float(f)) => { + Plus(Box::from(Mul(s1.clone(), s2.clone())), Box::from(Float(-f))) + } + + (Float(f), Mul(s1, s2)) => Plus( + Box::from(Float(f)), + Box::from(Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone())), + ), + + (Mul(s1, s2), Rational(r)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Rational(r.opposite())), + ), + + (Rational(r), Mul(s1, s2)) => Plus( + Box::from(Rational(r)), + Box::from(Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone())), + ), + + (Var(x, y, z), Mul(s1, s2)) => Plus( + Box::from(Var(x.clone(), y, z.clone())), + Box::from(Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone())), + ), + + (Mul(s1, s2), Var(x, y, z)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Var(Box::from(minus(Int(0), *x.clone(), ram)), y, z.clone())), + ), + + (Mul(s1, s2), Plus(s3, s4)) => Plus( + Box::from(Mul(s1.clone(), s2.clone())), + Box::from(Plus( + Box::from(minus(Int(0), *s3.clone(), ram)), + Box::from(minus(Int(0), *s4.clone(), ram)), + )), + ), + + (Plus(s3, s4), Mul(s1, s2)) => Plus( + Box::from(Plus(s3.clone(), s4.clone())), + Box::from(Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone())), + ), + + (Null, Mul(s1, s2)) => Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone()), + + (Mul(s1, s2), Null) => Mul(Box::from(minus(Int(0), *s1.clone(), ram)), s2.clone()), + + (Var(x, y, z), Var(x1, y1, z1)) => { + if z == z1 && y == y1 { + Var(Box::from(minus(*x.clone(), *x1.clone(), ram)), y, z) + } else { + Plus( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var( + Box::from(minus(Int(0), *x1.clone(), ram)), + y1.clone(), + z1.clone(), + )), + ) + } + } + + (Var(x, y, z), Identifier(s)) => { + if z == s && y == 1 { + Var(Box::from(minus(*x.clone(), Int(1), ram)), y, z) + } else { + Plus( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var(Box::from(Int(-1)), 1, s.clone())), + ) + } + } + + (Identifier(s), Var(x, y, z)) => { + if z == s && y == 1 { + Var(Box::from(minus(Int(1), *x.clone(), ram)), y, z) + } else { + Plus( + Box::from(Var( + Box::from(minus(Int(0), *x.clone(), ram)), + y.clone(), + z.clone(), + )), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ) + } + } + + (Int(i), Var(x, y, z)) => Plus( + Box::from(Int(i)), + Box::from(Var(Box::from(minus(Int(0), *x.clone(), ram)), y, z)), + ), + + (Var(x, y, z), Int(i)) => Plus(Box::from(Var(x, y, z)), Box::from(Int(-i))), + + (Float(f), Var(x, y, z)) => Plus( + Box::from(Float(f)), + Box::from(Var(Box::from(minus(Int(0), *x.clone(), ram)), y, z)), + ), + + (Var(x, y, z), Float(f)) => Plus(Box::from(Var(x, y, z)), Box::from(Float(-f))), + + (Rational(r), Var(x, y, z)) => Plus( + Box::from(Rational(r)), + Box::from(Var(Box::from(minus(Int(0), *x.clone(), ram)), y, z)), + ), + + (Var(x, y, z), Rational(r)) => { + Plus(Box::from(Var(x, y, z)), Box::from(Rational(r.opposite()))) + } + + (Var(x, y, z), Div(s1, s2)) => { + let first = Div( + Box::from(minus( + mult(Var(x.clone(), y, z.clone()), *s2.clone(), ram), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Div(s1, s2), Var(x, y, z)) => { + let first = Div( + Box::from(minus( + *s1.clone(), + mult(*s2.clone(), Var(x.clone(), y, z.clone()), ram), + ram, + )), + s2.clone(), + ); + first + } + + (Mul(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(minus( + mult(*s4.clone(), mult(*s1.clone(), *s2.clone(), ram), ram), + *s3.clone(), + ram, + )), + s4.clone(), + ); + first + } + + (Div(s1, s2), Mul(s3, s4)) => { + let first = Div( + Box::from(minus( + *s3.clone(), + mult(*s4.clone(), mult(*s1.clone(), *s2.clone(), ram), ram), + ram, + )), + s4.clone(), + ); + first + } + + (Div(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(minus( + mult(*s1.clone(), *s4.clone(), ram), + mult(*s2.clone(), *s3.clone(), ram), + ram, + )), + Box::from(mult(*s2.clone(), *s4.clone(), ram)), + ); + first + } + + (Div(s1, s2), Identifier(s)) => { + let first = Div( + Box::from(minus( + *s1.clone(), + mult( + *s2.clone(), + Var(Box::from(Parameters::Int(1)), 1, s.clone()), + ram, + ), + ram, + )), + s2.clone(), + ); + first + } + + (Identifier(s), Div(s1, s2)) => { + let first = Div( + Box::from(minus( + mult( + *s2.clone(), + Var(Box::from(Parameters::Int(1)), 1, s.clone()), + ram, + ), + *s1.clone(), + ram, + )), + s2.clone(), + ); + first + } + + (Div(s1, s2), Int(i)) => { + let first = Div(Box::from(mult(*s1.clone(), Int(i), ram)), s2.clone()); + first + } + + (Int(i), Div(s1, s2)) => { + let first = Div(Box::from(mult(Int(i), *s1.clone(), ram)), s2.clone()); + first + } + + (Div(s1, s2), Float(f)) => { + let first = Div(Box::from(mult(*s1.clone(), Float(f), ram)), s2.clone()); + first + } + + (Float(f), Div(s1, s2)) => { + let first = Div(Box::from(mult(Float(f), *s1.clone(), ram)), s2.clone()); + first + } + + (Div(s1, s2), Rational(r)) => { + let first = Div( + Box::from(minus(*s1.clone(), mult(*s2.clone(), Rational(r), ram), ram)), + s2.clone(), + ); + first + } + + (Rational(r), Div(s1, s2)) => { + let first = Div( + Box::from(minus(mult(Rational(r), *s2.clone(), ram), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + //x/y - a+b = x - y(a+b)/y + (Div(s1, s2), Plus(s3, s4)) => { + let first = Div( + Box::from(minus( + *s1.clone(), + mult(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + ram, + )), + s2.clone(), + ); + first + } + + (Plus(s3, s4), Div(s1, s2)) => { + let first = Div( + Box::from(minus( + mult(*s2.clone(), add(*s3.clone(), *s4.clone(), ram), ram), + *s1.clone(), + ram, + )), + s1.clone(), + ); + first + } + + (Null, Div(s1, s2)) => divide( + minus(Parameters::Int(0), *s1.clone(), ram), + *s2.clone(), + ram, + ), + + (Div(s1, s2), Null) => divide( + minus(Parameters::Int(0), *s1.clone(), ram), + *s2.clone(), + ram, + ), + + _ => Identifier("Those two values are incompatible with the - operator".to_string()), + } +} diff --git a/src/functions/mod.rs b/src/functions/mod.rs new file mode 100644 index 0000000..3742128 --- /dev/null +++ b/src/functions/mod.rs @@ -0,0 +1,6 @@ +pub mod add; +pub mod divide; +pub mod expo; +pub mod function; +pub mod minus; +pub mod mult; diff --git a/src/functions/mult.rs b/src/functions/mult.rs new file mode 100644 index 0000000..9d61189 --- /dev/null +++ b/src/functions/mult.rs @@ -0,0 +1,570 @@ +use crate::exact_math::rationals::Rationals; +use crate::exact_math::symbolic::size; +use crate::functions::add::add; +use crate::functions::function::apply_operator; +use crate::functions::function::apply_operator_reverse; +use crate::parsing::ast::Parameters; +use crate::parsing::ast::Parameters::*; +use crate::utils::matrix_utils::*; +use std::collections::HashMap; + +pub fn mult( + i: Parameters, + i2: Parameters, + ram: Option<&HashMap>, +) -> Parameters { + match (i, i2) { + (Null, Int(v)) => Int(v), + (Null, Float(f)) => Float(f), + (Int(v), Null) => Int(v), + (Float(f), Null) => Float(f), + (Int(v), Int(v2)) => Int(v * v2), + (Int(v), Float(f)) => Float((v as f64) * f), + (Float(v), Float(f)) => Float(v * f), + (Float(v), Int(i1)) => Float(v * (i1 as f64)), + + (Rational(s), Null) => Rational(s.clone()), + (Null, Rational(s)) => Rational(s.clone()), + (Rational(s), Rational(s2)) => Rational(s * s2), + (Rational(s), Int(i)) => Rational(s * Rationals::new(1, i)), + (Int(i), Rational(s)) => Rational(s * Rationals::new(1, i)), + (Rational(s), Float(f)) => Float(s.approx() * f), + (Float(f), Rational(s)) => Float(f * s.approx()), + (Null, InterpreterVector(vec)) => InterpreterVector(vec.clone()), + (InterpreterVector(vec), Null) => InterpreterVector(vec.clone()), + (InterpreterVector(vec), Int(v)) => { + let mut result = Vec::new(); + vec.into_iter() + .map(|x| mult(x.clone(), Int(v), ram)) + .for_each(|x| result.push(x)); + InterpreterVector(Box::from(result)) + } + (Int(v), InterpreterVector(vec)) => { + let mut result = Vec::new(); + vec.into_iter() + .map(|x| mult(x.clone(), Int(v), ram)) + .for_each(|x| result.push(x)); + InterpreterVector(Box::from(result)) + } + (InterpreterVector(vec), Float(v)) => { + let mut result = Vec::new(); + vec.into_iter() + .map(|x| mult(x.clone(), Float(v), ram)) + .for_each(|x| result.push(x)); + InterpreterVector(Box::from(result)) + } + (Float(v), InterpreterVector(vec)) => { + let mut result = Vec::new(); + vec.into_iter() + .map(|x| mult(x.clone(), Float(v), ram)) + .for_each(|x| result.push(x)); + InterpreterVector(Box::from(result)) + } + + (InterpreterVector(vec), InterpreterVector(vec2)) => { + let mut res1 = Vec::new(); + let mut is_matrix = true; + let mut res = Vec::new(); + let mut res2 = Vec::new(); + + vec.clone().into_iter().for_each(|x| match x { + InterpreterVector(l) => res.push(l.to_vec()), + p => { + is_matrix = false; + res1.push(p); + } + }); + vec2.clone().into_iter().for_each(|x| match x { + InterpreterVector(l) => res2.push(l.to_vec()), + _ => { + is_matrix = false; + } + }); + + if !is_matrix { + let mut sum = Null; + (*vec) + .into_iter() + .zip(vec2.into_iter()) + .map(|(a, b)| mult(a.clone(), b.clone(), ram)) + .for_each(|x| sum = add(sum.clone(), x, ram)); + + match sum { + Int(i) => Int(i), + Float(f) => Float(f), + _ => Float(f64::NAN), + } + } else { + let matrix_result = mult_matrix(res, res2, ram); + + let mut res = Vec::new(); + + if matrix_result.len() == 0 { + return Null; + } + + matrix_result + .into_iter() + .for_each(|x| res.push(InterpreterVector(Box::from(x)))); + + InterpreterVector(Box::from(res)) + } + } + + (Bool(_), Int(i)) => Int(i), + (Bool(_), Float(i)) => Float(i), + (Int(i), Bool(_)) => Int(i), + (Float(i), Bool(_)) => Float(i), + (Bool(b), Null) => Bool(b), + (Null, Bool(b)) => Bool(b), + (Bool(b), Bool(b2)) => Bool(b && b2), + (Identifier(s), Identifier(s2)) => match ram { + None => { + if s == s2 { + Var(Box::from(Int(1)), 2, s.clone()) + } else { + Mul( + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + Box::from(Var(Box::from(Int(1)), 1, s2.clone())), + ) + } + } + Some(_) => apply_operator(Identifier(s), Identifier(s2), ram, mult), + }, + (Identifier(s), Int(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Int(i), ram, mult), + None => Var(Box::from(Int(i)), 1, s.clone()), + }, + + (Rational(r), Identifier(ss)) => match ram { + None => Var(Box::from(Rational(r)), 1, ss.clone()), + Some(_) => apply_operator_reverse(Rational(r), Identifier(ss.clone()), ram, mult), + }, + (Identifier(ss), Rational(r)) => match ram { + Some(_) => apply_operator(Identifier(ss), Rational(r), ram, mult), + None => Var(Box::from(Rational(r)), 1, ss.clone()), + }, + (Int(i), Identifier(s)) => match ram { + None => Var(Box::from(Int(i)), 1, s.clone()), + Some(_) => apply_operator(Identifier(s), Int(i), ram, mult), + }, + (Identifier(s), InterpreterVector(vec)) => match ram { + None => InterpreterVector(vec.clone()), + Some(_) => apply_operator(Identifier(s), InterpreterVector(vec.clone()), ram, mult), + }, + (InterpreterVector(vec), Identifier(s)) => match ram { + None => InterpreterVector(vec.clone()), + Some(_) => { + apply_operator_reverse(InterpreterVector(vec.clone()), Identifier(s), ram, mult) + } + }, + (Null, Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, mult), + None => Var(Box::from(Int(1)), 1, s.clone()), + }, + (Identifier(s), Null) => match ram { + Some(_) => apply_operator(Identifier(s), Null, ram, mult), + None => Var(Box::from(Int(1)), 1, s.clone()), + }, + (Identifier(s), Float(i)) => match ram { + Some(_) => apply_operator(Identifier(s), Float(i), ram, mult), + None => Var(Box::from(Float(i)), 1, s.clone()), + }, + (Float(i), Identifier(s)) => match ram { + Some(_) => apply_operator(Identifier(s), Float(i), ram, mult), + None => Var(Box::from(Float(i)), 1, s.clone()), + }, + (Bool(b), Identifier(s)) => match ram { + Some(_) => apply_operator_reverse(Bool(b), Identifier(s), ram, mult), + None => Bool(b), + }, + (Identifier(s), Bool(b)) => match ram { + Some(_) => apply_operator(Identifier(s), Bool(b), ram, mult), + None => Bool(b), + }, + (Plus(s1, s2), Plus(s3, s4)) => { + let first = Plus( + Box::from(add( + mult(*s1.clone(), *s3.clone(), ram), + mult(*s2.clone(), *s3.clone(), ram), + ram, + )), + Box::from(add( + mult(*s1.clone(), *s4.clone(), ram), + mult(*s2.clone(), *s4.clone(), ram), + ram, + )), + ); + let second = Plus( + Box::from(add( + mult(*s1.clone(), *s3.clone(), ram), + mult(*s2.clone(), *s4.clone(), ram), + ram, + )), + Box::from(add( + mult(*s2.clone(), *s3.clone(), ram), + mult(*s1.clone(), *s4.clone(), ram), + ram, + )), + ); + + let (s1, s2) = (size(&first), size(&second)); + + if s1 > s2 { + second + } else { + first + } + } + (Plus(s1, s2), Identifier(s3)) => { + let first = Plus( + Box::from(mult( + *s1.clone(), + Var(Box::from(Int(1)), 1, s3.clone()), + ram, + )), + Box::from(mult( + *s2.clone(), + Var(Box::from(Int(1)), 1, s3.clone()), + ram, + )), + ); + first + } + (Identifier(s3), Plus(s1, s2)) => { + let first = Plus( + Box::from(mult(Var(Box::new(Int(1)), 1, s3.clone()), *s1.clone(), ram)), + Box::from(mult(Var(Box::new(Int(1)), 1, s3.clone()), *s2.clone(), ram)), + ); + first + } + + (Int(i), Plus(s1, s2)) => { + let first = Plus( + Box::from(mult(Int(i), *s1.clone(), ram)), + Box::from(mult(Int(i), *s2.clone(), ram)), + ); + first + } + + (Plus(s1, s2), Int(i)) => { + let first = Plus( + Box::from(mult(*s1.clone(), Int(i), ram)), + Box::from(mult(*s2.clone(), Int(i), ram)), + ); + first + } + + (Float(f), Plus(s1, s2)) => { + let first = Plus( + Box::from(mult(Float(f), *s1.clone(), ram)), + Box::from(mult(Float(f), *s2.clone(), ram)), + ); + first + } + + (Plus(s1, s2), Float(f)) => { + let first = Plus( + Box::from(mult(*s1.clone(), Float(f), ram)), + Box::from(mult(*s2.clone(), Float(f), ram)), + ); + first + } + (Rational(r), Plus(s1, s2)) => { + let first = Plus( + Box::from(mult(Rational(r), *s1.clone(), ram)), + Box::from(mult(Rational(r), *s2.clone(), ram)), + ); + first + } + + (Plus(s1, s2), Rational(r)) => { + let first = Plus( + Box::from(mult(*s1.clone(), Rational(r), ram)), + Box::from(mult(*s2.clone(), Rational(r), ram)), + ); + first + } + + (Var(x, y, z), Plus(s1, s2)) => Plus( + Box::from(mult(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + Box::from(mult(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ), + + (Plus(s1, s2), Var(x, y, z)) => Plus( + Box::from(mult(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + Box::from(mult(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ), + + (Null, Plus(s1, s2)) => Plus(s1.clone(), s2.clone()), + + (Plus(s1, s2), Null) => Plus(s1.clone(), s2.clone()), + + (Var(x, y, z), Mul(s1, s2)) => { + let first = Mul( + Box::from(mult(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + s2.clone(), + ); + let second = Mul( + s1.clone(), + Box::from(mult(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Var(x, y, z)) => { + let first = Mul( + Box::from(mult(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + s2.clone(), + ); + let second = Mul( + s1.clone(), + Box::from(mult(*s2.clone(), Var(x.clone(), y, z.clone()), ram)), + ); + + let (ss1, ss2) = (size(&first), size(&second)); + + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Mul(s3, s4)) => { + let first = Mul( + Box::from(mult(*s1.clone(), *s3.clone(), ram)), + Box::from(mult(*s2.clone(), *s4.clone(), ram)), + ); + let second = Mul( + Box::from(mult(*s1.clone(), *s4.clone(), ram)), + Box::from(mult(*s2.clone(), *s3.clone(), ram)), + ); + + let (ss1, ss2) = (size(&first), size(&second)); + if ss1 > ss2 { + second + } else { + first + } + } + + (Mul(s1, s2), Identifier(s)) => Mul( + Box::from(mult(*s1.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram)), + s2.clone(), + ), + + (Identifier(s), Mul(s1, s2)) => Mul( + Box::from(mult(*s1.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram)), + s2.clone(), + ), + + (Mul(s1, s2), Int(i)) => Mul(Box::from(mult(*s1.clone(), Int(i), ram)), s2.clone()), + + (Int(i), Mul(s1, s2)) => Mul(Box::from(mult(*s1.clone(), Int(i), ram)), s2.clone()), + + (Mul(s1, s2), Float(f)) => Mul(Box::from(mult(*s1.clone(), Float(f), ram)), s2.clone()), + + (Float(f), Mul(s1, s2)) => Mul(Box::from(mult(*s1.clone(), Float(f), ram)), s2.clone()), + + (Mul(s1, s2), Rational(r)) => { + Mul(Box::from(mult(*s1.clone(), Rational(r), ram)), s2.clone()) + } + + (Rational(r), Mul(s1, s2)) => { + Mul(Box::from(mult(*s1.clone(), Rational(r), ram)), s2.clone()) + } + + (Mul(s1, s2), Plus(s3, s4)) => Plus( + Box::from(mult(mult(*s1.clone(), *s3.clone(), ram), *s2.clone(), ram)), + Box::from(mult(mult(*s1.clone(), *s4.clone(), ram), *s2.clone(), ram)), + ), + + (Plus(s3, s4), Mul(s1, s2)) => Plus( + Box::from(mult(mult(*s1.clone(), *s3.clone(), ram), *s2.clone(), ram)), + Box::from(mult(mult(*s1.clone(), *s4.clone(), ram), *s2.clone(), ram)), + ), + + (Null, Mul(s1, s2)) => Mul(s1.clone(), s2.clone()), + + (Mul(s1, s2), Null) => Mul(s1.clone(), s2.clone()), + + (Var(x, y, z), Var(x1, y1, z1)) => { + if z == z1 { + Var(Box::from(mult(*x.clone(), *x1.clone(), ram)), y + y1, z) + } else { + Mul( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var( + Box::from(mult(Int(1), *x1.clone(), ram)), + y1.clone(), + z1.clone(), + )), + ) + } + } + + (Var(x, y, z), Identifier(s)) => { + if z == s { + Var(Box::from(x.clone()), y + 1, z) + } else { + Mul( + Box::from(Var(x.clone(), y.clone(), z.clone())), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ) + } + } + + (Identifier(s), Var(x, y, z)) => { + if z == s { + Var(Box::from(x.clone()), y + 1, z) + } else { + Mul( + Box::from(Var( + Box::from(mult(Int(1), *x.clone(), ram)), + y.clone(), + z.clone(), + )), + Box::from(Var(Box::from(Int(1)), 1, s.clone())), + ) + } + } + + (Int(i), Var(x, y, z)) => Var(Box::from(mult(*x.clone(), Int(i), ram)), y, z.clone()), + + (Var(x, y, z), Int(i)) => Var(Box::from(mult(*x.clone(), Int(i), ram)), y, z.clone()), + + (Float(f), Var(x, y, z)) => Var(Box::from(mult(Float(f), *x.clone(), ram)), y, z.clone()), + + (Var(x, y, z), Float(f)) => Var(Box::from(mult(*x.clone(), Float(f), ram)), y, z.clone()), + + (Rational(r), Var(x, y, z)) => { + Var(Box::from(mult(Rational(r), *x.clone(), ram)), y, z.clone()) + } + + (Var(x, y, z), Rational(r)) => { + Var(Box::from(mult(*x.clone(), Rational(r), ram)), y, z.clone()) + } + + (Var(x, y, z), Div(s1, s2)) => { + let first = Div( + Box::from(mult(Var(x.clone(), y, z.clone()), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Div(s1, s2), Var(x, y, z)) => { + let first = Div( + Box::from(mult(*s1.clone(), Var(x.clone(), y, z.clone()), ram)), + s2.clone(), + ); + first + } + + (Mul(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(mult(*s3.clone(), mult(*s1.clone(), *s2.clone(), ram), ram)), + s4.clone(), + ); + first + } + + (Div(s1, s2), Mul(s3, s4)) => { + let first = Div( + Box::from(mult(*s1.clone(), mult(*s3.clone(), *s4.clone(), ram), ram)), + s2.clone(), + ); + first + } + + (Div(s1, s2), Div(s3, s4)) => { + let first = Div( + Box::from(mult(*s1.clone(), *s3.clone(), ram)), + Box::from(mult(*s2.clone(), *s4.clone(), ram)), + ); + first + } + + (Div(s1, s2), Identifier(s)) => { + let first = Div( + Box::from(mult(*s1.clone(), Var(Box::from(Int(1)), 1, s.clone()), ram)), + s2.clone(), + ); + first + } + + (Identifier(s), Div(s1, s2)) => { + let first = Div( + Box::from(mult(Var(Box::from(Int(1)), 1, s.clone()), *s1.clone(), ram)), + s2.clone(), + ); + first + } + + (Div(s1, s2), Int(i)) => { + let first = Div(Box::from(mult(*s1.clone(), Int(i), ram)), s2.clone()); + first + } + + (Int(i), Div(s1, s2)) => { + let first = Div(Box::from(mult(Int(i), *s1.clone(), ram)), s2.clone()); + first + } + + (Div(s1, s2), Float(f)) => { + let first = Div(Box::from(mult(*s1.clone(), Float(f), ram)), s2.clone()); + first + } + + (Float(f), Div(s1, s2)) => { + let first = Div(Box::from(mult(Float(f), *s1.clone(), ram)), s2.clone()); + first + } + + (Div(s1, s2), Rational(r)) => { + let first = Div( + Box::from(mult(*s1.clone(), Int(r.over), ram)), + Box::from(mult(*s2.clone(), Int(r.under), ram)), + ); + first + } + + (Rational(r), Div(s1, s2)) => { + let first = Div( + Box::from(mult(Int(r.over), *s1.clone(), ram)), + Box::from(mult(*s2.clone(), Int(r.under), ram)), + ); + first + } + + (Div(s1, s2), Plus(s3, s4)) => { + let first = Div( + Box::from(mult(*s1.clone(), add(*s3.clone(), *s4.clone(), ram), ram)), + s2.clone(), + ); + first + } + + (Plus(s3, s4), Div(s1, s2)) => { + let first = Div( + Box::from(mult(*s1.clone(), add(*s3.clone(), *s4.clone(), ram), ram)), + s2.clone(), + ); + first + } + + (Null, Div(s1, s2)) => Div(s1.clone(), s2.clone()), + + (Div(s1, s2), Null) => Div(s1.clone(), s2.clone()), + + _ => Identifier("@Those two values are incompatible with the * operator".to_string()), + } +} diff --git a/src/interpreting/function.rs b/src/interpreting/function.rs deleted file mode 100644 index 37f5fe1..0000000 --- a/src/interpreting/function.rs +++ /dev/null @@ -1,1308 +0,0 @@ -use std::collections::HashMap; - -use crate::exact_math::rationals::Rationals; -use crate::parsing::ast::Parameters; -use crate::parsing::ast::Parameters::Bool; -use crate::utils::matrix_utils::mult_matrix; - -pub fn apply_operator( - value: Parameters, - value2: Parameters, - ram: Option<&HashMap>, - f: fn(Parameters, Parameters, Option<&HashMap>) -> Parameters, -) -> Parameters { - let s = match value { - Parameters::Identifier(s) => s, - _ => "".to_string(), - }; - if s == "".to_string() { - return Parameters::Null; - } - match ram { - None => value2, - Some(i_ram) => { - let value = i_ram.get(&s); - match value { - None => value2, - Some(val) => f(val.clone(), value2.clone(), ram), - } - } - } -} - -pub fn apply_operator_reverse( - value: Parameters, - value2: Parameters, - ram: Option<&HashMap>, - f: fn(Parameters, Parameters, Option<&HashMap>) -> Parameters, -) -> Parameters { - let s = match value2 { - Parameters::Identifier(s) => s, - _ => "".to_string(), - }; - if s == "".to_string() { - return Parameters::Null; - } - match ram { - None => value, - Some(i_ram) => { - let val3 = i_ram.get(&s); - match val3 { - None => value, - Some(val) => f(value.clone(), val.clone(), ram), - } - } - } -} - -pub fn add(i: Parameters, i2: Parameters, ram: Option<&HashMap>) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(v)) => Parameters::Int(v), - (Parameters::Null, Parameters::Float(f)) => Parameters::Float(f), - (Parameters::Null, Parameters::InterpreterVector(vec)) => { - Parameters::InterpreterVector(vec.clone()) - } - (Parameters::InterpreterVector(vec), Parameters::Null) => { - Parameters::InterpreterVector(vec.clone()) - } - (Parameters::Int(v), Parameters::Null) => Parameters::Int(v), - (Parameters::Float(f), Parameters::Null) => Parameters::Float(f), - (Parameters::Rational(s), Parameters::Null) => Parameters::Rational(s.clone()), - (Parameters::Null, Parameters::Rational(s)) => Parameters::Rational(s.clone()), - (Parameters::Rational(s), Parameters::Rational(s2)) => Parameters::Rational(s + s2), - (Parameters::Rational(s), Parameters::Int(i)) => { - Parameters::Rational(s + Rationals::new(1, i)) - } - (Parameters::Int(i), Parameters::Rational(s)) => { - Parameters::Rational(s + Rationals::new(1, i)) - } - (Parameters::Rational(s), Parameters::Float(f)) => Parameters::Float(s.approx() + f), - (Parameters::Float(f), Parameters::Rational(s)) => Parameters::Float(f + s.approx()), - (Parameters::Int(v), Parameters::Int(v2)) => Parameters::Int(v + v2), - (Parameters::Int(v), Parameters::Float(f)) => Parameters::Float((v as f64) + f), - (Parameters::Float(v), Parameters::Float(f)) => Parameters::Float(v + f), - (Parameters::Float(v), Parameters::Int(i1)) => Parameters::Float(v + (i1 as f64)), - (Parameters::InterpreterVector(vec), Parameters::InterpreterVector(vec2)) => { - let mut res = Vec::new(); - vec.into_iter() - .zip(vec2.into_iter()) - .map(|(x, y)| add(x.clone(), y.clone(), ram)) - .for_each(|s| res.push(s)); - Parameters::InterpreterVector(Box::from(res)) - } - (Bool(_), Parameters::Int(i)) => Parameters::Int(i), - (Bool(_), Parameters::Float(i)) => Parameters::Float(i), - (Parameters::Int(i), Bool(_)) => Parameters::Int(i), - (Parameters::Float(i), Bool(_)) => Parameters::Float(i), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - add, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, add) - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, add) - } - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - add, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - add, - ), - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, add) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, add) - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, add) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, add) - } - (Parameters::Identifier(s), Parameters::InterpreterVector(vec)) => apply_operator( - Parameters::Identifier(s), - Parameters::InterpreterVector(vec.clone()), - ram, - add, - ), - (Parameters::InterpreterVector(vec), Parameters::Identifier(s)) => apply_operator( - Parameters::Identifier(s), - Parameters::InterpreterVector(vec.clone()), - ram, - add, - ), - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, add) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, add) - } - _ => Parameters::Identifier( - "@Those two values are incompatible with the + operator".to_string(), - ), - } -} - -pub fn minus( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(v)) => Parameters::Int(-v), - (Parameters::Null, Parameters::Float(f)) => Parameters::Float(-f), - (Parameters::Int(v), Parameters::Null) => Parameters::Int(-v), - (Parameters::Float(f), Parameters::Null) => Parameters::Float(-f), - (Parameters::Int(v), Parameters::Int(v2)) => Parameters::Int(v - v2), - - (Parameters::Rational(s), Parameters::Null) => { - Parameters::Rational(Rationals::new(1, 0) - s) - } - - (Parameters::Null, Parameters::Rational(s)) => { - Parameters::Rational(Rationals::new(1, 0) - s) - } - (Parameters::Rational(s), Parameters::Rational(s2)) => Parameters::Rational(s - s2), - (Parameters::Rational(s), Parameters::Int(i)) => { - Parameters::Rational(s - Rationals::new(1, i)) - } - (Parameters::Int(i), Parameters::Rational(s)) => { - Parameters::Rational(Rationals::new(1, i) - s) - } - (Parameters::Rational(s), Parameters::Float(f)) => Parameters::Float(s.approx() - f), - (Parameters::Float(f), Parameters::Rational(s)) => Parameters::Float(f - s.approx()), - (Parameters::InterpreterVector(vec), Parameters::Null) => { - let mut res = Vec::new(); - vec.into_iter() - .map(|x| minus(Parameters::Null, x.clone(), ram)) - .for_each(|z| res.push(z)); - Parameters::InterpreterVector(Box::from(res)) - } - - (Parameters::Null, Parameters::InterpreterVector(vec)) => { - let mut res = Vec::new(); - vec.into_iter() - .map(|x| minus(Parameters::Null, x.clone(), ram)) - .for_each(|z| res.push(z)); - Parameters::InterpreterVector(Box::from(res)) - } - - (Parameters::InterpreterVector(vec), Parameters::InterpreterVector(vec2)) => { - let mut res = Vec::new(); - vec.into_iter() - .zip(vec2.into_iter()) - .map(|(x, y)| minus(x.clone(), y.clone(), ram)) - .for_each(|z| res.push(z)); - Parameters::InterpreterVector(Box::from(res)) - } - (Parameters::Int(v), Parameters::Float(f)) => Parameters::Float((v as f64) - f), - (Parameters::Float(v), Parameters::Float(f)) => Parameters::Float(v - f), - (Parameters::Float(v), Parameters::Int(i1)) => Parameters::Float(v - (i1 as f64)), - - (Bool(_), Parameters::Int(i)) => Parameters::Int(i), - (Bool(_), Parameters::Float(i)) => Parameters::Float(i), - (Parameters::Int(i), Bool(_)) => Parameters::Int(i), - (Parameters::Float(i), Bool(_)) => Parameters::Float(i), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - minus, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, minus) - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, minus) - } - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - minus, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - minus, - ), - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, minus) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - let v = apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, minus); - match v { - Parameters::Int(i) => Parameters::Int(-i), - _ => Parameters::Null, - } - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, minus) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - let v = apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, minus); - match v { - Parameters::Float(i) => Parameters::Float(-i), - _ => Parameters::Null, - } - } - - (Parameters::InterpreterVector(vec), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::InterpreterVector(vec.clone()), - Parameters::Identifier(s), - ram, - minus, - ), - (Parameters::Identifier(s), Parameters::InterpreterVector(vec)) => apply_operator( - Parameters::Identifier(s), - Parameters::InterpreterVector(vec.clone()), - ram, - minus, - ), - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, minus) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, minus) - } - _ => Parameters::Identifier( - "Those two values are incompatible with the - operator".to_string(), - ), - } -} - -pub fn mult( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(v)) => Parameters::Int(v), - (Parameters::Null, Parameters::Float(f)) => Parameters::Float(f), - (Parameters::Int(v), Parameters::Null) => Parameters::Int(v), - (Parameters::Float(f), Parameters::Null) => Parameters::Float(f), - (Parameters::Int(v), Parameters::Int(v2)) => Parameters::Int(v * v2), - (Parameters::Int(v), Parameters::Float(f)) => Parameters::Float((v as f64) * f), - (Parameters::Float(v), Parameters::Float(f)) => Parameters::Float(v * f), - (Parameters::Float(v), Parameters::Int(i1)) => Parameters::Float(v * (i1 as f64)), - - (Parameters::Rational(s), Parameters::Null) => Parameters::Rational(s.clone()), - (Parameters::Null, Parameters::Rational(s)) => Parameters::Rational(s.clone()), - (Parameters::Rational(s), Parameters::Rational(s2)) => Parameters::Rational(s * s2), - (Parameters::Rational(s), Parameters::Int(i)) => { - Parameters::Rational(s * Rationals::new(1, i)) - } - (Parameters::Int(i), Parameters::Rational(s)) => { - Parameters::Rational(s * Rationals::new(1, i)) - } - (Parameters::Rational(s), Parameters::Float(f)) => Parameters::Float(s.approx() * f), - (Parameters::Float(f), Parameters::Rational(s)) => Parameters::Float(f * s.approx()), - (Parameters::Null, Parameters::InterpreterVector(vec)) => { - Parameters::InterpreterVector(vec.clone()) - } - (Parameters::InterpreterVector(vec), Parameters::Null) => { - Parameters::InterpreterVector(vec.clone()) - } - (Parameters::InterpreterVector(vec), Parameters::Int(v)) => { - let mut result = Vec::new(); - vec.into_iter() - .map(|x| mult(x.clone(), Parameters::Int(v), ram)) - .for_each(|x| result.push(x)); - Parameters::InterpreterVector(Box::from(result)) - } - (Parameters::Int(v), Parameters::InterpreterVector(vec)) => { - let mut result = Vec::new(); - vec.into_iter() - .map(|x| mult(x.clone(), Parameters::Int(v), ram)) - .for_each(|x| result.push(x)); - Parameters::InterpreterVector(Box::from(result)) - } - (Parameters::InterpreterVector(vec), Parameters::Float(v)) => { - let mut result = Vec::new(); - vec.into_iter() - .map(|x| mult(x.clone(), Parameters::Float(v), ram)) - .for_each(|x| result.push(x)); - Parameters::InterpreterVector(Box::from(result)) - } - (Parameters::Float(v), Parameters::InterpreterVector(vec)) => { - let mut result = Vec::new(); - vec.into_iter() - .map(|x| mult(x.clone(), Parameters::Float(v), ram)) - .for_each(|x| result.push(x)); - Parameters::InterpreterVector(Box::from(result)) - } - - (Parameters::InterpreterVector(vec), Parameters::InterpreterVector(vec2)) => { - let mut res1 = Vec::new(); - let mut is_matrix = true; - let mut res = Vec::new(); - let mut res2 = Vec::new(); - - vec.clone().into_iter().for_each(|x| match x { - Parameters::InterpreterVector(l) => res.push(l.to_vec()), - p => { - is_matrix = false; - res1.push(p); - } - }); - vec2.clone().into_iter().for_each(|x| match x { - Parameters::InterpreterVector(l) => res2.push(l.to_vec()), - _ => { - is_matrix = false; - } - }); - - if !is_matrix { - let mut sum = Parameters::Null; - (*vec) - .into_iter() - .zip(vec2.into_iter()) - .map(|(a, b)| mult(a.clone(), b.clone(), ram)) - .for_each(|x| sum = add(sum.clone(), x, ram)); - - match sum { - Parameters::Int(i) => Parameters::Int(i), - Parameters::Float(f) => Parameters::Float(f), - _ => Parameters::Float(f64::NAN), - } - } else { - let matrix_result = mult_matrix(res, res2, ram); - - let mut res = Vec::new(); - - if matrix_result.len() == 0 { - return Parameters::Null; - } - - matrix_result - .into_iter() - .for_each(|x| res.push(Parameters::InterpreterVector(Box::from(x)))); - - Parameters::InterpreterVector(Box::from(res)) - } - } - - (Bool(_), Parameters::Int(i)) => Parameters::Int(i), - (Bool(_), Parameters::Float(i)) => Parameters::Float(i), - (Parameters::Int(i), Bool(_)) => Parameters::Int(i), - (Parameters::Float(i), Bool(_)) => Parameters::Float(i), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - mult, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, mult) - } - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - mult, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - mult, - ), - (Parameters::Int(i), Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, mult) - } - (Parameters::Identifier(s), Parameters::InterpreterVector(vec)) => apply_operator( - Parameters::Identifier(s), - Parameters::InterpreterVector(vec.clone()), - ram, - mult, - ), - (Parameters::InterpreterVector(vec), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::InterpreterVector(vec.clone()), - Parameters::Identifier(s), - ram, - mult, - ), - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, mult) - } - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, mult) - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, mult) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, mult) - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, mult) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, mult) - } - _ => Parameters::Identifier( - "@Those two values are incompatible with the * operator".to_string(), - ), - } -} - -pub fn divide( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(v)) => Parameters::Int(v), - (Parameters::Null, Parameters::Float(f)) => Parameters::Float(f), - (Parameters::Int(v), Parameters::Null) => Parameters::Int(v), - (Parameters::Float(f), Parameters::Null) => Parameters::Float(f), - (Parameters::Int(v), Parameters::Int(v2)) => Parameters::Rational(Rationals::new(v2, v)), - (Parameters::Int(v), Parameters::Float(f)) => Parameters::Float((v as f64) / f), - (Parameters::Float(v), Parameters::Float(f)) => Parameters::Float(v / f), - (Parameters::Float(v), Parameters::Int(i1)) => Parameters::Float(v / (i1 as f64)), - (Parameters::Null, Parameters::InterpreterVector(vec)) => { - Parameters::InterpreterVector(vec.clone()) - } - (Parameters::InterpreterVector(vec), Parameters::Null) => { - Parameters::InterpreterVector(vec.clone()) - } - - (Parameters::Rational(s), Parameters::Null) => { - Parameters::Rational(Rationals::new(1, 1) / s) - } - (Parameters::Null, Parameters::Rational(s)) => { - Parameters::Rational(Rationals::new(1, 1) / s) - } - (Parameters::Rational(s), Parameters::Rational(s2)) => Parameters::Rational(s / s2), - - (Parameters::Rational(s), Parameters::Int(i)) => { - Parameters::Rational(s / Rationals::new(1, i)) - } - (Parameters::Int(i), Parameters::Rational(s)) => { - Parameters::Rational(Rationals::new(1, i) / s) - } - (Parameters::Rational(s), Parameters::Float(f)) => Parameters::Float(s.approx() / f), - (Parameters::Float(f), Parameters::Rational(s)) => Parameters::Float(f / s.approx()), - (Bool(_), Parameters::Int(i)) => Parameters::Int(i), - (Bool(_), Parameters::Float(i)) => Parameters::Float(i), - (Parameters::Int(i), Bool(_)) => Parameters::Int(i), - (Parameters::Float(i), Bool(_)) => Parameters::Float(i), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - divide, - ), - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - divide, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - divide, - ), - - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, divide) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - let v = apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, divide); - match v { - Parameters::Float(i) => Parameters::Float(1.0 / i), - _ => Parameters::Null, - } - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, divide) - } - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, divide) - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, divide) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - let v = apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, divide); - match v { - Parameters::Float(i) => Parameters::Float(1.0 / i), - _ => Parameters::Null, - } - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, divide) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, divide) - } - _ => Parameters::Identifier( - "@Those two values are incompatible with the / operator".to_string(), - ), - } -} - -pub fn expo( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(v)) => Parameters::Int(v), - (Parameters::Null, Parameters::Float(f)) => Parameters::Float(f), - (Parameters::Int(v), Parameters::Null) => Parameters::Int(v), - (Parameters::Float(f), Parameters::Null) => Parameters::Float(f), - (Parameters::Int(v), Parameters::Int(v2)) => Parameters::Float((v as f64).powf(v2 as f64)), - (Parameters::Int(v), Parameters::Float(f)) => Parameters::Float((v as f64).powf(f)), - (Parameters::Float(v), Parameters::Float(f)) => Parameters::Float(v.powf(f)), - (Parameters::Float(v), Parameters::Int(i1)) => Parameters::Float(v.powf(i1 as f64)), - - (Parameters::Rational(s), Parameters::Null) => Parameters::Rational(s.clone()), - (Parameters::Null, Parameters::Rational(s)) => Parameters::Rational(s.clone()), - (Parameters::Rational(s), Parameters::Rational(s2)) => { - Parameters::Float(s.approx().powf(s2.approx())) - } - (Parameters::Rational(s), Parameters::Int(i)) => { - Parameters::Float(s.approx().powf(i as f64)) - } - (Parameters::Int(i), Parameters::Rational(s)) => { - Parameters::Float((i as f64).powf(s.approx())) - } - (Parameters::Rational(s), Parameters::Float(f)) => Parameters::Float(s.approx().powf(f)), - (Parameters::Float(f), Parameters::Rational(s)) => Parameters::Float(f.powf(s.approx())), - (Bool(_), Parameters::Int(i)) => Parameters::Int(i), - (Bool(_), Parameters::Float(i)) => Parameters::Float(i), - (Parameters::Int(i), Bool(_)) => Parameters::Int(i), - (Parameters::Float(i), Bool(_)) => Parameters::Float(i), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - expo, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, expo) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Int(i), Parameters::Identifier(s), ram, expo) - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, expo) - } - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - expo, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - expo, - ), - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, expo) - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, expo) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Float(i), Parameters::Identifier(s), ram, expo) - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, expo) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, expo) - } - - _ => Parameters::Identifier( - "@Those two values are incompatible with the ^ operator".to_string(), - ), - } -} - -pub fn assign(s: Parameters, s2: Parameters) -> (String, Parameters) { - match s { - Parameters::Identifier(s) => (s, s2), - _ => ("".to_string(), s2), - } -} - -pub fn greater( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(_)) => Bool(true), - (Parameters::Null, Parameters::Float(_)) => Bool(true), - (Parameters::Int(_), Parameters::Null) => Bool(true), - (Parameters::Float(_), Parameters::Null) => Bool(true), - (Parameters::Int(v), Parameters::Int(v2)) => Bool(v > v2), - (Parameters::Int(v), Parameters::Float(f)) => Bool((v as f64) > f), - (Parameters::Float(v), Parameters::Float(f)) => Bool(v > f), - (Parameters::Float(v), Parameters::Int(i1)) => Bool(v > (i1 as f64)), - (Parameters::Rational(_), Parameters::Null) => Bool(true), - (Parameters::Null, Parameters::Rational(_)) => Bool(true), - (Parameters::Rational(s), Parameters::Rational(s2)) => Bool(s > s2), - (Parameters::Rational(s), Parameters::Int(i)) => Bool(s > Rationals::new(1, i)), - (Parameters::Int(i), Parameters::Rational(s)) => Bool(Rationals::new(1, i) > s), - (Parameters::Rational(s), Parameters::Float(f)) => Bool(s.approx() > f), - (Parameters::Float(f), Parameters::Rational(s)) => Bool(f > s.approx()), - (Bool(b), Parameters::Int(_)) => Bool(b), - (Bool(b), Parameters::Float(_)) => Bool(b), - (Parameters::Int(_), Bool(b)) => Bool(b), - (Parameters::Float(_), Bool(b)) => Bool(b), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - greater, - ), - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - greater, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - greater, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, greater) - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, greater) - } - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, greater) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Int(i), Parameters::Identifier(s), ram, greater) - } - (Parameters::Identifier(s), Parameters::Float(i)) => apply_operator( - Parameters::Identifier(s), - Parameters::Float(i), - ram, - greater, - ), - (Parameters::Float(i), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::Float(i), - Parameters::Identifier(s), - ram, - greater, - ), - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, greater) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, greater) - } - - _ => Parameters::Identifier( - "@Those two values are incompatible with the > operator".to_string(), - ), - } -} - -pub fn lesser( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(_)) => Bool(false), - (Parameters::Null, Parameters::Float(_)) => Bool(false), - (Parameters::Int(_), Parameters::Null) => Bool(false), - (Parameters::Float(_), Parameters::Null) => Bool(false), - (Parameters::Int(v), Parameters::Int(v2)) => Bool(v < v2), - (Parameters::Int(v), Parameters::Float(f)) => Bool((v as f64) < f), - (Parameters::Float(v), Parameters::Float(f)) => Bool(v < f), - (Parameters::Float(v), Parameters::Int(i1)) => Bool(v < (i1 as f64)), - (Parameters::Rational(_), Parameters::Null) => Bool(true), - (Parameters::Null, Parameters::Rational(_)) => Bool(true), - (Parameters::Rational(s), Parameters::Rational(s2)) => Bool(s < s2), - (Parameters::Rational(s), Parameters::Int(i)) => Bool(s < Rationals::new(1, i)), - (Parameters::Int(i), Parameters::Rational(s)) => Bool(Rationals::new(1, i) < s), - (Parameters::Rational(s), Parameters::Float(f)) => Bool(s.approx() < f), - (Parameters::Float(f), Parameters::Rational(s)) => Bool(f < s.approx()), - (Bool(b), Parameters::Int(_)) => Bool(b), - (Bool(b), Parameters::Float(_)) => Bool(b), - (Parameters::Int(_), Bool(b)) => Bool(b), - (Parameters::Float(_), Bool(b)) => Bool(b), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b && b2), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - lesser, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, lesser) - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, lesser) - } - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - lesser, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - lesser, - ), - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, lesser) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Int(i), Parameters::Identifier(s), ram, lesser) - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, lesser) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Float(i), Parameters::Identifier(s), ram, lesser) - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, lesser) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, lesser) - } - - _ => Parameters::Identifier( - "@Those two values are incompatible with the < operator".to_string(), - ), - } -} - -pub fn greater_or_equal( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(_)) => Bool(true), - (Parameters::Null, Parameters::Float(_)) => Bool(true), - (Parameters::Int(_), Parameters::Null) => Bool(true), - (Parameters::Float(_), Parameters::Null) => Bool(true), - (Parameters::Int(v), Parameters::Int(v2)) => Bool(v >= v2), - (Parameters::Int(v), Parameters::Float(f)) => Bool((v as f64) >= f), - (Parameters::Float(v), Parameters::Float(f)) => Bool(v >= f), - (Parameters::Float(v), Parameters::Int(i1)) => Bool(v >= (i1 as f64)), - (Bool(b), Parameters::Int(_)) => Bool(b), - (Bool(b), Parameters::Float(_)) => Bool(b), - (Parameters::Int(_), Bool(b)) => Bool(b), - (Parameters::Float(_), Bool(b)) => Bool(b), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b == b2), - - (Parameters::Rational(_), Parameters::Null) => Bool(true), - (Parameters::Null, Parameters::Rational(_)) => Bool(true), - (Parameters::Rational(s), Parameters::Rational(s2)) => Bool(s >= s2), - (Parameters::Rational(s), Parameters::Int(i)) => Bool(s >= Rationals::new(1, i)), - (Parameters::Int(i), Parameters::Rational(s)) => Bool(Rationals::new(1, i) >= s), - (Parameters::Rational(s), Parameters::Float(f)) => Bool(s.approx() >= f), - (Parameters::Float(f), Parameters::Rational(s)) => Bool(f >= s.approx()), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - greater_or_equal, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => apply_operator( - Parameters::Identifier(s), - Parameters::Int(i), - ram, - greater_or_equal, - ), - (Parameters::Null, Parameters::Identifier(s)) => apply_operator( - Parameters::Identifier(s), - Parameters::Null, - ram, - greater_or_equal, - ), - (Parameters::Identifier(s), Parameters::Null) => apply_operator( - Parameters::Identifier(s), - Parameters::Null, - ram, - greater_or_equal, - ), - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - greater_or_equal, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - greater_or_equal, - ), - (Parameters::Int(i), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::Int(i), - Parameters::Identifier(s), - ram, - greater_or_equal, - ), - (Parameters::Identifier(s), Parameters::Float(i)) => apply_operator( - Parameters::Identifier(s), - Parameters::Float(i), - ram, - greater_or_equal, - ), - (Parameters::Float(i), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::Float(i), - Parameters::Identifier(s), - ram, - greater_or_equal, - ), - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, greater_or_equal) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, greater_or_equal) - } - - _ => Parameters::Identifier( - "@Those two values are incompatible with the >= operator".to_string(), - ), - } -} - -pub fn lesser_or_equal( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(_)) => Bool(false), - (Parameters::Null, Parameters::Float(_)) => Bool(false), - (Parameters::Int(_), Parameters::Null) => Bool(false), - (Parameters::Float(_), Parameters::Null) => Bool(false), - (Parameters::Int(v), Parameters::Int(v2)) => Bool(v <= v2), - (Parameters::Int(v), Parameters::Float(f)) => Bool((v as f64) <= f), - (Parameters::Float(v), Parameters::Float(f)) => Bool(v <= f), - (Parameters::Float(v), Parameters::Int(i1)) => Bool(v <= (i1 as f64)), - (Bool(b), Parameters::Int(_)) => Bool(b), - (Bool(b), Parameters::Float(_)) => Bool(b), - (Parameters::Int(_), Bool(b)) => Bool(b), - (Parameters::Float(_), Bool(b)) => Bool(b), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Bool(b), Bool(b2)) => Bool(b == b2), - - (Parameters::Rational(_), Parameters::Null) => Bool(true), - (Parameters::Null, Parameters::Rational(_)) => Bool(true), - (Parameters::Rational(s), Parameters::Rational(s2)) => Bool(s <= s2), - (Parameters::Rational(s), Parameters::Int(i)) => Bool(s <= Rationals::new(1, i)), - (Parameters::Int(i), Parameters::Rational(s)) => Bool(Rationals::new(1, i) <= s), - (Parameters::Rational(s), Parameters::Float(f)) => Bool(s.approx() <= f), - (Parameters::Float(f), Parameters::Rational(s)) => Bool(f <= s.approx()), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - lesser_or_equal, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => apply_operator( - Parameters::Identifier(s), - Parameters::Int(i), - ram, - lesser_or_equal, - ), - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - lesser_or_equal, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - lesser_or_equal, - ), - (Parameters::Null, Parameters::Identifier(s)) => apply_operator( - Parameters::Identifier(s), - Parameters::Null, - ram, - lesser_or_equal, - ), - (Parameters::Identifier(s), Parameters::Null) => apply_operator( - Parameters::Identifier(s), - Parameters::Null, - ram, - lesser_or_equal, - ), - (Parameters::Int(i), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::Int(i), - Parameters::Identifier(s), - ram, - lesser_or_equal, - ), - (Parameters::Identifier(s), Parameters::Float(i)) => apply_operator( - Parameters::Identifier(s), - Parameters::Float(i), - ram, - lesser_or_equal, - ), - (Parameters::Float(i), Parameters::Identifier(s)) => apply_operator_reverse( - Parameters::Float(i), - Parameters::Identifier(s), - ram, - lesser_or_equal, - ), - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, lesser_or_equal) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, lesser_or_equal) - } - - _ => Parameters::Identifier( - "@Those two values are incompatible with the <= operator".to_string(), - ), - } -} - -pub fn equal( - i: Parameters, - i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match (i, i2) { - (Parameters::Null, Parameters::Int(_)) => Bool(true), - (Parameters::Null, Parameters::Float(_)) => Bool(true), - (Parameters::Int(_), Parameters::Null) => Bool(true), - (Parameters::Float(_), Parameters::Null) => Bool(true), - (Parameters::Int(v), Parameters::Int(v2)) => Bool(v == v2), - (Parameters::Int(v), Parameters::Float(f)) => Bool((v as f64) == f), - (Parameters::Float(v), Parameters::Float(f)) => Bool(v == f), - (Parameters::Float(v), Parameters::Int(i1)) => Bool(v == (i1 as f64)), - (Bool(_), Parameters::Int(_)) => Bool(false), - (Bool(_), Parameters::Float(_)) => Bool(false), - (Parameters::Int(_), Bool(_)) => Bool(false), - (Parameters::Float(_), Bool(_)) => Bool(false), - (Bool(_), Parameters::Null) => Bool(false), - (Parameters::Null, Bool(_)) => Bool(false), - (Bool(b), Bool(b2)) => Bool(b == b2), - - (Parameters::Rational(_), Parameters::Null) => Bool(true), - (Parameters::Null, Parameters::Rational(_)) => Bool(true), - (Parameters::Rational(s), Parameters::Rational(s2)) => Bool(s == s2), - (Parameters::Rational(s), Parameters::Int(i)) => Bool(s == Rationals::new(1, i)), - (Parameters::Int(i), Parameters::Rational(s)) => Bool(Rationals::new(1, i) == s), - (Parameters::Rational(s), Parameters::Float(f)) => Bool(s.approx() == f), - (Parameters::Float(f), Parameters::Rational(s)) => Bool(f == s.approx()), - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - equal, - ), - (Parameters::Identifier(s), Parameters::Int(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Int(i), ram, equal) - } - (Parameters::Null, Parameters::Identifier(s)) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, equal) - } - (Parameters::Identifier(s), Parameters::Null) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, equal) - } - (Parameters::Int(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Int(i), Parameters::Identifier(s), ram, equal) - } - (Parameters::Identifier(s), Parameters::Float(i)) => { - apply_operator(Parameters::Identifier(s), Parameters::Float(i), ram, equal) - } - (Parameters::Float(i), Parameters::Identifier(s)) => { - apply_operator_reverse(Parameters::Float(i), Parameters::Identifier(s), ram, equal) - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, equal) - } - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, equal) - } - - (Parameters::Rational(s), Parameters::Identifier(ss)) => apply_operator_reverse( - Parameters::Rational(s.clone()), - Parameters::Identifier(ss.clone()), - ram, - equal, - ), - (Parameters::Identifier(ss), Parameters::Rational(s)) => apply_operator( - Parameters::Identifier(ss), - Parameters::Rational(s), - ram, - equal, - ), - - _ => Parameters::Identifier( - "@Those two values are incompatible with the == operator".to_string(), - ), - } -} - -pub fn not( - i: Parameters, - _i2: Parameters, - ram: Option<&HashMap>, -) -> Parameters { - match i { - Bool(b) => Bool(!b), - Parameters::Identifier(s) => { - apply_operator(Parameters::Identifier(s), Parameters::Null, ram, not) - } - _ => Bool(false), - } -} - -pub fn and(i: Parameters, i2: Parameters, ram: Option<&HashMap>) -> Parameters { - match (i, i2) { - (Bool(b), Bool(b2)) => Bool(b && b2), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, and) - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, and) - } - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - and, - ), - _ => Bool(false), - } -} - -pub fn or(i: Parameters, i2: Parameters, ram: Option<&HashMap>) -> Parameters { - match (i, i2) { - (Bool(b), Bool(b2)) => Bool(b || b2), - (Bool(b), Parameters::Null) => Bool(b), - (Parameters::Null, Bool(b)) => Bool(b), - (Parameters::Identifier(s), Bool(b)) => { - apply_operator(Parameters::Identifier(s), Bool(b), ram, or) - } - (Bool(b), Parameters::Identifier(s)) => { - apply_operator_reverse(Bool(b), Parameters::Identifier(s), ram, or) - } - (Parameters::Identifier(s), Parameters::Identifier(s2)) => apply_operator( - Parameters::Identifier(s), - Parameters::Identifier(s2), - ram, - or, - ), - _ => Bool(false), - } -} - -#[cfg(test)] -mod test { - use crate::interpreting::function::{add, divide, minus, mult}; - use crate::parsing::ast::Parameters; - - #[test] - pub fn test_add_null() { - let expected = Parameters::Int(1); - let result = add(Parameters::Int(1), Parameters::Null, None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_add_simple() { - let expected = Parameters::Int(2); - let result = add(Parameters::Int(1), Parameters::Int(1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_add_float() { - let expected = Parameters::Float(2.1); - let result = add(Parameters::Float(0.1), Parameters::Float(2.0), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_add_int_float() { - let expected = Parameters::Float(2.1); - let result = add(Parameters::Int(2), Parameters::Float(0.1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_add_float_int() { - let expected = Parameters::Float(2.1); - let result = add(Parameters::Float(0.1), Parameters::Int(2), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_minus_null() { - let expected = Parameters::Int(-1); - let result = minus(Parameters::Int(1), Parameters::Null, None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_minus_null_rev() { - let expected = Parameters::Int(-1); - let result = minus(Parameters::Null, Parameters::Int(1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_minus_simple() { - let expected = Parameters::Int(0); - let result = minus(Parameters::Int(1), Parameters::Int(1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_minus_float() { - let expected = Parameters::Float(1.9); - let result = minus(Parameters::Float(2.0), Parameters::Float(0.1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_minus_int_float() { - let expected = Parameters::Float(1.9); - let result = minus(Parameters::Int(2), Parameters::Float(0.1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_minus_float_int() { - let expected = Parameters::Float(-1.9); - let result = minus(Parameters::Float(0.1), Parameters::Int(2), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_mult_null() { - let expected = Parameters::Int(1); - let result = mult(Parameters::Int(1), Parameters::Null, None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_mult_simple() { - let expected = Parameters::Int(2); - let result = mult(Parameters::Int(1), Parameters::Int(2), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_mult_float() { - let expected = Parameters::Float(0.2); - let result = mult(Parameters::Float(0.1), Parameters::Float(2.0), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_mult_int_float() { - let expected = Parameters::Float(0.2); - let result = mult(Parameters::Int(2), Parameters::Float(0.1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_mult_float_int() { - let expected = Parameters::Float(0.2); - let result = mult(Parameters::Float(0.1), Parameters::Int(2), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_divide_null() { - let expected = Parameters::Int(1); - let result = divide(Parameters::Int(1), Parameters::Null, None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_divide_simple() { - let expected = - Parameters::Rational(crate::exact_math::rationals::Rationals { under: 1, over: 1 }); - let result = divide(Parameters::Int(1), Parameters::Int(1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_divide_float() { - let expected = Parameters::Float(0.05); - let result = divide(Parameters::Float(0.1), Parameters::Float(2.0), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_divide_int_float() { - let expected = Parameters::Float(20.0); - let result = divide(Parameters::Int(2), Parameters::Float(0.1), None); - assert_eq!(result, expected); - } - - #[test] - pub fn test_divide_float_int() { - let expected = Parameters::Float(0.05); - let result = divide(Parameters::Float(0.1), Parameters::Int(2), None); - assert_eq!(result, expected); - } -} diff --git a/src/interpreting/interpreter.rs b/src/interpreting/interpreter.rs index 29a610f..af27e94 100644 --- a/src/interpreting/interpreter.rs +++ b/src/interpreting/interpreter.rs @@ -1,10 +1,12 @@ use std::collections::HashMap; use crate::exact_math::rationals::Rationals; -use crate::interpreting::function::{ - add, and, assign, divide, equal, expo, greater, greater_or_equal, lesser, lesser_or_equal, - minus, mult, not, or, -}; +use crate::functions::add::add; +use crate::functions::divide::divide; +use crate::functions::expo::expo; +use crate::functions::function::*; +use crate::functions::minus::minus; +use crate::functions::mult::mult; use crate::interpreting::stdlib::exec; use crate::parsing::ast::{Ast, Parameters}; @@ -89,6 +91,10 @@ pub fn interpret( Parameters::InterpreterVector(Box::from(vec)) } Parameters::InterpreterVector(a) => Parameters::InterpreterVector(a.clone()), + Parameters::Var(x, y, z) => Parameters::Var(x.clone(), y.clone(), z.clone()), + Parameters::Plus(x, y) => add(*x.clone(), *y.clone(), Some(&ram)), + Parameters::Mul(x, y) => mult(*x.clone(), *y.clone(), Some(&ram)), + Parameters::Div(x, y) => divide(*x.clone(), *y.clone(), Some(&ram)), }; last.clone() } diff --git a/src/interpreting/mod.rs b/src/interpreting/mod.rs index 7468fc8..4900225 100644 --- a/src/interpreting/mod.rs +++ b/src/interpreting/mod.rs @@ -1,3 +1,2 @@ -pub mod function; pub(crate) mod interpreter; pub mod stdlib; diff --git a/src/interpreting/stdlib.rs b/src/interpreting/stdlib.rs index d03e874..8c602c9 100644 --- a/src/interpreting/stdlib.rs +++ b/src/interpreting/stdlib.rs @@ -9,7 +9,8 @@ use crate::parsing::ast::{Ast, Parameters}; use crate::utils::matrix_utils::{lup_decompose, lup_determinant, lup_invert, transpose}; use crate::utils::plot_utils::computes_lines; -use super::function::{add as other_add, mult}; +use crate::functions::add::add as other_add; +use crate::functions::mult::mult; pub fn exec( s: String, diff --git a/src/main.rs b/src/main.rs index a16269a..364154a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ use std::io::BufRead; mod configuration; mod exact_math; +mod functions; mod interpreting; mod lexing; mod parsing; @@ -262,7 +263,7 @@ fn handle_config(line: &str, config: Config) -> (String, Option) { fn main() { let mut args: Args = env::args(); - let version: String = "v2.13.2".to_string(); + let version: String = "v3.0.0".to_string(); if args.len() > 1 || !atty::is(Stream::Stdin) { let mut a = vec![]; diff --git a/src/parsing/ast.rs b/src/parsing/ast.rs index 9ae87fd..21d7f37 100644 --- a/src/parsing/ast.rs +++ b/src/parsing/ast.rs @@ -32,6 +32,10 @@ pub enum Parameters { ExpoOperation, Vector(Box>), InterpreterVector(Box>), + Var(Box, i64, String), + Plus(Box, Box), + Mul(Box, Box), + Div(Box, Box), } #[derive(Debug, Clone, PartialEq)] @@ -48,6 +52,41 @@ pub enum Ast { }, } +fn int_to_superscript_string(i: i64) -> String { + fn digit_to_superscript_char(i: &str) -> &str { + match i { + "-" => "⁻", + "0" => "⁰", + "1" => "¹", + "2" => "²", + "3" => "³", + "4" => "⁴", + "5" => "⁵", + "6" => "⁶", + "7" => "⁷", + "8" => "⁸", + "9" => "⁹", + _ => "", + } + } + + let mut vec = vec![]; + let string_int = i.to_string(); + string_int + .split("") + .map(|x| digit_to_superscript_char(x)) + .for_each(|f| vec.push(f)); + + let i = vec.join(""); + if i == "⁰".to_string() { + "error".to_string() + } else if i == "¹" { + "".to_string() + } else { + i + } +} + impl Display for Parameters { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -74,6 +113,10 @@ impl Display for Parameters { InterpreterVector(a) => write!(f, "{:?}", a), Str(s) => write!(f, "{s}"), Rational(s) => write!(f, "{s}"), + Plus(x, y) => write!(f, "(({x})+({y}))"), + Mul(x, y) => write!(f, "(({x})*({y}))"), + Var(x, y, s) => write!(f, "({x}){s}{}", int_to_superscript_string(*y)), + Div(x, y) => write!(f, "(({x})/({y}))"), } } } @@ -116,7 +159,7 @@ impl Parameters { return self.to_string(); } else { match ram.as_mut().unwrap().get(s) { - None => "This variable is not initialized yet".to_string(), + None => s.to_string(), Some(t) => t.clone().pretty_print( Some(ram.as_mut().unwrap()), Some(function.as_mut().unwrap()), @@ -125,6 +168,131 @@ impl Parameters { } } } + + Var(x, y, z) => { + let l = int_to_superscript_string(*y); + if l == "error".to_string() { + format!("{}", x.clone()) + } else { + let division = l.starts_with("⁻"); + let separator = if division { "/" } else { "" }; + let v = &x.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + let vs = format!("({v})"); + + let first_attach = match **x { + Int(1) => { + if division { + "1" + } else { + "" + } + } + Float(f) if f >= 1.0 - 1e10 && f <= 1.0 + 1e10 => { + if division { + "1" + } else { + "" + } + } + Rational(r) if r.clone() == Rationals::new(1, 1) => { + if division { + "1" + } else { + "" + } + } + Int(-1) => { + if division { + "-1" + } else { + "-" + } + } + Float(f) if f <= -1.0 - 1e10 && f >= -1.0 + 1e10 => { + if division { + "-1" + } else { + "" + } + } + Rational(r) if r.clone() == Rationals::new(-1, 1) => { + if division { + "-1" + } else { + "" + } + } + _ => vs.as_str(), + }; + let e = l.replace("⁻", ""); + format!( + "{}{}{}{}", + first_attach, + separator, + z, + if l == "¹" { + "" + } else if l == "⁻¹" { + "" + } else { + e.as_str() + } + ) + } + } + + Mul(x, y) => { + let x_printed = x.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + let y_printed = y.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + format!("({x_printed})*({y_printed})") + } + + Plus(x, y) => { + let mut x_printed = x.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + let y_printed = y.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + if x_printed == "0" { + x_printed = "".to_string() + } + match y_printed.chars().nth(0) { + Some('-') => format!("({}{})", x_printed, y_printed), + _ => { + if y_printed == "0".to_string() { + format!("{}", x_printed) + } else { + format!("({})+({})", x_printed, y_printed) + } + } + } + } + + Div(x, y) => { + let x_printed = x.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + let y_printed = y.pretty_print( + Some(ram.as_mut().unwrap()), + Some(function.as_mut().unwrap()), + ); + + format!("({x_printed})/({y_printed})") + } + InterpreterVector(lst) => { let mut vec = Vec::new(); diff --git a/src/utils/matrix_utils.rs b/src/utils/matrix_utils.rs index b696937..75a016e 100644 --- a/src/utils/matrix_utils.rs +++ b/src/utils/matrix_utils.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; use crate::{ - interpreting::function::{add, divide, greater, minus, mult}, - parsing::ast::Parameters, + functions::add::add, functions::divide::divide, functions::function::*, + functions::minus::minus, functions::mult::mult, parsing::ast::Parameters, }; pub fn transpose(matrix: Vec>) -> Vec> { @@ -225,8 +225,7 @@ pub fn lup_invert( mod test { use crate::{ - interpreting::function::{greater, minus}, - parsing::ast::Parameters, + functions::function::greater, functions::minus::minus, parsing::ast::Parameters, utils::matrix_utils::lup_determinant, };