Skip to content

Commit 4557186

Browse files
ShadowMitialeios
andauthored
Add Rust implementation for The Barnsley Fern (#818)
* 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>
1 parent 7bae159 commit 4557186

File tree

3 files changed

+116
-1
lines changed

3 files changed

+116
-1
lines changed

contents/barnsley/barnsley.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ The biggest differences between the two code implementations is that the Barnsle
125125
{% method %}
126126
{% sample lang="jl" %}
127127
[import, lang:"julia"](code/julia/barnsley.jl)
128+
{% sample lang="rs" %}
129+
[import, lang:"rust"](code/rust/src/main.rs)
128130
{% sample lang="cpp" %}
129131
[import, lang:"cpp"](code/c++/barnsley.cpp)
130132
{% sample lang="c" %}
@@ -133,7 +135,6 @@ The biggest differences between the two code implementations is that the Barnsle
133135
[import, lang:"java"](code/java/Barnsley.java)
134136
{% sample lang="coco" %}
135137
[import, lang:"coconut"](code/julia/barnsley.coco)
136-
137138
{% endmethod %}
138139

139140
### Bibliography
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "rust"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
rand = "0.8.4"
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use rand::prelude::*;
2+
#[derive(Clone, Copy)]
3+
struct Point2 {
4+
x: f64,
5+
y: f64,
6+
}
7+
8+
#[derive(Clone, Copy)]
9+
struct Point3 {
10+
x: f64,
11+
y: f64,
12+
z: f64,
13+
}
14+
15+
impl Point3 {
16+
fn new(x: f64, y: f64, z: f64) -> Self {
17+
Self { x, y, z }
18+
}
19+
20+
fn matrix_mul(self, rhs: Vec<Point3>) -> Self {
21+
let x = rhs[0].x * self.x + rhs[0].y * self.y + rhs[0].z * self.z;
22+
let y = rhs[1].x * self.x + rhs[1].y * self.y + rhs[1].z * self.z;
23+
let z = rhs[2].x * self.x + rhs[2].y * self.y + rhs[2].z * self.z;
24+
Self::new(x, y, z)
25+
}
26+
}
27+
28+
fn select_array(hutchinson_op: &[Vec<Point3>], probabilities: &[f64]) -> Vec<Point3> {
29+
let mut rng = rand::thread_rng();
30+
let mut rnd = rng.gen::<f64>();
31+
32+
for (i, probability) in probabilities.iter().enumerate() {
33+
if rnd < *probability {
34+
return hutchinson_op[i].clone();
35+
}
36+
rnd -= probability;
37+
}
38+
39+
return vec![];
40+
}
41+
42+
fn chaos_game(
43+
iters: usize,
44+
initial_location: Point2,
45+
hutchinson_op: &[Vec<Point3>],
46+
probabilities: &[f64],
47+
) -> Vec<Point2> {
48+
let mut point = Point3 {
49+
x: initial_location.x,
50+
y: initial_location.y,
51+
z: 1.0,
52+
};
53+
(0..iters)
54+
.into_iter()
55+
.map(|_| {
56+
let old_point = point;
57+
let operation = select_array(hutchinson_op, probabilities);
58+
point = point.matrix_mul(operation);
59+
Point2 {
60+
x: old_point.x,
61+
y: old_point.y,
62+
}
63+
})
64+
.collect()
65+
}
66+
67+
fn main() {
68+
let barnsley_hutchinson = vec![
69+
vec![
70+
Point3::new(0.0, 0.0, 0.0),
71+
Point3::new(0.0, 0.16, 0.0),
72+
Point3::new(0.0, 0.0, 1.0),
73+
],
74+
vec![
75+
Point3::new(0.85, 0.04, 0.0),
76+
Point3::new(-0.04, 0.85, 1.60),
77+
Point3::new(0.0, 0.0, 1.0),
78+
],
79+
vec![
80+
Point3::new(0.20, -0.26, 0.0),
81+
Point3::new(0.23, 0.22, 1.60),
82+
Point3::new(0.0, 0.0, 1.0),
83+
],
84+
vec![
85+
Point3::new(-0.15, 0.28, 0.0),
86+
Point3::new(0.26, 0.24, 0.44),
87+
Point3::new(0.0, 0.0, 1.0),
88+
],
89+
];
90+
91+
let barnsley_probabilities = vec![0.01, 0.85, 0.07, 0.07];
92+
93+
let mut out = String::new();
94+
95+
for point in chaos_game(
96+
10_000,
97+
Point2 { x: 0.0, y: 0.0 },
98+
&barnsley_hutchinson,
99+
&barnsley_probabilities,
100+
) {
101+
out += format!("{}\t{}\n", point.x, point.y).as_str();
102+
}
103+
104+
std::fs::write("./out.dat", out).unwrap();
105+
}

0 commit comments

Comments
 (0)