Skip to content

Commit 2c47302

Browse files
Add Barnsley Fern in C (#832)
* Add Barnsley Fern in C * Add comments and fix typos Co-authored-by: James Schloss <jrs.schloss@gmail.com>
1 parent c1467a8 commit 2c47302

File tree

3 files changed

+112
-1
lines changed

3 files changed

+112
-1
lines changed

CONTRIBUTORS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,5 @@ This file lists everyone, who contributed to this repo and wanted to show up her
5656
- Ishaan Verma
5757
- Delphi1024
5858
- ntindle
59-
- Ridham177
59+
- Mahdi Sarikhani
60+
- Ridham177

contents/barnsley/barnsley.md

Lines changed: 2 additions & 0 deletions
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="c" %}
129+
[import, lang:"c"](code/c/barnsley.c)
128130
{% sample lang="java" %}
129131
[import, lang:"java"](code/java/Barnsley.java)
130132
{% endmethod %}

contents/barnsley/code/c/barnsley.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
struct matrix {
5+
double xx, xy, xz,
6+
yx, yy, yz,
7+
zx, zy, zz;
8+
};
9+
10+
struct point2d {
11+
double x, y;
12+
};
13+
14+
struct point3d {
15+
double x, y, z;
16+
};
17+
18+
struct point3d matmul(struct matrix mat, struct point3d point)
19+
{
20+
struct point3d out = {
21+
mat.xx * point.x + mat.xy * point.y + mat.xz * point.z,
22+
mat.yx * point.x + mat.yy * point.y + mat.yz * point.z,
23+
mat.zx * point.x + mat.zy * point.y + mat.zz * point.z
24+
};
25+
return out;
26+
}
27+
28+
// This function reads in the Hutchinson operator and corresponding
29+
// probabilities and returns a randomly selected transform
30+
// This works by choosing a random number and then iterating through all
31+
// probabilities until it finds an appropriate bin
32+
struct matrix select_array(struct matrix *hutchinson_op, double *probabilities,
33+
size_t num_op)
34+
{
35+
// random number to be binned
36+
double rnd = (double)rand() / RAND_MAX;
37+
38+
// This checks to see if a random number is in a bin, if not, that
39+
// probability is subtracted from the random number and we check the next
40+
// bin in the list
41+
for (size_t i = 0; i < num_op; ++i) {
42+
if (rnd < probabilities[i]) {
43+
return hutchinson_op[i];
44+
}
45+
rnd -= probabilities[i];
46+
}
47+
}
48+
49+
// This is a general function to simulate a chaos game
50+
// - output_points: pointer to an initialized output array
51+
// - num: the number of iterations
52+
// - initial_point: the starting point of the chaos game
53+
// - hutchinson_op: the set of functions to iterate through
54+
// - probabilities: the set of probabilities corresponding to the likelihood
55+
// of choosing their corresponding function in hutchingson_op
56+
// - nop: the number of functions in hutchinson_op
57+
void chaos_game(struct point2d *output_points, size_t num,
58+
struct point2d initial_point, struct matrix *hutchinson_op,
59+
double *probabilities, size_t nop)
60+
{
61+
// extending point to 3D for affine transform
62+
struct point3d point = {initial_point.x, initial_point.y, 1.0};
63+
64+
for (size_t i = 0; i < num; ++i) {
65+
point = matmul(select_array(hutchinson_op, probabilities, nop), point);
66+
output_points[i].x = point.x;
67+
output_points[i].y = point.y;
68+
}
69+
}
70+
71+
int main()
72+
{
73+
struct matrix barnsley_hutchinson[4] = {
74+
{
75+
0.0, 0.0, 0.0,
76+
0.0, 0.16, 0.0,
77+
0.0, 0.0, 1.0
78+
},
79+
{
80+
0.85, 0.04, 0.0,
81+
-0.04, 0.85, 1.60,
82+
0.0, 0.0, 1.0
83+
},
84+
{
85+
0.2, -0.26, 0.0,
86+
0.23, 0.22, 1.60,
87+
0.0, 0.0, 1.0
88+
},
89+
{
90+
-0.15, 0.28, 0.0,
91+
0.26, 0.24, 0.44,
92+
0.0, 0.0, 1.0
93+
}
94+
};
95+
96+
double barnsley_probabilities[4] = {0.01, 0.85, 0.07, 0.07};
97+
struct point2d output_points[10000];
98+
struct point2d initial_point = {0.0, 0.0};
99+
chaos_game(output_points, 10000, initial_point, barnsley_hutchinson,
100+
barnsley_probabilities, 4);
101+
FILE *f = fopen("barnsley.dat", "w");
102+
for (size_t i = 0; i < 10000; ++i) {
103+
fprintf(f, "%f\t%f\n", output_points[i].x, output_points[i].y);
104+
}
105+
fclose(f);
106+
107+
return 0;
108+
}

0 commit comments

Comments
 (0)