Files
cw_tree/README.org
2025-12-12 04:28:21 +00:00

84 lines
3.4 KiB
Org Mode

#+title: Calkin-Wilf trees
#+author: Aryadev Chavali
#+date: 2024-07-27
#+filetags: cpp cw_tree
#+options: toc:nil
A graphical visualisation of
[[https://en.wikipedia.org/wiki/Calkin%E2%80%93Wilf_tree][Calkin-Wilf
trees]].
Currently visualises it using a self adjusting number line, from the
smallest fraction to the largest fraction generated. Both are always
positive.
The bound fractions are drawn in white, while all other fractions are
in red. On any one iteration (taking any one fraction and generating
its two children fractions), the generated fractions are in blue while
the generator fraction is in green.
This was done just for fun really, but it's quite fun to see it
generate a dense number line over many iterations.
* TODOs
** TODO Tree visualisation
Instead of a number line, how about visualising the actual tree at
work as a graph of nodes? Maybe colouring nodes based on where it is
on the number line.
** TODO Don't walk the tree everytime we compute_bounds
[[file:src/state.cpp::void DrawState::compute_bounds()][location]]
We already have the latest bound nodes so we're part-way through the
tree. Just keep going down what we have so far surely? Even better,
don't use nodes _at all_. Run with an index!
** TODO Fix weird issue at past 100K nodes
std::vector seems to crap itself past 100K nodes - we keep getting
heap-use-after-free issues when trying to access the allocator nodes
at that point. Seemingly random. What's going on?
** DONE Prettify code base
It's a big blob of code currently in the graphics portion. Not very
pretty but it gets the job done. Try modularisation.
** DONE Multithreading
Currently single threaded. A multithreaded implementation could have
multiple nodes generated at once, which would speed up the
implementation.
Might need to study my current implementation to see if it could be
done better.
*** DONE Formalise state structure (separate drawing functions)
Make a dedicated header and fit the necessary functions to our state
structure: [[file:src/main.cpp::struct State][state structure]].
We need this in order so that we can get multithreading (using mutexes
on the actual state itself) working.
A good working name would be ~cw_state~.
We could then have a separate structure for the drawing context
(~cw_draw~) which can update itself by reading the ~cw_state~.
*** DONE Setup a queue and allocator mutex on state
We need one for the queue so we can make clean pushes and pops, and
one for the allocator to ensure we're not messing up our indices in
the nodes.
We could just set these up in the state structure itself to make
lookup easier.
*** DONE Make iterate use the state structure and mutexes
[[file:src/numerics.cpp::std::tuple<Fraction, Fraction, Fraction>
iterate(std::queue<word_t> &queue,]]
- Locking scheme could be:
- Lock queue when popping a value as root, then unlock.
- Leave queue and allocator unlocked while getting root/left/right
values (readonly) and computing (but not setting/allocating) the
left and right node values
- Allocator Lock when allocating the left/right values, setting the
root's left and right, then unlock.
- Queue lock when pushing the left and right fractions for further
processing, then unlock
- Unlock all when returning relevant values
I think this scheme minimises the any mutex is locked to just the bare
minimum, ensuring other threads can get in on the action.
*** DONE Setup a thread pool utilising state and iterate