aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2024-07-26 21:44:08 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2024-07-26 21:44:08 +0100
commitbb6ded706f87abe5d5f92404b0145ac95de76a11 (patch)
tree4886d27218841f1f21c6b5ec927c012a15ba818a
parentca7931e0c29785314d2fe88279dabd55c9afc7c2 (diff)
downloadcw_tree-bb6ded706f87abe5d5f92404b0145ac95de76a11.tar.gz
cw_tree-bb6ded706f87abe5d5f92404b0145ac95de76a11.tar.bz2
cw_tree-bb6ded706f87abe5d5f92404b0145ac95de76a11.zip
Move all functions and state into one struct
One God structure which will hold all the necessary state, ensuring I only need to compute stuff like bounds at most once, better than computing it on every draw (which is WAY slower at scale).
-rw-r--r--src/main.cpp137
1 files changed, 70 insertions, 67 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 5f8bc3c..1718090 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -32,30 +32,6 @@
#define LINE_TOP (7 * HEIGHT / 16)
#define LINE_BOTTOM (9 * HEIGHT / 16)
-Node rightmost_node(const NodeAllocator &allocator)
-{
- auto node = allocator.getVal(0);
- while (node.right.has_value())
- node = allocator.getVal(node.right.value());
- return node;
-}
-
-Node leftmost_node(const NodeAllocator &allocator)
-{
- auto node = allocator.getVal(0);
- while (node.left.has_value())
- node = allocator.getVal(node.left.value());
- return node;
-}
-
-constexpr word_t clamp_to_width(long double value, long double min,
- long double max)
-{
- // translate v in [min, max] -> v' in [0, WIDTH]
- // [min, max] -> [0, max-min] -> [0, WIDTH]
- return WIDTH / (max - min) * (value - min);
-}
-
void draw_fraction(Fraction f, word_t x, word_t y)
{
std::string s{to_string(f)};
@@ -64,54 +40,77 @@ void draw_fraction(Fraction f, word_t x, word_t y)
DrawText(s.c_str(), x - width / 2, y - FONT_SIZE, FONT_SIZE, WHITE);
}
-void draw_node_number_line(const NodeAllocator &allocator, long double lower,
- long double upper)
+struct State
{
- std::stack<Node> stack;
- stack.push(allocator.getVal(0));
- while (!stack.empty())
+ NodeAllocator allocator;
+ std::queue<word_t> iteration_queue;
+ word_t root;
+ Node leftmost, rightmost;
+ long double lower_bound, upper_bound;
+
+ State(const Fraction start) : allocator{256}
{
- Node n = stack.top();
- stack.pop();
- word_t x = clamp_to_width(n.value.norm, lower, upper);
- DrawLine(x, LINE_TOP, x, LINE_BOTTOM, RED);
- if (n.left.has_value())
- stack.push(allocator.getVal(n.left.value()));
- if (n.right.has_value())
- stack.push(allocator.getVal(n.right.value()));
+ root = allocator.alloc(start);
+ iteration_queue.push(root);
+ leftmost = allocator.getVal(root);
+ rightmost = allocator.getVal(root);
+ compute_bounds();
}
-}
-void draw_number_line(const NodeAllocator &allocator)
-{
- // Draw a general guide number line
- DrawLine(0, HEIGHT / 2, WIDTH, HEIGHT / 2, WHITE);
- // Figure out the leftmost and rightmost nodes for bounds
- const auto right = rightmost_node(allocator);
- const auto left = leftmost_node(allocator);
- const auto upper_bound = std::ceill(right.value.norm);
- const auto lower_bound = std::floorl(left.value.norm);
-
- // Draw all the nodes
- draw_node_number_line(allocator, lower_bound, upper_bound);
-
- // Draw the bounds, with their values, in white
- word_t lower_x = clamp_to_width(left.value.norm, lower_bound, upper_bound);
- word_t upper_x = clamp_to_width(right.value.norm, lower_bound, upper_bound);
- draw_fraction(left.value, lower_x, 3 * HEIGHT / 8);
- draw_fraction(right.value, upper_x, 3 * HEIGHT / 8);
- DrawLine(lower_x, LINE_TOP, lower_x, LINE_BOTTOM, WHITE);
- DrawLine(upper_x, LINE_TOP, upper_x, LINE_BOTTOM, WHITE);
-}
+ void compute_bounds()
+ {
+ lower_bound = std::floorl(leftmost.value.norm);
+ upper_bound = std::ceill(rightmost.value.norm);
+ }
+
+ void compute_bound_nodes()
+ {
+ leftmost = allocator.getVal(0);
+ while (leftmost.left.has_value())
+ leftmost = allocator.getVal(leftmost.left.value());
+
+ rightmost = allocator.getVal(0);
+ while (rightmost.right.has_value())
+ rightmost = allocator.getVal(rightmost.right.value());
+ }
+
+ constexpr word_t clamp_to_width(long double value)
+ {
+ return WIDTH / (upper_bound - lower_bound) * (value - lower_bound);
+ }
+
+ void draw_bounds()
+ {
+ word_t lower_x = clamp_to_width(leftmost.value.norm);
+ word_t upper_x = clamp_to_width(rightmost.value.norm);
+ draw_fraction(leftmost.value, lower_x, 3 * HEIGHT / 8);
+ draw_fraction(rightmost.value, upper_x, 3 * HEIGHT / 8);
+ DrawLine(lower_x, LINE_TOP, lower_x, LINE_BOTTOM, WHITE);
+ DrawLine(upper_x, LINE_TOP, upper_x, LINE_BOTTOM, WHITE);
+ }
+
+ void draw_nodes()
+ {
+ std::stack<Node> stack;
+ stack.push(allocator.getVal(0));
+ while (!stack.empty())
+ {
+ Node n = stack.top();
+ stack.pop();
+ word_t x = clamp_to_width(n.value.norm);
+ DrawLine(x, LINE_TOP, x, LINE_BOTTOM, RED);
+ if (n.left.has_value())
+ stack.push(allocator.getVal(n.left.value()));
+ if (n.right.has_value())
+ stack.push(allocator.getVal(n.right.value()));
+ }
+ }
+};
int main(void)
{
- // Setup CW tree
- NodeAllocator allocator{0};
- std::queue<word_t> to_iterate;
- Fraction best_frac{1, 2};
- word_t root = allocator.alloc({best_frac});
- to_iterate.push(root);
+ // Setup state
+ State state{{1, 2}};
// Setup meta text (counter, iterations, etc)
word_t count = 1, prev_count = 0;
@@ -124,7 +123,9 @@ int main(void)
{
if (IsKeyPressed(KEY_SPACE))
{
- iterate(to_iterate, allocator);
+ iterate(state.iteration_queue, state.allocator);
+ state.compute_bound_nodes();
+ state.compute_bounds();
count += 2;
}
if (prev_count != count)
@@ -139,7 +140,9 @@ int main(void)
ClearBackground(BLACK);
BeginDrawing();
- draw_number_line(allocator);
+ DrawLine(0, HEIGHT / 2, WIDTH, HEIGHT / 2, WHITE);
+ state.draw_nodes();
+ state.draw_bounds();
DrawText(format_str.c_str(), WIDTH / 2 - format_str_width / 2,
LINE_TOP - HEIGHT / 4, FONT_SIZE * 2, WHITE);
EndDrawing();