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).
This commit is contained in:
119
src/main.cpp
119
src/main.cpp
@@ -32,30 +32,6 @@
|
|||||||
#define LINE_TOP (7 * HEIGHT / 16)
|
#define LINE_TOP (7 * HEIGHT / 16)
|
||||||
#define LINE_BOTTOM (9 * 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)
|
void draw_fraction(Fraction f, word_t x, word_t y)
|
||||||
{
|
{
|
||||||
std::string s{to_string(f)};
|
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);
|
DrawText(s.c_str(), x - width / 2, y - FONT_SIZE, FONT_SIZE, WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_node_number_line(const NodeAllocator &allocator, long double lower,
|
struct State
|
||||||
long double upper)
|
|
||||||
{
|
{
|
||||||
|
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}
|
||||||
|
{
|
||||||
|
root = allocator.alloc(start);
|
||||||
|
iteration_queue.push(root);
|
||||||
|
leftmost = allocator.getVal(root);
|
||||||
|
rightmost = allocator.getVal(root);
|
||||||
|
compute_bounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
std::stack<Node> stack;
|
||||||
stack.push(allocator.getVal(0));
|
stack.push(allocator.getVal(0));
|
||||||
while (!stack.empty())
|
while (!stack.empty())
|
||||||
{
|
{
|
||||||
Node n = stack.top();
|
Node n = stack.top();
|
||||||
stack.pop();
|
stack.pop();
|
||||||
word_t x = clamp_to_width(n.value.norm, lower, upper);
|
word_t x = clamp_to_width(n.value.norm);
|
||||||
DrawLine(x, LINE_TOP, x, LINE_BOTTOM, RED);
|
DrawLine(x, LINE_TOP, x, LINE_BOTTOM, RED);
|
||||||
if (n.left.has_value())
|
if (n.left.has_value())
|
||||||
stack.push(allocator.getVal(n.left.value()));
|
stack.push(allocator.getVal(n.left.value()));
|
||||||
if (n.right.has_value())
|
if (n.right.has_value())
|
||||||
stack.push(allocator.getVal(n.right.value()));
|
stack.push(allocator.getVal(n.right.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Setup CW tree
|
// Setup state
|
||||||
NodeAllocator allocator{0};
|
State state{{1, 2}};
|
||||||
std::queue<word_t> to_iterate;
|
|
||||||
Fraction best_frac{1, 2};
|
|
||||||
word_t root = allocator.alloc({best_frac});
|
|
||||||
to_iterate.push(root);
|
|
||||||
|
|
||||||
// Setup meta text (counter, iterations, etc)
|
// Setup meta text (counter, iterations, etc)
|
||||||
word_t count = 1, prev_count = 0;
|
word_t count = 1, prev_count = 0;
|
||||||
@@ -124,7 +123,9 @@ int main(void)
|
|||||||
{
|
{
|
||||||
if (IsKeyPressed(KEY_SPACE))
|
if (IsKeyPressed(KEY_SPACE))
|
||||||
{
|
{
|
||||||
iterate(to_iterate, allocator);
|
iterate(state.iteration_queue, state.allocator);
|
||||||
|
state.compute_bound_nodes();
|
||||||
|
state.compute_bounds();
|
||||||
count += 2;
|
count += 2;
|
||||||
}
|
}
|
||||||
if (prev_count != count)
|
if (prev_count != count)
|
||||||
@@ -139,7 +140,9 @@ int main(void)
|
|||||||
|
|
||||||
ClearBackground(BLACK);
|
ClearBackground(BLACK);
|
||||||
BeginDrawing();
|
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,
|
DrawText(format_str.c_str(), WIDTH / 2 - format_str_width / 2,
|
||||||
LINE_TOP - HEIGHT / 4, FONT_SIZE * 2, WHITE);
|
LINE_TOP - HEIGHT / 4, FONT_SIZE * 2, WHITE);
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|||||||
Reference in New Issue
Block a user