Skip to content

Commit

Permalink
rf: split sources into different files (#6)
Browse files Browse the repository at this point in the history
* feat: move avg func to his own file

* feat: update deps

* rf: move variance into its own file

* rf: move stddev into its own file

* rf: move zscore into its own file

* rf: move erf and pro_density into its own files

* rf: split sources into files

* fix: make erf function precision to 1e-5

* rf: format sources using rustfmt

* fix: update codecov ci
  • Loading branch information
Lsh0x authored Sep 30, 2024
1 parent 9d80ffc commit 381ac4a
Show file tree
Hide file tree
Showing 14 changed files with 792 additions and 436 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ jobs:

- name: Run cargo-tarpaulin
uses: actions-rs/[email protected]
with:
version: '0.15.0'
args: '-- --test-threads 1'


- name: Upload to codecov.io
uses: codecov/codecov-action@v1
Expand Down
110 changes: 14 additions & 96 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ license = "GPL-3.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
num = "0.1"
num = "0.4.3"
47 changes: 47 additions & 0 deletions src/average.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/// average gets the number expressing the central or typical value in a set of data
#[inline]
pub fn average<T: num::ToPrimitive>(t: &[T]) -> Option<f64> {
if t.is_empty() {
return None;
}
Some(t.iter().map(|x| x.to_f64().unwrap()).sum::<f64>() / t.len() as f64)
}
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_average_integers() {
let data = vec![1, 2, 3, 4, 5];
let result = average(&data);
assert_eq!(result, Some(3.0));
}

#[test]
fn test_average_floats() {
let data = vec![1.5, 2.5, 3.5, 4.5];
let result = average(&data);
assert_eq!(result, Some(3.0));
}

#[test]
fn test_average_mixed_types() {
let data = vec![1.0, 2.0, 3.0, 4.5, 5.5]; // All elements are f64
let result = average(&data);
assert_eq!(result, Some(3.2));
}

#[test]
fn test_average_empty_slice() {
let data: Vec<f64> = Vec::new();
let result = average(&data);
assert_eq!(result, None);
}

#[test]
fn test_average_single_value() {
let data = vec![10.0];
let result = average(&data);
assert_eq!(result, Some(10.0));
}
}
106 changes: 106 additions & 0 deletions src/cummulative_distrib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use std::f64::consts::SQRT_2;

use crate::erf;
use crate::z_score;

/// CDF return the CDF using the mean and the standard deviation given
/// https://en.wikipedia.org/wiki/Cumulative_distribution_function#Definition
#[inline]
pub fn cummulative_distrib(x: f64, avg: f64, stddev: f64) -> f64 {
(1.0 + erf(z_score(x, avg, stddev) / SQRT_2)) / 2.0
}

#[cfg(test)]
mod tests {
use super::*;
const EPSILON: f64 = 1e-5;

#[test]
fn test_cdf_standard_normal_at_mean() {
// For a standard normal distribution (avg = 0, stddev = 1)
// The CDF at the mean (0) should be 0.5
let x = 0.0;
let avg = 0.0;
let stddev = 1.0;
let result = cummulative_distrib(x, avg, stddev);
let expected = 0.5;
assert!(
(result - expected).abs() < EPSILON,
"CDF at the mean should be 0.5"
);
}

#[test]
fn test_cdf_standard_normal_positive() {
// For a standard normal distribution (avg = 0, stddev = 1)
// The CDF at 1.0 (z = 1.0) is approximately 0.841344746
let x = 1.0;
let avg = 0.0;
let stddev = 1.0;
let result = cummulative_distrib(x, avg, stddev);
let expected = 0.841344746;
assert!(
(result - expected).abs() < EPSILON,
"CDF for z = 1.0 should match expected"
);
}

#[test]
fn test_cdf_standard_normal_negative() {
// For a standard normal distribution (avg = 0, stddev = 1)
// The CDF at -1.0 (z = -1.0) is approximately 0.158655254
let x = -1.0;
let avg = 0.0;
let stddev = 1.0;
let result = cummulative_distrib(x, avg, stddev);
let expected = 0.158655254;
assert!(
(result - expected).abs() < EPSILON,
"CDF for z = -1.0 should match expected"
);
}

#[test]
fn test_cdf_non_standard_distribution() {
// For a normal distribution with avg = 10, stddev = 2
// We can compute the CDF for x = 12, which should give the same result as z = 1.0 for a standard normal distribution
let x = 12.0;
let avg = 10.0;
let stddev = 2.0;
let result = cummulative_distrib(x, avg, stddev);
let expected = 0.841344746; // CDF for z = 1.0 in standard normal
assert!(
(result - expected).abs() < EPSILON,
"CDF for x = 12 in normal distribution with mean 10 and stddev 2 should match expected"
);
}

#[test]
fn test_cdf_large_positive_x() {
// For a normal distribution (avg = 0, stddev = 1), a very large positive x should have a CDF close to 1
let x = 5.0;
let avg = 0.0;
let stddev = 1.0;
let result = cummulative_distrib(x, avg, stddev);
let expected = 0.999999713; // Approximate value of CDF(5.0)
assert!(
(result - expected).abs() < EPSILON,
"CDF for x = 5.0 should be very close to 1"
);
}

#[test]
fn test_cdf_large_negative_x() {
// For a normal distribution (avg = 0, stddev = 1), a very large negative x should have a CDF close to 0
let x = -5.0;
let avg = 0.0;
let stddev = 1.0;
let result = cummulative_distrib(x, avg, stddev);
println!("resuilit large negatif : {:?}", result);
let expected = 0.000000287; // Approximate value of CDF(-5.0)
assert!(
(result - expected).abs() < EPSILON,
"CDF for x = -5.0 should be very close to 0"
);
}
}
Loading

0 comments on commit 381ac4a

Please sign in to comment.