Skip to content

Commit

Permalink
Add new functionalities to the app
Browse files Browse the repository at this point in the history
Add stats directory
Add utils folder
Add functions in each folder
  • Loading branch information
dr-saad-la committed Jul 1, 2024
1 parent 27f4b57 commit 05e6e5d
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 2 deletions.
6 changes: 4 additions & 2 deletions rustapps/advanced_calculator/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod calc;
pub mod tools;
mod calc;
mod stats;
mod tools;
mod utils;
35 changes: 35 additions & 0 deletions rustapps/advanced_calculator/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
#![allow(unused_imports)]

mod calc;
mod stats;
mod tools;
mod utils;

use calc::{add, divide, log, multiply, power, sqrt, subtract, trig};
use calc::{complex, exp, hyperbolic, hyperbolic_inverse, inverse_trig};
use calc::{factorial, gcd_lcm};
use num_complex::Complex;
use tools::banner;

use stats::{correlation, mean, median, mode, std};
use utils::constants::{E, PI};
use utils::conversion::{deg_to_rad, rad_to_deg};
use utils::num_methods::derivative;

fn main() {
let a = 10.0;
let b = 5.0;
Expand Down Expand Up @@ -48,6 +57,20 @@ fn main() {
let complex_b = Complex::new(3.0, 4.0);
let complex_sum = complex::add_complex(complex_a, complex_b);

let radians = deg_to_rad(180.0);
let degrees = rad_to_deg(PI);
let derivative_result = derivative(|x| x.powi(2), 2.0, 1e-5);

let data = [1.0, 2.0, 3.0, 4.0, 5.0];
let mean_result = mean::mean(&data);
let median_result = median::median(&data);
let mode_result = mode::mode(&data);
let stddev_result = std::std(&data);

let x = [1.0, 2.0, 3.0];
let y = [1.0, 2.0, 3.0];
let correlation_result = correlation::corr(&x, &y);

println!("{:<20} {}", "sum:", sum);
println!("{:<20} {}", "Difference:", difference);
println!("{:<20} {}", "Product:", product);
Expand Down Expand Up @@ -85,4 +108,16 @@ fn main() {
println!("GCD: {}", gcd_result);
println!("LCM: {}", lcm_result);
println!("Complex Sum: {}", complex_sum);

banner("*", 62, "Conversion Operations");
println!("Radians: {}", radians);
println!("Degrees: {}", degrees);
println!("Derivative: {}", derivative_result);

banner("*", 62, "Statistical Operations");
println!("Mean: {}", mean_result);
println!("Median: {}", median_result);
println!("Mode: {:?}", mode_result);
println!("Standard Deviation: {}", stddev_result);
println!("Correlation: {}", correlation_result);
}
5 changes: 5 additions & 0 deletions rustapps/advanced_calculator/src/stats.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod correlation;
pub mod mean;
pub mod median;
pub mod mode;
pub mod std;
37 changes: 37 additions & 0 deletions rustapps/advanced_calculator/src/stats/correlation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// Calculates the Pearson correlation coefficient between two slices of numbers.
///
/// # Arguments
///
/// * `x` - The first slice of f64 numbers.
/// * `y` - The second slice of f64 numbers.
///
/// # Returns
///
/// The Pearson correlation coefficient between `x` and `y`.
///
/// # Examples
///
/// ```
/// use advanced_calculator::stats::correlation::corr;
/// let x = [1.0, 2.0, 3.0];
/// let y = [1.0, 2.0, 3.0];
/// let result = corr(&x, &y);
/// assert_eq!(result, 1.0);
/// ```
pub fn corr(x: &[f64], y: &[f64]) -> f64 {
assert_eq!(x.len(), y.len());

let mean_x = super::mean::mean(x);
let mean_y = super::mean::mean(y);

let numerator: f64 = x
.iter()
.zip(y.iter())
.map(|(&x, &y)| (x - mean_x) * (y - mean_y))
.sum();

let denominator_x: f64 = x.iter().map(|&x| (x - mean_x).powi(2)).sum();
let denominator_y: f64 = y.iter().map(|&y| (y - mean_y).powi(2)).sum();

numerator / (denominator_x.sqrt() * denominator_y.sqrt())
}
22 changes: 22 additions & 0 deletions rustapps/advanced_calculator/src/stats/mean.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// Calculates the mean of a slice of numbers.
///
/// # Arguments
///
/// * `data` - A slice of f64 numbers.
///
/// # Returns
///
/// The mean of the numbers.
///
/// # Examples
///
/// ```
/// use advanced_calculator::stats::mean::mean;
/// let data = [1.0, 2.0, 3.0, 4.0, 5.0];
/// let result = mean(&data);
/// assert_eq!(result, 3.0);
/// ```
pub fn mean(data: &[f64]) -> f64 {
let sum: f64 = data.iter().sum();
sum / data.len() as f64
}
28 changes: 28 additions & 0 deletions rustapps/advanced_calculator/src/stats/median.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// Calculates the median of a slice of numbers.
///
/// # Arguments
///
/// * `data` - A slice of f64 numbers.
///
/// # Returns
///
/// The median of the numbers.
///
/// # Examples
///
/// ```
/// use advanced_calculator::stats::median::median;
/// let data = [1.0, 2.0, 3.0, 4.0, 5.0];
/// let result = median(&data);
/// assert_eq!(result, 3.0);
/// ```
pub fn median(data: &[f64]) -> f64 {
let mut sorted_data = data.to_vec();
sorted_data.sort_by(|a, b| a.partial_cmp(b).unwrap());
let len = sorted_data.len();
if len % 2 == 0 {
(sorted_data[len / 2 - 1] + sorted_data[len / 2]) / 2.0
} else {
sorted_data[len / 2]
}
}
41 changes: 41 additions & 0 deletions rustapps/advanced_calculator/src/stats/mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::collections::HashMap;

/// Converts an `f64` to `i64` by scaling. This approach is simple but may lose precision for very large or small values.
fn float_to_int_key(value: f64) -> i64 {
(value * 1_000_000.0) as i64
}

/// Calculates the mode of a slice of numbers.
///
/// # Arguments
///
/// * `data` - A slice of f64 numbers.
///
/// # Returns
///
/// A vector containing the mode(s) of the numbers.
///
/// # Examples
///
/// ```
/// use advanced_calculator::stats::mode::mode;
/// let data = [1.0, 2.0, 2.0, 3.0];
/// let result = mode(&data);
/// assert_eq!(result, vec![2.0]);
/// ```
pub fn mode(data: &[f64]) -> Vec<f64> {
let mut occurrences: HashMap<i64, usize> = HashMap::new();
for &value in data {
let key = float_to_int_key(value);
*occurrences.entry(key).or_insert(0) += 1;
}

let max_occurrence = occurrences.values().cloned().max().unwrap_or(0);
let modes: Vec<f64> = occurrences
.into_iter()
.filter(|&(_, count)| count == max_occurrence)
.map(|(key, _)| key as f64 / 1_000_000.0)
.collect();

modes
}
31 changes: 31 additions & 0 deletions rustapps/advanced_calculator/src/stats/std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// Calculates the standard deviation of a slice of numbers.
///
/// # Arguments
///
/// * `data` - A slice of f64 numbers.
///
/// # Returns
///
/// The standard deviation of the numbers.
///
/// # Examples
///
/// ```
/// use advanced_calculator::stats::std::std;
/// let data = [1.0, 2.0, 3.0, 4.0, 5.0];
/// let result = std(&data);
/// assert_eq!(result, 1.5811388300841898);
/// ```
pub fn std(data: &[f64]) -> f64 {
let mean = super::mean::mean(data);
let variance = data
.iter()
.map(|value| {
let diff = mean - *value;
diff * diff
})
.sum::<f64>()
/ data.len() as f64;

variance.sqrt()
}
3 changes: 3 additions & 0 deletions rustapps/advanced_calculator/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod constants;
pub mod conversion;
pub mod num_methods;
4 changes: 4 additions & 0 deletions rustapps/advanced_calculator/src/utils/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/// Mathematical constants.
pub const PI: f64 = std::f64::consts::PI;
pub const E: f64 = std::f64::consts::E;
pub const GOLDEN_RATIO: f64 = 1.61803398875;
41 changes: 41 additions & 0 deletions rustapps/advanced_calculator/src/utils/conversion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/// Converts degrees to radians.
///
/// # Arguments
///
/// * `degrees` - The angle in degrees.
///
/// # Returns
///
/// The angle in radians.
///
/// # Examples
///
/// ```
/// use advanced_calculator::utils::conversions::deg_to_rad;
/// let result = deg_to_rad(180.0);
/// assert_eq!(result, std::f64::consts::PI);
/// ```
pub fn deg_to_rad(degrees: f64) -> f64 {
degrees * (std::f64::consts::PI / 180.0)
}

/// Converts radians to degrees.
///
/// # Arguments
///
/// * `radians` - The angle in radians.
///
/// # Returns
///
/// The angle in degrees.
///
/// # Examples
///
/// ```
/// use advanced_calculator::utils::conversions::rad_to_deg;
/// let result = rad_to_deg(std::f64::consts::PI);
/// assert_eq!(result, 180.0);
/// ```
pub fn rad_to_deg(radians: f64) -> f64 {
radians * (180.0 / std::f64::consts::PI)
}
26 changes: 26 additions & 0 deletions rustapps/advanced_calculator/src/utils/num_methods.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// Calculates the derivative of a function at a given point using central difference.
///
/// # Arguments
///
/// * `f` - The function to differentiate.
/// * `x` - The point at which to calculate the derivative.
/// * `h` - A small step size.
///
/// # Returns
///
/// The derivative of the function at the given point.
///
/// # Examples
///
/// ```
/// use advanced_calculator::utils::numerical_methods::derivative;
/// let f = |x: f64| x.powi(2);
/// let result = derivative(f, 2.0, 1e-5);
/// assert_eq!(result, 4.0);
/// ```
pub fn derivative<F>(f: F, x: f64, h: f64) -> f64
where
F: Fn(f64) -> f64,
{
(f(x + h) - f(x - h)) / (2.0 * h)
}

0 comments on commit 05e6e5d

Please sign in to comment.