Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigonometric functions #643

Merged
merged 8 commits into from
Jan 2, 2024
Next Next commit
log and least_square_approx functions are now generic
  • Loading branch information
mihaubuhai committed Jan 1, 2024
commit e8195a188a24438d53db56a7c1b83502564c14a9
13 changes: 10 additions & 3 deletions src/math/least_square_approx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
///
/// degree -> degree of the polynomial
///
pub fn least_square_approx(points: &[(f64, f64)], degree: i32) -> Vec<f64> {
pub fn least_square_approx<T: Into<f64> + Copy>(points: &[(T, T)], degree: i32) -> Vec<f64> {
use nalgebra::{DMatrix, DVector};

/* Used for rounding floating numbers */
Expand All @@ -18,16 +18,23 @@ pub fn least_square_approx(points: &[(f64, f64)], degree: i32) -> Vec<f64> {
(value * multiplier).round() / multiplier
}

/* Casting the data parsed to this function to f64 (as some points can have decimals) */
let vals: Vec<(f64, f64)> = points
.iter()
.map(|(x, y)| ((*x).into(), (*y).into()))
/* Because of dereferencing the refferences we need the Copy Trait for T */
.collect();

/* Computes the sums in the system of equations */
let mut sums = Vec::<f64>::new();
for i in 1..=(2 * degree + 1) {
sums.push(points.iter().map(|(x, _)| x.powi(i - 1)).sum());
sums.push(vals.iter().map(|(x, _)| x.powi(i - 1)).sum());
}

let mut free_col = Vec::<f64>::new();
/* Compute the free terms column vector */
for i in 1..=(degree + 1) {
free_col.push(points.iter().map(|(x, y)| y * (x.powi(i - 1))).sum());
free_col.push(vals.iter().map(|(x, y)| y * (x.powi(i - 1))).sum());
}
let b = DVector::from_row_slice(&free_col);

Expand Down
16 changes: 9 additions & 7 deletions src/math/logarithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,36 @@ use std::f64::consts::E;
/// <p>-> tol: tolerance; the precision of the approximation
///
/// Advisable to use **std::f64::consts::*** for specific bases (like 'e')
pub fn log(base: f64, mut x: f64, tol: f64) -> f64 {
pub fn log<T: Into<f64>>(base: T, x: T, tol: f64) -> f64 {
let mut rez: f64 = 0f64;
let mut argument: f64 = x.into();
let usable_base: f64 = base.into();

if x <= 0f64 || base <= 0f64 {
if argument <= 0f64 || usable_base <= 0f64 {
println!("Log does not support negative argument or negative base.");
f64::NAN
} else if x < 1f64 && base == E {
} else if argument < 1f64 && usable_base == E {
/*
For x in (0, 1) and base 'e', the function is using MacLaurin Series:
ln(|1 + x|) = Σ "(-1)^n-1 * x^n / n", for n = 1..inf
Substituting x with x-1 yields:
ln(|x|) = Σ "(-1)^n-1 * (x-1)^n / n"
*/
x -= 1f64;
argument -= 1f64;

let mut prev_rez = 1f64;
let mut step: i32 = 1;

while (prev_rez - rez).abs() > tol {
prev_rez = rez;
rez += (-1f64).powi(step - 1) * x.powi(step) / step as f64;
rez += (-1f64).powi(step - 1) * argument.powi(step) / step as f64;
step += 1;
}

rez
} else {
let ln_x = x.ln();
let ln_base = base.ln();
let ln_x = argument.ln();
let ln_base = usable_base.ln();

ln_x / ln_base
}
Expand Down