Skip to content

Commit c134159

Browse files
Implement IFS in C++ (#701)
* Implement IFS in C++ * Add my name to contributors * Simpler version, no template * Separate rand function for int * Add comments * fix comment
1 parent 6ec324c commit c134159

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ This file lists everyone, who contributed to this repo and wanted to show up her
4848
- dovisutu
4949
- Antetokounpo
5050
- Akash Dhiman
51+
- Vincent Zalzal

contents/IFS/IFS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ Here, instead of tracking children of children, we track a single individual tha
128128
{% method %}
129129
{% sample lang="jl" %}
130130
[import:4-17, lang:"julia"](code/julia/IFS.jl)
131+
{% sample lang="cpp" %}
132+
[import:39-52, lang:"cpp"](code/c++/IFS.cpp)
131133
{% endmethod %}
132134

133135
If we set the initial points to the on the equilateral triangle we saw before, we can see the Sierpinski triangle again after a few thousand iterations, as shown below:
@@ -180,6 +182,8 @@ In addition, we have written the chaos game code to take in a set of points so t
180182
{% method %}
181183
{% sample lang="jl" %}
182184
[import, lang:"julia"](code/julia/IFS.jl)
185+
{% sample lang="cpp" %}
186+
[import, lang:"cpp"](code/c++/IFS.cpp)
183187
{% endmethod %}
184188

185189
### Bibliography

contents/IFS/code/c++/IFS.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <cmath>
2+
#include <fstream>
3+
#include <random>
4+
#include <vector>
5+
6+
// Simple X-Y point structure, along with some operators
7+
struct Point {
8+
double x, y;
9+
};
10+
11+
Point operator+(Point lhs, Point rhs) { return {lhs.x + rhs.x, lhs.y + rhs.y}; }
12+
Point operator*(double k, Point pt) { return {k * pt.x, k * pt.y}; }
13+
Point operator*(Point pt, double k) { return k * pt; }
14+
15+
using PointVector = std::vector<Point>;
16+
17+
// Returns a pseudo-random number generator
18+
std::default_random_engine& rng() {
19+
// Initialize static pseudo-random engine with non-deterministic random seed
20+
static std::default_random_engine randEngine(std::random_device{}());
21+
return randEngine;
22+
}
23+
24+
// Returns a random double in [0, 1)
25+
double drand() {
26+
return std::uniform_real_distribution<double>(0.0, 1.0)(rng());
27+
}
28+
29+
// Returns a random integer in [0, numElems-1]
30+
std::size_t randrange(std::size_t numElems) {
31+
return std::uniform_int_distribution<std::size_t>(0, numElems - 1)(rng());
32+
}
33+
34+
// Return a random point from the non-empty PointVector
35+
Point choose(const PointVector& points) {
36+
return points[randrange(points.size())];
37+
}
38+
39+
// This is a function to simulate a "chaos game"
40+
PointVector chaosGame(int numOutputPoints, const PointVector& inputPoints) {
41+
// Choose first point randomly
42+
Point curPoint = {drand(), drand()};
43+
44+
// For each output point, compute midpoint to random input point
45+
PointVector outputPoints(numOutputPoints);
46+
for (auto& outPoint : outputPoints) {
47+
outPoint = curPoint;
48+
curPoint = 0.5 * (curPoint + choose(inputPoints));
49+
}
50+
51+
return outputPoints;
52+
}
53+
54+
int main() {
55+
// This will generate a Sierpinski triangle with a chaos game of n points for
56+
// an initial triangle with three points on the vertices of an equilateral
57+
// triangle.
58+
PointVector inputPoints = {{0.0, 0.0}, {0.5, std::sqrt(0.75)}, {1.0, 0.0}};
59+
auto outputPoints = chaosGame(10000, inputPoints);
60+
61+
// It will output the file sierpinski.dat, which can be plotted after
62+
std::ofstream ofs("sierpinski.dat");
63+
for (auto pt : outputPoints)
64+
ofs << pt.x << '\t' << pt.y << '\n';
65+
}

0 commit comments

Comments
 (0)