feat(maths::solver): 2nd degree and print

This commit is contained in:
gbrochar 2023-08-23 11:24:55 +02:00
parent a3fc212283
commit bc830947b1
6 changed files with 3844 additions and 4 deletions

3372
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,3 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tectonic = "0.14.1"

BIN
file-modified.pdf Normal file

Binary file not shown.

View File

@ -1,5 +1,8 @@
use std::env;
use std::fs::File;
use std::io::Write;
use std::process;
use tectonic;
fn main() {
let args: Vec<String> = env::args().collect();
@ -21,4 +24,19 @@ fn main() {
if is_equation {
computorv1::maths::solver::solve(evaluated);
}
/*
let latex = r#"
\documentclass{article}
\begin{document}
Hello, world!
\end{document}
"#;
let pdf_data: Vec<u8> = tectonic::latex_to_pdf(latex).expect("processing failed");
println!("Output PDF size is {} bytes", pdf_data.len());
// Write the modified data.
let mut f = File::create("file-modified.pdf").unwrap();
f.write_all(pdf_data.as_slice()).unwrap();
*/
}

View File

@ -28,7 +28,13 @@ impl Rational {
pub fn reduce(&self) -> Self {
let gcd = gcd(self.numerator, self.denominator);
Rational::new(self.numerator / gcd, self.denominator / gcd)
let mut res = Rational::new(self.numerator / gcd, self.denominator / gcd);
if res.numerator < 0 && res.denominator < 0 {
res = -1 * res;
} else if res.denominator < 0 {
res = Rational::new(-res.numerator, -res.denominator);
}
res
}
pub fn inverse(&self) -> Self {
@ -50,6 +56,18 @@ impl Rational {
let res = Rational::new(lhs.numerator * rhs.denominator, lhs.denominator * rhs.numerator);
res.reduce()
}
pub fn is_zero(&self) -> bool {
self.numerator == 0
}
pub fn numerator(&self) -> i128 {
self.numerator
}
pub fn denominator(&self) -> i128 {
self.denominator
}
}
impl ops::Add<Rational> for Rational {
@ -173,6 +191,18 @@ impl GaussianRational {
self.imaginary.print();
print!("i");
}
pub fn is_real(&self) -> bool {
self.imaginary.is_zero()
}
pub fn real(&self) -> Rational {
self.real
}
pub fn imaginary(&self) -> Rational {
self.imaginary
}
}
impl ops::Add<GaussianRational> for GaussianRational {
@ -199,6 +229,22 @@ impl ops::Mul<GaussianRational> for GaussianRational {
}
}
impl ops::Mul<i128> for GaussianRational {
type Output = GaussianRational;
fn mul(self, rhs: i128) -> GaussianRational {
GaussianRational::new(self.real * rhs, self.imaginary * rhs)
}
}
impl ops::Mul<GaussianRational> for i128 {
type Output = GaussianRational;
fn mul(self, rhs: GaussianRational) -> GaussianRational {
GaussianRational::new(self * rhs.real, self * rhs.imaginary)
}
}
impl ops::Div<GaussianRational> for GaussianRational {
type Output = GaussianRational;
@ -207,3 +253,19 @@ impl ops::Div<GaussianRational> for GaussianRational {
GaussianRational::new(Rational::simplify(self.real * rhs.real + self.imaginary * rhs.imaginary, cd_squared), Rational::simplify(self.imaginary * rhs.real - self.real * rhs.imaginary, cd_squared))
}
}
/*
pub struct SquareRoot {
rational: Rational,
irrational: Rational,
}
pub struct Algebraic {
rational: Rational,
algebraic: SquareRoot,
}
pub struct GaussianAlgebraic {
real: Algebraic,
imaginary: Algebraic,
}*/

View File

@ -24,12 +24,367 @@ fn degree_one(equation: Vec<GaussianRational>) {
println!("{:?}", x);
}
#[derive(Debug)]
struct MySqrt {
numerator_natural: i128,
numerator_irrational: i128,
denominator: i128,
}
#[derive(Debug)]
struct MyCompSqrt {
sqrt: MySqrt,
rational: Rational,
sign: i128,
}
fn simplify_sqrt(mut n: i128) -> (i128, i128) {
if n == 0 {
return (0, 0);
}
let mut prime_factors = vec![];
let mut prime = 3;
println!("stuck {n}");
while n != 1 {
if n % (prime - 1) == 0 {
println!("stuck {n} {}", prime - 1);
prime_factors.push(prime - 1);
n /= prime - 1;
} else if n % (prime + 1) == 0 {
println!("stuck {n} {}", prime + 1);
prime_factors.push(prime + 1);
n /= prime + 1;
} else {
if prime > 5 {
prime += 6;
} else {
prime += 1;
}
}
}
let (mut natural, mut irrational) = (1, 1);
prime_factors = prime_factors.into_iter().rev().collect();
while prime_factors.len() > 1 {
let pop = prime_factors.pop().unwrap();
if *prime_factors.last().unwrap() == pop {
natural *= pop;
prime_factors.pop();
} else {
irrational *= pop;
}
}
if let Some(n) = prime_factors.pop() {
irrational *= n;
}
(natural, irrational)
}
fn comp_sqrt(c: GaussianRational) -> MyCompSqrt {
println!("c in comp_sqrt: {:?}", c);
let real = c.real();
let imag = c.imaginary();
let n = real * real + imag * imag;
let numerator_irrational = n.numerator * n.denominator;
println!("numerator_irrational {:?}", numerator_irrational);
let (mut numerator_natural, numerator_irrational) = simplify_sqrt(numerator_irrational);
println!("numerator_irrational {:?} numerator_natural {:?}", numerator_irrational, numerator_natural);
let mut denominator = n.denominator;
let gcd_var = gcd(numerator_natural, denominator);
denominator /= gcd_var;
numerator_natural /= gcd_var;
println!("{numerator_natural} * sqrt({numerator_irrational})");
println!("----------------------");
println!("{denominator}");
let mut sqrt = MySqrt {
numerator_natural,
numerator_irrational,
denominator,
};
let mut sign = 1;
if c.imaginary.numerator < 0 {
sign = -1;
}
let mut rational = c.real;
rational = rational / 2;
if sqrt.numerator_natural % 2 == 0 {
sqrt.numerator_natural /= 2;
} else {
sqrt.denominator *= 2;
}
// Here we multiply by 4 to avoid dividing by 2 later and ease ascii art
if sqrt.denominator != rational.denominator {
let mem = sqrt.denominator;
sqrt.denominator *= rational.denominator * 4;
sqrt.numerator_natural *= rational.denominator;
rational.numerator *= mem;
rational.denominator *= mem * 4;
}
let gcd = gcd(gcd(sqrt.denominator, sqrt.numerator_natural), rational.numerator);
sqrt.denominator /= gcd;
sqrt.numerator_natural /= gcd;
rational.numerator /= gcd;
rational.denominator /= gcd;
MyCompSqrt {
sqrt,
rational,
sign,
}
}
fn get_strings(left_part: Rational, sqrt_delta: MySqrt) -> (String, String, String, String, String, String) {
let mut a = left_part.numerator;
let mut b = sqrt_delta.numerator_natural;
if b < 0 {
b = -b;
}
let c = sqrt_delta.numerator_irrational;
let mut d = left_part.denominator;
if d < 0 {
a = -a;
d = -d;
}
let mut string = String::from("");
if b != 0 || c != 0 {
if b != 1 && c != 1 {
string = format!("+ {b} * sqrt({c})");
} else if b != 1 {
string = format!("+ {b}");
} else if c != 1 {
string = format!("+ sqrt({c})");
} else {
string = format!("+ 1");
}
}
let string_a = format!("{a} {string}");
let string_b = format!("{} {string}", -a);
let len = std::cmp::max(string_a.len(), format!("{d}").len()) + 2;
let len_b = std::cmp::max(string_b.len(), format!("{d}").len()) + 2;
println!("len {len}, b {len_b}");
let len1 = len - string_a.len();
let len2 = len - d.to_string().len();
let len1b = len_b - string_b.len();
let len2b = len_b - d.to_string().len();
println!("len1 {len1}, 2 {len2}, b {len1b} 2b {len2b}");
println!("{a} {b} {c} {d}");
let mut string1 = String::from("");
let mut string2 = String::from("");
let mut string3 = String::from("");
let mut string4 = String::from("");
let mut string5 = String::from("");
let mut string6 = String::from("");
if d != 1 {
string1 = format!("{}{string_a}{}", " ".repeat(len1 / 2), " ".repeat(len1 / 2 + len1 % 2));
string2 = format!("{}", "-".repeat(len));
string3 = format!("{}{d}{}", " ".repeat(len2 / 2), " ".repeat(len2 / 2 + len2 % 2));
string4 = format!("{}{string_b}{}", " ".repeat(len1b / 2), " ".repeat(len1b / 2 + len1b % 2));
string5 = format!("{}", "-".repeat(len_b));
string6 = format!("{}{d}{}", " ".repeat(len2b / 2), " ".repeat(len2b / 2 + len2b % 2));
} else if string.len() > 0 {
string1 = format!("{}", string.len());
string2 = format!("{string_a}");
string3 = format!("{}", string.len());
string4 = format!("{}", string.len());
string5 = format!("{string_b}");
string6 = format!("{}", string.len());
} else {
string1 = format!(" ");
string2 = format!("0");
string3 = format!(" ");
string4 = format!(" ");
string5 = format!("0");
string6 = format!(" ");
}
(string1, string2, string3, string4, string5, string6)
}
fn degree_two_complex(a: GaussianRational, b: GaussianRational, c: GaussianRational) {
// Here we divide by a to avoid dividing by complex later and ease ascii art
let b = b / a;
let c = c / a;
let delta = b * b - 4 * c;
println!("this is complex {:?}", delta);
let sqrt_delta = comp_sqrt(delta);
println!("{:?}", sqrt_delta);
let b = b / GaussianRational::new(Rational::new(2, 1), Rational::new(0, 1));
println!("BEWARE IM GOING TO PRINT THE SOLUTIONS MDR");
/*
2362 / 473 + sqrt(7896511271) \ 49 / -473 + sqrt(7896511271) \
---- + sqrt | ------------------------ | + -- i sign sqrt | ------------------------- | i
32 \ 45150 / 13 \ 45150 /
*/
let b_real_len = std::cmp::max(format!("{}", b.real.denominator).len(), format!("{}", b.real.numerator).len()) + 2;
let b_imag_len = std::cmp::max(format!("{}", b.imaginary.denominator).len(), format!("{}", b.imaginary.numerator).len()) + 2;
let mut sign = '+';
if sqrt_delta.sign < 0 {
sign = '-';
}
let (s1, s2, s3, s4, s5, s6) = get_strings(sqrt_delta.rational, sqrt_delta.sqrt);
let space1 = b_real_len - format!("{}", b.real.numerator).len();
let space2 = b_imag_len - format!("{}", b.imaginary.numerator).len();
let space3 = b_real_len - format!("{}", b.real.denominator).len();
let space4 = b_imag_len - format!("{}", b.imaginary.denominator).len();
let string1 = format!("{}{}{} / {s1} \\ {}{}{} / {s4} \\ ", " ".repeat(space1 / 2), b.real.numerator, " ".repeat(space1 / 2 + space1 % 2), " ".repeat(space2 / 2), b.imaginary.numerator, " ".repeat(space2 / 2 + space2 % 2));
let string2 = format!("{} + sqrt | {s2} | + {} i {sign} sqrt | {s5} | i", "-".repeat(b_real_len), "-".repeat(b_imag_len));
let string3 = format!("{}{}{} \\ {s3} / {}{}{} \\ {s6} / ", " ".repeat(space3 / 2), b.real.denominator, " ".repeat(space3 / 2 + space3 % 2), " ".repeat(space4 / 2), b.imaginary.denominator, " ".repeat(space4 / 2 + space4 % 2));
println!("{string1}");
println!("{string2}");
println!("{string3}");
}
fn sqrt(n: Rational, a: Rational) -> MySqrt {
let numerator_irrational = n.numerator * n.denominator;
let (mut numerator_natural, numerator_irrational) = simplify_sqrt(numerator_irrational);
numerator_natural *= a.denominator;
let mut denominator = n.denominator * 2 * a.numerator;
let gcd = gcd(numerator_natural, denominator);
denominator /= gcd;
numerator_natural /= gcd;
MySqrt {
numerator_natural,
numerator_irrational,
denominator,
}
}
fn print_degree_two_real(left_part: Rational, sqrt_delta: MySqrt, imaginary: bool) {
let mut a = left_part.numerator;
let mut b = sqrt_delta.numerator_natural;
if b < 0 {
b = -b;
}
let c = sqrt_delta.numerator_irrational;
let mut d = left_part.denominator;
if d < 0 {
a = -a;
d = -d;
}
let mut string = String::from("");
if a != 0 {
string = format!("{a} ");
}
if b != 0 || c != 0 {
if imaginary == true {
if b != 1 && c != 1 {
string = format!("{string}± ({b} * sqrt({c}))i");
} else if b != 1 {
string = format!("{string}± {b}i");
} else if c != 1 {
string = format!("{string}± sqrt({c})i");
} else {
string = format!("{string}± i");
}
} else {
if b != 1 && c != 1 {
string = format!("{string}± {b} * sqrt({c})");
} else if b != 1 {
string = format!("{string}± {b}");
} else if c != 1 {
string = format!("{string}± sqrt({c})");
} else {
string = format!("{string}± 1");
}
}
}
let len = std::cmp::max(string.chars().count(), format!("{d}").len()) + 2;
println!("{a} {b} {c} {d}");
println!("len {len} s_len {}", string.len());
println!("{string}");
if b != 0 || c != 0 {
println!("The two solutions are:");
} else {
println!("The solution is:");
}
if d != 1 {
println!("{}{string}", " ".repeat(4 + (len - string.chars().count()) / 2));
println!("x = {}", "-".repeat(len));
println!("{}{d}", " ".repeat(4 + (len - d.to_string().len()) / 2));
} else if string.len() > 0 {
println!("x = {string}");
} else {
println!("x = 0");
}
}
fn degree_two_real(a: Rational, b: Rational, c: Rational) {
println!("a {:?} b {:?} c {:?}", a, b ,c);
let mut delta = b * b - 4 * a * c;
println!("delta {:?}", delta);
println!("anumera {:?}", a.numerator());
let mut imaginary = false;
if delta.numerator < 0 {
imaginary = true;
println!("imag {:?}", delta);
delta = -1 * delta;
println!("imag {:?}", delta);
}
let mut sqrt_delta = sqrt(delta, a);
let mut left_part = (-1 * b) / (2 * a);
let tmp = left_part.denominator;
left_part.denominator *= sqrt_delta.denominator;
left_part.numerator *= sqrt_delta.denominator;
sqrt_delta.numerator_natural *= tmp;
sqrt_delta.denominator *= tmp;
let gcd = gcd(gcd(sqrt_delta.numerator_natural, left_part.numerator), left_part.denominator);
left_part.denominator /= gcd;
left_part.numerator /= gcd;
sqrt_delta.numerator_natural /= gcd;
sqrt_delta.denominator /= gcd;
print_degree_two_real(left_part, sqrt_delta, imaginary);
}
fn degree_two(equation: Vec<GaussianRational>) {
println!("Polynomial degree: 2");
let delta = equation[1] * equation[1] + 4 * equation[0] * equation[0];
let (a, b, c) = (equation[2], equation[1], equation[0]);
if a.is_real() && b.is_real() && c.is_real() {
degree_two_real(a.real(), b.real(), c.real());
} else {
degree_two_complex(a, b, c);
}
}
*/
pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> {
for i in (1..equation.len()).rev() {
@ -44,8 +399,40 @@ pub fn solve(mut equation: Vec<GaussianRational>) -> Vec<GaussianRational> {
0 => unreachable!(),
1 => degree_zero(equation),
2 => degree_one(equation),
//3 => degree_two(equation),
3 => degree_two(equation),
_ => println!("Polynomial of degree greater than 2 detected, I can't solve that !"),
}
vec![]
}
/*
2362 / 473 + sqrt(7896511271) \ 49 / -473 + sqrt(7896511271) \
---- + sqrt | ------------------------ | + -- i sign sqrt | ------------------------- | i
32 \ 45150 / 13 \ 45150 /
*/
/*
/
sqrt |
\
/ 473 + sqrt(7896511271) \ / -473 + sqrt(7896511271) \
2362 + 37 * sqrt | ------------------------ | + 46 * sqrt | ------------------------- |
\ 45150 / \ 45150 /
--------------------------------------------------------------------------------------------- +
21615671563
/ -473 + sqrt(7896511271) \ / 473 + sqrt(7896511271) \
2362 + 37 * sqrt | ------------------------ | - 46 * sqrt | ------------------------- |
\ 45150 / \ 45150 /
--------------------------------------------------------------------------------------------- i
21615671563
*/