Skip to content

Commit

Permalink
Add Rust implementation for The Barnsley Fern (#818)
Browse files Browse the repository at this point in the history
* Add Rust implementation for The Barnsley Fern

* Change operators constants and add Cargo.toml

* Fix bug in matrix multiplication

Co-authored-by: James Schloss <jrs.schloss@gmail.com>
  • Loading branch information
ShadowMitia and leios authored Sep 15, 2021
1 parent 7bae159 commit 4557186
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
3 changes: 2 additions & 1 deletion contents/barnsley/barnsley.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ The biggest differences between the two code implementations is that the Barnsle
{% method %}
{% sample lang="jl" %}
[import, lang:"julia"](code/julia/barnsley.jl)
{% sample lang="rs" %}
[import, lang:"rust"](code/rust/src/main.rs)
{% sample lang="cpp" %}
[import, lang:"cpp"](code/c++/barnsley.cpp)
{% sample lang="c" %}
Expand All @@ -133,7 +135,6 @@ The biggest differences between the two code implementations is that the Barnsle
[import, lang:"java"](code/java/Barnsley.java)
{% sample lang="coco" %}
[import, lang:"coconut"](code/julia/barnsley.coco)

{% endmethod %}

### Bibliography
Expand Down
9 changes: 9 additions & 0 deletions contents/barnsley/code/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.8.4"
105 changes: 105 additions & 0 deletions contents/barnsley/code/rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use rand::prelude::*;
#[derive(Clone, Copy)]
struct Point2 {
x: f64,
y: f64,
}

#[derive(Clone, Copy)]
struct Point3 {
x: f64,
y: f64,
z: f64,
}

impl Point3 {
fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}

fn matrix_mul(self, rhs: Vec<Point3>) -> Self {
let x = rhs[0].x * self.x + rhs[0].y * self.y + rhs[0].z * self.z;
let y = rhs[1].x * self.x + rhs[1].y * self.y + rhs[1].z * self.z;
let z = rhs[2].x * self.x + rhs[2].y * self.y + rhs[2].z * self.z;
Self::new(x, y, z)
}
}

fn select_array(hutchinson_op: &[Vec<Point3>], probabilities: &[f64]) -> Vec<Point3> {
let mut rng = rand::thread_rng();
let mut rnd = rng.gen::<f64>();

for (i, probability) in probabilities.iter().enumerate() {
if rnd < *probability {
return hutchinson_op[i].clone();
}
rnd -= probability;
}

return vec![];
}

fn chaos_game(
iters: usize,
initial_location: Point2,
hutchinson_op: &[Vec<Point3>],
probabilities: &[f64],
) -> Vec<Point2> {
let mut point = Point3 {
x: initial_location.x,
y: initial_location.y,
z: 1.0,
};
(0..iters)
.into_iter()
.map(|_| {
let old_point = point;
let operation = select_array(hutchinson_op, probabilities);
point = point.matrix_mul(operation);
Point2 {
x: old_point.x,
y: old_point.y,
}
})
.collect()
}

fn main() {
let barnsley_hutchinson = vec![
vec![
Point3::new(0.0, 0.0, 0.0),
Point3::new(0.0, 0.16, 0.0),
Point3::new(0.0, 0.0, 1.0),
],
vec![
Point3::new(0.85, 0.04, 0.0),
Point3::new(-0.04, 0.85, 1.60),
Point3::new(0.0, 0.0, 1.0),
],
vec![
Point3::new(0.20, -0.26, 0.0),
Point3::new(0.23, 0.22, 1.60),
Point3::new(0.0, 0.0, 1.0),
],
vec![
Point3::new(-0.15, 0.28, 0.0),
Point3::new(0.26, 0.24, 0.44),
Point3::new(0.0, 0.0, 1.0),
],
];

let barnsley_probabilities = vec![0.01, 0.85, 0.07, 0.07];

let mut out = String::new();

for point in chaos_game(
10_000,
Point2 { x: 0.0, y: 0.0 },
&barnsley_hutchinson,
&barnsley_probabilities,
) {
out += format!("{}\t{}\n", point.x, point.y).as_str();
}

std::fs::write("./out.dat", out).unwrap();
}

0 comments on commit 4557186

Please sign in to comment.