2023-08-01 14:36:58 +00:00
|
|
|
use std::error::Error;
|
2023-08-02 05:28:49 +00:00
|
|
|
use crate::parser::tokenizer::tokenize;
|
|
|
|
use crate::parser::sanitizer::sanitize_tokens;
|
2023-08-02 20:18:52 +00:00
|
|
|
use crate::parser::ast_builder::{build_ast, Node};
|
2023-08-06 12:07:10 +00:00
|
|
|
use crate::maths::GaussianRational;
|
2023-08-01 14:36:58 +00:00
|
|
|
|
2023-08-02 05:28:49 +00:00
|
|
|
pub mod parser;
|
2023-08-03 06:21:21 +00:00
|
|
|
pub mod maths;
|
2023-08-01 14:36:58 +00:00
|
|
|
|
2023-08-06 12:07:10 +00:00
|
|
|
|
2023-11-22 18:33:45 +00:00
|
|
|
pub fn format(v: &Vec<GaussianRational>) -> String {
|
|
|
|
let mut format;
|
|
|
|
format = v[0].format();
|
|
|
|
if v.len() > 1 {
|
|
|
|
if format == "" {
|
|
|
|
format = format!("{}x", v[1].format());
|
|
|
|
} else {
|
|
|
|
format = format!("{format} + {}x", v[1].format());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i in 2..v.len() {
|
|
|
|
let tmp = v[i].format();
|
|
|
|
if tmp != "" {
|
|
|
|
if format == ""{
|
|
|
|
format = format!("{tmp}x^{i}");
|
|
|
|
} else {
|
|
|
|
format = format!("{format} + {}x^{i}", tmp);
|
|
|
|
}
|
|
|
|
}
|
2023-08-06 12:07:10 +00:00
|
|
|
}
|
2023-11-22 18:33:45 +00:00
|
|
|
format = format.split("+ -").collect::<Vec<_>>().join("- ");
|
|
|
|
format = format.split("1x").collect::<Vec<_>>().join("x");
|
|
|
|
format.split("1i").collect::<Vec<_>>().join("i")
|
2023-08-06 12:07:10 +00:00
|
|
|
}
|
|
|
|
|
2023-08-02 20:18:52 +00:00
|
|
|
pub fn parse(query: &str) -> Result<Node, Box<dyn Error>> {
|
2023-08-01 14:36:58 +00:00
|
|
|
let tokens = tokenize(query)?;
|
|
|
|
let sanitized_tokens = sanitize_tokens(tokens)?;
|
2023-08-02 20:18:52 +00:00
|
|
|
let ast = build_ast(sanitized_tokens);
|
2023-08-01 14:36:58 +00:00
|
|
|
|
2023-08-02 20:18:52 +00:00
|
|
|
Ok(ast)
|
2023-08-01 14:36:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn print_reduced_form(equation: &Vec<f64>) {
|
|
|
|
let mut string = String::from("Reduced form: ");
|
|
|
|
|
|
|
|
for (i, n) in equation.iter().enumerate() {
|
|
|
|
let mut n = *n;
|
|
|
|
if n < 0. {
|
|
|
|
string += " - ";
|
|
|
|
n *= -1.;
|
|
|
|
} else if i != 0 {
|
|
|
|
string += " + ";
|
|
|
|
}
|
|
|
|
string.push_str(&n.to_string());
|
|
|
|
string.push_str(" * X^");
|
|
|
|
string.push_str(&i.to_string());
|
|
|
|
}
|
|
|
|
string += " = 0";
|
|
|
|
|
|
|
|
println!("{string}");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn sqrt(n: f64) -> f64 {
|
|
|
|
let mut z = 1.;
|
|
|
|
|
|
|
|
for _ in 0..10 {
|
|
|
|
z -= (z * z - n) / (2. * z);
|
|
|
|
}
|
|
|
|
|
|
|
|
z
|
|
|
|
}
|
|
|
|
|
|
|
|
fn solve_degree_0(equation: Vec<f64>) {
|
|
|
|
if equation[0] == 0. {
|
|
|
|
println!("Each real number is a solution.");
|
|
|
|
} else {
|
|
|
|
println!("There are no solutions to this equation");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn solve_degree_1(equation: Vec<f64>) {
|
|
|
|
println!("The solution is:");
|
|
|
|
println!("{}", -1. * equation[0] / equation[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn solve_degree_2(equation: Vec<f64>) {
|
|
|
|
let delta = equation[1] * equation[1] - 4. * equation[2] * equation[0];
|
|
|
|
|
|
|
|
if delta > 0. {
|
|
|
|
let sqrt_delta = sqrt(delta);
|
|
|
|
let x1 = (-equation[1] - sqrt_delta) / (2. * equation[2]);
|
|
|
|
let x2 = (-equation[1] + sqrt_delta) / (2. * equation[2]);
|
|
|
|
println!("Discriminant is strictly positive, the two solutions are:");
|
|
|
|
println!("{x1}");
|
|
|
|
println!("{x2}");
|
|
|
|
} else if delta < 0. {
|
|
|
|
let sqrt_delta = sqrt(delta);
|
|
|
|
let a = -equation[1] / (2. * equation[2]);
|
|
|
|
let b = sqrt_delta / (2. * equation[2]);
|
|
|
|
println!("Discriminant is strictly negative, the two complex solutions are:");
|
|
|
|
println!("{a} + {b}i");
|
|
|
|
println!("{a} - {b}i");
|
|
|
|
} else {
|
|
|
|
let x = -equation[1] / (2. * equation[2]);
|
|
|
|
println!("Discriminant is zero, the solution is:");
|
|
|
|
println!("{x}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn solve(equation: Vec<f64>) {
|
|
|
|
let degree = equation.len() - 1;
|
|
|
|
|
|
|
|
print_reduced_form(&equation);
|
|
|
|
println!("Polynomial degree: {degree}");
|
|
|
|
match degree {
|
|
|
|
0 => solve_degree_0(equation),
|
|
|
|
1 => solve_degree_1(equation),
|
|
|
|
2 => solve_degree_2(equation),
|
|
|
|
_ if degree > 2 => println!("The polynomial degree is strictly greater than 2, I can't solve."),
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|