commit 6e67d2a9a8b3d470595bdd74139b3fc011dd6fd3 Author: Timo Schneider Date: Thu Apr 11 15:58:13 2024 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a07da8c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "MonteCarlo-Rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies.rand] +version = "0.8.5" diff --git a/src/bounds.rs b/src/bounds.rs new file mode 100644 index 0000000..b375edb --- /dev/null +++ b/src/bounds.rs @@ -0,0 +1,30 @@ +use crate::linear_bounds::LinearBounds; +use crate::point::Point; + +#[derive(Copy, Clone)] +pub struct Bounds { + x: LinearBounds, + y: LinearBounds, +} + +impl Bounds { + pub fn new(x: LinearBounds, y: LinearBounds) -> Bounds { + return Bounds {x, y}; + } + + pub fn get_area(self) -> f64 { + return self.x.get_length() * self.y.get_length(); + } + + pub fn get_random_point(self) -> Point { + return Point::new(self.x.get_random_value(), self.y.get_random_value()); + } + + pub fn get_x(self) -> LinearBounds { + return self.x; + } + + pub fn get_y(self) -> LinearBounds { + return self.y; + } +} diff --git a/src/linear_bounds.rs b/src/linear_bounds.rs new file mode 100644 index 0000000..1363909 --- /dev/null +++ b/src/linear_bounds.rs @@ -0,0 +1,31 @@ +use rand::rngs::ThreadRng; +use rand::{Rng, thread_rng}; + +#[derive(Copy, Clone)] +pub struct LinearBounds { + lower: f64, + higher: f64, +} + +impl LinearBounds { + pub fn new(lower: f64, higher: f64) -> LinearBounds { + return LinearBounds {lower, higher}; + } + + pub fn get_length(self) -> f64 { + return (self.higher - self.lower).abs(); + } + + pub fn get_random_value(self) -> f64 { + let mut rand: ThreadRng = thread_rng(); + return self.lower + self.get_length() * rand.gen::(); + } + + pub fn get_lower(self) -> f64 { + return self.lower; + } + + pub fn get_higher(self) -> f64 { + return self.higher; + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..cee91a5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,67 @@ +use std::thread::JoinHandle; +use std::time::Instant; +use crate::bounds::Bounds; +use crate::linear_bounds::LinearBounds; +use crate::point::Point; + +const SAMPLES: u64 = 1_000_000_000; +const THREAD_CNT: u64 = 8; + +mod point; +mod linear_bounds; +mod bounds; + +fn f(x: f64) -> f64 { + return x.powi(4) - 4_f64 * x.powi(3) + 18_f64 * x.powi(2) - 12_f64 * x - 69_f64 +} + +fn is_inside(point: Point) -> bool { + let y_0: f64 = f(point.get_x()); + return y_0.abs() > point.get_y().abs() && y_0 * point.get_y() >= 0_f64; +} + +fn get_real_integral(bounds: LinearBounds) -> f64 { + return big_f(bounds.get_higher()) - big_f(bounds.get_lower()); +} + +fn big_f(x: f64) -> f64 { + return 0.2 * x.powi(5) - x.powi(4) + 6_f64 * x.powi(3) - 6_f64 * x.powi(2) - 69_f64 * x; +} + +fn main() { + let start: Instant = Instant::now(); + let mut points_inside: u64 = 0; + let bounds: Bounds = Bounds::new(LinearBounds::new(0_f64, 20_f64), LinearBounds::new(-100_f64, 150000_f64)); + + let mut threads: Vec> = vec![]; + + for _ in 0..THREAD_CNT { + threads.push(std::thread::spawn(move || { + let mut points_inside: u64 = 0; + for _ in 0..SAMPLES { + let point: Point = bounds.get_random_point(); + if is_inside(point) { + points_inside += 1; + } + } + return points_inside; + })) + } + + for thread in threads { + points_inside += thread.join().unwrap(); + } + + let total_samples: u64 = SAMPLES * THREAD_CNT; + + let approximated_integral: f64 = (points_inside as f64 / total_samples as f64) * bounds.get_area(); + println!("The approximated Integral of the function is: {:.2}", approximated_integral); + + let real_integral: f64 = get_real_integral(bounds.get_x()); + println!("The real Integral of the function is: {:.2}", real_integral); + + let error: f64 = (real_integral - approximated_integral).abs(); + println!("That's an error of {:.2} or {:.5}%", error, (error/real_integral) * 100_f64); + + println!("And the whole thing took {:.5} Seconds for {} samples", start.elapsed().as_micros() as f64 / 1000000_f64, total_samples); +} \ No newline at end of file diff --git a/src/point.rs b/src/point.rs new file mode 100644 index 0000000..70d0857 --- /dev/null +++ b/src/point.rs @@ -0,0 +1,19 @@ +#[derive(Clone, Copy, Debug)] +pub struct Point { + x: f64, + y: f64, +} + +impl Point { + pub fn new(x: f64, y: f64) -> Point { + return Point {x, y}; + } + + pub fn get_x(self) -> f64 { + return self.x; + } + + pub fn get_y(self) -> f64 { + return self.y; + } +} \ No newline at end of file