From 00858cf74f2d1a92d1a1e911d26350919d7f6103 Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Fri, 28 Nov 2025 17:24:33 +0000 Subject: [PATCH] Rewrite main to draw based on our new state/draw_state Arranges a thread set, draws based on draw_state. No need to lock the mutex since drawing should only require reading. Still has a timer in case we need to do timed checks. --- src/main.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ca14199..ac6e419 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,18 +5,22 @@ * Commentary: 2024-07-25 */ -#include "./numerics.hpp" - #include #include #include #include #include #include +#include #include #include +#include "base.hpp" +#include "node.hpp" +#include "numerics.hpp" +#include "worker.hpp" + #define WIDTH 1024 #define HEIGHT 1024 #define FONT_SIZE 20 @@ -24,6 +28,9 @@ #define LINE_TOP (7 * HEIGHT / 16) #define LINE_BOTTOM (9 * HEIGHT / 16) +using cw::state::DrawState; +using cw::state::State; + std::pair fraction_to_string(Fraction f) { std::string s{to_string(f)}; @@ -40,6 +47,120 @@ void draw_fraction(Fraction f, word_t x, word_t y) DrawText(s.c_str(), x - width / 2, y - FONT_SIZE, FONT_SIZE, WHITE); } +constexpr u64 clamp_to_width(const DrawState &ds, f64 val) +{ + return (WIDTH / (ds.bounds.upper_val - ds.bounds.lower_val)) * + (val - ds.bounds.lower_val); +} + +void draw_tree(const DrawState &ds) +{ + // Number line + DrawLine(0, HEIGHT / 2, WIDTH, HEIGHT / 2, WHITE); + + // Bounds + u64 lower_x = clamp_to_width(ds, ds.bounds.leftmost.value.norm); + u64 upper_x = clamp_to_width(ds, ds.bounds.rightmost.value.norm); + DrawLine(lower_x, LINE_TOP, lower_x, LINE_BOTTOM, WHITE); + DrawLine(upper_x, LINE_TOP, upper_x, LINE_BOTTOM, WHITE); + + std::stack stack; + stack.push(ds.state.allocator.get_val(0)); + while (!stack.empty()) + { + auto n = stack.top(); + stack.pop(); + u64 x = clamp_to_width(ds, n.value.norm); + DrawLine(x, LINE_TOP, x, LINE_BOTTOM, RED); + if (n.left >= 0) + stack.push(ds.state.allocator.get_val(n.left)); + if (n.right >= 0) + stack.push(ds.state.allocator.get_val(n.right)); + } +} + +using Clock = std::chrono::steady_clock; +using Ms = std::chrono::milliseconds; + +int main(void) +{ + // Init general state + cw::state::State state; + cw::state::DrawState draw_state{state}; + + // Init timer + auto time_current = Clock::now(); + auto time_previous = time_current; + constexpr auto time_delta = 1; + + // Init meta text (counter, iterations, etc) + u64 count = 1, prev_count = 0; + std::stringstream format_stream; + std::string format_str; + u64 format_str_width = 0; + + // Setup our first node (1/1) + state.allocator.alloc(cw::node::Node{{1, 1}, -1, -1}); + state.queue.push(0); + + // Init thread + std::thread threads[] = { + std::thread(cw::worker::worker, std::ref(state)), + std::thread(cw::worker::worker, std::ref(state)), + std::thread(cw::worker::worker, std::ref(state)), + std::thread(cw::worker::worker, std::ref(state)), + }; + + // Setup raylib window + InitWindow(WIDTH, HEIGHT, "Calkin-Wilf tree"); + SetTargetFPS(60); + + while (!WindowShouldClose()) + { + // Update + time_current = Clock::now(); + count = state.allocator.vec.size(); + if (!state.pause_work && + std::chrono::duration_cast(time_current - time_previous).count() >= + time_delta) + { + time_previous = time_current; + } + + if (prev_count != count) + { + draw_state.compute_bounds(); + prev_count = count; + format_stream << "Count=" << count << "\n\n" + << "Iterations=" << (count - 1) / 2 << "\n\n" + << "Lower=" << to_string(draw_state.bounds.leftmost.value) + << "\n\n" + << "Upper=" << to_string(draw_state.bounds.rightmost.value); + format_str = format_stream.str(); + format_stream.str(""); + format_str_width = MeasureText(format_str.c_str(), FONT_SIZE * 2); + } + + // Draw + + ClearBackground(BLACK); + BeginDrawing(); + draw_tree(draw_state); + DrawText(format_str.c_str(), WIDTH / 2 - format_str_width / 2, HEIGHT / 8, + FONT_SIZE, WHITE); + EndDrawing(); + } + + CloseWindow(); + + state.stop_work = true; + for (auto &thread : threads) + { + thread.join(); + } + return 0; +} + #if 0 struct State {