feat(maths): creation + clean maths in parser
This commit is contained in:
parent
b1eb997703
commit
8e3ebcd2a5
16
src/lib.rs
16
src/lib.rs
|
@ -4,16 +4,7 @@ use crate::parser::sanitizer::sanitize_tokens;
|
||||||
use crate::parser::ast_builder::{build_ast, Node};
|
use crate::parser::ast_builder::{build_ast, Node};
|
||||||
|
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
pub mod maths;
|
||||||
struct _Rational {
|
|
||||||
numerator: i128,
|
|
||||||
denominator: i128,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _GaussianRational {
|
|
||||||
real: _Rational,
|
|
||||||
imaginary: _Rational,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse(query: &str) -> Result<Node, Box<dyn Error>> {
|
pub fn parse(query: &str) -> Result<Node, Box<dyn Error>> {
|
||||||
let tokens = tokenize(query)?;
|
let tokens = tokenize(query)?;
|
||||||
|
@ -109,8 +100,3 @@ pub fn solve(equation: Vec<f64>) {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
use std::ops;
|
||||||
|
|
||||||
|
//TODO slow ? check Stein's algorithm (binaryGCD)
|
||||||
|
fn gcd(a: i128, b: i128) -> i128 {
|
||||||
|
if b == 0 {
|
||||||
|
a
|
||||||
|
} else {
|
||||||
|
gcd(b, a % b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Rational {
|
||||||
|
numerator: i128,
|
||||||
|
denominator: i128,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rational {
|
||||||
|
pub fn new(numerator: i128, denominator: i128) -> Self {
|
||||||
|
Self {
|
||||||
|
numerator,
|
||||||
|
denominator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reduce(&self) -> Self {
|
||||||
|
let gcd = gcd(self.numerator, self.denominator);
|
||||||
|
Rational::new(self.numerator / gcd, self.denominator / gcd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Add<Rational> for Rational {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn add(self, rhs: Rational) -> Rational {
|
||||||
|
Rational::new(self.numerator * rhs.denominator + rhs.numerator * self.denominator, self.denominator * rhs.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Add<i128> for Rational {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn add(self, rhs: i128) -> Rational {
|
||||||
|
Rational::new(self.numerator + rhs * self.denominator, self.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Add<Rational> for i128 {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn add(self, rhs: Rational) -> Rational {
|
||||||
|
Rational::new(self * rhs.denominator + rhs.numerator, rhs.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Sub<Rational> for Rational {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Rational) -> Rational {
|
||||||
|
Rational::new(self.numerator * rhs.denominator - rhs.numerator * self.denominator, self.denominator * rhs.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul<Rational> for Rational {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Rational) -> Rational {
|
||||||
|
Rational::new(self.numerator * rhs.numerator, self.denominator * rhs.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul<i128> for Rational {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn mul(self, rhs: i128) -> Rational {
|
||||||
|
Rational::new(self.numerator * rhs, self.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Mul<Rational> for i128 {
|
||||||
|
type Output = Rational;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Rational) -> Rational {
|
||||||
|
Rational::new(self * rhs.numerator, rhs.denominator).reduce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct GaussianRational {
|
||||||
|
real: Rational,
|
||||||
|
imaginary: Rational,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GaussianRational {
|
||||||
|
pub fn new(real: Rational, imaginary: Rational) -> Self {
|
||||||
|
Self {
|
||||||
|
real,
|
||||||
|
imaginary,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,5 @@
|
||||||
use super::Token;
|
use super::Token;
|
||||||
|
use crate::maths::{GaussianRational, Rational};
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct Rational {
|
|
||||||
numerator: i128,
|
|
||||||
denominator: i128,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct GaussianRational {
|
|
||||||
real: Rational,
|
|
||||||
imaginary: Rational,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
|
@ -23,76 +11,37 @@ pub enum Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
fn rational_zero() -> Rational {
|
||||||
pub struct Node {
|
Rational::new(0, 1)
|
||||||
_lhs: Option<Box<Node>>,
|
|
||||||
_rhs: Option<Box<Node>>,
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
fn rational_one() -> Rational {
|
||||||
|
Rational::new(1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rational_minus_one() -> Rational {
|
||||||
|
Rational::new(-1, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn zero() -> GaussianRational {
|
fn zero() -> GaussianRational {
|
||||||
GaussianRational {
|
GaussianRational::new(rational_zero(), rational_zero())
|
||||||
real: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
},
|
|
||||||
imaginary: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn minus_one() -> GaussianRational {
|
|
||||||
GaussianRational {
|
|
||||||
real: Rational {
|
|
||||||
numerator: -1,
|
|
||||||
denominator: 1,
|
|
||||||
},
|
|
||||||
imaginary: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn one() -> GaussianRational {
|
fn one() -> GaussianRational {
|
||||||
GaussianRational {
|
GaussianRational::new(rational_one(), rational_zero())
|
||||||
real: Rational {
|
|
||||||
numerator: 1,
|
|
||||||
denominator: 1,
|
|
||||||
},
|
|
||||||
imaginary: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn minus_one() -> GaussianRational {
|
||||||
|
GaussianRational::new(rational_minus_one(), rational_zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn i() -> GaussianRational {
|
fn i() -> GaussianRational {
|
||||||
GaussianRational {
|
GaussianRational::new(rational_zero(), rational_one())
|
||||||
real: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
},
|
|
||||||
imaginary: Rational {
|
|
||||||
numerator: 1,
|
|
||||||
denominator: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn minus_i() -> GaussianRational {
|
fn minus_i() -> GaussianRational {
|
||||||
GaussianRational {
|
GaussianRational::new(rational_zero(), rational_minus_one())
|
||||||
real: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
},
|
|
||||||
imaginary: Rational {
|
|
||||||
numerator: -1,
|
|
||||||
denominator: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn x() -> Vec<GaussianRational> {
|
fn x() -> Vec<GaussianRational> {
|
||||||
|
@ -128,34 +77,25 @@ fn get_parentheses_map(tokens: &Vec<Token>) -> Vec<usize> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_number(string: &String, sign: i128) -> GaussianRational {
|
fn parse_number(string: &String, sign: i128) -> GaussianRational {
|
||||||
let mut number = Rational {
|
let mut number = rational_zero();
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
};
|
|
||||||
let mut is_floating = false;
|
let mut is_floating = false;
|
||||||
|
|
||||||
for c in string.chars() {
|
for c in string.chars() {
|
||||||
match c {
|
match c {
|
||||||
'.' => is_floating = true,
|
'.' => is_floating = true,
|
||||||
'0'..='9' => {
|
'0'..='9' => {
|
||||||
number.numerator = 10 * number.numerator + String::from(c).parse::<i128>().unwrap();
|
number = 10 * number + String::from(c).parse::<i128>().unwrap();
|
||||||
if is_floating == true {
|
if is_floating == true {
|
||||||
number.denominator *= 10;
|
number = number * Rational::new(1, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
number.numerator *= sign;
|
number = number * sign;
|
||||||
|
|
||||||
GaussianRational {
|
GaussianRational::new(number, rational_zero())
|
||||||
real: number,
|
|
||||||
imaginary: Rational {
|
|
||||||
numerator: 0,
|
|
||||||
denominator: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_parentheses(tokens: &Vec<Token>) -> bool {
|
fn check_parentheses(tokens: &Vec<Token>) -> bool {
|
||||||
|
@ -432,8 +372,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn two_plus_two() {
|
fn two_plus_two() {
|
||||||
let mut two = one();
|
let two = GaussianRational::new(Rational::new(2, 1), rational_zero());
|
||||||
two.real.numerator = 2;
|
|
||||||
|
|
||||||
let tokens = vec![two_token(), plus(), two_token()];
|
let tokens = vec![two_token(), plus(), two_token()];
|
||||||
let results = Node::Internal {
|
let results = Node::Internal {
|
||||||
|
|
Loading…
Reference in New Issue