<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Justin Meiners Site</title>
<description>Welcome to my personal site about programming, math, and philosophy!</description>
<link>https://www.jmeiners.com</link>
<lastBuildDate>Fri, 28 Aug 2026 23:00:38 -0600</lastBuildDate>
<item>
<pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate>
<title>Take your time</title>
<guid>https://www.jmeiners.com/take-your-time/</guid>
<link>https://www.jmeiners.com/take-your-time/</link>
<description>
<![CDATA[
<h2> Take your time</h2>

<p><strong>11/24/2025</strong></p>

<p>I&rsquo;m someone who likes to work a little slower,
explore a subject in-depth,  and  always go back to basics.
If you&rsquo;re reading this, you probably appreciate a similar <em>craftsmen</em>-like  approach,
and often find good ideas, <a href="/keeping-up-to-date">overlooked</a> by popular trends.</p>

<p>Craftsmen  correctly identify that  true principles and skills that don&rsquo;t change.
This helps them see past the latest craze, tune out noise, and focus on long-term impact.
But success with this approach can grow into a temptation to ignore time entirely.
We can come to believe that our work is <em>time-less</em>.
If we put in the hard work to make a great project, it will be appreciated, no matter when it&rsquo;s done or what comes after.</p>

<p>On a personal level, this is obviously not true.
We go through seasons of life where time, skills, energy, and interests vary,
Seasons for projects are limited, and the nature of the work we can do in each season also changes.
I unfortunately, have had to leave projects behind, not because they are not good, but because I am no longer the person who
had the vision and excitement that started them.</p>

<p>I recently saw an <a href="https://www.youtube.com/watch?v=znJPn3FSFmM">interview</a> with John Carmack, that prompted this topic:</p>

<blockquote><p>I used to be known for the catch line, &ldquo;It&rsquo;ll be done when it&rsquo;s done.&rdquo;. You know, &ldquo;When will Doom ship?&rdquo;, &ldquo;When it&rsquo;s done.&rdquo;</p>

<p>With a little bit more perspective now. If you&rsquo;re talking slipping a quarter, slipping six months? Yeah great that&rsquo;s definitely fine. But, when you&rsquo;re talking about slipping years? When years go by, the world changes around you. Time has a physicality that you may not appreciate.</p>

<p>We spent six years on that game [Rage]. It was using flashy new technology. We had an E3 where we were game of show. But it didn&rsquo;t quite ship. And by the time it got out, the world had changed around us. The technology decisions that were made for some earlier systems weren&rsquo;t necessarily the right thing for the latest ones. We now had Call of Duty and Battlefield as these juggernauts we were competing with. I look back at it as one of those real decisions. I think we should have done whatever it would have taken to ship that two years earlier. Be less ambitious with some of the technologies and get it out earlier.</p></blockquote>

<p>Changing technology, and competition were specifically identified but we can list all kinds
of things that change for-the-worse over a long project:</p>

<ul>
<li><p>The vision becomes less inspiring, as contributors and customers acclimate to the message.</p></li>
<li><p>The insights behind the project become realized by others, and incorporated into other works.</p></li>
<li><p>Marketing which rang culturally true, now sounds out of place.</p></li>
<li><p>Knowledge about project details become lost to turnover and memory.</p></li>
</ul>


<p>Every project makes assumptions about what the world will look like when it&rsquo;s finished (what  people will like, use, want, etc).
The longer that prediction must extend into the future, the harder it is to get right,
and the greater the cost to update, and maintain those parts that expire.</p>

<p>And those changing seasons of life? They happen to every single person contributing to a project.
You cannot expect anyone to operate or contribute in the exact same way they do now,
even if they are committed to seeing it through.</p>

<p>John follows up with a related experience, from a different project:</p>

<blockquote><p>Quake was the first really traumatic game to ship, internally. We&rsquo;re still only talking like two-year developments but at the time it felt really long. We had all sorts of internal strife because we were trying to do so many things: six degree of freedom rendering, modding, internet-based game servers, and it was a lot of stuff. I later looked back and said, we could have done half of those things in a &ldquo;Super Doom&rdquo; and shipped it earlier and then done the other half even better on a game coming later. I still roll that over in my mind.</p></blockquote>

<p>I find this quote striking.  Because unlike Rage, Quake was an out-of-the park success!
The game was well received. It made a lot of money.
The technology was incredible, influenced the whole industry, and set them up for different projects.
But he is still &ldquo;rolling over&rdquo; decisions that might have saved 6-12 months, nearly 30 years later! <sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<p>&ndash;</p>

<p>Recently, I was working at a startup that shared  a lot of my interests in craftsmanship.
They wanted to  build the right technology, had a big long-term plan, and a great market opportunity.
It probably goes without saying, but this is a rare gig to find.</p>

<p>I also was able to join at a magical time.
The product had been prototyped, all the funding was secured,
they had smart people, and all we had to do was execute.</p>

<p>But strangely that time never came, not because of many major roadblocks.
We just kept on doing what craftsmen do well; finding better ways to do things, coming across new technologies, growing our feature set.
It became momentum for the whole organization.
Months went by, then years, and somehow we weren&rsquo;t any closer to ship.
All of the learning that would come from pausing development, polishing,
and engaging with real customer problems, kept being pushed down the road.</p>

<p>I was growing impatient, but otherwise occupied with interesting technical problems.
Then I heard Carmack&rsquo;s interview and realized  my fun and comfortable job was actually becoming an urgent issue.
I left for another opprotunity, which turned out to be exactly what I needed.
It taught me all I originally wanted to learn about startups,  and allowed more of my skills to be appreciated,
I can tell you about it another time.
But what I know is my life would be very different had I stayed working on that same project for a few more years.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
It&rsquo;s interesting to pair this with Abrash&rsquo;s <a href="https://www.bluesnews.com/abrash/chap70.shtml">Quake experience</a> . &ldquo;Here’s the secret to success in just two words:  Ship it.  Finish the product and get it out the door, and you’ll be a hero.&rdquo;<a href="#fnref:1" rev="footnote">&#8617;</a></li>
</ol>
</div>

]]>
</description>
</item>
<item>
<pubDate>Sat, 02 Aug 2025 00:00:00 +0000</pubDate>
<title>Water Hammer Arrestor</title>
<guid>https://www.jmeiners.com/water-hammer/</guid>
<link>https://www.jmeiners.com/water-hammer/</link>
<description>
<![CDATA[
<h1>Water Hammer Arrestor</h1>

<p><strong>08/02/25</strong></p>

<p>I&rsquo;m back with another house maintenance project (and not talking about computer technology).</p>

<p>My irrigation system has been making awful water hammer noises.
It&rsquo;s so bad, that I haven&rsquo;t felt comfortable watering my lawn, due to fear of damaging the plumbing.
Here are the symptoms of my problem:</p>

<ol>
<li>Only occurs when a valve opens, not when it closes. (fast moving water slamming into a valve is a common problem).</li>
<li>Occurs regardless of how long the sprinkler has been on. I can close a valve, and reopen it 10 seconds later and it&rsquo;s the same.</li>
<li>Severity varies across different zones. Zones closer to the manifold seem worse.</li>
</ol>


<p>These rule out most of the quick water hammer fixes,
for example adding a delay between zone activation doesn&rsquo;t help.
So I determined the best solution was to install a water hammer arrestor.
Here is how that went.</p>

<p><img src="arrestor.jpg" alt="water hammer arrestor" /></p>

<p><strong>Disclaimer:</strong> I am an occasional DIYer, not a professional plumber. My intent is to share my exprience with the hope that it might be helpful for you.</p>

<h2>Plan</h2>

<p><img src="box1.jpg" alt="manifold box" /></p>

<p>I want to insert the arrestor as close as possible to the manifold,
so it provides benefit for all zones, and protects as much of the plumbing as possible.
Unfortunately, the sprinkler box is out of space, so I needed to dig up and insert on to the incoming line.</p>

<p><img src="pipe1.jpg" alt="pipe" /></p>

<p>I also want make enough space for a new box to house the arrestor, so I can access it later.</p>

<p>There are quite a few positions and orientations to consider.
Vertical orientation seems natural, but the arrestor is actually too long, and so I chose to lay it horizontally (OK for this model).
I could replace the elbow with a tee to get shock absorption at the corner, but I don&rsquo;t want to rebuild the manifold connection.</p>

<p><img src="placement.jpg" alt="placement" /></p>

<h2>Attempt 1</h2>

<p>So I cut the pipe, attached the tee, and put it all together.
The elbow with the threaded manifold connection gives me an advantage.
I can connect this piece last and avoid the challenge of connecting two pieces of PVC.
(This is classic plumbing problem where there is insufficient space to slide a coupling on to both sides.).</p>

<p><img src="attempt1.jpg" alt="attempt 1" /></p>

<p>My expectation was that the threaded piece would haves some give and allow me to easily connect back to the manifold.
But that was not the case.
With everything assembled, the pipe and the manifold were offset from each other by about 1/8",
and there was absolutely no give.</p>

<p><img src="offset.jpg" alt="offset" /></p>

<p>I was completely out of luck.
Not anticipating this problem was an <em>amateur</em> mistake.</p>

<h2>Attempt 2</h2>

<p>I needed to try again.
I researched alternative ways to join the pipe (and avoid the same problem), but none looked better than my initial idea.</p>

<p>So I cut the tee and redid it all.
This time I was extra careful, and measured everything with the elbow piece attached to the manifold.
On the final assembly step, I connected the elbow and threaded it to the manifold with the cement wet.
This was tricky because I had about 5 seconds to insert the piece, rotate it into position through the box,
and get the threads aligned.
One trick that helped was inserting a piece of plastic underneath the connection to keep them out of the mud.</p>

<p><img src="attempt2.jpg" alt="attempt 2" /></p>

<p>It all worked out!</p>

<h2>Arrestor assembly</h2>

<p>Although not strictly necessary, I attached a PVC 40 nipple rather than threading the arrestor directly into the tee.
Brass into PVC connections are less reliable, and I want to protect the tee&rsquo;s threads if I need to replace in the future.</p>

<p>I filled the arrestor box with gravel and cut a block for the weight to rest on.</p>

<p><img src="arrestor_assembly.jpg" alt="water hammer arrestor in box" /></p>

<h2>Results</h2>

<p>I was pleasantly surprised with how well this little part works.
3 of my zones are completely quiet, and 1 has small bump when it starts.</p>

<p><img src="final.jpg" alt="final box" /></p>

<p>(Yes, I spilled PVC primer all over my lid.)</p>

<p>Thanks to ChatGPT for all the plumbing advice!</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 22 Jun 2025 00:00:00 +0000</pubDate>
<title>Replacing hardboard siding</title>
<guid>https://www.jmeiners.com/siding/</guid>
<link>https://www.jmeiners.com/siding/</link>
<description>
<![CDATA[
<h1>Replacing hardboard siding</h1>

<p><strong>06/21/2025</strong></p>

<p>This summer I replaced part of the siding on my 1970s house in Boulder.
The project turned out great, better than I hoped!</p>

<p><img src="painted.jpg" alt="painted" /></p>

<p>While planning, I had a hard time finding good information about the techniques and materials
used for this style of home.
This <a href="https://youtube.com/watch?v=Ne-lAjU0MZI">video</a> gave me confidence that I could do it,
but lacked a lot of detail, especially in regards to possible replacement materials.
So I wanted to share what I learned in the project, in case it can help anyone else.</p>

<p><strong>Disclaimer:</strong> I am an occasional DIY'er not a construction professional.</p>

<h2>Siding materials</h2>

<p>The original siding on the house is a wood composite material
 referred to as hardboard, or by the brand name &ldquo;Masonite&rdquo;.
It&rsquo;s basically glorified cardboard,
and has long been defunct as it doesn&rsquo;t hold up well to moisture.
Very dry climates like Colorado may be the only places where it&rsquo;s still surviving.</p>

<p>Here you can see some moderate bubbling indicating moisture damage:</p>

<p><img src="rotting_hardboard.jpg" alt="rotting masonite/hardboard" /></p>

<p>About half of my house was actually in good shape.
But the parts that are heavily exposed to sun and rain were in disrepair.</p>

<p>The original board is 12" wide and 7/16" thick.</p>

<p><img src="hardboard_front.jpg" alt="hardboard front" /></p>

<p>Notice the water damage on the edge:</p>

<p><img src="hardboard_back.jpg" alt="hardboard back" /></p>

<p>I was unable to find anyone who supplies the original hardboard, so I had to substitute.
I chose LP Smartside smooth finish, which is 12" wide and 3/8" thick.
This is a much higher quality material made from OSB, but has similar dimensions and appearance.
The manufacturer also provided recommendations for install and materials like nails, which were helpful to refer to.</p>

<h2>Removing old boards</h2>

<p>The previous stuff was face nailed so it&rsquo;s pretty easy to get underneath with a pry bar.
After a little effort, the nail typically separates from the siding, making it easy to pull out with a hammer. Since it&rsquo;s being removed, you can be pretty rough with every board except the last.</p>

<p><img src="sheathing.jpg" alt="sheathing" /></p>

<p>You&rsquo;ll notice that my sheathing is not modern OSB but instead fiberboard, another defunct product.</p>

<p><img src="fiberboard.jpg" alt="fiboardboard" /></p>

<p>I don&rsquo;t know too much about it.
Part of my motivation for the project was to determine if any places needed to be replaced.
I was pleasantly surprised to find it in good condition and didn&rsquo;t need to touch it.</p>

<p>You&rsquo;ll notice that there is no vapor barrier/house wrap on the outside.
This is more common for older homes, but my research also indicated it&rsquo;s more acceptable for fiberboard constructions.</p>

<h2>Assembly</h2>

<p>The house is 24 ft wide, so a single row requires a 16ft and 8ft board.
The long and short side alternate with each row to protect and hide seams.</p>

<p><img src="siding1.jpg" alt="siding 1" /></p>

<p>One piece of siding was ripped into 2" strips for the base.
This is installed below the bottom row along the foundation.
The first row of siding then rests upon this.</p>

<p>Once the first row is done, it gets much easier.
You just lay the next board above at the proper height and nail it in.
I chose to pre-drill holes in the siding to prevent splitting on the thin side.</p>

<p><img src="siding2.jpg" alt="siding 2" /></p>

<p>We did hammer the whole thing by hand.
I considered purchasing a pneumatic nailer,
but they are really only available at professional price points.
Note that siding requires a special kind of nailer
as the nails are different than the ones you can use with a framing or roofing nailer.
It&rsquo;s worth it if you do the whole house.</p>

<h2>Painting</h2>

<p>The boards come primed on the outside side.
So it&rsquo;s ready to paint with 2 coats.
Large rollers worked well for these large boards.
The color match turned out great and look just like the old boards!</p>

<p>The new seams and edges must be caulked before painting.
I also took time to cleanup up the old boards and seams were not replaced.</p>

<p><img src="painting.jpg" alt="painting" /></p>

<p>All done! Thanks to my family for all their help!</p>
]]>
</description>
</item>
<item>
<pubDate>Sat Apr 5 14:17:58 MDT 2025</pubDate>
<title>Combat Robot</title>
<guid>https://www.jmeiners.com/combat-robot/</guid>
<link>https://www.jmeiners.com/combat-robot/</link>
<description>
<![CDATA[
<h1>Combat Robot</h1>

<p><strong>04/05/2025</strong></p>

<p>As a kid, I loved getting books from the library about combat robots.
I was always interested in tools and building things,
but the idea of making a robot was just a little more exciting than making furniture.</p>

<p><img src="building_bots.jpg" alt="Buildings Bots. William Gurstelle." />
<img src="build_your_own_combat_robot.jpg" alt="Build your own Combat Robot. Pete Miles. Tom Carroll" /></p>

<p>Learning about robots introduced me to new building techniques,
but unfortunately actually making a combat robot, was just not very accessible at the time.
Welding? Car batteries? Wheel-chair motors?
It&rsquo;s a tough sell for parents and suburban neighbors.</p>

<p>After 20 years, the hobby has gotten a lot more accessible, thanks to 3D printers,
but also improvements in batteries, motors, and radio.
The whole process is smaller, cheaper, and easier to assemble,
so that even local schools have robot making programs.</p>

<p>Recently a friend (who is a 3D printer enthusiast) invited me to make a 150g robot for a small community event,
and I had a great time.
We didn&rsquo;t do anything extraordinary,
but I wanted to share a little bit about the project.
My takeaway, is this can be a great hobby
for learning about electronics and mechanics,
especially for kids.</p>

<p><img src="robot.jpg" alt="before battle" /></p>

<h3>Design</h3>

<p>At 150g most robots use a body that&rsquo;s 3D-printed or adapted from an RC cars.
To keep weight low, they typically only have 2 wheels.
The main design decision to make is how your robot will attack.
Most of your weight and body will arrange itself around that.</p>

<p>Spinning weapons are the most popular.
It&rsquo;s a simple and effective design that&rsquo;s <em>really</em> hard to beat.
But we wanted to try something a little different.
We found an idea online about a <a href="https://www.youtube.com/watch?v=63BY414Va0E">spring loaded flipper</a>.
The spring is loaded by lifting an arm using a &ldquo;snail cam&rdquo; which can be rotated continuously.</p>

<p>We had high hopes of having multiple weapons,
but as these things tend to go, you must simplify and cut scope as you go.</p>

<h3>Cam</h3>

<p>The main part I worked on is the flipping arm and snail cam.
It&rsquo;s designed with an increasing, but decelerating slope,
so that the work required by the motor stays constant.</p>

<p>My first attempt was to cut one with a hand saw from UHMW polyethylene.
They may not look excellent, but should work, after a little sanding.</p>

<p><img src="plastic_cams.jpg" alt="plastic snail cam" /></p>

<p>We found the 3D printing was sturdy and smooth enough,
so we chose that instead.
I wrote a python script to generate the basic curve in Blender,
and then used simple boolean cuts to get all the parts we need.</p>

<p><img src="cam_boolean.png" alt="cam" />
<img src="cam.png" alt="cam" /></p>

<h3>Electronics</h3>

<p>N20 is a popular style of motor for this size.
Apparently they vary greatly in quality and specification.
We just got a few cheap ones on Amazon.
I like that you can order them with a small gearbox targeted for a specific RPM,
so it&rsquo;s easy to get the torque/speed you need.
For example, the cam uses a much lower RPM than wheel motors.</p>

<p><img src="motor.jpg" alt="n20 motor" /></p>

<p>The radio receiver, and motor controllers are available as a single board.
Just wire the motors to the appropriate terminals.
The model we used is called &ldquo;Malenki Nano&rdquo; which is very popular.
Connecting the receiver to a controller was as easy too.</p>

<p><img src="wiring.jpg" alt="Wiring to malenki nano" /></p>

<h3>Body</h3>

<p>The body was drawn in a traditional CAD program.
It went through many iterations and printings as we tried to fit everything in.
Here are a few techniques we found helpful:</p>

<ol>
<li><p>Attach components with zip ties. It makes it easy to move parts between bodies, and is very sturdy.
Just add holes for them in your CAD design.</p></li>
<li><p>Prototype parts in cardboard first. If you have a simple base, it&rsquo;s easy to tape on pieces to see how they will fit.</p></li>
<li><p>Use fast and cheap printer settings until the final revision (and it&rsquo;s always one more than you think).</p></li>
</ol>


<p><img src="fit_check.jpg" alt="fit check" /></p>

<h3>Battle</h3>

<p>The event was very casual and had a positive atmosphere.
People were open about showing their robots and learning from each other.
Ages varied greatly, with some younger kids, teenagers, and a few Dad&rsquo;s joining their sons.</p>

<p>A pro stopped by to show off his full-size robot!</p>

<p><img src="pro.jpg" alt="pro robot" /></p>

<p>In our first (and only) battle we took a few big hits from a spinning blade.
Luckily none of our major parts were damaged.
So we should be ready to try again after printing a new body.</p>

<p><img src="robot_after.jpg" alt="after battle" /></p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate>
<title>Building Scanning Patents</title>
<guid>https://www.jmeiners.com/floorplan-scanning/</guid>
<link>https://www.jmeiners.com/floorplan-scanning/</link>
<description>
<![CDATA[
<h1>Building Scanning Patents</h1>

<p>At a previous startup, I invented an Augmented Reality (AR) system for scanning buildings,
and automatically extracting floor plans from scans.
Recently a few of the patents I wrote were published, and I wanted to share those, with a brief summary.</p>

<h2>Capturing Environmental Features Using 2D and 3D Scans</h2>

<p><a href="US-11989895-B2.pdf">US-11989895-B2</a></p>

<p><img src="ar-scan.png" alt="ar scan" /></p>

<p>This describes an augmented reality workflow for capturing a 3D mesh of an environment, and recording points of interest.
A key idea is to capture all the user interactions and raw 3D data first.
Later in a post-process step, we determine user intent and relative positioning using complete global information.</p>

<h2>Floor Plan Extraction</h2>

<p><a href="US-12299784-B2.pdf">US-12299784-B2</a></p>

<p><img src="possible-scans.png" alt="possible-scans" /></p>

<p>Once we have a 3D scan of an environment, how do we go about turning this into a 2D floor plan?
Floor plans are conceptual, rather than objective, and so are guided by user input.
This invention describes both an augmented reality workflow and an algorithm for processing that input.
It turns out, doing this perfectly is likely NP-complete, but this proper understanding guides effective heuristics.</p>

<h2>Surface Animation During Dynamic Floor Plan Generation</h2>

<p><a href="US-12229859-B2.pdf">US-12229859-B2</a></p>

<p><img src="animation.png" alt="animation" /></p>

<p>It&rsquo;s important to give feedback to the user during the scanning process.
One way we do that is through the augmented reality visualization that shows which parts of a room are captured,
and is programmed through shaders.
The biggest challenge is to show accurate estimates quickly, despite the scan being incomplete.</p>

<h2>Aligning Polygon-like Representations With Inaccuracies</h2>

<p><a href="US-12651104-B2.pdf">US-12651104-B2</a></p>

<p><img src="align-shapes.png" alt="align shapes" /></p>

<p>Scan measurements contain error, and the real world is imperfect.
How can we correct the alignment of complex floor plan shapes with minimal distortion?
One answer is to simultaneously move all points of the floor plan in a <a href="/why-train-when-you-can-optimize/">multi-variable optimization</a> approach.</p>

<h2>Door and Window Detection in an AR Environment</h2>

<p><a href="US-12423828-B2.pdf">US-12423828-B2</a></p>

<p><img src="wall-3d.png" alt="wall 3D" /></p>

<p><img src="wall-2d.png" alt="wall 2D" /></p>

<p>Along with the shape of the building, we are also interested in the apertures of each room.
The polygonal shape tells us where the walls are in 3D.
We can then render the  portion of the 3D mesh corresponding to each wall, and detect cutouts in the rendered image.
This transforms a complex 3D detection problem into a traditional 2D computer vision problem.
These 2D detections are then projected back into 3D features on the wall.</p>
]]>
</description>
</item>
<item>
<pubDate>Fri, 18 Nov 2022 00:00:00 +0000</pubDate>
<title>Thinking styles from math</title>
<guid>https://www.jmeiners.com/thinking-styles/</guid>
<link>https://www.jmeiners.com/thinking-styles/</link>
<description>
<![CDATA[
<h1>Thinking styles from math</h1>

<p><strong>11/18/2022</strong></p>

<p>A surprising lesson I learned from graduate school is that math is just very different than everything else I have tried learning in the past.
It has it&rsquo;s own style of thinking that has become my <a href="/think-in-math/">primary method</a> for solving hard problems.
But, coming from a background in professional software development for years before, I expected a lot more of my core engineering skills to carry over.
Here I want to discuss some differences I noticed and their implications.</p>

<h2>Debugging and Proving</h2>

<p>Debugging programs taught me to check my work with a radically empirical approach.
When something isn&rsquo;t working as expected, I &ldquo;turn off&rdquo; that part of my brain that makes assumptions about what it should be doing, and directly examine the behavior of the program.
Usually it starts with, &ldquo;does this line ever get called?&rdquo;, and grows increasingly more skeptical, &ldquo;does 2+2 really equal 4?&rdquo;.
When the problem is tricky, no question is too stupid to ask.
The goal is to quickly find the gap in my mental model and accommodate it.
It&rsquo;s a simplified version of the scientific method, with a bit of a bias towards experimenting over hypothesizing.</p>

<p>Beginners struggle with debugging because they aren&rsquo;t as skeptical.
They feel the computer is doing impossible or magical things outside their control.
Perhaps it&rsquo;s uncomfortable or unintuitive for them to question their understanding when it&rsquo;s already shaky.</p>

<p>However, this skill of &ldquo;turning off&rdquo; your judgment and observing gets you almost nowhere in math.
Proving a theorem is all about building up new information from facts you know.
You have to look at it a conceptual object and assert with confidence, &ldquo;This fits into X category. I know X category has this property. Therefore&hellip; &rdquo;.
It&rsquo;s an active thinking process that takes constant energy and work.
While debugging is an exercise in humility, proving is all about making bold claims.</p>

<p>Even though it takes a lot of work, then end result is very satisfying.
In the process of proving you demonstrate that you know something in the truest way possible.
You don&rsquo;t just happen to hold a true opinion, but can explain, at increasing levels of detail, why it&rsquo;s true.</p>

<p>There is still an experimental aspect to math (some mathematicians prefer more experimentation than others), it just isn&rsquo;t like
interacting with a computer and passively observing output.
When you don&rsquo;t know where to go, you study examples and try to discern patterns.
This is very engaging work as you must be the one to construct the examples.
The most insight comes from exotic examples, that push things to the extreme, and take some creativity to come up with.</p>

<h2>Engineering and Discovery</h2>

<p>Debugging is just one small part of programming, and is usually an easy part.
What about the engineering skills that go into designing programs, like determining goals, evaluating trade-offs, creating plans, prototyping solutions step by step?
In my experience, there just isn&rsquo;t a whole lot of these that are applicable either.</p>

<p>Occasionally it&rsquo;s helpful in math to plan out a strategy for approaching a larger theorem,
but you have no idea what will be true or false, so you can&rsquo;t get into much detail, or make many assumptions that rely on prior steps.
There aren&rsquo;t really trade-offs to speak of, except where you want to spend your time and effort.</p>

<p>Engineers solve problems by iteratively improving solutions to overcome key technical challenges in the project.
In each iteration, they determine components that worked and components that didn&rsquo;t, and it&rsquo;s a matter
of keeping what worked and fortifying or replacing the broken stuff.</p>

<p>Mathematicians obviously try a lot of potential solutions, but rarely is it componentized in the same way.
Either the whole approach works or not.
The solution usually comes in the form of a key discovery, or a sudden flash of insight, after a lot of thought and experimentation.
This insight reveals the inter workings of the problem.</p>

<p>There is an alternative theory that programming is more like a craft than engineering, like woodworking, writing, or <a href="http://www.paulgraham.com/hp.html">painting</a>.
A craftsmen starts with a rough outline or plan, and then gradually improves individual portions of the work, occasionally making sweeping corrections across the entire piece.
Once again, I see very few parallels with math.
There is little hope to transform a false result into a true one, or to discover new insights with highly local refinements.</p>

<p>Why is there such a big gap in these experiences?
It&rsquo;s hard to say.
Math is certainly more focused on discovery and questioning what is true, as opposed to constructing something.
This suggests a more direct encounter with constraints imposed by the world.
But, even this distinction isn&rsquo;t very clear, as engineering also requires dealing with natural trade-offs.</p>

<h2>Meta-learning skills</h2>

<p>All of this has changed how I think about meta-learning.
There is an idea that all fields are pretty much the same, except for details, and you can just transfer skills between them.
Perhaps you have heard the goal of university is to teach you &ldquo;how to learn&rdquo;.
That just doesn&rsquo;t appear completely true.
Some things are similar enough for a transfer, but some are just different.</p>

<p>Despite differences I want to call out a meta-learning skill, which is used in math, that is hugely underrated in engineering and especially software.
That is deliberate practice combined with feedback or coaching.
Of course, it gets plenty of attention in sports and music.
But engineers argue that this doesn&rsquo;t matter for the kind of work they do.
Their low-level implementation skills could optimized, but they aren&rsquo;t the bottleneck.
Most of their effort is spent on tasks that are not focused on efficiency, and not even repeatable.
Consider tasks like conceptualizing the problem, gathering requirements, etc.</p>

<p>Dan Luu has <a href="https://danluu.com/productivity-velocity/">responded</a> to this, arguing that increased velocity significantly aids the other tasks, including simply being able to try more iterations in the same amount of time.
Read his article to get all the details.
I just want to add that math has been built up almost entirely of unique breakthroughs and discoveries, which rarely are the same as what&rsquo;s come before.
In other words, the solutions are even less repurposable than what engineers deal with.
Yet, mathematicians place significant weight in memorization, practice, coaching, and studying a variety of areas.</p>

<p>There are a few rationales for this.
Of course, practicing solving problems emulates the experience of actually making a mathematical discovery.
It&rsquo;s a pretty good emulation too, except that you have the assurance
there is a solution and that the teachers have tailored it to your skill level.</p>

<p>Another reason is making new breakthroughs is just easier if you are fluent with lower level concepts.
It&rsquo;s hard to do calculus, if you struggle with algebra.
Remember the discussion about how proving is difficult because you have to actively make new claims?
How do you get better at this process?
Either your learn the material more thoroughly so you can assert with more confidence from memory,
or learn adjacent material so you can perform logical consistency checks as you go.
Both of these are essentially just fluency.</p>

<p>Mathematicians also believe that the techniques used for old problems will become useful in the future.
Even if you never reproduce a proof exactly, it becomes a tool in your toolbox and a source of inspiration.
You may have noticed in college that math professors tend to have a &ldquo;nack&rdquo; for knowing what to try on a problem.
They seem to get right to the core issue while you are left thinking &ldquo;I would never have thought of that&rdquo;.
Although it may appear that they must have known the answer, it&rsquo;s actually their trained intuition, built up from being required to solve a lot of problems in a short amount of time.</p>

<p>What would it like to adopt similar practices in programming?
Of course, we should look at speed of writing code, following problem solving procedures, workspace improvements, etc.
Coaching suggests a whole set of interesting opportunities to be explored.</p>

<p>But, I think at the most basic level it starts with mindset.
Do we want to work hard to get better?
There seems to be an attitude of avoiding learning at all costs, because it doesn&rsquo;t directly count as productivity.
Why don&rsquo;t we embrace curiosity and practice as a separate and worthwhile activity?
Why don&rsquo;t we make a systematic study of the programs that have come before?</p>
]]>
</description>
</item>
<item>
<pubDate>Thu, 27 Oct 2022 00:00:00 +0000</pubDate>
<title>Iterating grid cell neighbors</title>
<guid>https://www.jmeiners.com/grid-neighbors/</guid>
<link>https://www.jmeiners.com/grid-neighbors/</link>
<description>
<![CDATA[
<h1>Iterating grid cell neighbors</h1>

<p><strong>10/27/22</strong></p>

<p>Suppose we need to iterate over the neighbors of a cell in a 2D grid:</p>

<pre><code>* * *
* - *
* * *
</code></pre>

<p>This can be done with the following well known pattern:</p>

<pre><code>void all_neighbors() {
    for (int i = -1; i &lt;= 1; ++i) {
        for (int j = -1; j &lt;= 1; ++j) {
            if (i == 0 &amp;&amp; j == 0) continue;
            std::cout &lt;&lt; i &lt;&lt; ", " &lt;&lt; j &lt;&lt; std::endl;
        }
    }
}
</code></pre>

<p>But what if we just want to iterate the horizontal and vertical neighbors, skipping the diagonal?</p>

<pre><code>   *
 * - *
   *
</code></pre>

<p>Most programs explicilty repeat the operation 4 times, or use a table.
But there is a trick to do it in a loop.
Think of the neighbor as a vector offset, and then rotate it 90 degrees, 4 times.</p>

<pre><code>template &lt;typename I&gt;
void rotate_2d(I&amp; a, I&amp; b) {
    std::swap(a, b);
    b = -b;
}

void direct_neighbors() {
    int i = 1;
    int j = 0;
    for (int k = 0; k &lt; 4; ++k) {
        std::cout &lt;&lt; i &lt;&lt; ", " &lt;&lt; j &lt;&lt; std::endl;
        rotate_2d(i, j);
    }
}
</code></pre>

<p>Try it out!</p>

<pre><code>int main() {
    std::cout &lt;&lt; "diagonal" &lt;&lt; std::endl;
    all_neighbors();
    std::cout &lt;&lt; "square" &lt;&lt; std::endl;
    direct_neighbors();
}
</code></pre>
]]>
</description>
</item>
<item>
<pubDate>Mon, 12 Sep 2022 00:00:00 +0000</pubDate>
<title>Volcano Drop (js13kgames entry)</title>
<guid isPermaLink="true">https://js13kgames.com/entries/volcano-drop</guid>
</item>
<item>
<pubDate>Thu, 21 Jul 2022 00:00:00 +0000</pubDate>
<title>The Quake entity system: shell scripting for games</title>
<guid>https://www.jmeiners.com/quake-entities/</guid>
<link>https://www.jmeiners.com/quake-entities/</link>
<description>
<![CDATA[
<h1>The Quake entity system: shell scripting for games</h1>

<p><strong>By: Justin Meiners</strong></p>

<p><strong>07/20/2022</strong></p>

<p>The <em>Quake</em> engine provided the foundation for many early 3D games,
including contributions to hit titles like <em>Half-Life</em>, <em>Call of Duty</em>, and <em>Star Wars Jedi Knight II: Jedi Outcast</em>.
But its influence on 3D technology runs much deeper than source code.
An entire generation of developers and modders
was introduced to making 3D games through <em>Quake</em>,
and the concepts it introduced can be found throughout game technology today.</p>

<p>Most of what&rsquo;s been written about the <em>Quake</em> engine focuses on 3D graphics or multiplayer.
And it&rsquo;s hard to overstate just how many brilliant innovations the team came up with during its relatively brief development. (See <a href="https://www.bluesnews.com/abrash/contents.shtml">Michael Abrash&rsquo;s</a> first-hand account,
<a href="https://fabiensanglard.net">Fabien Sanglard&rsquo;s</a> code reviews,
and, more recently, the excellent videos from <a href="https://www.youtube.com/@MattsRamblings">Matt&rsquo;s Ramblings</a>.)</p>

<p>But much overlooked is the innovative <em>Quake</em> <strong>entity system</strong>
which enables designers to craft interactive levels without writing custom code.
Of particular interest is its similarity in design to UNIX.
Both systems provide simple computational building blocks
and a language (known as a shell) for combining them in complex ways.
This system is modular for extension and is also emergent,
enabling new gameplay not anticipated by the original engineers.</p>

<p>This article provides a brief introduction to how the system works,
identifies several creative case studies from <em>Quake</em>,
and discusses the parallels with UNIX design.</p>

<p><img src="e4m3_platforms.jpg" alt="e4m3 platforms" /></p>

<h2>Entity basics</h2>

<p>We will start by describing the interface for the engine, the <code>.map</code> file format.
This is a text format describing a level.
It will undergo several offline compilation steps before being loaded into the game runtime,
but ultimately represents the features the engine provides to designers.</p>

<p>Every object in the <em>Quake</em> world is called an <strong>entity</strong>.
An entity is a list of key-value properties.
All entities have a property, <code>classname</code>, which specifies the entity&rsquo;s kind.</p>

<p>The following specifies where the player will spawn in 3D space:</p>

<pre><code>{
    "spawnflags" "0"
    "classname" "info_player_start"
    "origin" "32 32 24"
}
</code></pre>

<p>The meaning of a key, and whether it is applicable, is determined entirely by the <code>classname</code>.
Many keys are common across a family of entity types, like <code>spawnflags</code>.
Some keys are only useful for a particular class.
For example, the <code>light</code> key configures brightness and applies only to the <code>light</code> class:</p>

<pre><code>{
    "light" "250"
    "origin" "480 96 168"
    "classname" "light"
}
</code></pre>

<p>A <code>.map</code> file consists of one or more entities concatenated together.
All aspects of a level, including lighting, interactive objects, and scenery, are described as entities.
Thus a <strong>map editor</strong> is basically a tool for placing entities and modifying their properties.</p>

<h3>Point entities</h3>

<p>Let&rsquo;s introduce the common entity structures.
<strong>Point entities</strong> have a 3D position, specified by the <code>origin</code> property.
For example, a monster:</p>

<p><img src="monster.jpg" alt="monster" /></p>

<p>or a weapon pickup:</p>

<p><img src="weapon.jpg" alt="weapon pickup" /></p>

<p>Point entities are typically visualized as a 3D mesh.
Some, like <code>light</code>, are nonvisual at runtime and are depicted in the editor as icons.</p>

<h3>Solid entities</h3>

<p><strong>Solid entities</strong> are represented by a 3D volume.
This volume is constructed from convex <strong>brushes</strong> which will be discussed later.</p>

<p>A moving platform is an example of a solid entity:</p>

<p><img src="platform.jpg" alt="platform" /></p>

<p>and so is a button:</p>

<p><img src="button.jpg" alt="func_button" /></p>

<p>Solid entities do not share a visual representation.
The shape and size of each instance is customized for each use case.</p>

<h3>Runtime representation</h3>

<p>Entities that are loaded into the game all use the same <code>entity</code> data structure<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>.
This provides a uniform interface
for communicating between entities and for systems to inspect them.</p>

<h2>targetname basics</h2>

<p>So far, <code>.map</code> is elegant, but doesn&rsquo;t appear very special.
Every game has objects that need to be placed in the world,
and it&rsquo;s helpful to make their properties configurable.
What else would you do?!
And many games have been successfully built
by creating different entity types for all interactive objects in the game.</p>

<p>Instead, <em>Quake</em> adds a powerful way to combine entities.
It does this through a property called <code>targetname</code>.
This gives an entity a name that other entities can reference
in one of their <code>*target</code> properties.
For example, <code>target</code> means:</p>

<blockquote><p>&ldquo;When I am <em>activated</em>, find all the entities with a <code>targetname</code> matching my <code>target</code> and activate them.&rdquo;</p></blockquote>

<p>A <code>targetname</code> is not unique, so multiple entities can respond to the same action.</p>

<p>&ldquo;Activate&rdquo; is used loosely,
as the exact meaning is determined by the type of entity.
What&rsquo;s essential is that relationships between entities can be created in the map editor.
Using this system, a designer can set up novel interactive gameplay in each
level without custom programming.</p>

<h3>E1M1 Jump instructions</h3>

<p>Let&rsquo;s look at a few introductory examples.</p>

<p><img src="e1m1_jump.jpg" alt="e1m1 jump instructions" /></p>

<p>The trigger on the left fires when the player touches it, with a <code>wait</code> time of five seconds
before reactivating. When activated, it displays a message and plays a sound:</p>

<pre><code>{
    "classname" "trigger_multiple"
    "message" "You can jump across..."
    "sounds" "2"
    "targetname" "t32"
    "wait" "5"
}
</code></pre>

<p>Across the gap is another trigger which fires and is removed when the player touches it.
This uses <code>killtarget</code> to also delete the previous entity.</p>

<pre><code>{
    "classname" "trigger_once"
    "killtarget" "t32"
}
</code></pre>

<p>The intent is to teach the player how to make their first jump.
After their ability to do so has been demonstrated, the message is removed.</p>

<h3>E1M1 Patrol path</h3>

<p>Let&rsquo;s look at a very different example where <code>targetname</code> is used to represent
a logical linkage rather than an activation or event.
Here, a path is specified for a monster to patrol until it is aggravated by the player:</p>

<p><img src="e1m1_path.jpg" alt="e1m1 monster path" /></p>

<p>A path is constructed from a sequence of <code>path_corner</code> entities.
Each has a <code>targetname</code> and a <code>target</code> referring to the next node in the path.
The <code>target</code> of the monster is set to the first node in the path.</p>

<pre><code>{
    "classname" "path_corner"
    "origin" "-560 2352 40"
    "targetname" "t23"
    "target" "t24"
}

{
    "classname" "path_corner"
    "origin" "-104 2352 40"
    "targetname" "t24"
    "target" "t23"
}
</code></pre>

<p>In this screenshot, the two nodes are linked to each other in a cycle.
The monster therefore repeats its walk along the path until aggravated.</p>

<h3>E1M1 Ramp</h3>

<p>This example shows more entities combined to create a larger system.
As the player moves down the ramp, several interactions occur.</p>

<p><img src="e1m1_counter.jpg" alt="e1m1 counter" /></p>

<p>The large <code>trigger_once</code> on the path activates a light farther down the ramp:</p>

<pre><code>{
    "classname" "trigger_once"
    "sounds" "3"
    "target" "t11"
}

{
    "classname" "light"
    "light" "400"
    "origin" "752 2000 -88"
    "spawnflags" "1"
    "targetname" "t11"
}
</code></pre>

<p>A <code>func_door</code> is used to pop up a depiction
of the light source. (A &ldquo;door&rdquo; is just something that moves back and forth.)</p>

<pre><code>{
    "classname" "func_door"
    "angle" "-1"
    "sounds" "1"
    "spawnflags" "1"
    "targetname" "t11"
}
</code></pre>

<p>The light reveals a nearby button.</p>

<pre><code>{
    "classname" "func_button"
    "spawnflags" "2048"
    "target" "t9"
    "wait" "-1"
    "angle" "270"
}
</code></pre>

<p>The buttons are wired to a <code>trigger_counter</code>.
After all three buttons are pressed, a door opens below.</p>

<pre><code>{
    "classname" "trigger_counter"
    "count" "3"
    "target" "t10"
    "targetname" "t9"
}
</code></pre>

<h3>What is an entity?</h3>

<p>The <code>targetname</code> system is very simple but powerful.
It transforms what would be a property editor into a primitive scripting system,
by providing a <strong>means of combination</strong><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>, one of the essential capabilities of any programming system.</p>

<p>But just linking two objects together,
like a door to the switch that opens it,
is not enough to constitute scripting.</p>

<p>The breakthrough in <em>Quake</em> is recognizing that the ability
to combine behaviors also changes the behaviors that you need to build.
Instead of a suite of complex gameplay objects,
you really need very simple building blocks that perform fundamental operations.
These entities compose well and become reusable, enabling more applications with less code.</p>

<p>For example, <code>func_door</code> isn&rsquo;t really a door.
It&rsquo;s an abstract conception of a door in a 3D game.
It&rsquo;s an object that moves from its resting position
to a neighboring position and perhaps back again.
Its meaning as a door depends on visuals and how it&rsquo;s configured in a system.
(We&rsquo;ve already seen a completely different usage above.)</p>

<p>This line of thinking also leads to abstraction.
Logical entities like gates, timers, and counters
are introduced that enable machines to be built around the simple components.</p>

<p>One of <em>Quake</em>&rsquo;s contributions is to invent this set of fundamental building blocks for 3D games.</p>

<h3>Abstract entities</h3>

<p>An odd consequence of the <code>targetname</code> scripting system
is that many abstract entities live in 3D space,
but that information is of no use to the game, and is entirely incidental.
<code>trigger_counter</code> is one example of such an abstract entity.</p>

<p>But 3D placement does turn out to have some interesting benefits.
Designers naturally place the entities that work together next to each other.
So the entities that work together are visually associated.
But their layout can also suggest how the machine operates,
for example, when entities are placed in a directional sequence
or arranged to lead toward an objective.</p>

<p>This provides a mnemonic benefit to designers who can often tell how something
works just by looking at it.
Similarly, debug tools can show entity systems running in-game.</p>

<h2>UNIX philosophy</h2>

<p>Here we start to see an analogy with UNIX.
The shell is a text-based language that enables interaction with a computer through a command line
and allows those same commands to be automated in scripts.
The key feature of the shell is that the input and output of entire programs can be routed via pipes.
One program can pass its output to be transformed by another.</p>

<p>How the shell works is not similar to <em>Quake</em>, nor is the data it interacts with.
But its role is very similar.
The introduction of composable programs changed how engineers conceived of programs.<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup>
Instead of a monolithic script for solving a business problem, a program became a single logical operation,
usually with just a few hundred lines of code,
behind a well-defined input/output interface.</p>

<p>Iterating on this idea produced a core set of programs that
are generally useful across many computer tasks.
These programs do so little that they appear trivial
and useless on first encounter,
without an appreciation of their usage in larger systems.
For example, <code>head</code> returns the first few lines of its input and discards the rest.
<code>tr</code> replaces one character with another.</p>

<p>Combining these and a few more, we can find the 10 most common words in a book<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup>:</p>

<pre><code>tr -cs '[:alpha:]' '\n' &lt; book.txt \
    | tr '[:upper:]' '[:lower:]' \
    | sort \
    | uniq -c \
    | sort -nr \
    | head
</code></pre>

<p>In a not dissimilar manner, a file downloader, an HTML converter, and a text editor
can be combined to make a web browser.</p>

<p>Both the shell and <code>targetname</code> face a similar critique:
their interfaces are <em>too</em> unstructured,
leading to bugs and excessive reliance on convention.<sup id="fnref:5"><a href="#fn:5" rel="footnote">5</a></sup>
<em>Quake</em> lets you link entities together, but it does not guarantee compatibility,
and the semantics of those links are loose.</p>

<h3>Modularization</h3>

<p>The UNIX philosophy enables all kinds of economic benefits through modularization.
Programs can be thrown away and replaced while the system is preserved.
They can be tested and qualified in isolation.</p>

<p>But the primary benefit is <strong>emergent applications</strong>.
Programs can be useful in solving problems never anticipated by their designers<sup id="fnref:6"><a href="#fn:6" rel="footnote">6</a></sup>.
And old programs that have been used for decades
can suddenly be complemented by a new program that gives them
new meaning and applications.</p>

<p>The variety and ingenuity of entity creations in
<em>Quake</em> and the projects built upon it demonstrate a similar story.</p>

<h3>Monism</h3>

<p>We mentioned that at runtime all entities share the same data structure.
UNIX has a similar focus on the concept of a <strong>file</strong>.
It takes what were traditionally very distinct computer systems like
data storage, networking, displays, and input devices,
and unifies them under one read/write interface.</p>

<p>The benefit both systems enjoy is an elimination of special cases.
Programs can be written to manipulate files and can then apply to many use cases.
Similarly, <em>Quake</em> enables uniform operations on entities regardless of their type
and despite their many behaviors.</p>

<h3>How faithful is Quake to UNIX?</h3>

<p>UNIX went through decades of iteration to get its core functionality.
The entities in <em>Quake</em> are much closer to a first draft of the idea
that future games attempt to refine.</p>

<p>One indication of this immaturity is that obviously unrelated functionality is provided by the same entity.
For example, <code>trigger_once</code> can show a message <em>and</em> play a sound.
A hypothetical fix would be to have separate <code>func_sound</code> and <code>func_message</code> entities,
each of which could be activated by the same trigger.</p>

<p>An obvious way in which this increases flexibility and reuse is that a trigger
can now play multiple sounds, and each entity that plays sound
doesn&rsquo;t duplicate that work.
This specific correction was made in Valve&rsquo;s <a href="https://developer.valvesoftware.com/wiki/SDK_Docs">Source Engine</a>.<sup id="fnref:7"><a href="#fn:7" rel="footnote">7</a></sup></p>

<p>Combining multiple functions is tempting for convenience,
but weakens the modularization benefits of the core design.
This flaw can also be seen in immature UNIX systems.
Programs gradually expand with flags to modify program functionality,
often with viral impact.<sup id="fnref:8"><a href="#fn:8" rel="footnote">8</a></sup>
Eventually, this leads to a clarification of responsibilities and a split
into separate parts.</p>

<h2>The game world</h2>

<p>So far we&rsquo;ve focused on the interactive and logical capabilities of entities.
Let&rsquo;s now look at how entities construct the levels themselves, including the structure
and scenery for the gameplay.</p>

<h3>worldspawn</h3>

<p>Each map contains exactly one instance of the <code>worldspawn</code> class,
a solid entity that describes the 3D shape of the level.
<code>worldspawn</code> is also a &ldquo;catch-all&rdquo; for configuring the general setting and appearance of a level,
such as the ambient level of light.</p>

<p>As established before, a <code>.map</code> file consists only of entities,
and they follow the same basic schema.
But the engine is free to treat them specially.</p>

<p><code>worldspawn</code> is such an entity with a special role.
The level geometry needs to be preprocessed
into an efficient representation for visibility testing, rendering, and collision.
<code>light</code> entities are also closely related to <code>worldspawn</code>.
High-quality lighting data is precomputed for the level geometry,
so most <code>light</code> entities are removed prior to game runtime.</p>

<p>All of this results in static scenery, a tradeoff necessary to meet performance requirements.
This special treatment is an implementation detail that is hidden from the <code>.map</code> interface.</p>

<h3>Brushes</h3>

<p>The following explains in detail how the 3D shape of a solid entity is specified.
A brush is the enclosed space of four or more planes (&ldquo;oriented half-spaces&rdquo; for math folks).
For example, a cube is a brush constructed from six planes.<sup id="fnref:9"><a href="#fn:9" rel="footnote">9</a></sup></p>

<p>Each plane is defined by three points lying on it, along with a few texture parameters:</p>

<pre><code>( 256 64 16 ) ( 256 64 0 ) ( 256 0 16 ) mmetal1_2 0 0 0 1 1
</code></pre>

<p>Below are a variety of brush shapes from <em>Quake</em>:</p>

<p><img src="brush1.jpg" alt="quake brush sample" />
<img src="brush2.jpg" alt="quake brush2" />
<img src="brush3.jpg" alt="quake brush3" />
<img src="brush4.jpg" alt="quake brush4" /></p>

<p>Brushes have a few nice properties:</p>

<ul>
<li>They can be converted into a 3D triangle mesh for rendering.<sup id="fnref:10"><a href="#fn:10" rel="footnote">10</a></sup></li>
<li>Texture coordinates can be generated for them easily.</li>
<li>They simplify physics calculations, such as collision detection.</li>
</ul>


<p>Brushes can be drawn right in the level editor,
so a designer can quickly tailor the shape of an entity or sketch a space.</p>

<h3>Brushwork</h3>

<p>Brush-based modeling is much less common in games<sup id="fnref:11"><a href="#fn:11" rel="footnote">11</a></sup>.
So let&rsquo;s review a few examples from <em>Quake</em> to understand
how <code>worldspawn</code> works.</p>

<h4>E1M4</h4>

<p><img src="e1m4_brush.jpg" alt="e1m4 brushwork" /></p>

<p>The archway is constructed from wedge slices
that linearly approximate a curve.
Note the irregular cut to give the ground around the door an organic appearance.</p>

<h4>E1M5</h4>

<p><img src="e1m5_brush.jpg" alt="e1m5 brushwork" /></p>

<p>This building makes heavy use of rounded columns and archways.
Notice the many shim pieces needed to fill the gaps.
The trim pieces around the column give a surface for an alternative texture.</p>

<h4>E4M3</h4>

<p><img src="e4m3_brush.jpg" alt="e4m3 brushwork" /></p>

<p>This outdoor area shows brushes being used to model small objects,
rather than architecture.
The grave bump is also a nice effect that disguises
the flat shape of the grass.</p>

<h2>Separation of view and model</h2>

<p>Video games rely heavily on visuals, sound, and atmosphere
to provide context and meaning for player interactions.
The simulation itself can be very crude.
What the player experiences as a medieval dungeon filled with knights
is understood by the computer as a few boxes in space.</p>

<p>The <em>Quake</em> entity system leverages this idea
by separating the behavior of an entity
from its visual depiction,
like the classical view/model distinction in programming.
This enables more reuse of entities and flexibility for designers,
rather than combining the behavior and visual representation in one game object.</p>

<h3>Solid entity customization</h3>

<p>The first way it does this is through the brush system.
Solid entities like doors, buttons, and trains are drawn
for each use case with no programmatic functionality changes.
So the doors all look different and can take on new shapes.</p>

<h4>E4M7 doors</h4>

<p>A few creative entity depictions were already shown.
Here is one more where a <code>func_door</code> pulls apart interlocked bars:</p>

<p><img src="e4m7_door.jpg" alt="E4M7 Door" /></p>

<h3>Invisible entities</h3>

<p>Another way this is done is by simply placing an invisible
entity over a visual object, effectively granting it that behavior.
Let&rsquo;s look at a few of these.</p>

<h4>START difficulty selection</h4>

<p>The game difficulty is selected by jumping through a portal<sup id="fnref:12"><a href="#fn:12" rel="footnote">12</a></sup>.</p>

<p><img src="start_no_trigger.jpg" alt="start no trigger" /></p>

<p>The portal itself is static geometry with an animated center texture.</p>

<p>Placed on top of the model are an invisible trigger to set the difficulty
and an invisible teleporter to move the player into the next room.
These rest in front of the model.</p>

<p><img src="start_trigger.jpg" alt="start trigger" /></p>

<h4>E4M4 Healing pool</h4>

<p>Near a small pool of water, the game announces, &ldquo;You found a healing pool!&rdquo;</p>

<p>The pool is constructed as a plane in the floor with a water texture.
But underneath the surface are many health packs that cannot be seen.</p>

<p><img src="e4m4_pool.jpg" alt="e4m4 pool" /></p>

<p>An invisible trigger that displays the message and plays an ambient sound completes the effect.</p>

<p>Here we have a familiar entity, but by making it invisible
we can give it a new visual that gives the player a fresh experience.
And most players are completely unaware the pool is only finite!</p>

<h2>Advanced entities</h2>

<p>With an understanding of the entity system, let&rsquo;s look at a few
case studies from <em>Quake</em> that leverage all parts of the system
to create memorable experiences.</p>

<h3>E1M7 Lightning puzzle</h3>

<p>Chthon, the boss, can be defeated by zapping him between two lightning rods.</p>

<p><img src="e1m7_lightning.jpg" alt="e1m7 lightning" /></p>

<p>Each rod is tied to a nearby button, with a third button used to activate the lightning.</p>

<p>(Notice that there are actually four buttons, but only two are ever selected, depending on the difficulty level.)
The lightning effect itself requires some in-game hard-coding to position itself,
but otherwise is an example of the entity system creating new gameplay mechanics.</p>

<h3>E1M3 platforms</h3>

<p>The player is locked in a room with the ceiling descending.
Previously, they encountered similar rooms that could squash them.
At the last second, the ceiling separates into two pieces,
and the floor lifts the player up to the end of the level.</p>

<p><img src="e1m3_platform.jpg" alt="e1m3 platform" /></p>

<p>The ceiling is constructed from two separate <code>func_train</code> entities.
A path positioned at the corners of each entity guides it through the movement.</p>

<p>The floor is actually a <code>func_door</code>.
Its lifting motion is activated by a <code>trigger_once</code> timer
with a <code>wait</code> time designed to coincide with the train movement.</p>

<p><img src="e1m3_paths.png" alt="e1m3 paths" /></p>

<h3>E1M7 fireworks celebration</h3>

<p>After Chthon is defeated, the level ends, and in the background, gibs rain down on the arena.
This effect is built entirely with the entity system.</p>

<p>Completing the level activates a network of entities in an offscreen room.</p>

<p><img src="e1m7_machine.jpg" alt="e1m7 firework machine" /></p>

<p>A sequence of timers starts counting down, wired to activate an accompanying set of teleporters.
These continue to fire as the world simulation continues independently of the player&rsquo;s existence.</p>

<p><img src="e1m7_monsters.jpg" alt="e1m7 firework machine with monsters" /></p>

<p>On top of each teleporter are two monsters that will be destroyed immediately
after being transported.
(Destruction is a consequence of two entities trying to teleport into the same place.)</p>

<p>This example represents a machine or program made with <em>Quake</em>.
It combines the logic of the <code>targetname</code> system with the physical consequences of the world simulation.
And this room exists entirely offscreen!
It&rsquo;s literally a black box whose internal operation and 3D existence are incidental
to its function.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>Every runtime entity is an instance of the same <a href="https://github.com/id-Software/Quake/blob/master/QW/server/progdefs.h">entity struct</a>
that contains every field needed for all classes.
Here&rsquo;s a snippet to give you an idea:</p>

<pre><code>typedef struct
{
    float modelindex;
    vec3_t absmin;
    vec3_t absmax;
    float ltime;
    float lastruntime;
    float movetype;
    float solid;
    vec3_t origin;
    // ...
    string_t noise2;
    string_t noise3;
} entvars_t;
</code></pre>

<p>This pattern of unioning together all the fields needed
by all cases is called a <strong>fat struct</strong>, as many of the fields may go unused.</p>

<p>This idea may conflict with what you learned in object-oriented programming,
but it has a lot of design benefits. The entity array is allocated upfront and has
a fixed cost of ~1000 entities.
Compared to the size of 3D textures and sounds in a game,
the unused space is tiny!</p>

<p>A game system, such as physics, can just visit the entire list of entities and perform
the same operation for each entity. Entities opt into a behavior by configuring
the relevant properties.</p><a href="#fnref:1" rev="footnote">&#8617;</a></li>
<li id="fn:2">
See <a href="https://web.mit.edu/6.001/6.037/sicp/html/book/book-Z-H-10.html#%_sec_1.1"><em>Structure and Interpretation of Computer Programs</em></a> chapter 1.<a href="#fnref:2" rev="footnote">&#8617;</a></li>
<li id="fn:3">
<p>Windows conceives of a program as a complete application,
including a user interface, menu bar, file-management options, etc.
And if you&rsquo;ve only used Windows, it&rsquo;s hard to imagine an alternative.</p>

<p>UNIX programs try to do less, but not because they are less capable.
The conventions and culture of UNIX have set different expectations,
grounded in the compositional power of the shell.</p><a href="#fnref:3" rev="footnote">&#8617;</a></li>
<li id="fn:4">
<p>The first <code>tr</code> puts each word on a new line.
The second replaces uppercase with lowercase.
<code>sort</code> orders all the words, and <code>uniq</code> removes duplicate adjacent words (with counts).
The last sort reorders the words based on this count.
Finally, <code>head</code> discards everything after the top few lines of input, with a default line count of 10.</p><a href="#fnref:4" rev="footnote">&#8617;</a></li>
<li id="fn:5">
The main critique of UNIX is that the input/output interface is unstructured text.
So if a producer has structured data it must format it to text.
The consumer must then also parse the input, which is error-prone.
And of course programmers often make poor parsers and formatters that choke
on unexpected character sequences.<a href="#fnref:5" rev="footnote">&#8617;</a></li>
<li id="fn:6">
In contrast, desktop software development and testing focus
on <em>key workflows</em>, suggesting that their use cases have been anticipated
up front.<a href="#fnref:6" rev="footnote">&#8617;</a></li>
<li id="fn:7">
<p>Source is an evolution of the <em>Quake</em> entity system for more complex games.
It&rsquo;s been greatly expanded with new entity types and features.
But almost all of the original <em>Quake</em> entities (<code>func_button</code>, <code>func_train</code>, <code>trigger_once</code>, etc.) are still present (see a <a href="https://developer.valvesoftware.com/wiki/List_of_entities">full list</a>)!</p>

<p>Below is an interactive <a href="https://developer.valvesoftware.com/wiki/Keypad">keypad</a> made by a Source community member
that demonstrates how powerful the system is.</p>

<p><img src="source_keypad.jpg" alt="source keypad" /></p>

<blockquote><p>It includes visual and audio responses to any four-digit code. If the code is correct, it opens the door, plays an acceptance sound, and blinks a green light. Otherwise, it plays a rejection sound and blinks a red light.</p></blockquote>

<p>There are 23 total entities in the system, including:</p>

<ul>
<li><code>func_button</code>: one for each button on the keypad, for a total of 11.</li>
<li><code>func_detail</code>: the 3D model of the keypad.</li>
<li><code>prop_dynamic</code>: the door model, which opens.</li>
<li><code>func_door</code>: the logical entity that controls the door&rsquo;s motion.</li>
<li><code>logic_case</code>: stores the sequence of four expected numbers and the events for a successful code.</li>
<li><code>logic_timer</code>: resets the keypad entry after a period of inactivity.</li>
<li><code>ambient_generic</code>: plays the acceptance or rejection sounds.</li>
</ul>
<a href="#fnref:7" rev="footnote">&#8617;</a></li>
<li id="fn:8">
A common temptation in UNIX programming is to add new functionality
via flags, rather than separate programs. Many programs have options to perform a transformation
that duplicates functionality available in other core programs.<a href="#fnref:8" rev="footnote">&#8617;</a></li>
<li id="fn:9">
<p>Below is a 64 × 64 × 64 cube in <code>.map</code> syntax:</p>

<pre><code>{
    ( 64 64 64 ) ( 64 64 0 ) ( 64 0 64 ) mmetal1_2 0 0 0 1 1
    ( 0 0 0 ) ( 0 64 0 ) ( 0 0 64 ) mmetal1_2 0 0 0 1 1
    ( 64 64 64 ) ( 0 64 64 ) ( 64 64 0 ) mmetal1_2 0 0 0 1 1
    ( 0 0 0 ) ( 0 0 64 ) ( 64 0 0 ) mmetal1_2 0 0 0 1 1
    ( 64 64 0 ) ( 64 0 0 ) ( 0 64 0 ) mmetal1_2 0 0 0 1 1
    ( 0 0 64 ) ( 64 0 64 ) ( 0 64 64 ) mmetal1_2 0 0 0 1 1
}
</code></pre><a href="#fnref:9" rev="footnote">&#8617;</a></li>
<li id="fn:10">
<p>To construct a 3D mesh from a brush, we need to intersect all the planes.
This is done by examining each triplet of planes and forming a linear system of equations.
The solution to this system (if a unique one exists) is the point where the planes intersect.</p>

<p>The intersection points form a vertex candidate list.
Points that are behind any brush plane (outside the brush) can be removed,
along with duplicates.
On each plane, a collection of points remains that outlines
a polygon.
This polygon becomes the face of the mesh.</p>

<p><img src="intersect_planes.png" alt="intersect planes" /></p><a href="#fnref:10" rev="footnote">&#8617;</a></li>
<li id="fn:11">
Modern game scenery is created from 3D models using 3D art software.
But brush-style modeling is still extremely popular with level designers
to quickly prototype spaces for gameplay.
Brushes can be drawn easily and they naturally fit architectural modeling.
After a space is sketched, the brushwork is either thrown away or used
as a skeleton which the 3D models are placed on top.<a href="#fnref:11" rev="footnote">&#8617;</a></li>
<li id="fn:12">
Integrating menu options into the gameplay is not a gimmick.
Selecting a higher difficulty requires the player to make a dangerous
jump to access the portal. Thus the player demonstrates some level of readiness through the interaction.<a href="#fnref:12" rev="footnote">&#8617;</a></li>
</ol>
</div>

]]>
</description>
</item>
<item>
<pubDate>Sat, 25 Jun 2022 00:00:00 +0000</pubDate>
<title>A simple mesh adjacency data structure</title>
<guid>https://www.jmeiners.com/mesh-adjacency-trick/</guid>
<link>https://www.jmeiners.com/mesh-adjacency-trick/</link>
<description>
<![CDATA[
<h1>A simple mesh adjacency data structure</h1>

<p><strong>06/25/2022</strong></p>

<p>Do you need a mesh adjacency structure?
Are you considering implementing <a href="https://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm">half edge</a> or <a href="https://wiki.blender.org/wiki/Source/Modeling/BMesh/Design">bmesh</a>?
Here is a trick to consider first, that may save you some energy.</p>

<p>Take your mesh&rsquo;s indices array and reverse it:</p>

<pre><code>// f -&gt; v
uint32_t *index_to_vert = indices;

// v -&gt; f:
multimap&lt;uint32_t, uint32_t&gt; vert_to_index;
for (size_t i = 0; i &lt; index_count; ++i)
{
    vert_to_index.insert(make_pair(index_to_vert[i], i));
}
</code></pre>

<p>This <a href="https://en.cppreference.com/w/cpp/container/multimap">multimap</a> can handle most mesh traversal queries efficiently,
such as:</p>

<pre><code>// return number of faces a vertex belongs to
size_t degree(uint32_t vert)
{
    auto range = vert_to_index.equal_range(vert);
    return (size_t)(range.second - range.first);
}
</code></pre>

<h3>Details</h3>

<p>So what&rsquo;s going on here?
The original <code>indices</code> can be thought of as a map from faces to vertices (technically 3 indices for each triangle, but that&rsquo;s the idea).</p>

<p><img src="face_to_vertex.png" alt="face to vertex" /></p>

<p>This new multimap goes in the opposite direction.
It maps vertices to faces.
Because a single vertex may be shared between faces, the map does not have unique keys (hence <code>multi-</code>).</p>

<p><img src="vertex_to_face.png" alt="vertex to face" /></p>

<p>It is a little more cumbersome to write certain operations.
But this is mostly a matter of writing a few good helper functions.
Let&rsquo;s look at one more:</p>

<pre><code>vector&lt;uint32_t&gt; neighboring_faces(uint32_t face_index)
{
    vector&lt;uint32_t&gt; neighbors;
    for (uint32_t f = 0; f &lt; 3; ++f)
    {
        // visit vertex in this face
        uint32_t vert_index = indices[face_index * 3 + f];

        // find attached faces
        auto range = verts_to_faces.equal_range(vert_index);
        for_each(range.begin(), range.end(), [](auto i) {
            uint32_t neighbor_face_index = i / 3;
            if (neighbor_face_index == face_index) return;

            neighbors.push_back(neighbor_face_index);
        });
    }

    return neighbors;
    // TODO: remove duplicate results
    // TODO: you want to allocate a new vector for this. It's for illustrative purposes.
}
</code></pre>

<h3>What are its limitations?</h3>

<p>This data structure is an easy to implement solution for traversing a mesh.
But if you need to <em>edit</em> the mesh, it usually won&rsquo;t help.
Addding or remove a mesh element typically requires rebuilding part of the multimap, which is inefficient, and tedious.
As <a href="https://fgiesen.wordpress.com/2012/02/21/half-edge-based-mesh-representations-theory/">Fabien describes</a>, it&rsquo;s hard enough to maintain the invariants of a 3D mesh during editing, without this extra work.</p>

<p>Some editing algorithms may skim by.
One technique is to use the multimap to visit the mesh, marking which faces and vertices to delete,
and then throwing away the multimap and applying the changes.</p>

<p>It&rsquo;s probably less efficient than a half-edge mesh, which maintains direct pointers.
But the algorithmic complexity should be the same.</p>

<h3>No manifold requirements</h3>

<p>This technique has another advantageous property that&rsquo;s worth calling out.
Adjacency structures typically impose additional mathematical requirements on the mesh structure.
These can be tedious to verify, and hard to fix if the mesh wasn&rsquo;t constructed with them in mind.
For example half-edges only work if the mesh is a <a href="https://en.wikipedia.org/wiki/Manifold#Manifold_with_boundary"><em>2-manifold with boundary</em></a>,
consequently edges have at most 2 faces attached.</p>

<p>But the multimap has no such requirement!
It can be constructed for any indexed triangle soup!</p>

<p>One caveat to is that several mesh processing algorithms still assume similar requirements,
so watch out for that.</p>

<h3>What if you can&rsquo;t use multimap?</h3>

<p>The C++ <strong>std::multimap</strong> is a pretty complex data structure on its own,
and most standard libraries don&rsquo;t have an equivalent.
So is it just hiding all the complexity?
No! You can implement a cheap version using a sorted array and binary search.</p>

<p>The construction is very similar, but we sort at the end:</p>

<pre><code>uint32_t *index_to_vert = indices;

using ReverseIndex = pair&lt;uint32_t, uint32_t&gt;;
ReverseIndex* vert_to_index = new ReverseIndex[index_count];

for (uint32_t i = 0; i &lt; index_count; ++i) {
    vert_to_index[i] = make_pair(index_to_vert[i], i);
}

sort(vert_to_face, vert_to_face + index_count);
</code></pre>

<p>Note that <code>index_to_vert</code> and <code>vert_to_index</code> have the same size.</p>

<p>The purpose of sorting is to enable binary search
(see <a href="https://en.cppreference.com/w/cpp/algorithm/lower_bound"><code>lower_bound</code></a>, <a href="https://en.cppreference.com/w/cpp/algorithm/upper_bound"><code>upper_bound</code></a>, and <a href="https://en.cppreference.com/w/cpp/algorithm/equal_range"><code>equal_range</code></a>).
The cost of a binary is <code>O(log(n))</code> which in practice is not much different than <code>O(1)</code>
(you can binary search a billion records in 32 steps).</p>

<p>Here is an example:</p>

<pre><code>// compute a smooth vertex normal
vec3 average_normal(uint32_t v0)
{
    auto key = make_pair(v0, 0);
    auto i = lower_bound(vert_to_face, vert_to_face + n, key);

    vec3 n;

    while (i != vert_to_face + n &amp;&amp; i-&gt;first == v0)
    {
        uint32_t face_index = (i-&gt;second) / 3;
        n += face_normals[face_index];
        ++i;
    }
    return n.normalized();
 }
</code></pre>

<p>Hope that helps!</p>

<p>I have one other reason for liking this simple array representation.
In mathematical terms <em>functions</em> are sets of pairs.
Indicies is a subset of the cartresion product <code>F x V</code>.
The reverse index is build by swapping pairs from this set construction.
This new set is a subset of <code>V x F</code> and weakens from <em>function</em> to a  <em>relation</em>.</p>
]]>
</description>
</item>
<item>
<pubDate>Thu, 21 Apr 2022 00:00:00 +0000</pubDate>
<title>Why Train When You Can Optimize?</title>
<guid isPermaLink="true">https://www.jmeiners.com/why-train-when-you-can-optimize/</guid>
<description>Learn multi-variable optimization by creating a drawing assistant. No deep learning required!</description>
</item>
<item>
<pubDate>Mon, 07 Mar 2022 00:00:00 +0000</pubDate>
<title>Literate programming is much more than commenting code</title>
<guid>https://www.jmeiners.com/literate-programming/</guid>
<link>https://www.jmeiners.com/literate-programming/</link>
<description>
<![CDATA[
<!-- Generated by srcweave. https://github.com/justinmeiners/srcweave -->
<h1 id="literate-programming-is-much-more-than-commenting-code">Literate programming is much more than commenting code</h1>


<p><strong>03/07/22</strong></p>

<p>Most programmers haven&rsquo;t heard of <a href="https://en.wikipedia.org/wiki/Literate_programming">literate programming</a>,
and the few that have tend to think it means writing a lot of comments around your code.
However, simply explaining code with prose, <em>does not</em> constitute literate programming.
Consider the following quote from it&rsquo;s inventor:</p>

<blockquote><p> Some of my major programs could not have been written with any other methodology that I&rsquo;ve ever heard of.
The complexity was simply too daunting for my limited brain to handle;
without literate programming, the whole enterprise would have flopped miserably.
&hellip; Literate programming is what you need to rise above the ordinary level of achievement &ndash; Donald Knuth</p></blockquote>

<p>Does this extraordinary leap in effectiveness sound like something that comes from re-explaining what code does?
I didn&rsquo;t think so.</p>

<p>The real advantages of literate programming come from two principles:</p>

<ol>
<li><p>Code should be written for humans not machines.</p></li>
<li><p>Program designers utilize many types of information, not just code.</p></li>
</ol>


<p>Literate programming systems help programmers apply these principles
by providing two standard operations <strong>tangle</strong> and <strong>weave</strong> which
 manipulate and organize source code.</p>

<h2 id="tangle">Tangle</h2>


<p>Literate programs are written in plain text documents,
but between the traditional prose, blocks of code (in any language) are interleaved.
For example:</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":test-subsets" href="#:test-subsets">test subsets</a></em></strong></span>
<pre class="prettyprint"><code class="">console.log( subsets([1, 2, 3, 4]) );
</code></pre>
<p class="block-usages"><small>Used by <a href="#:subsets.js" title="subsets.js">1</a> </small></p></div>


<p>You can think of them like markdown documents, but with an important addition.
In a literate program, blocks of code have <em>identifiers</em>, and they can <em>reference</em> each other.
Each reference modifies the contents of a prior block,
or includes it at the specificied location.</p>

<p>The operation <strong>tangle</strong> resolves all these references and produces normal source code to be read by the compiler.</p>

<h3>Example</h3>

<p>Let&rsquo;s try it out.
In the block above we introduced a <code>subsets</code> function, also known as the powerset:</p>

<div class="math-block"><code>\begin{equation}   \mathcal{P}(A) = \{ S \text{ is a set } \colon S \subseteq A \}\end{equation}</code></div>


<p>Implementing it can be a little bit tricky.
If you have never done it before, I recommend you write out some examples
on paper and see if you can figure it out.</p>

<div class="math-block"><code>\begin{align}    \mathcal{P}(\{1, 2, 3\}) = \{ &\{1, 2, 3\}, \\
                                  &\{1, 2\}, \{1, 3\}, \{2, 3\}, \\
                                  &\{1\}, \{2\}, \{3\}, \\
                                  &\emptyset \} \\\end{align}</code></div>


<p>The key insight, is that if we take an element out of the original set,
and all the subsets which contain it, we can get back
the full subsets, by making a copy of each other subset and inserting
the element back in.
In other words, the number of subsets <em>doubles</em> with each element in the set:</p>

<div class="math-block"><code>\begin{equation}    |\mathcal{P}(A)| = 2^{|A|}\end{equation}</code></div>


<p>Here is rough outline in code:</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":subsets.js" href="#:subsets.js">subsets.js</a></em></strong></span>
<pre class="prettyprint"><code class="">function subsets(set) {
    <em class="block-link nocode"><a href="#:base-case">@{base case}</a></em>
    <em class="block-link nocode"><a href="#:remove-element-and-compute-subsets-of-smaller-set">@{remove element and compute subsets of smaller set}</a></em>
    return <em class="block-link nocode"><a href="#:subsets-without-element">@{subsets without element}</a></em>
        .concat( <em class="block-link nocode"><a href="#:subsets-with-element">@{subsets with element}</a></em> );
}

<em class="block-link nocode"><a href="#:test-subsets">@{test subsets}</a></em>
</code></pre>
</div>


<p>This a recursive function, so we need a base case.
If the input set is empty, its only subset is the empty set:</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":base-case" href="#:base-case">base case</a></em></strong></span>
<pre class="prettyprint"><code class="">if (set.length == 0) { return [[]]; }
</code></pre>
<p class="block-usages"><small>Used by <a href="#:subsets.js" title="subsets.js">1</a> </small></p></div>


<p>We use recursion by removing one element and computing the subsets of that array:</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":remove-element-and-compute-subsets-of-smaller-set" href="#:remove-element-and-compute-subsets-of-smaller-set">remove element and compute subsets of smaller set</a></em></strong></span>
<pre class="prettyprint"><code class="">const element = set.pop();
const smaller = subsets(set);
</code></pre>
<p class="block-usages"><small>Used by <a href="#:subsets.js" title="subsets.js">1</a> </small></p></div>


<p>All the smaller subsets are still subsets of our original set, so we want to include those.</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":subsets-without-element" href="#:subsets-without-element">subsets without element</a></em></strong></span>
<pre class="prettyprint"><code class="">smaller
</code></pre>
<p class="block-usages"><small>Used by <a href="#:subsets.js" title="subsets.js">1</a> </small></p></div>


<p>But, we are missing all the subsets involving <code>element</code>. We simply
add <code>element</code> in to each set.</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":subsets-with-element" href="#:subsets-with-element">subsets with element</a></em></strong></span>
<pre class="prettyprint"><code class="">smaller.map(s =&gt; s.concat([element]))
</code></pre>
<p class="block-usages"><small>Used by <a href="#:subsets.js" title="subsets.js">1</a> </small></p></div>


<p>That&rsquo;s all!
Applying <strong>tangle</strong> to the <a href="index.lit">literate</a> file produces a single source file <a href="src/subsets.js">subsets.js</a>.</p>

<p>A typical literate file produces many source files.
Block types aren&rsquo;t limited to a single language either.
Here is how to run it in your command line:</p>

<div class="code-block">
<span class="block-header">
<strong class="block-title"><em><a id=":test-command" href="#:test-command">test command</a></em></strong></span>
<pre class="prettyprint"><code class="">node subsets.js
</code></pre>
</div>




<h2 id="discussion">Discussion</h2>


<p>Of course, the example above goes into more detail, and is separated into more blocks,
than is helpful for most production code.
It is just meant to illustrate how a little explanation, analysis,
and division into logical parts, can make code significantly more readable.</p>

<p>At the micro-level we can overcome a lot of limitations imposed by the language syntax,
kind of like a powerful macro system.
In the example we break out small sub-expressions, even from the middle of statement,
to explain further, or to make things more readable.</p>

<p>Some other use cases include:</p>

<ul>
<li>Separating inline SQL queries from string literals.</li>
<li>Avoiding forward declarations in <code>C</code>.</li>
<li>Breaking up large switch cases.</li>
<li>Separating error handling from main logic.</li>
</ul>


<p>More importantly, at the macro level we can control the overall presentation of the program.
This is difficult to convey in a brief article,
but think of it like writing code as a book or article.
You can introduce your code with an overview,
take time to develop the most important ideas and characters,
gradually build up to the big picture,
and then maybe fill in some extra details.</p>

<p>Consider the last time you started working on a large code base someone else wrote.
It was probably overwhelming, especially considering how much of modern code is boiler plate, and interfacing between systems.
You probably wanted to know:</p>

<ul>
<li>What code is most important and should be read first?</li>
<li>What are they key data structures and algorithms?</li>
<li>How is data stored?</li>
<li>Which files are boiler plate that I can ignore?</li>
</ul>


<p>A well-written README can point you to some files to get started,
but it won&rsquo;t isolate the core concepts from all the other code
details surrounding them.
Literate programs allow you to answer these questions naturally.</p>

<h2 id="weave">Weave</h2>


<p>The <strong>weave</strong> operation generates documentation files from the literate file.
This is a nicely formatted document like the one you are reading right now!
This presents the code in a readable form,</p>

<p>If you are like me, you probably maintain some kind of design document recording decisions make
during the project and data to provide justifications.
Not, all of this content is appropriate to include in the source code, but a lot of it is,
and the literate <strong>weave</strong> operation let&rsquo;s you do just that.</p>

<p>Here are some examples of media you can include, as well as a specific use case I have desired in the past:</p>

<ul>
<li>Diagrams and images (instead of the ASCII kind). Illustrate a suite of test cases.</li>
<li>Graphs and plots. Illustrate what a function looks like.</li>
<li>Math formulas and equations. Analyze the complexity of an algorithm.</li>
<li>Tables of data. Record survey data that justifies a decision made in code.</li>
<li>Screenshots. Show a bug which is fixed by a particular section of code.</li>
<li>Example inputs and outputs. Show how to use a pieces of code.</li>
</ul>


<p>It&rsquo;s important to note how this is different from tools which generate interface &ldquo;documentation&rdquo; from source code.
Literate programs usually include the <em>entire</em> source, not just interfaces.
Since it focuses on prose, it&rsquo;s much more natural to include other media formats.
You aren&rsquo;t littering comments with awkward media references.</p>

<h2 id="getting-started">Getting started</h2>


<p>I have told you a bit about why I like Literate programming,
but to really understand how
it benefits your code read some examples, or better yet,
try it on your next project.
To get started you will need a literate programming tool of which there are many.</p>

<h3>srcweave</h3>

<p>I recently wrote <a href="https://github.com/justinmeiners/srcweave">srcweave</a> which was used to write this article you are reading now.
See my article <a href="https://www.jmeiners.com/tiny-blockchain/">&ldquo;Write your own Proof-of-Work Blockchain&rdquo;</a> for another example.</p>

<h3>Literate</h3>

<p><a href="https://zyedidia.github.io/literate/">Literate</a> is the system I used for several years, before writing my own.
It is self hosting, which I find pretty cool, so you can read it&rsquo;s <a href="https://zyedidia.github.io/literate/literate-source/">own source code</a>.</p>

<h3>web</h3>

<p>Donald Knuth wrote the original literate programming tools <a href="https://ctan.org/tex-archive/systems/knuth/dist/web?lang=en">web</a> and cweb.
Of course, they output TeX instead of HTML for documentation.
I don&rsquo;t know anyone else who actually uses his tools, since TeX is more involved than most people need,
 but they are still worth learning from.
The <a href="https://ctan.org/tex-archive/systems/knuth/dist/tex?lang=en">source for TeX</a> is written in it, and is famous for having
very few bugs and being extremely reliable.</p>
]]>
</description>
</item>
<item>
<pubDate>Sat, 05 Mar 2022 00:00:00 +0000</pubDate>
<title>Deploying Common Lisp Scripts</title>
<guid>https://www.jmeiners.com/common-lisp-scripts/</guid>
<link>https://www.jmeiners.com/common-lisp-scripts/</link>
<description>
<![CDATA[
<h2>Deploying Common Lisp Scripts</h2>

<p><strong>3/05/22</strong></p>

<p>Do you want a Common Lisp workflow like Python or Perl?
No dumping images, or complex deployments.
Just install <em>a single lisp interpreter</em> on your computer (<code>/usr/local/bin/sbcl</code>) and
<em>write, run, and share</em> source files.
I&rsquo;ve done a lot of research and I&rsquo;m here to explain how to get exactly that.</p>

<p>A step in the right direction is a <code>.lisp</code> file with an appropriate shebang:</p>

<pre><code>#!/usr/bin/sbcl --script
(write-string "Hello, World!")
</code></pre>

<p>It can be run with</p>

<pre><code>$ ./hello.lisp
</code></pre>

<p>But you&rsquo;ll quickly run into roadblocks after &ldquo;Hello, World!&rdquo;.
How do you include other source files without knowing their installation path?
How do you load libraries?</p>

<p>The solution is a Quicklisp command for downloading libraries and exporting them called <strong><a href="https://www.quicklisp.org/beta/bundles.html">ql:bundle-systems</a></strong>.
It creates a single folder with an index file called <code>bundle.lisp</code>.
After running <code>(load bundle.lisp)</code>, all of your dependencies are available to be load via <code>asdf:load-system</code>.
The result is entirely self-contained.</p>

<h2>Example using <code>ql:bundle-system</code></h2>

<ol>
<li><p>Create a bundle containing your Quicklisp dependencies:</p>

<pre><code> (ql:bundle-systems (list "alexandria" "cl-ppcre" ...) :to "bundle/")
</code></pre>

<p> This <code>bundle/</code> folder will contain  <code>alexandria</code> and <code>cl-ppcre</code>, along with their transitive dependencies.
 Each package will be organized as its own an <code>asdf</code> system.</p></li>
<li><p>Create an <code>.asd</code> file describing your project and its dependencies (see <a href="https://asdf.common-lisp.dev/asdf.html#Defining-systems-with-defsystem">defsystem docs</a> for details).</p>

<pre><code> (asdf:defsystem "my-lisp-program"
     :depends-on (:alexandria :cl-ppcre ...)
     :build-pathname "my-lisp-program"
     :components (
         (:file "...")
         ...))
</code></pre>

<p> The <code>:depends-on</code> list must only reference systems which were downloaded by <code>ql:bundle-systems</code>.</p></li>
<li><p>Copy your application source into the bundle:</p>

<pre><code> $ mkdir -p bundle/local-projects/my-lisp-program
 $ cp *.lisp bundle/local-projects/my-lisp-program
 $ cp *.asd bundle/local-projects/my-lisp-program
</code></pre>

<p> Now your code is just another <code>asdf:system</code>, alongside the others.</p></li>
<li><p>Install the bundle in a global system path. I prefer <code>/usr/local/lib</code>:</p>

<pre><code> $ cp -r bundle/ /usr/local/lib/my-lisp-program
</code></pre></li>
<li><p>Create a brief script which loads the <code>bundle.lisp</code> and the <code>asdf</code> system. For example <code>my-lisp-program</code></p>

<pre><code> #!/usr/bin/sbcl --script
 (load "/usr/local/lib/my-lisp-program/bundle.lisp")
 (asdf:load-system "myapp")
 (my-lisp-program:do-stuff)
</code></pre>

<p> <code>asdf:load-system</code> will examine your projects <code>.asd</code> file and load its dependencies, transitively.</p></li>
<li><p>Install the launch script in a global system path:</p>

<pre><code> $ mv my-lisp-program /usr/local/bin/
</code></pre></li>
<li><p>Run your script!</p>

<pre><code> $ my-lisp-program
</code></pre></li>
</ol>


<p>That&rsquo;s all! Consider automating these steps for your project, such as with <code>make install</code>.</p>

<p>The first time you run the script you may see a long log
as <code>sbcl</code> compiles the code into <code>.fasl</code> files, for faster subsequent runs.</p>

<h3>Further guidance</h3>

<p>I use this approach in <a href="https://github.com/justinmeiners/srcweave">srcweave</a>.
Take a look at the make file for a real-world example.</p>

<h2>Why other solutions didn&rsquo;t work for me</h2>

<p>There are a myriad of articles that claim to solve this problem.
But after much research and trial and error, I found none of them to be satisfactory.
Let&rsquo;s review them:</p>

<h3>Dumping an image</h3>

<p>The popular advice for deploying Common Lisp is to <a href="https://lispcookbook.github.io/cl-cookbook/scripting.html">dump an image</a> of the compiler (<code>save-lisp-and-die</code>),</p>

<p>This makes a copy of the entire Lisp compiler with your source code included.
This is a good solution for large applications.
For example, if you want to deploy a web application to server,
it&rsquo;s pretty convenient to <code>scp</code> up an image file and be done.</p>

<p>However, it&rsquo;s quite cumbersome if you have more than a handful to keep track of.
Your computer becomes littered with a bunch of independent copies of Lisp.
If you want to update <code>sbcl</code> you need to track down all your old images, delete them, and rebuild new ones.
Images files are also notoriously large (~50 MB for <code>sbcl</code>).</p>

<h3>Using Quicklisp in scripts</h3>

<p>Can you make a shebang script that loads code with Quicklisp?
You certainly can, but first note that <code>sbcl --script</code> will skip loading your system configuration (<code>.sbclrc</code>),
so you need to hard code a path to load Quicklisp.</p>

<p>But now imaging if calling <code>import</code> in a Python started downloading code from the internet!
That&rsquo;s a security and reliability nightmare.
But that&rsquo;s how Quicklisp works!</p>

<p>That&rsquo;s because Quicklisp isn&rsquo;t intended to be a library loader.
It&rsquo;s a tool for downloading and <em>discovering</em> libraries.
But it shouldn&rsquo;t be distributed in your source code.</p>

<p>You should be using <code>asdf</code> for that instead.
It&rsquo;s the standard way to describe and load libraries,
and it&rsquo;s already included in most distributions.</p>

<p>Note that Quicklisp is also organized as a rolling release like your operating system.
Rather than picking out individual library version tags, you pick a Quicklisp version which
is a snapshot in time of all the libraries that aims to be compatible.</p>

<p>To reiterate, I will share an explanation from Reddit user <a href="https://old.reddit.com/r/lisp/comments/iai2ab/repairing_asdf_package_storage/g1pnxdt/">eayse</a>:</p>

<blockquote><p>I advocate the habit of installing things with <code>ql:quickload</code>, but after initial installation, using <code>asdf:load-system</code> to actually bring the systems into memory.
After all missing dependencies have been satisfied by network installations from the distributions configured in Quicklisp, <code>ql:quickload</code> just thunks down to ASDF.</p></blockquote>

<h3>Roswell?</h3>

<p><a href="https://roswell.github.io/Roswell-as-a-Scripting-Environment.html">Roswell</a> is advertised as a solution, but it&rsquo;s possibly the most un-Lispy tool in the ecosystem.
It doesn&rsquo;t download dependencies, or help you build them.
What does it do? Help you download sbcl?
Why in the world does it use a config file syntax that isn&rsquo;t s-expressions?
Why is part of it written in C?
<em>sigh</em>.</p>

<h2>Busybox style</h2>

<p>The overhead of dumping an image can be shared by putting many scripts into a single image, instead of making an image for each.
I call this &ldquo;Busybox style&rdquo; because it was popularized in C by the <a href="https://fare.livejournal.com/184127.html">Busybox</a> project.
For a Common Lisp tutorial, see <a href="https://stevelosh.com/blog/2021/03/small-common-lisp-cli-programs/">Steve&rsquo;s article</a>.</p>

<p>This certainly solves some of the disk usage problems.
But it&rsquo;s kind of a crutch, and the workflow is just not as good as Python.</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 19 Sep 2021 00:00:00 +0000</pubDate>
<title>Classic Colors</title>
<guid isPermaLink="true">https://github.com/justinmeiners/classic-colors</guid>
<description>Paint program for Unix. Inspired by MS Paint (Windows 95-98).</description>
</item>
<item>
<pubDate>Sat, 31 Jul 2021 00:00:00 +0000</pubDate>
<title>Efficient Programming with Components</title>
<guid isPermaLink="true">https://www.jmeiners.com/efficient-programming-with-components/</guid>
</item>
<item>
<pubDate>Wed, 28 Jul 2021 00:00:00 +0000</pubDate>
<title>Almost Solving the Halting Problem</title>
<guid>https://www.jmeiners.com/almost-solving-the-halting-problem/</guid>
<link>https://www.jmeiners.com/almost-solving-the-halting-problem/</link>
<description>
<![CDATA[
<h1>Almost Solving the Halting Problem</h1>

<p>By: <a href="https://github.com/justinmeiners">Justin Meiners</a></p>

<p>The halting problem is to devise a method that can determine whether a given
Turing machine terminates in a finite amount of time. It is well-known to be
undecidable; no such method exists.
Naturally, if you ever write a proof that implies how to solve it, there is reason for concern.</p>

<p>In doing research for my master&rsquo;s thesis, unfortunately, I did just that.
It took quite a bit of reading and discussion to detect what went wrong.
It turns out I didn&rsquo;t make any major mistakes,
but I learned that the difference
between computability and incomputability is quite subtle.
I wanted to share this insight into what it means
for a function to be incomputable.</p>

<p>My thesis focused on braid group algebra, and reasoning about
how a particular property of braids can be computed.
Since this is a specialized topic and the details aren&rsquo;t important,
I will explain a similar problem using Turing Machines directly.</p>

<h2>Turing machine</h2>

<p>A Turing machine consists of:</p>

<ul>
<li>An infinitely long tape, divided into cells.
Each cell has a symbol written on it.
This symbol comes from a finite alphabet <code>S</code> (often <code>{ 0, 1 }</code> where <code>0</code> can be called &ldquo;blank&rdquo;).</li>
<li>A read/write head positioned over a particular cell on the tape.</li>
<li>A controller that moves the tape and reads and writes symbols.
The controller is a finite state machine <code>Q</code>.</li>
</ul>


<p><img src="turing-machine.png" alt="a depiction of a turing machine" /></p>

<p>As a Turing machine runs, the read/write head sends the current symbol to the controller.
The controller can then:</p>

<ol>
<li>replace the symbol.</li>
<li>transition to a new state.</li>
<li>shift the tape by a finite amount.</li>
</ol>


<p>Which symbol to write and which transition to make is determined entirely by the controller&rsquo;s
state and the symbol that was read.</p>

<p>For answering questions about computability and complexity, it doesn&rsquo;t matter how many symbols
the alphabet has or how complex the finite state machine is.</p>

<h2>Estimating the number of operations</h2>

<p>How do we go about determining whether a Turing machine will halt?
Here is the basic idea: run the machine for a large number of steps.
If it runs for longer than we expected, it probably won&rsquo;t terminate!</p>

<p>Ok, that&rsquo;s obvious and not very helpful. &ldquo;probably won&rsquo;t&rdquo; isn&rsquo;t good enough.
The actual difficulty is that the machine might run for longer than we expect and still terminate.
We might just need to run it a little bit longer.
But, what if we could determine <em>exactly</em> what that threshold is?
In other words, what if there was a specific number of steps that any terminating machine would not exceed?
It might seem like there is no way to determine such a bound, but it is actually pretty straightforward.</p>

<p>We can estimate how long a Turing machine will run based on its <em>complexity</em>.
In computer science, we often think longer programs are more complex.
Similarly, a Turing machine with a lot of information on the tape has a &ldquo;long program&rdquo;
to run and work with.</p>

<p>A Turing machine has only finitely many non-blank squares.
For a fixed state machine <code>Q</code> and alphabet <code>S</code>, define <code>A(n, Q, S)</code> to be the set of Turing
machines in <code>Q</code> and <code>S</code> that:</p>

<ul>
<li>halt</li>
<li>have exactly <code>n</code> non-blank squares.
(<code>n</code> can be thought of as an estimate of program length).</li>
</ul>


<p>There are at most <code>|S|^n</code> machines of this kind;
therefore, <code>A(n, Q, S)</code> is a finite set.
If we then let <code>l(T)</code> be the number of steps machine <code>T</code> runs for before termination,
<code>{ l(T) : T in A(n, Q, S) }</code> is finite and thus has a maximum <code>M</code>.</p>

<p>So given any Turing machine with this particular controller and configuration,
we can run it for <code>M</code> steps, and if it goes longer, then we <em>know</em> it will never terminate!
We can even define a function <code>f_{S, Q}(n)</code> that is the approximate <code>M</code> value for our inputs!
In fact, we don&rsquo;t care about <code>f</code> in particular;
ANY function that is strictly larger than <code>f</code> will do.</p>

<h2>Incomputability</h2>

<p>So why can&rsquo;t we do this?
Well, to know when to stop running, we would actually have to be able to compute the bound <code>f</code> in the real world.
In other words, we need an <em>effective procedure</em> or algorithm for computing <code>f</code>.
Since there is no way to solve the halting problem,
the only conclusion is that <code>f</code> grows faster than any function that can be computed in the real world.
Even though we can write programs to compute functions such as polynomials and exponentials, none of those grow fast enough.
Perhaps we could compute a lookup table to store this bound, but that would also require infinite space.</p>

<p>This shows us that uncomputability is primarily a problem of growth rates, not any kind
of tricky function definition.
Some functions just grow too quickly to be computed by a machine.</p>

<p>Note that the same limitation occurs for less sophisticated models of computation.
The <a href="https://en.wikipedia.org/wiki/Ackermann_function">Ackermann function</a> is a classic
example of a function that requires the full power of a Turing machine to compute.
This is due to its fast rate of growth.</p>

<h2>References</h2>

<p>Minsky. Computation: Finite and Infinite Machines. Chapter 8.</p>
]]>
</description>
</item>
<item>
<pubDate>Mon, 14 Jun 2021 00:00:00 +0000</pubDate>
<title>Swift Proposal: Balanced Binary Reduction</title>
<guid>https://www.jmeiners.com/swift-balanced-reduce/</guid>
<link>https://www.jmeiners.com/swift-balanced-reduce/</link>
<description>
<![CDATA[
<h1>Swift Proposal: Balanced Binary Reduction</h1>

<p><strong>By:</strong> Justin Meiners
<strong>06/14/2021</strong></p>

<h2>Introduction</h2>

<p>Swift&rsquo;s <code>reduce</code> can be used to accumulate elements in a sequence.
For example:</p>

<pre><code>[1.0, 2.0, 3.0, 4.0].reduce(0.0, +)
</code></pre>

<p>If we visualize the expression tree for this operation
it&rsquo;s essentially linear.
You can think of it as a binary tree which is completely unbalanced.</p>

<pre><code> -----3.0----6.0---10.0
/     /      /    /
1.0   2.0   3.0  4.0
</code></pre>

<p>Assuming the binary operation is associative then we can choose which
order to evalulate arguments in.
For example, we could image a function <code>balancedReduce</code> which rearranges
the order of evaluation to the following:</p>

<pre><code>      10.0
    /      \
   /         \
  3.0       7.0
 /  \      /    \
1.0  2.0  3.0  4.0
</code></pre>

<p>We haven&rsquo;t changed the result at all, just the order it&rsquo;s evaluated in.
It&rsquo;s mathematically equivalent.
However, there are lot&rsquo;s
of good computational reasons why one might want to do this.</p>

<h2>Example Applications</h2>

<p>These are just a few to illustrate it is a general problem:</p>

<ol>
<li><p>Adding up many floating point results (as in my example above).
Adding small numbers to larger numbers produced poor numerical results.
Given a long enough list of values of similar magnitutdes
this is guarenteed to happen.</p>

<p>In contrast a balanced evaluation of such values will
only add similarly sized values. (Intermediate results which are
the result of adding equal numbers of values together).</p></li>
<li><p>Merge sort can be written by applying the binary operation
of &ldquo;merge sorted list&rdquo; to a sequence of lists:</p>

<pre><code>[ [a1], [a2], ... [an] ]
</code></pre>

<p> If you do this with <code>reduce</code> it is essentially insertion sort,
 one element is inserted into the growing list at a time.
 If you use a <code>balancedReduce</code> it will only merge lists
 that are roughly the same size, giving a proper
 <code>O(n log(n))</code> merge.</p></li>
<li><p>It can be used to solve the problem of finding the smallest
element, and second smallest element, in a sequence
in the optimal number of comparisons.
(Described in 5.3.3 of Volume 3 of Art of Computer Programming).</p></li>
</ol>


<h2>Proposed changes.</h2>

<p>This capability can be added with a simple extension to <code>Sequences</code>
of <code>Equatable</code> types.</p>

<pre><code>extension Sequence where Element: Equatable {
    func balancedReduce(
        zero: Element,
        operation op: (Element, Element) -&gt; Element
    ) -&gt; Element{
        var counter = Array(repeating: zero, count: 32)

        for x in self {
            let carry = BinaryCounter.add(to: &amp;counter,
                                          x: x,
                                          zero: zero,
                                          operation: op)

            assert(carry == zero, "reduced too many things")
        }

        return BinaryCounter.reduce(counter: &amp;counter,
                                    zero: zero,
                                    operation: op)
    }
}

struct BinaryCounter {
    private init() {}

    static func add&lt;C: MutableCollection&gt;(
        to counter: inout C,
        x: C.Element,
        zero: C.Element,
        operation op: (C.Element, C.Element) -&gt; C.Element
    ) -&gt; C.Element where C.Element: Equatable {

        var i = counter.startIndex
        let end = counter.endIndex

        var carry = x
        while i != end {
            if counter[i] == zero {
                counter[i] = carry
                return zero
            }

            carry = op(counter[i], carry)
            counter[i] = zero
            i = counter.index(after: i)
        }

        return carry
    }

    static func reduce&lt;C: MutableCollection&gt;(
        counter: inout C,
        zero: C.Element,
        operation op: (C.Element, C.Element) -&gt; C.Element
    ) -&gt; C.Element where C.Element: Equatable {

        var i = counter.startIndex
        let end = counter.endIndex

        // find first non-zero
        while i != end &amp;&amp; counter[i] == zero {
            i = counter.index(after: i)
        }

        if i == end {
            return zero
        }

        var x = counter[i]
        i = counter.index(after: i)
        assert(x != zero)

        while i != end {
            if counter[i] != zero {
                x = op(x, counter[i])
            }
            i = counter.index(after: i)
        }

        return x
    }
}
</code></pre>

<p>The implentation is very efficent, adding very few additional
computaitons and using an additional piece of memory, roughly
of size <code>log(n)</code>.</p>

<h2>Application examples</h2>

<p>This implementation of merge sort
is just for fun to show how it works.</p>

<pre><code>func mergeSorted&lt;T&gt;(
    _ a: [T],
    _ b: [T]
) -&gt; [T] where T: Comparable  {
    var i = a.startIndex
    var j = b.startIndex

    var out: [T] = []

    while i != a.endIndex &amp;&amp; j != b.endIndex {
        if b[j] &lt; a[i] {
            out.append(b[j])
            j = a.index(after: j)
        } else {
            out.append(a[i])
            i = a.index(after: i)
        }
    }

    if j != a.endIndex {
        out.append(contentsOf: b.suffix(from: j))
    } else {
        out.append(contentsOf: a.suffix(from: i))
    }

    return out
}

func mergeSort&lt;S: Sequence&gt;(
    _ items: S
) -&gt; [S.Element] where S.Element: Comparable {

    let singletons: [[S.Element]] = items.map { [$0] }
    let zero: [S.Element] = []

    return singletons.balancedFold(zero: zero, operation: mergeSorted)
}
</code></pre>

<h2>Questions/Concerns</h2>

<p><strong>It&rsquo;s too theoretical</strong></p>

<p>All of the theory is hidden inside,
outside it looks like just <code>fold</code>/<code>reduce</code>.
If you don&rsquo;t know what it does, it still gives expected results.</p>

<p>Furthmore, it can be benefecial even if you don&rsquo;t
copmletely understand it.
For example, advice could be given to &ldquo;use this one to add up large lists of <code>float</code>&rdquo;
and it would benefit them.</p>

<p><strong>The zero parameter is weird. Should it be nil instead?</strong></p>

<p>I am unsure.
My assumption was that introducing <code>nil</code> in the intermediate
computation adds a lot of boxing/unboxing.</p>

<p><strong>The name is bad/wrong</strong></p>

<p>I am not attached to the name and happy to hear recommendations.</p>

<p><strong>Can we make the 32/64 parameter less arbitary?</strong></p>

<p>Of course <code>2^64</code> is the max of a 64 bit integer.
Arrays of more than <code>2^64</code> elements are probably already disallowed.
That&rsquo;s assuming every element is a byte,
so <code>2^32</code> seems like a reasonable upper bound assumption for the size
of a sequence.</p>

<p>It could be a parameter, although this seems like a messy detail
to expose.</p>

<h2>References</h2>

<p>I learned about this techinque from Alex Stepanov, the author
of C++ STL.
It is described in the book <a href="http://elementsofprogramming.com/">&ldquo;Elements of Programming&rdquo;</a>
chapter 11.2.</p>

<p>There is a related concept in C++.
<a href="https://en.cppreference.com/w/cpp/algorithm/accumulate">std::accumlate</a>
does a normal left fold,
<a href="https://en.cppreference.com/w/cpp/algorithm/reduce">std::reduce</a>
is allowed to associate its arguments
in any order it prefers.
It additionally requires the operation is commutative,
which I do not think is necessary for this.
It appears <code>std::reduce</code> is primarily to facilitate parallel
computation, but it demonstrates two similar operations
whose results only differ on their association order.</p>
]]>
</description>
</item>
<item>
<pubDate>Mon, 03 May 2021 00:00:00 +0000</pubDate>
<title>Three Myths about Passive Investing</title>
<guid>https://www.jmeiners.com/three-myths-passive-investing/</guid>
<link>https://www.jmeiners.com/three-myths-passive-investing/</link>
<description>
<![CDATA[
<h1>Three Myths about Passive Investing</h1>

<p><strong>5/3/2021</strong></p>

<p>Stock markets are at tremendous highs, not only in absolute price, but also in terms of <a href="https://www.multpl.com/s-p-500-earnings-yield">earnings yield</a>.
At the same time we see <a href="https://twitter.com/TikTokInvestors">unsophisticated participants</a> taking incredible risks in Robinhood, Gamestop, Dogecoin, and Tesla, indicating a public excitement alongside the financial metrics.
So is the top in?</p>

<p>Seasoned passive investor should be amused by this question.
It&rsquo;s merely commotion for financial news.
It matters for day traders and speculators.
But, by passively holding broad market index funds for a long time horizon, we don&rsquo;t need to worry about such things.
Someone will always insist &ldquo;this time is different&rdquo;, but
we just need to stay the course and ignore the market swings.
Right?</p>

<p>Broadly, this message is correct.
But, safe activities become dangerous when we become too comfortable.
Just as we see recklessness among
traders, a different brand of recklessness appears to be sneaking into
passive investing.</p>

<p>For example, in the market decline around March 2020, due to the spread of COVID-19 and the associated lock downs,
most Vanguard investors <a href="https://personal.vanguard.com/pdf/coronavirus-market-volatility.pdf">purchased additional equities</a> rather than selling
or acquiring less volatile assets.
Buying when others are fearful is the adage,
but if everyone is buying, the consensus is actually optimistic.
Either:</p>

<ol>
<li>Investors didn&rsquo;t really believe economic effects would be that bad.</li>
<li>Investors discounted the negative effects years into the future and rebalanced out of cash.</li>
<li>Investors believed stocks would go up, regardless of negative economic effects.</li>
</ol>


<p>Even among skeptics 1. wasn&rsquo;t common during the first few weeks of uncertainty.
Many investors held belief 2., but considering savings rates and that younger people need capital in coming years (such as for down payments on homes) its hard to believe the majority are prepared for their portfolios to be below par for 5 to 10 years.</p>

<p>This is concerning because those in camp 3 believe they can&rsquo;t lose.
No matter what happens they will make money in a time frame usable for them.
This isn&rsquo;t what passive investing teaches, and is instead
based on passive myths.</p>

<h2>Myth #1: Asset prices don&rsquo;t matter.</h2>

<p>New traders learn that &ldquo;buy high&rdquo; &ldquo;sell low&rdquo; is a lot harder than it sounds.
It&rsquo;s not just hard to find opprotunities, psychologically people seem biased towards losing money.
Passive investors observe teach &ldquo;time in the market&rdquo; tends to beat &ldquo;timing the market&rdquo;.
Instead, the passive investor focuses on accumulation of assets over the long term rather than trading price trends.</p>

<p>This is sound investment advice, but many investors
have concluded that this means price doesn&rsquo;t matter.
We should pay any price, because no matter what the index will go up and we will eventually get our returns.
(If you believe this, can I sell you some stock?)</p>

<p>Let&rsquo;s make an axiomatic observation.
The gross yield of an investment is:</p>

<pre><code>(price sold + dividends recieved) / price purchased
</code></pre>

<p>(Inflation and time discounting proportional are proportional modifications).
Thus, increasing purchase price, lowers returns.
Therefore, <strong>price purchased determines your returns</strong>,
so it cannot be ignored.
Consequently we should always try to pay the lowest prices possible.</p>

<p>So is it time to start reading charts? No.
Markets tend to do well at pricing assets (especially on public exchanges), and its difficult to  predict where price will go.
Purchasing at regular intervals (of any duration) at market prices, such as dollar-cost averaging,
is an effective strategy to pay fair prices, and avoid extremes which may occur for short periods.</p>

<p><a href="https://www.bogleheads.org/wiki/Rebalancing">Rebalancing</a> between assets at regular periods is another way to &ldquo;buy high&rdquo; and &ldquo;sell low&rdquo;.
Adjusting asset allocation in response to extreme price moves is not day trading.</p>

<h3>Revision: Always get the best prices you can and don&rsquo;t overpay. Dollar-cost averaging is a strategy for getting good prices.</h3>

<h2>Myth #2: Buying broad market indices is the optimal investment strategy.</h2>

<p>Passive investing is based on the idea that large markets typically price assets efficiently.
<a href="https://www.investopedia.com/terms/m/modernportfoliotheory.asp">Modern portfolio theory</a> attempts to describe how to earn returns in such an environment,
and is supportive of passive investing.
It argues that assets are primarily distinguished by their level of risk and time horizons.
Long term risky investments are cheaper than short term sure bets.
Since the market understands how to price levels of risk, there is no free lunch.</p>

<p>Picture each ETF or mutual fund (such as an S&amp;P index) lying on a graph of risk to return.
Given this model, its absurd to think any one investment gives the greatest possible returns.
Unless its the riskiest asset available, one can always shift down the risk curve
and find something with higher returns.
If S&amp;P is a sure thing, wouldn&rsquo;t leveraged S&amp;P be even better?</p>

<p>The real question is how an index performs <a href="https://en.wikipedia.org/wiki/Efficient_frontier"><em>relative</em></a> to other assets
with the same level of risk. The effectiveness of popular indices like S&amp;P as benchmarks
for other assets, suggests it performs well.
But, you it would still be hard to argue that it is the <em>best</em> for all time.</p>

<p>An enormous advantage to buying an index is that is easy and cheap.
That&rsquo;s worth a lot, even if a complex combination exists that is slightly better.</p>

<h3>Revision: Passive investing can offer good returns relative to risk levels and is easy.</h3>

<h2>Myth #3: It&rsquo;s impossible for an investor or fund to beat broad market indices.</h2>

<p>When a <a href="https://www.bogleheads.org/">Boglehead</a> is shown a fund that outperforms a popular index, they immediately
conclude it must be fraudulent, or soon headed for disaster.
We just learned that one possible explanation is that they are simply taking on more risk.
But another is that the fund is run by people with expertise, putting in time
to squeeze out extra risk/return efficiency..
After all, we believe markets are efficient because there are experts of varying beliefs
 scrutinizing all kinds of information.</p>

<p>Let&rsquo;s imagine five of your friends are indepdendtly starting restaurants and seek your investment.
You are going to invest in a few of them.
They offer to present their finances and business plan to you.
Do you think it would be worth consider that information, or would you be better
off just picking them randomly?</p>

<p>You can probably think of some obvious information that would be much better than random.
Have any of them run a business before? Were they successful? How much money do they have?
Is anyone else helping them?
It may turn out your picks are unlucky, or others are successful underdogs,
but its obvious at the small scale that its possible for you to make some judgment about
their investment quality.</p>

<p>Professionals can ask the same kinds of questions about large companies.
They can study business and corporate leadership, accounting practices, and
perhaps having run businesses of their own.
So they should be able to identify good businesses from bad, or at least eliminate the worst contenders.</p>

<p>This is made complicated by the context of a global economy, with so much uncertainty,
and interdependence. But, the principle is no different.
<strong>It&rsquo;s possible for a person to reason about whether a business will succeed or not.</strong>
If you accept that principle, then you can expect some professionals might
make investments better than random, even if it takes a lot of effort and skill
to obtain much of an edge,</p>

<p>Whether these kinds of people work at any of the high-fee funds in your company 401k is a
separate question.
As a matter of practicality, it may not be worth looking for them.
But good investors almost certainly exist.
There <em>will</em> be funds that outperform passive funds.
That is entirely OK.
The idea of passive investing is that its easy and cheap.
You can beat <em>most</em> investors just by purchasing a broad market index.
Isn&rsquo;t that fantastic?</p>

<h3>Revision: Professional investors participate in pricing assets. They can often make additional money through this activity and expertise. Passive funds are easier and cheaper than most publicly available investment products.</h3>

<p>One commonality among these myths is that they imply you no longer have to think.
Prices are always correct. Stop thinking about whether you&rsquo;re over paying and buy.
Stop thinking about whether an investment is worthwhile or if you should consider, better alternatives.
The market is just unknowable, so you might as well not try.
That doesn&rsquo;t sound anything like shrewd investing,
it sounds like marketing.</p>

<p>If we accept the revised statements there is endless opportunity for learning and improvement.
What are good strategies for purchasing and rebalancing?
Are there other funds I should consider in my portfolio?
Are there investment opportunities in my local community?
All of these questions are worth considering slowly and methodically.</p>
]]>
</description>
</item>
<item>
<pubDate>Tue, 06 Apr 2021 00:00:00 +0000</pubDate>
<title>Master's Thesis: Computing the Rank of Braids</title>
<guid isPermaLink="true">https://github.com/justinmeiners/braid-rank-thesis</guid>
</item>
<item>
<pubDate>Sun, 27 Dec 2020 00:00:00 +0000</pubDate>
<title>Advent of Code 2020 Day 18: Rethinking Operator Precedence</title>
<guid>https://www.jmeiners.com/aoc-2020-18/</guid>
<link>https://www.jmeiners.com/aoc-2020-18/</link>
<description>
<![CDATA[
<h1>Advent of Code 2020 Day 18: Rethinking Operator Precedence</h1>

<p><strong>12/27/20</strong></p>

<p>Part 2 of  <a href="https://adventofcode.com/2020/day/18">AOC Day 18</a> asks
you to evaluate some math expressions, but with a twist.
<code>+</code> has a greater operator precedence than <code>*</code>.
(This is opposite of how we typically read math):</p>

<pre><code>2 * 3 + (4 * 5)
2 * 3 + 20
2 * 23
46
</code></pre>

<p>The standard method for expression evaluation is the <a href="https://en.wikipedia.org/wiki/Shunting-yard_algorithm">shunting yard</a> algorithm.
This is the <em>right</em> and efficient way to solve this problem.
But, it&rsquo;s also not very obvious or natural.
It&rsquo;s hard to imagine how you would think if it yourself,
and doesn&rsquo;t really match how people actually see mathematical expressions.</p>

<p>I want to show off an alternative solution demonstrating
how you could think of it yourself.
My code is written in Common Lisp.
For this particular problem this choice goes a bit deeper than just syntax
as the solution makes heavy use of a symbolic expression manipulation which is harder to do in most languages.</p>

<p><strong>Thinking about Precedence</strong></p>

<p>What does operator precedence actually mean?
It tells us the <em>order in which to evaluate operators</em>.
So naively we should just do all the additions first, and then the multiplications.
Can we program that?
We certainly can, but doing just one operation at a time,
means at each step we produce an intermediate result which is itself a math expression, just simplified a bit.
For example given the expression:</p>

<pre><code> (1 + 2 * 3 + 4)
</code></pre>

<p>We first evaluate all the <code>+</code> to produce:</p>

<pre><code>(3 * 7)
</code></pre>

<p>And then we evaluate all the &lsquo;*&rsquo; to produce:</p>

<pre><code>(21)
</code></pre>

<p>After evaluating every operator, we should get a list containing a single number.</p>

<p>Below is some code which does just that.
The input <code>chain</code> is an expression (list of numbers and operators)
and <code>allowed</code> is the operator we want to evaluate.</p>

<pre><code>(defun simplify-chain (chain allowed)
  (prog ((result '())
         (op nil)
         (l nil)
         (r nil))

        (setf l (car chain))
        (setf chain (cdr chain))

        loop
        (setf op (car chain))
        (setf chain (cdr chain))

        (setf r (car chain))
        (setf chain (cdr chain))

        (if (eq op allowed)

            ; evaluate the operation.
            ; put the result back in the expression

            (setf l (funcall op l r))

            ; not an operation we want to evaluate right now.
            ; put it's symbols back in an the expression
            (progn (push l result)
                   (push op result)
                   (setf l r)))

        (if (consp chain)
            (go loop))

        (push l result)
        (return (reverse result))))
</code></pre>

<p><strong>Handling Parenthesis</strong></p>

<p>That is quite straightforward!
All the trickiness is fiddling with infix.
But, there is one problem.
Due to parenthesis the operands may not be &ldquo;ready&rdquo; to evaluate.
If we have:</p>

<pre><code>3 + (2 * 4)
</code></pre>

<p>We can&rsquo;t apply the <code>+</code> operation until the <code>(2 * 4)</code> is taken care of.
But evaluating <code>(2 * 4)</code> is something we could do directly.
There are only finitely many nested
statements, so eventually following parenthesis must end with a list containing only numbers and operators.
This is clearly a recursive problem!
We need to evaluate all the parenthesized statements in a list, before we can evaluate
the list itself.</p>

<p>The algorithm for evaluation looks like the following:</p>

<ul>
<li>To evaluate a number or operator symbol, just return it. (base case)</li>
<li><p>To evaluate a list:</p>

<ol>
<li>evaluate every entry in the list. (take care of parenthesis)</li>
<li>simplify the expression by applying each operator in order. (simplify chain)</li>
<li>Return the only item left in the list.</li>
</ol>
</li>
</ul>


<p>Let&rsquo;s write an eval function which does this, building upon simplify chain:</p>

<pre><code>(defun eval-expr (expr)
  (if (listp expr)
        (car (reduce #'simplify-chain 
                     '(+ *)
                     :initial-value (mapcar #'eval-expr expr)))
        expr))
</code></pre>

<p>To summarize <code>simplify-chain</code> takes mathematical expressions
and returns expressions that are simpler, while <code>eval-expr</code> always returns a number.
Note that this works for any number of operators and adjusting
precedence is as simple as changing the order of the <code>'(+ *)</code> list.</p>
]]>
</description>
</item>
<item>
<pubDate>Sat, 19 Dec 2020 00:00:00 +0000</pubDate>
<title>Advent of Code 2020 Day 19: An Easy way to do Part 2</title>
<guid>https://www.jmeiners.com/aoc-2020-19/</guid>
<link>https://www.jmeiners.com/aoc-2020-19/</link>
<description>
<![CDATA[
<h1>Advent of Code 2020 Day 19: An Easy way to do Part 2</h1>

<p><strong>12/19/20</strong></p>

<p>A fun mechanic in <a href="https://adventofcode.com/2020">AOC</a> is that the problem is divided
into two parts, with the second only revealed after completion of
the first.
This challenges you to adapt an initial solution to new requirements,
encouraging flexibility of design.
In the case of <a href="https://adventofcode.com/2020/day/19">problem 19</a>, a seemingly minor change, completely transforms
the requirements.
It may seem you have to rethink everything from scratch,
but there is actually a tiny change to part 1 which solves the problem</p>

<p>My personal ranking wasn&rsquo;t great, but you can see I still
managed to catch up a bit on part 2 (even taking an additional hour!) as others got stuck.</p>

<p><img src="personal_stats.png" alt="personal stats aoc 2020" /></p>

<p><strong>SPOILERS AHEAD</strong></p>

<h2>Part 1</h2>

<p>Let&rsquo;s outline a fairly standard solution to part 1.
We will stick to psuedocode, but at then end I will show some of my Common Lisp code.</p>

<p><strong>Parsing</strong></p>

<p>We need to parse the rules and turn them into a structure we can work with.
I chose to transform them into an expression tree.
A rule such as:</p>

<pre><code>3 4 | "a" "b"
</code></pre>

<p>Becomes:</p>

<pre><code>(or (3 4) ("a" "b"))
</code></pre>

<p>All the rules are stored in an array,
with their index corresponding to their rule number.</p>

<p>Lisp makes it easy to parse.
I first replace the <code>|</code> with <code>^</code> because pipe has special semantics for the lisp reader.
Whenever a rule contains a <code>^</code> I split it&rsquo;s components
into a left side and right side and wrap them in an <code>or</code>.</p>

<p><strong>Evaluation</strong></p>

<p>Now we need a recursive evaluation function to handle the rule.
It takes a rule and a string as input.
It returns <code>FAIL</code> if it cannot match,
or the modified string location, if it did match.
For example when the rule &ldquo;a&rdquo; is applied to the following string:</p>

<pre><code>"abc"
</code></pre>

<p>It returns &ldquo;bc&rdquo; indicating successful matching.</p>

<p>The evaluation recursively handles the following cases:</p>

<ul>
<li>evaluate a char: check that the first character agrees</li>
<li>evaluate a number: lookup the rule at that index and evaluate it.</li>
<li>evaluate an or form <code>(OR r1 r2)</code>: evaluate both options. If one succeeded, return that. Otherwise fail.</li>
<li>evaluate a list <code>(r1, ... ,rn)</code>: evaluate each rule in the list in order. Stop early if there is a failure.
                 If the string ends before the list ends, the match failed.</li>
</ul>


<p>Success is indicated by returning an empty string.
This means we used everything up and it matched.
Test how many entries pass and you&rsquo;re done.</p>

<h2>Part 2</h2>

<p><strong>What is going on?</strong></p>

<p>Part 2 makes two substitutions to the rules list.</p>

<pre><code>8: 42        -&gt;    8: 42 | 42 8
11: 42 31    -&gt;    11: 42 31 | 42 11 31
</code></pre>

<p>It&rsquo;s not immediately clear why this breaks our recursive evaluation.
In fact, if you run it, it will not crash and still give you an (incorrect) answer.
So what is going on? (This question took most of my time!)</p>

<p>Consider the following rule:</p>

<pre><code>"a" | "a" "b"
</code></pre>

<p>The string &ldquo;ab&rdquo; now matches <em>BOTH</em> possible choices. How do we know which one to pick?
Logically, a disjunction (or) operation shouldn&rsquo;t care.
But whatever choice
is made will actually have an effect on whether the remaining rules in the pattern
match.</p>

<p>Here is an example of what can go wrong.
Suppose our string is &ldquo;abc&rdquo;.</p>

<pre><code>0: 1 2
1: "a" | "a" "b"
2: "c"
</code></pre>

<p>Starting with rule 0, we try rule 1.
<code>"abc"</code> matches both <code>"a"</code> and <code>"a" "b"</code>.
So let&rsquo;s pick the first rule.
Now onto rule &ldquo;c&rdquo; which does not match &ldquo;b c&rdquo;.
The match fails.</p>

<p>If we had chosen &ldquo;a&rdquo; &ldquo;b&rdquo; then we move
to rule 2 &ldquo;c&rdquo; matches the remainder &ldquo;c&rdquo;.
We have a successful match.</p>

<p><strong>The Hard Solution</strong></p>

<p>Every time we an encounter an <code>OR</code> and both cases
match, we no longer know which one to pick.
The global success of a match can no longer be determined locally.</p>

<p>We aren&rsquo;t going to get false positives, but we may get false negatives
if we choose the wrong path to take.</p>

<p>A proper solution must diverge at every or, creating branching possible evaluations.
This can certainly be implemented, but is going to look very different than part 1,
and be more complicated.</p>

<p><strong>An Easy Solution</strong></p>

<p>What we really want to know is whether there is <em>SOME</em> set of choices for each OR that will cause the pattern to match.
Since we don&rsquo;t know what they are, we can just try a whole bunch, and see if we can find a set that does.
The easiest way to do this is by introducing probability.
Randomly pick a branch at each or.
We can then run the matcher a bunch of times and see if it finds a set of choices that match.</p>

<p>Let&rsquo;s work through the details.
We want to replace the code for &ldquo;evaluate an or form <code>(OR R1 R2)</code>&rdquo;.
The original descrpition was:</p>

<ul>
<li>If one succeeded, return that. Otherwise fail.</li>
</ul>


<p>Let&rsquo;s change it to a randomized choice when we don&rsquo;t have a better option:</p>

<ul>
<li>evaluate both options. If either one failed, return the other.
  Otherwise both succeeded, so randomly pick which one to return.</li>
</ul>


<p>Now for each string run the pattern matcher a few hundred times.
Each time it will (hopefully) try different choices for each OR.
With enough tries, it should get lucky and find the best path
if there is one.</p>

<p>Remember, changing branch directions never introduces false positives, only false negatives.
So if it matches even one time, then we know it works.
Experiment with different numbers of times until you get a match rate that stabilizes.
If you don&rsquo;t run it enough times, then you will get changing answers each time you run it.
It works!</p>

<p>Want to learn more? Checkout <a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3">chapter 4.3</a> of SICP
on non-deterministic computing.</p>

<h2>My Code</h2>

<p>Here are the key snippets,
some of it is a little ugly.</p>

<p><strong>Eval (With Random)</strong></p>

<pre><code>(defun eval-rule (str rule all-rules)
  (cond ((stringp rule) (if (char= (car str) (char rule 0))
                            (cdr str)
                            'FAIL))

        ((numberp rule) (eval-rule str (aref all-rules rule) all-rules))
        ((and (listp rule) (eq 'or (car rule))) 
         (let ((first (eval-rule str (nth 1 rule) all-rules))
               (second (eval-rule str (nth 2 rule) all-rules)))
           (if (eq 'FAIL first)
               second
               (if (eq 'FAIL second)
                   first
                   (if (= (random 2) 1) 
                       first
                       second
                       )))))
        ((listp rule)
         (prog ((s str)
                (l rule)
                (result nil))

               step
               (setf result (eval-rule s (car l) all-rules))

               (if (eq result 'FAIL)
                   (return result))

               (setf s result)
               (setf l (cdr l))

               (if (consp l)
                   (if (consp s)
                        (go step)
                        (return 'FAIL))
                   (return s))
              ))
        (t (error "unknown rule "))))
</code></pre>

<p><strong>Solve Part 2</strong></p>

<pre><code>(defun solve-2 (all-rules inputs)
  (remove-if-not 
    (lambda (string)
      ; use probablity!
      (some #'identity (loop for i from 1 to 500 collect
                             (not (eval-rule (coerce string 'list) (aref all-rules 0) all-rules)))))
      inputs))
</code></pre>
]]>
</description>
</item>
<item>
<pubDate>Sun, 15 Nov 2020 00:00:00 +0000</pubDate>
<title>The Universal Property of Quotients</title>
<guid>https://www.jmeiners.com/universal-property-quotients/</guid>
<link>https://www.jmeiners.com/universal-property-quotients/</link>
<description>
<![CDATA[
<h1>The Universal Property of Quotients</h1>

<p><strong>11/15/20</strong></p>

<p><img src="1.png" alt="universal property of quotients" /></p>

<p>The first time you encounter a theorem concluding with &ldquo;an arrow that
makes the diagram commute&rdquo; can be quite confusing.
But with a little thought you can typically find that the idea expressed the theorem is obvious.
The provided arrow is simply the one thing that could possibly fit.
It may be tedious to construct, but understanding the theorem clarifies
why it must always be there, revealing patterns hidden in the construction.</p>

<p>Let&rsquo;s see how this works by studying the universal property of quotients, which was
the first example of a commutative diagram I encountered.
If you are familiar with topology, this property
applies to quotient maps.
But we will focus on quotients induced by equivalence relation on sets and ignored
additional structure.</p>

<p>An equivalence relation <code>~</code> is a binary relation satisfying the following properties:</p>

<ul>
<li>reflexive: <code>x ~ x</code></li>
<li>symmetric: <code>x ~ y &lt;=&gt; y ~ z</code></li>
<li>transitive:  <code>x ~ y and y ~ z implies x ~ z</code>.</li>
</ul>


<p>Examples include equality of real numbers, whether numbers are both even or odd (parity),
matrix similarity, isomorphism, etc.</p>

<p><strong>Exercise:</strong> Prove matrix similarity is an equivalence relation.</p>

<p>Given an equivalence relation ~ and an element <code>x</code> we can form it&rsquo;s equivalence
class <code>[x]</code> which is the set of things equivalent to it.
The set of a equivalence classes form a new set <code>X/~</code> with an analogous
structure to the original, but with portions &ldquo;grouped up&rdquo; or &ldquo;collapsed&rdquo;</p>

<p><strong>Exercise:</strong> Prove distinct equivalence classes are disjoint.</p>

<h2>Universal Property of Quotients</h2>

<p>Let <code>q(x) = [x]</code> be a map from an element to it&rsquo;s equivalence class.
Given a map <code>f</code> from <code>X</code> to <code>Y</code> which is constant on equivalence
classes (<code>q(x) = q(y) =&gt; f(x) = f(y)</code>),
we obtain a unique map from <code>X/~</code> to <code>Y</code> making the diagram commute.</p>

<p><img src="1.png" alt="universal property of quotients" /></p>

<p>What is going on here? <code>f</code> isn&rsquo;t just any map,
it&rsquo;s constant on equivalent elements of <code>X</code>.
So a lot of the information in <code>X</code> isn&rsquo;t really needed to compute the image of <code>f</code>.
Since equal elements get sent to the same place,
we could imagine picking just one element from each class and seeing where it goes.</p>

<p><img src="2.png" alt="equivalence collapse" /></p>

<p>In other words, we could define a function on each equivalence class.
This map would have the same image as <code>f</code> and this is precisely what the universal property tells us
is possible</p>

<p>Let&rsquo;s apply this theorem to a particular example and attempt to fill in the diagram.
Suppose our domain is the solid disc.</p>

<p><img src="3.png" alt="disc" /></p>

<p>To construct an equivalence relation on the disk, think of  properties that make points in the disc similar to one another.
One such property is their distance from the center.
Define <code>x ~ y</code> whenever <code>||x|| ~ ||y||</code>.
What does the quotient space <code>X/~</code> look like under this relation?
Each class is a ring at a particular radius <code>L</code>, so denote it <code>[L]</code>.
The radii of course vary continuously so we get set of classes isomorphic
to a closed interval <code>[0, 1]</code>.</p>

<p><img src="4.png" alt="disc radii classes" /></p>

<p><strong>Exercise:</strong> Find an equivalence relation on D<sup>2</sup> without 0 (punctured disc) whose classes
form the circle.</p>

<p>Now define a function <code>f(x) = x^2 + y^2</code> so our codomain is the real numbers R.
The graph is a multivariable calculus style paraboloid living in <code>R^3</code> above
the unit disc:</p>

<p><img src="5.png" alt="parabaloid" /></p>

<p>Can we apply the universal property?
Almost, we need to confirm <code>f</code> is constant on equivalence classes.
Suppose <code>(x, y) ~ (a, b)</code>.
Then <code>sqrt(x^2 + y^2) = sqrt(a^2 + b^2)</code>.
Squaring both sides we get that <code>f(x, y) = f(a, b)</code>.</p>

<p>Ah! We can clearly see <code>f</code> only depends on radius.
No matter what angle you are at <code>f</code> does the same thing.
So the disc is more information than we need,
we can define a similar function on the space of equivalence classes <code>X/~ = [0, 1]</code>.
Can you figure out what it is?</p>

<p>&hellip;</p>

<p>The missing function is of course <code>h([L]) = L^2</code>.
It&rsquo;s graph is a parabola in 2D which carves out the same range as <code>f</code> in the real numbers.</p>

<p><img src="6.png" alt="graph parabola" /></p>

<p>To check commutativity take a point <code>(x, y)</code> and apply <code>f(x, y) = x^2 + y^2</code>.
Now send it to it&rsquo;s equivalence class <code>q(x, y) = [L]</code> where <code>L = sqrt(x^2 + y^2)</code>.
Now <code>h(L) = x^2 + y^2 = f(x, y)</code>.</p>

<p>Easy right? You probably could see right away that <code>f</code> was just the square of the distance.
In other examples constructing such a function <code>h</code> might be less obvious,
but the universal property tells us it is always there.</p>

<p>Next time you an encounter a commutative diagram proof, try a few examples
to figure out what basic idea it is telling you.</p>

<p><strong>Exercise:</strong> Prove that <code>h</code> is unique. In other words, no other function could make the diagram commute.</p>

<h2>Further Reading</h2>

<p>Commutative diagrams are the central focus of category theory which attempts to understand
such properties at a higher level of abstraction than set theory.
From a category theory perspective the quotient set <code>X/~</code> is the co-equalizer
or co-limit of the diagram projecting and equivalent pair to it&rsquo;s parts.</p>

<p>The book Topoi by Robert Goldblatt offers a fairly comprehensive look at category
theory, starting at a basic understanding of sets and number theory.</p>

<p><img src="topoi.jpg" alt="Topoi Goldblatt" />]</p>

<p>Quotient spaces are studied in depth in Topology by Munkres.</p>

<p><img src="munkres.jpg" alt="Munkres Topology" />]</p>

<p>The later chapter on Algebraic Topology have
More elaborate constructions.
These gave me a lot of practice with commutative diagrams,
such as the chapter on <a href="https://en.wikipedia.org/wiki/Seifert%E2%80%93van_Kampen_theorem">Seifert-Van Kampen&rsquo;s</a> theorem.</p>

<p><img src="van-kampen.png" alt="van-kampen" /></p>
]]>
</description>
</item>
<item>
<pubDate>Thu, 08 Oct 2020 00:00:00 +0000</pubDate>
<title>Questioning Probability</title>
<guid>https://www.jmeiners.com/questioning-probability/</guid>
<link>https://www.jmeiners.com/questioning-probability/</link>
<description>
<![CDATA[
<h1>Questioning Probability</h1>

<p><strong>10/8/20</strong></p>

<h3>Are Elections Actually Random?</h3>

<p>A popular narrative explaining the outcome of the 2016 election is Hilary Clinton was just unlucky.
On election night, the odds were in her favor,
but when the dice were cast she unfortunately rolled snake eyes.
In a weird way, if the election were just run another day, she would win.</p>

<p>The underlying assumption is that elections are sort of random.
But, how similar is winning an election to playing roulette?
Let&rsquo;s briefly relate what actually happens on voting day.
People who want to vote, visit a voting location.
They select a name either by pushing a button or writing it in.
Later, the votes are tallied and grouped by region and a winner is announced.
Where is the randomness?
At each step of the process it&rsquo;s simple cause and effect.</p>

<p>An individual might have an unexpected accident, preventing them
from voting,
but like most other days,
the vast majority of the population is able to carry out their intentions.
It&rsquo;s even difficult to detect rapidly changing variables
which might appear random.
The cultural and economic context have been slowly evolving over years.
The media environment has been built up over months leading up to it.
Individual&rsquo;s political views move slowly, as
they are predominantly a product of deeply rooted
influences, including family upbringing, income, ethnicity, religion, and education.</p>

<p>If the unlucky dice roll doesn&rsquo;t hold up to a little scrutiny, then why is this view so popular?
Perhaps it is because its message avoids uncomfortable conclusions.
If it was just bad lack, then
it was nobody&rsquo;s fault.
We still have the popular ides.
It&rsquo;s not even clear that our strategy must change to win next time.
The alternatives are much harder to look at.</p>

<p>Hold on a minute.
Perhaps this is all a misunderstanding.
People don&rsquo;t actually believe elections function like a lottery.
When journalists use percentages they are just referring to the confidence intervals
of polls.
Pollsters want to survey public opinion.
But, they can&rsquo;t talk to everyone in the country, so they talk to a
sample, and then use probability to guess how likely it is that
this sample represents the whole population.
It&rsquo;s basic statistics (as described in this <a href="https://www.pewresearch.org/fact-tank/2016/11/09/why-2016-election-polls-missed-their-mark/">Pew Research article</a>).</p>

<p>This may correctly describe where the numbers come from.
Perhaps in a back office somewhere, there actually is a Ph.D
in Stats coolly scrutinizing surveying models.
But this is clearly not how these figures are interpreted
 by journalists and otherwise intelligent or
scientific people.
If it was, they  would be concerned with potential gaps
between sample and population, instead of calculating their odds.
Look at how randomness and chance is implied in the following popular media:</p>

<p><strong>Election as a Pachinko/Plinko Machine</strong></p>

<p>From: <a href="https://presidential-plinko.com/">presidential-plinko.com</a>,
a site created by a Northwestern University professor.</p>

<p><img src="pachinko.png" alt="pachinko machine" /></p>

<p><strong>Election as an Unlucky Dice Roll</strong></p>

<p>From Paul Graham&rsquo;s Twitter, a popular figure in tech and startups.</p>

<p><img src="random_roll.png" alt="random roll" /></p>

<p><strong>20% is still 1 in 5</strong></p>

<p>A comment on the Silicon Valley forum &ldquo;Hacker News&rdquo;.</p>

<p><img src="math.png" alt="math" /></p>

<p><strong>The unlikely combination</strong></p>

<p>From <a href="https://www.reuters.com/article/us-usa-election-poll/clinton-has-90-percent-chance-of-winning-reuters-ipsos-states-of-the-nation-idUSKBN1322J1">Reuters</a>.</p>

<p><img src="reuters.png" alt="reuters" /></p>

<p>If so many smart people are doing inappropriate probabilistic thinking in this area,
are there others where we might be making similar mistakes?</p>

<h3>A Cultural Belief in Randomness</h3>

<p>Stats is  at the forefront of business, marketing, medicine, sports, finance, academia, and science.
Many of it&rsquo;s concrete applications are no doubt useful and appropriate.
But, our society&rsquo;s interest in it goes well beyond it&rsquo;s technical or economic usefulness.
Its popularity is partially an extension of our love for science and logic.
Just look at all the numbers, equations, and graphs!
But, that also isn&rsquo;t enough to explain its significance.
Consider the following ideas prominent in popular culture:</p>

<ul>
<li>Don&rsquo;t plan too far into the future, or commit to any one thing in your career.
Nobody knows what the world will look like the future (see &ldquo;Zero to One&rdquo; chapter 6 for more on these ideas).</li>
<li>Scientific discovery is mostly good luck.
The best we can do is setup Fleming or Darwinian style projects
to tip chance in our favor.</li>
<li>Stats and data are the way smart people make decisions and overcomes biases.
Don&rsquo;t blinded by personal experience and intuition. Haven&rsquo;t you seen Money Ball?</li>
<li>Nobody knows which business ventures will be successful, just try a bunch of them.
Invest in startup incubators or index funds.</li>
<li>The universe is just atoms crashing into each other in the void,
combined with strange quantum uncertainty.
Who knows what will happen.
It might even form a new universe.</li>
<li>Nobody knows how to solve hard computer science problems like computer vision,
or understanding natural language.
If we correlate a bunch of data with a machine learning
system, it will probably do figure out what&rsquo;s going on.</li>
</ul>


<p>If we apply the same step-by-step analysis
as we did with the election, these ideas immediately begin to seem
 less plausible, or at least in need of some qualification and refinement.
Perhaps the cultural prevalence of randomness nudges us to reach for that option more
often than alternatives.
Contributing to this bias is the fact that randomness can provide us with comfortable answers to hard questions,
or mask the fact that the underlying mechanisms are not well understood.</p>

<h3>When is Probability Useful?</h3>

<p>Let&rsquo;s step back a bit.
Probability itself is a sound mathematical model.
Just because an underlying process is not random,
does not mean that probability cannot offer an accurate description
or be a useful tool.
Sometimes statistics is the best way to talk about complicated deterministic systems.</p>

<p>For example, statistics can be used in physics to describe
the motion of bodies, which can otherwise be accurately described
by deterministic cause and effect.
A gas might be modeled as a cloud of individual particles, each
of which is well understood, but there may just be too many
of them to keep track of.
Because, the task is overwhelming, and we care most about the global behavior,
 we settle for partial information (see <a href="https://en.wikipedia.org/wiki/Kinetic_theory_of_gases">Wikipedia</a>).</p>

<p>Consider even a dice roll.
With Newtonian mechanics we can understand gravity, the force of the throw, the friction in the air,
the impact on the table,
and with all this make an accurate prediction of the outcome.
But no human can capture all those parameters in a split second and apply them.
Without a controlled environment for study, probability is a good model.</p>

<p>Computers despite being artificially deterministic, benefit
greatly from probability.
Random numbers generated on a computer are usually just <a href="https://en.wikipedia.org/wiki/Pseudorandom_number_generator">functions</a> which are difficult to predict.
Despite this, they can compute and solve problems using probability (see <a href="https://en.wikipedia.org/wiki/Monte_Carlo_method">Monte Carlo methods</a>).</p>

<p>The difference then between helpful and misleading attributions of randomness,
is of course how closely the model actually resembles reality.
Statistical models in physics don&rsquo;t just start by assuming processes are random.
They construct deterministic relationships between the elements; the energy, the area, the force,
 and then insert a tiny amount of probability to account for the arts that are too complex.
The random processes are tightly constrained by the physical laws.
Furthermore, they can usually quantify the information lost by assuming randomness.</p>

<h3>A Universal Way of Understanding</h3>

<p>It may seem like the only conclusion we can draw is,
&ldquo;lazily constructed models give poor results&rdquo;.
But, this analysis also reveals how backwards common statistical practices is.
Statistics is the go-to tool when we have no ideas what&rsquo;s going on.
Fields like politics, financial markets, and human behavior come to mind.
Instead of starting with well understood systems and then carefully relaxing
assumptions and summarizing details,
Data is automatically correlated,
and everything is basically assumed to follow random distributions.
Randomness replaces cause and effect,
instead of working in concert with it.</p>

<p>The sophistication of the math involved,
disguises all this.
But, is it any surprise that we observe &ldquo;black swan&rdquo; events when we assume
everything uniformly follows a bell curve?</p>

<p>In <a href="http://classics.mit.edu/Plato/republic.11.x.html">The Republic X</a>, Plato observes a related attitude in painting and poetry:</p>

<blockquote><p>The imitator, I said, is a long way off the truth, and can do all things because he lightly touches on a small part of them, and that part an image.
For example: A painter will paint a cobbler, carpenter, or any other artist, though he knows nothing of their arts; and, if he is a good artist, he may deceive children or simple persons, when he shows them his picture of a carpenter from a distance, and they will fancy that they are looking at a real carpenter.</p>

<p> And whenever any one informs us that he has found a man knows all the arts, and all things else that anybody knows [&hellip;] I think that we can only imagine to be a simple creature who is likely to have been deceived by some wizard or actor whom he met, and whom he thought all-knowing, because he himself was unable to analyze the nature of knowledge and ignorance and imitation.</p>

<p>And so, when we hear persons saying that the tragedians, and Homer, who is at their head, know all the arts and all things human, virtue as well as vice, and divine things too, for that the good poet cannot compose well unless he knows his subject, and that he who has not this knowledge can never be a poet, we ought to consider whether here also there may not be a similar illusion. Perhaps they may have come across imitators and been deceived by them</p></blockquote>

<p>Statistics students and professionals hold the same remarkable belief about their own field today.
They don&rsquo;t need to study any subject or &ldquo;applications&rdquo;, besides statistics itself.
Their statistical knowledge is immediately transferable to
understanding any problem thrown their way.
It&rsquo;s a universal framework for understanding.
This makes it the perfect career in the culture of randomness, and ironically
minimize the need to make predictions about the future.</p>

<p>But can you understand business without running one?
Can you understand voting patterns without understanding what
is happening in people&rsquo;s lives?
Can you understand psychology without thinking, observing, and talking to people?
In these areas, as in politics, we can conclude that probability and statistics are being used as poor substitutes
for explanatory theory.</p>

<p><strong>Update 09/25/2021:</strong> Heavily edited the second half to clarify intended message. The election discussion is largely the same.</p>
]]>
</description>
</item>
<item>
<pubDate>Sat, 26 Sep 2020 00:00:00 +0000</pubDate>
<title>Understanding LINQ GroupBy</title>
<guid>https://www.jmeiners.com/understanding-groupby/</guid>
<link>https://www.jmeiners.com/understanding-groupby/</link>
<description>
<![CDATA[
<h1>Understanding LINQ GroupBy</h1>

<p><strong>09/26/20</strong></p>

<p>As a C# programmer, you are probably familiar with  <code>Select</code>, <code>Where</code>, and <code>Aggregate</code>,
the LINQ equivalents of the fundamental functional programming operations <code>map</code>, <code>filter</code>, and <code>reduce</code>.
<code>GroupBy</code> is an equally useful function, which you may be less familiar with, but should definitely learn about.
It solves the following problem:
Given a list of items, partition them into groups so that equivalent elements are together.
For example, given a list of <code>Student</code>s in the school, we may want to
group them by <code>teacher</code> to build a class roster.</p>

<p>Functional programming aims to specify &ldquo;what&rdquo; needs to be done, rather than how to do it.
As a programmer, this helps shift your focus and concern to a higher level of abstraction,
leading to cleaner and more direct code.
<code>GroupBy</code> is a beautiful example of these principles.
It solves a general problem, in a reusable way, which would otherwise take a bit of thought to write correctly
by hand (as we shall see).
Furthmore, it combines harmoniously with the other LINQ operations.</p>

<h3>How to use GroupBy</h3>

<p>With the brief description above in mind,
let&rsquo;s examine the method <a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.groupby?view=netcore-3.1#definition">signature</a>:</p>

<pre><code>IEnumerable&lt;TResult&gt; GroupBy&lt;TSource, TKey, TElement, TResult&gt; (
    IEnumerable&lt;TSource&gt; source,
    Func&lt;TSource,TKey&gt; keySelector,
    Func&lt;TSource,TElement&gt; elementSelector,
    Func&lt;TKey,IEnumerable&lt;TElement&gt;,TResult&gt; resultSelector,
    IEqualityComparer&lt;TKey&gt; comparer
);
</code></pre>

<p>Bleh! That looks pretty meaningless and intimidating.
Ignore the generic types for now and I will explain the 4 functions that must be provided:</p>

<ul>
<li><code>TKey keySelector(TSource item)</code> given an <code>item</code>, return a key which will determine which group to place this <code>item</code>. Typically this is a field on <code>item</code>.</li>
<li><code>TElement elementSelector(TSource item)</code> given an <code>item</code>, return the value that will actually be stored in the group,
Often this returns a field on the item or the item itself.</li>
<li><code>TResult resultSelector(TKey key, IEnumerable&lt;TElement&gt; contents)</code> after elements are grouped together,
this function will be called on each group to produce a final result. The <code>key</code> is the identifier for this group and the <code>contents</code> is an enumerable
object containing the results. Most often you will just return <code>contents</code>, but you may want to store the result in a new class.</li>
<li><code>int comparer(..)</code> provide a function so that keys can be compared.
 This can be left off for key types like integer and string which are already comparable.</li>
</ul>


<p>With an understanding of the functions, the meaning of the 4 generic types is now clear:</p>

<ul>
<li><code>TSource</code> the type of the input items.</li>
<li><code>TKey</code> the type of the key that will identify which group the item belongs to.</li>
<li><code>TElement</code> each item has the opportunity to be transformed before being put into a group.
 This type is the output of that transformation.</li>
<li><code>TResult</code> The result type from obtaining a result from a group. If you were to return each group as an array, this type would be <code>[TElement]</code>.</li>
</ul>


<h3>Example 1: Classroom roster by student id</h3>

<p>Let&rsquo;s try the example mentioned above.
Given a list of <code>Student</code> objects,
we want to group them by <code>teacher</code> to create class roster.
However, in this example, we don&rsquo;t need the whole student object,
we only want their student ids.</p>

<pre><code>List&lt;Student&gt; students = ...;

students.GroupBy(
   s =&gt; s.teacher,                 // keySelector
   s =&gt; s.id,                      // elementSelector
   (teacher, ids) =&gt; ids.ToArray()  // resultSelector
).ToArray();

// Result: [ [id1, id2, ..], [id1, id2] ] 
</code></pre>

<h3>Example 2: A histogram of purchases</h3>

<p>Let&rsquo;s imagine we are building a personal finance application.
One useful tool would be a histogram showing purchases withn typical
price ranges (for example $0-$10, $10-$20, etc),
For each range, we would want to know the total number of purchaes, and their total value.
We will use a tuple to store these calculations for each resulting bucket.</p>

<pre><code>struct Purchase {
   double amount;
   ...
}

List&lt;Purchase&gt; purchases = ...;

purchases.GroupBy(
   p =&gt; (int)Math.Floor(p.amount / 10.0),    // keySelector
   p =&gt; p.amount,                            // elementSelector
   (bucket, amounts) =&gt; {                    // resultSelector
      return ValueTuple.Create(
         bucket,
         amounts.Count(),
         amounts.Sum()
      );
   }
).ToArray();

// Result:
// [ (bucket, number of purchases, total purchase amount), ... ]
</code></pre>

<p><strong>Note:</strong> Assuming the range of buckets was known up front,
one could simply allocate an array with the proper
number of buckets and place each item directly.
But, <code>GroupBy</code> also works if the data is sparse and
forgoes the awkward need to translate between bucket values and indices.</p>

<h3>Implementing GroupBy with sort and merge</h3>

<p>That may be all you want to know about <code>GroupBy</code> now.
For those who are curious, let&rsquo;s talk about how it works and performs.
At first, grouping elements appears inherently complex.
An initial idea might be to loop through each item, and then loop through all the other items to find matches.
This works, but is an <code>O(n^2)</code> algorithm so will quickly become unwieldy.</p>

<p>The next natural implementation is to create a dictionary similar to <code>Dictionary&lt;TKey, List&lt;TElement&gt;&gt;</code>.
Iterate over each item in the list once, and insert it into the list corresponding to it&rsquo;s proper group.
This solution has pretty good <code>O</code> complexity, but comes with some practical performance problem.
The main concern is with how memory is used.
Depending on the dictionary implementation, it has a memory allocation which it must resize and copy as it grows.
Furthermore, each individual group array does the same thing!
This is expensive, and not friendly to the cache.</p>

<p>We can do bit better in elegance and practical performance by &ldquo;sorting and merging&rdquo;.
First, <code>sort</code> elements by their key (<code>O(n log n)</code>).
After sorting, all the equivalent elements should be next to each other.
We can then apply a reduce-like operation to merge adjacent neighbors into a group <code>O(n)</code>.
This is a general technique which can solve a lot of algorithm problems (See <a href="https://github.com/psoberoi/stepanov-conversations-course/blob/master/styles/fortran4.cpp">Stepanov&rsquo;s bigrams</a> for one other application).</p>

<p>Let&rsquo;s give it a try:</p>

<pre><code>public static IEnumerable&lt;TResult&gt; GroupBy&lt;TSource, TKey, TElement, TResult&gt; (
    IEnumerable&lt;TSource&gt; source,
    Func&lt;TSource,TKey&gt; keySelector,
    Func&lt;TSource,TElement&gt; elementSelector,
    Func&lt;TKey,IEnumerable&lt;TElement&gt;,TResult&gt; resultSelector
) where TKey: IComparable
{
    var sorted = source.Select(item =&gt; ValueTuple.Create(keySelector(item), elementSelector(item))).ToList();
    if (sorted.Count == 0) yield break;
    sorted.Sort((a, b) =&gt; a.Item1.CompareTo(b.Item1));

    var startIndex = 0;
    var endIndex = 1;
    var groupKey = sorted[0].Item1;

    while (endIndex &lt; sorted.Count)
    {
        var key = sorted[endIndex].Item1;
        if (!groupKey.Equals(key))
        {
            var group = Enumerable.Range(startIndex, endIndex - startIndex).Select(i =&gt; sorted[i].Item2);
            yield return resultSelector(groupKey, group);
            startIndex = endIndex;
            groupKey = key;
        }
        ++endIndex;
    }

    var finalGroup = Enumerable.Range(startIndex, endIndex - startIndex).Select(i =&gt; sorted[i].Item2);
    yield return resultSelector(groupKey, finalGroup);
}
</code></pre>

<p><strong>Note:</strong> this is almost certainly NOT how LINQ is exactly implemented (<code>TKey</code> is only required to have equality testing, not <code>IComparable</code>),
but their approach is similar.</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 24 May 2020 00:00:00 +0000</pubDate>
<title>Boring Benefits of Lisp</title>
<guid>https://www.jmeiners.com/boring-benefits-of-lisp/</guid>
<link>https://www.jmeiners.com/boring-benefits-of-lisp/</link>
<description>
<![CDATA[
<h1>Boring Benefits of Lisp</h1>

<p><strong>10/07/20</strong></p>

<p>Lisp advocates are famous for having elaborate reasons for why Lisp is their favorite language.
You might have heard that it&rsquo;s the <a href="http://www.paulgraham.com/avg.html">most powerful language</a>,
thanks to features like <a href="http://gigamonkeys.com/book/macros-defining-your-own.html">macros</a>, first class functions, and <a href="https://en.wikipedia.org/wiki/Homoiconicity">homioconicity</a>.
Certainly, Lisp has no shortage of beautiful and influential ideas.
But, almost every modern language has copied it&rsquo;s most productive features.
Are there still compelling reasons to use it in production?</p>

<p>For me there are. But, my interest is much more boring and practical.
Fancy language abstractions <a href="https://www.jmeiners.com/think-in-math/">don&rsquo;t appeal to me</a>,
so the whole meta-programming isn&rsquo;t as important.
What I do care about is a reliable and stable ecosystem which
allows me to write quality code that can last for a long time.
Consider the following features:</p>

<ul>
<li><strong>Standards:</strong> Common Lisp and Scheme are both fully standardized language with specifications.
 Consequently, they are well understood, cross-platform, and have diverse implementations,
  including several with free licenses.</li>
<li><strong>Documentation:</strong>  <a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html">SICP</a> is &ldquo;the book&rdquo; for Scheme and computer science.
  Common Lisp has several great books worth reading even if you don&rsquo;t care about Lisp (see <a href="https://github.com/norvig/paip-lisp/">PAIP</a>).
  The <a href="http://www.lispworks.com/documentation/lw50/CLHS/Front/index.htm">CLHS</a> is as reliable and thorough as any language.</li>
<li><strong>Stability:</strong> Lisp has been around since the 60s and the ANSI standard about 30 years.
  It is extremely stable. Code be written once, and run again years later, without modification.</li>
<li><strong>Efficiency:</strong> Lisp implementations are reasonably fast.
  The true believers claim Common Lisp is as fast as C,
  it&rsquo;s probably much closer to Java.
  But, for a high-level, dynamic, language, <a href="https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/lisp.html">it&rsquo;s pretty fast</a>.</li>
<li><strong>Design:</strong> Lisp is well designed and founded on solid computer science principles.
It has a focused selection of features and an elegant evaluation model which make it easy to
write and compose functionality.</li>
</ul>


<p>You might think this list of features isn&rsquo;t remarkable or unique to Lisp.
That&rsquo;s certainly true.
C did them first, and established them as the recipe for releasing a successful language.
Languages since have followed various steps, but the surprising thing
is how few of them actually ended up with all the ingredients.
Of course each item in this list is somewhat of a spectrum; some languages do more than others,
but very few languages follow it to a degree that can be asserted with confidence.
Usually, you can say a language somewhat satisfies it, followed by a list of ugly qualifications.</p>

<p>Take Python for example. It&rsquo;s well designed, has great books and documentation, is fairly stable.
It has an <a href="https://norvig.com/python-lisp.html">elegant design</a> inspired by Lisp.
But, is it standardized? Not really. They have a spec, but it only has one defacto implementation
and changes all the time.
Whatever the CPython project chooses to do defines the language.
Alternative implementations exist, but they all have compatibility compromises.
Python is also not very efficient.
You can use a <a href="https://www.pypy.org">JIT</a> implementation which makes it tolerable,
but that has its own quirks, and you can&rsquo;t use many libraries with it.</p>

<p>Lisp and C aren&rsquo;t the only languages with all these benefits,
but there aren&rsquo;t as many as you think.
Since Lisp has these great features and a design I enjoy using and studying
it&rsquo;s become my go-to language.</p>

<p><strong>Update: 4/30/21</strong>: I recommend the article <a href="https://begriffs.com/posts/2020-08-31-portable-stable-software.html">&ldquo;Tips for stable and portable software&rdquo;</a> which discusses principles of stability at the language level, as well as the entire OS stack. It offers
specific advice for reliable unix software.</p>

<p><strong>Update: 09/23/21</strong>: Edited to clarify intended message.</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 12 Apr 2020 00:00:00 +0000</pubDate>
<title>10 Hard Decisions: A Model for Programmer Productivity</title>
<guid>https://www.jmeiners.com/10-hard-decisions/</guid>
<link>https://www.jmeiners.com/10-hard-decisions/</link>
<description>
<![CDATA[
<h1>10 Hard Decisions: A Model for Programmer Productivity</h1>

<p><strong>09/26/20</strong></p>

<p>How do you ensure that programmers are using time effectively?
What can you do to help them be productive?
Managers think a lot about these questions.
But too often they get the answers wrong despite being very earnest and smart.
This is because they have an unexamined mental model of how programming work is actually done.
With an inaccurate model, managers optimize the wrong things and make bad decisions
which would otherwise be good decisions in other work environments.</p>

<p>To understand the idea, let&rsquo;s look at a few examples of how productivity varies between jobs.
Simple manual labor, like digging holes, is easy to understand.
Productivity comes down to moving as much dirt per minutes as possible.
Progress is very measurable, and it easy to think about how to improve it.
As a manager, you might ensure there is a rotation of workers digging at all time,
and that everyone has the best tools possible.
However that looks very different than the working model for a professional baseball scout.
A scout can take a few years of evaluating players just to find one great pro.
There aren&rsquo;t simple metrics you can use to measure their progress.
It&rsquo;s hard to tell exactly what productive work should look like.
Exposure to a lot of players can help, but ultimately it comes down to a few big choices.</p>

<p>What kind of work is programming most like?
In my experience (especially in agencies), the typical
model of a programmer is an expensive factory machine.
This is the kind of machine that occupies a lot of space and attention in the factory.
It&rsquo;s operation is fragile, so it needs to be constantly checked on and maintained.
But most importantly, every minute that it is not working on jobs is expensive money wasted.
The primary metric for ensuring it stays productive is utilization time, even if that means spending time
on throw away jobs.</p>

<p>Managers understand this work model very well, perhaps they read &ldquo;The Goal&rdquo; in school.
They look for metrics to identify throughput and bottlenecks and do lots of shuffling of programmers
around to ensure maximum utilization.
In it&rsquo;s most exaggerated form this led managers to obsess over metrics &ldquo;lines of code per week&rdquo;.
Although we have moved beyond that.
The underlying thinking about what&rsquo;s going on has changed much.
We just think about programmers as feature producers.
The task the programmer needs to finish programmer needs to sit at the computer and type in the project.</p>

<p>Here is a common example of this thinking: Bob is busy finishing task 1 and then will start project 2.
Alice has a bit of downtime before she starts project 3.
Let&rsquo;s have Alice get started on project 2, then we can
have her hand off the incomplete work to Bob.
In a few weeks when he is ready, Alice can move on to project 3 and leave Bob with a head start.</p>

<p><img src="timeline.png" alt="sample timeline" /></p>

<p>This seems like smart move.
We made sure that Alice and Bob&rsquo;s valuable time was well used, right?</p>

<h2>A better Model</h2>

<p>To see why this decision may actually waste time, we need
a better understand what programming is like.
The model I will describe is not perfect, it&rsquo;s a great simplification, but
its a rough estimation that&rsquo;s far more accurate than the factory machine one.
That better model is the following:
<strong>each project consists of making 5-15 difficult software decisions</strong>.
All of these decisions are of course somewhat dependent on one another.
Each of those decisions that is made well, will lead to shipping the project,
Each decision made wrong, will cause delays and waste time, now or down the road.
That&rsquo;s all. That&rsquo;s the description of the job programmers need to do,
and how they occupy their time.
If programmers knew what to write beforehand, they could type it in no time!
The time they spend fiddling at the keyboard is actually gather information
through experiment and observation, in order to make decisions.</p>

<p>As a manager, the way to improve productivity
is to simply think about what would help you make hard decisions.
Here are some simple ideas that become immediately obvious, given this clearer model:</p>

<ul>
<li><p>Give programmers as much possible information about the project as early as possible.
It&rsquo;s difficult to make decisions with incomplete information.
When you get ideas early they can sit in the back of your mind and get some sleep
time.  Organize information so its easy to process.</p></li>
<li><p>Protect programmer time from interruptions.
Design large blocks of uninterrupted time.
Have quiet working environments.
It&rsquo;s hard to make good decisions without focus.
Other writers have written extensively about the cost of &ldquo;<a href="http://www.paulgraham.com/makersschedule.html">context switching</a>&rdquo;
when you have to forget about what you were thinking and start thinking about something new.</p></li>
<li><p>Ensure programmers have a clear understanding of project priorities and goals.
Clearly communicate expectations and requirements.
Making good decisions requires making trade-offs.
Unclear priorities will lead to programmers making bad decisions.
Changing priorities will invalidate previously good decisions.</p></li>
<li><p>It&rsquo;s OK if a programmer is not at their keyboard writing code.
Taking a walk or a rest is often productive time.
Distracting activities like watching a lot YouTube are not.</p></li>
<li><p>Don&rsquo;t treat programmers interchangeably.
Give them ownership of specific project pieces so they can make long term decisions and build on previous ones.
Would you hire a separate architect to design each room of a house?</p></li>
<li><p>Ensure your incentive structure rewards good decision making.
Do you reward band-aid approaches? Are programmers just trying to get it &ldquo;over the fence&rdquo;
so someone else has to deal with it? Are programmers are the receiving side of the fence?</p></li>
<li><p>Going through a crunch? <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">Don&rsquo;t add people</a> to a late project. Throw more money and effort at building an focused environment to making decisions. Can you pay someone to errands at home so the programmer doesn&rsquo;t have to think about them? Can you bring their family to the office for a lunch? (1)</p></li>
</ul>


<p>This is just a short list of suggestions and you can probably can come up with even better
ideas.
What&rsquo;s important is that as we think deeper about this model common productivity mistakes become apparent. (2)</p>

<p>Let&rsquo;s analyze the Bob and Alice example again using this model.
Did we help Alice and Bob make decisions or hurt them?
Recall, Alice starts working on task 2 for a few weeks, to get it started for Bob.
Then Bob picks it up, and Alice moves elsewhere.
In our rough model we can assume that when Alice finishes, she has made 2 of the 15 decisions, and has some vague ideas about 5 others.
The manager arranges a meeting for Alice to inform Bob of her work and she is swept off to task 3.
Now Bob has to start thinking about task 2 from scratch, but not only that,
he has to figure out what Alice was up to, whether the decisions she made were right,
and what direction she was heading to address the other 13 decisions.
This added information causes Bob to take more time than if he had started on his own.
In practice, its even worse because Alice and Bob will need to continue to take time from each other to coordinate about what Alice had in mind. (3)</p>

<h2>Smarter Alternatives</h2>

<p>You might say, &ldquo;that makes sense, but what am I supposed to do? Let Alice sit around for a week, wasting that time with an urgent project?&rdquo;. Let&rsquo;s use the model to work through better options.
In this scenario Alice is scheduled to eventually own project 3.
A better option would be to just let task 2 sit until Bob is ready, and get her stated on her project, even though it may be less urgent.
Alice will be able to spend more time thinking about her project, and leave Bob with a fresh slate.</p>

<p>&ldquo;But this is really urgent, I don&rsquo;t even want to think about project 3 yet&rdquo;.
The next alternative would be to identify decisions which Alice can make which have the least impact on the other work Bob needs to do.
One would be having Alice better define the requirements and organize resources for this project.
This will only help Bob make his decisions.
Another idea is to have Alice work on &ldquo;black boxes&rdquo; that Bob doesn&rsquo;t need to know how they work.
Maybe Alice has some special knowledge and can write a hard function he expects to use.
What you absolutely don&rsquo;t want to do is interrupt Bob and have him start thinking about what decisions Alice could be making, while he is making his decisions.
That doesn&rsquo;t make any sense!</p>

<h2>Notes</h2>

<ol>
<li><p>I don&rsquo;t think programmers <em>deserve</em> any of these special treatments over other jobs.
I am not suggesting that programmers should have special privileges or are somehow more important than other kinds of work.
It&rsquo;s all about the productivity model for the kind of work they do.</p></li>
<li><p>In video game production, art tends to be easy to outsource while programming is notoriously difficult and often unsuccessful. Perhaps this is because 3D art production can be better fit into a factory production productivity model.</p></li>
<li><p>One reason &ldquo;just write it from scratch&rdquo; is so appealing for programmers is that
they get to make their own decisions, instead of figuring out why others made (often bad) decisions.
Who wants to live with someone elses choices?
For large existing codebases this represents a lot of invested knowledge, so its usually bad,
but for a new task, Why would you rob a programmer of this opportunity by playing
musical chairs?</p></li>
</ol>

]]>
</description>
</item>
<item>
<pubDate>Thu, 23 Jan 2020 00:00:00 +0000</pubDate>
<title>Keeping Up-to-date</title>
<guid>https://www.jmeiners.com/keeping-up-to-date/</guid>
<link>https://www.jmeiners.com/keeping-up-to-date/</link>
<description>
<![CDATA[
<h2>Keeping Up-to-date</h2>

<p><strong>1/23/2020</strong></p>

<p>The software industry is synonmous with rapid innovation.
New discoveries require changing to better ways of doing things.
For programmers to stay relevant they need to constantly keep up on the latest technologies,
otherwise their skills will go out of date.
At least, that&rsquo;s what I&rsquo;ve been told,
but the more I study computer science from 50 years ago,
the more I find &ldquo;new&rdquo; ideas are actually old.
Perhaps the changes we see are only permutations
of underlying ideas.</p>

<p>In many obvious ways software does change.
Languages, libraries, and tools get replaced overtime.
Nobody is writing desktop applications in assembly anymore.
Many developers who wrote Windows applications moved on to mobile or web.
But rarely are these changes due to a technological advancement
or dramatic in change in how things are done, just new forms
of popular products, or improved hardware that gives us some wiggle room.</p>

<p>A good engineer can adapt to these changes, in the same way they can switch
to a company which uses different tools and processes.
Learning Python after C# should be easy, because you understand programs, not the syntax.
Moving to a language with significant design differences like Haskell requires a broader
understanding of functions and computation.
Now imagine there was similar knowledge that helped you approach every computer problem and perhaps
all of nature.
The knowledge I am describing is math and science!
For software it consists of <a href="https://teachyourselfcs.com/">computer science subjects</a> like OS theory, algorithms, software design, logic,
and calculus.
Because many programmers lack this, they struggle with change, and feel pressure
to keep up with trends. <sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p>

<p>Don&rsquo;t believe me?
Take a look at the hottest &ldquo;new&rdquo; areas of tech
AI/machine learning, blockchain, and big data/data science.
What barriers make it difficult for programmers to get into them and be successful?
For machine learning the answer is a bit of linear algebra and multivariable calculus,
evidenced by the many blog post promising to get readers up to speed.
This math is (should be) covered by every computer science degree
and has remained the same for at least 50 years,
down to the presentations and illustrations used to <a href="https://www.youtube.com/watch?v=wsOoClvZmic">teach it</a>.
<a href="https://www.jmeiners.com/neural-nets-sim/">Neural networks</a> themselves have been around for a <a href="https://en.wikipedia.org/wiki/Perceptrons_(book)">long time</a>,
although less mainstream.</p>

<p>For <a href="https://www.jmeiners.com/tiny-blockchain/">blockchain</a> the essentials are an understanding of cryptography,
and peer-to-peer networking. That doesn&rsquo;t even mean fancy understandings
of elliptic curves or number theory, just a solid grasp of hashes,
signatures, and asymetric key encrpytion.
Distributed systems is also a mature field of computer science.</p>

<p>Data science might be the most accessible.
A solid understanding of introductory probablity and statistics and databases
combined with a few tools such as linear regression, and polynomial interpolation
might be enough for 90% of applications.
But it&rsquo;s going to be really hard, if you can&rsquo;t understand a wikipedia page about <a href="https://en.wikipedia.org/wiki/Horner%27s_method">polynomials</a>.</p>

<p>I don&rsquo;t mean to suggest that these skills make an expert.
General theory is a longshot from research or novel contributions to the field.
Nor is it sufficient to be a good programmer; learning linear algebra does not immediately
make you good at writing machine learning programs (and scientists write some terrible code!).
Rather this is the &ldquo;hard stuff&rdquo; that prevents programmers from getting into these fields.
Once you know it, the other details are approachable. <sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>

<p>If you analyze other software advances from the past, from database theory
to graphics, you will find similar applications
of rather unextraordinary math and science.
Many programmers ask, how I can I predict what skills will be important in the future?
What do I need to learn to have a successful career?
Few can predict what specific trends will take off, but I
bet whatever is important in the future is going to require understanding
those broad areas of computer science.
Keep practicing and specializing in the area you work in, but if you regularly refresh and
broaden your base of fundamentals
you will be prepared to learn anything new that starts to look interesting. [^3]</p>

<p>Understanding fundamentals gives programmers another significant advantage.
They know what problems have been solved before.
It&rsquo;s unlikely you will remember every detail, but can say
&ldquo;I&rsquo;ve heard of this before&rdquo; and know where to learn more.
Consider how many new tools are bad solutions to problems solved by simple bash scripts,
of which the author was ignorant of.
This is just a tiny represenative of how much duplication and complexity
programmers are adding because they don&rsquo;t know whats already there.</p>

<p>It may sound as though I am advocating a kind of tech hipsterism;
everything interesting has already been done so we might
as well stop looking for new things. Rather I am arguing
that we will be able make more advancements, if we better
understand the big ideas behind what has come before.</p>

<p>Properly understood this flips the progress narrative of technology on it&rsquo;s head.
We don&rsquo;t have to chase headlines and blog posts about the latest frameworks
and build tools.
Nor do we have to guess which technologies might suddenly become useful, like day trading stocks.
That&rsquo;s for evangelists and IT consultants.
The foundations for our next ideas has have already been built by generations of smart people.
It&rsquo;s all written down waiting to be dusted off and rediscovered.
Rather than building and encyclopediac knowledge of novelties
 and press releases,
we continuosuly revisit the same core subjects, over and over, in pursuit of mastery.</p>

<p>of those who study STEM seem to lose it after going through the motions.</p>

<p>popular book <a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html">SICP</a>. In just a few hundred
pages it covers several major areas of CS and more
than most programmers understand in their whole career.
It&rsquo;s able to do that because it&rsquo;s not written
for a general audience.
It relies on the reader having a solid undergraduate understanding of another
area of math or science as an MIT student would have.</p>

<p>[^3] Experts in a very particular system
(for example OpenCL or <a href="https://v8.dev/blog">V8 internals</a>) can be extremely valuable.
But, most of them only get that level of depth with a solid
understanding of fundamental computer science.
Expertise is also a subject for another day.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
It doesn&rsquo;t have to come from a university, and a majority<a href="#fnref:1" rev="footnote">&#8617;</a></li>
<li id="fn:2">
A great example of this is the<a href="#fnref:2" rev="footnote">&#8617;</a></li>
</ol>
</div>

]]>
</description>
</item>
<item>
<pubDate>Tue, 21 Jan 2020 00:00:00 +0000</pubDate>
<title>MultiplyPoint3x4 in Unity</title>
<guid>https://www.jmeiners.com/unity-fast-multiply/</guid>
<link>https://www.jmeiners.com/unity-fast-multiply/</link>
<description>
<![CDATA[
<h1>MultiplyPoint3x4 in Unity</h1>

<p><strong>01/21/2020</strong></p>

<p>What is the difference between MultiplyPoint and MultiplyPoint3x4 in Unity3D?</p>

<p>What steps of a matrix multiplication could Unity possibly be skipping to make an optimization?
The optimization is possible because a scaling and rotation needs only a 3x3 matrix and another vector for the translation,
so part of the full 4x4 matrix is unused and can be ignored.</p>

<p>Here is the source code taken from the decompilation <a href="https://github.com/jameslinden/unity-decompiled/blob/master/UnityEngine/UnityEngine/Matrix4x4.cs">here</a>:</p>

<pre><code>public Vector3 MultiplyPoint(Vector3 v)
{
    Vector3 vector3;
    vector3.x =  ( m00 *  v.x +  m01 *  v.y +  m02 *  v.z) + m03;
    vector3.y =  ( m10 *  v.x +  m11 *  v.y +  m12 *  v.z) + m13;
    vector3.z =  ( m20 *  v.x +  m21 *  v.y +  m22 *  v.z) + m23;
    float num = 1f / ( ( m30 *  v.x +  m31 *  v.y +  m32 *  v.z) + m33); // this is 1/1=1 when m30, m31, m32 = 0 and m33 = 1
    vector3.x *= num; // so then multiplying by 1 is pointless..
    vector3.y *= num;
    vector3.z *= num;
    return vector3;
}
</code></pre>

<p>This is a full 4x4 * 4x1 matrix multiplication, and then scaling the x y z of the result by the w of the result.</p>

<pre><code> | m_0_0 m_0_1 m_0_2 m_0_3 |     | x |
 | m_1_0 m_1_1 m_1_2 m_1_3 |  *  | y |
 | m_2_0 m_2_1 m_2_2 m_2_3 |     | z |
 | m_3_0 m_3_1 m_3_2 m_3_3 |     | 1 |
</code></pre>

<p>This <code>w</code> necessary for projective transformations, but not for rotation and scaling.
This is why they have the faster 3x4 version.
It assumes the <code>w</code> component of each column is 0 and skips that bottom row of multiplication and scaling, because the resulting <code>w</code> is always 1.</p>

<pre><code>public Vector3 MultiplyPoint3x4(Vector3 v)
{
    Vector3 vector3;
    vector3.x =  ( m00 *  v.x +  m01 *  v.y +  m02 *  v.z) + m03;
    vector3.y =  ( m10 *  v.x +  m11 *  v.y +  m12 *  v.z) + m13;
    vector3.z =  ( m20 *  v.x +  m21 *  v.y +  m22 *  v.z) + m23;
    return vector3;
}
</code></pre>

<p>This function is equivalent to multiplying matrices which look like:</p>

<pre><code> | m_0_0 m_0_1 m_0_2 m_0_3 |     | x |
 | m_1_0 m_1_1 m_1_2 m_1_3 |  *  | y |
 | m_2_0 m_2_1 m_2_2 m_2_3 |     | z |
 | 0     0     0     1     |     | 1 |
</code></pre>
]]>
</description>
</item>
<item>
<pubDate>Sun, 28 Jul 2019 00:00:00 +0000</pubDate>
<title>Write Your Own Proof-of-Work Blockchain</title>
<guid isPermaLink="true">https://www.jmeiners.com/tiny-blockchain/</guid>
</item>
<item>
<pubDate>Sat, 08 Jun 2019 00:00:00 +0000</pubDate>
<title>Think in Math. Write in Code.</title>
<guid>https://www.jmeiners.com/think-in-math/</guid>
<link>https://www.jmeiners.com/think-in-math/</link>
<description>
<![CDATA[
<h2>Think in Math. Write in Code.</h2>

<p><strong>6/8/19</strong></p>

<p>Programmers love to discuss programming languages.
We not only debate their technical merits and aesthetic qualities,
but they become integrated into our personal identities,
along with the values and traits that we associate with them.
Some even defend a form of <a href="https://en.wikipedia.org/wiki/Linguistic_determinism">Linguistic Determinism</a> that thinking is confined to what the language
makes typable.</p>

<p>Since we spend so much time writing code, a keen interest in language design is justified.
However, the character of these discussions suggests that we think of them as much more,
and have perhaps forgotten their primary role.
Programming languages are <em>implementation tools</em> for instructing machines, not <em>thinking tools</em>
for expressing ideas.
They are strict formal systems riddled with design compromises and practical limitations.
At the end of the day, we hope they make controlling computers bearable for humans.
In contrast, thoughts are best expressed through a medium which is free and flexible.</p>

<h2>Thinking in Math</h2>

<p>The natural language which has been effectively used for thinking about computation, for thousands of years, is mathematics.
Most people don&rsquo;t think of math as free or flexible.
They think of scary symbols and memorizing steps to regurgitate on tests.
Others hear math and think category theory, lambda calculus, or other
methods of formalizing computation itself, but these are hardly
necessary for programming itself.</p>

<p>I hope readers of this article have had a better experience regarding what math is about, such as a graph theory, algorithms, or linear algebra course;
the kind that involves logic and theorems, and is written in prose with a mix of symbols (most symbols weren&rsquo;t even invented until the <a href="https://en.wikipedia.org/wiki/History_of_mathematical_notation#Symbolic_stage">16th century</a>).
This kind of math is about creating logical models to understand real world problems, through careful
definitions and deductions.
If you don&rsquo;t have a clear idea of what this looks like I recommend <a href="https://www.amazon.com/Introduction-Graph-Theory-Dover-Mathematics/dp/0486678709">Trudeau</a>,
<a href="https://www.fm2gp.com">Stepanov</a>, or <a href="https://www.amazon.com/Introduction-Algorithms-Creative-Udi-Manber/dp/0201120372">Manber</a>.</p>

<p>Math allows you to reason about logical structures, free from other constraints.
This is also what programming requires: creating logical systems to solve problems.
Take a look at the basic pattern for programming:</p>

<ol>
<li>Identify a problem</li>
<li>Design algorithms and data structures to solve it</li>
<li>Implement and test them</li>
</ol>


<p>In practice, work is not so well organized as there is interplay between steps.
You may write code to inform the design.
Even so, the basic pattern is followed over and over.</p>

<p>Notice that steps 1 and 2 are the ones that take most of our time, ability, and effort.
At the same time, these steps don&rsquo;t lend themselves to programming languages.
That doesn&rsquo;t stop programmers from attempting to solve them in their editor, but they end up with code that is muddled, slow, or that solves the wrong problem.
It&rsquo;s not that programming languages aren&rsquo;t good enough yet.
It&rsquo;s that <em>no formal language</em> could be good at it.
Our brains just don&rsquo;t think that way.
When problems get hard, we draw diagrams and discuss them with collaborators.</p>

<p>Ideally, steps 1 and 2 are solved first, and only then will a programming language be used to solve step 3.
This has an added benefit of transforming the implementation process.
With a mathematical solution in hand, you can then focus on choosing the best representation and implementation, and writing better code, knowing what the end goal will be.</p>

<h2>Implementation Concerns</h2>

<p>Why are programming languages burdensome thinking tools?
One reason is that writing code is inseparably connected with implementation concerns.
A computer is a device that must manage all kinds of tasks and while being bound by physical
and economic constraints.
Think about all the considerations for writing a simple function:</p>

<ul>
<li>What inputs should I provide?</li>
<li>What should they be named?</li>
<li>What types should they be? (Even dynamically typed languages must consider types, it&rsquo;s just implicit.)</li>
<li>Should I pass them by value or by reference?</li>
<li>What file should I put the function in?</li>
<li>Should the result be reused, or is it fast enough to recalculate it every time?</li>
</ul>


<p>The list can go on. The point is that these considerations have nothing to do with what the function does.
They distract from the problem the function is trying to solve.</p>

<p>Many languages aim to hide details such as these, which is helpful, especially for mundane tasks.
However, they cannot transcend their role as an implementation tool.
SQL is one of the most successful examples of this, but it is ultimately concerned with implementation concerns such as tables, rows, indices, and types.
Because of this, programmers still design complicated queries in informal terms, like what they want to &ldquo;get,&rdquo; before writing a bunch of <code>JOIN</code>s.</p>

<h2>Inflexible Abstractions</h2>

<p>Another limitation of programming languages is that they are poor abstraction tools.
Typically, when we discuss abstraction in engineering, we mean hiding implementation details.
A complex operation or process is packaged into a &ldquo;black box&rdquo; with its contents hidden and well-defined inputs and outputs exposed.
Accompanying the box is fictional story that explains what it does, in a greatly simplified way.</p>

<p><img src="black-box.gif" alt="black box picture" /></p>

<p>Black boxes are essential for engineering large systems since the details are too overwhelming to hold in your head.
They also have many well-known limitations.
A black box <a href="https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/">leaks</a> because its brief description cannot completely determine its behavior.
The opaque interfaces introduce <a href="https://www.youtube.com/watch?v=lHLpKzUxjGk">inefficiencies</a>, like duplication and fragmented design.</p>

<p>Most importantly for problem-solving, black boxes are rigid.
They must explicitly reveal some dials and knobs, and hide others,
committing to a particular view about what it is essential to expose to the user,
and what is noise.
In doing so, they present a fixed level of abstraction which may be too high-level or too low-level for the problem,
As an example, a high-level web server may provide a terrific interface for serving JSON, but be useless if one wants an interface for serving incomplete data streams, such as output from a program.
In theory, you can always look inside the box, but in code, the abstraction level at any one time is fixed.</p>

<p>In contrast, the word abstraction in math is nothing like hiding information.
Here, abstraction means extracting the essential features or characteristics of something, in relation to a particular context.
Unlike black boxes, no information is hidden.
They don&rsquo;t leak in the same way.
You are encouraged to adjust to the right level of abstraction and quickly jump between perspectives.
You might ask:</p>

<ul>
<li>Is this problem best represented as a table? Or, a function?</li>
<li>Can I look at the whole system as a function?</li>
<li>Can I treat this collection of things as a single unit?</li>
<li>Should I look at the whole system or a single part?</li>
<li>What assumptions should I make? Should I make them stronger or weaker?</li>
</ul>


<p>Just look at the many ways of looking at a function:</p>

<p><a href="https://www.youtube.com/watch?v=ACZDnF8-9Ks"><img src="functions.gif" alt="function representations" /></a></p>

<p>Thinking in math allows one to use whichever brings the most clarity at any moment.</p>

<p>It turns out most abstract concepts can be understood from many perspectives, just like functions.
Studying math provides one with a versatile toolbox of perspectives for studying all kinds of problems.
You might first describe a problem with a formula, and then switch to understanding it <a href="https://en.wikipedia.org/wiki/Felix_Klein#Erlangen_program">geometrically</a>,
then recognize some group theory (abstract algebra) is at play, and
all of this combines to give insight and understanding.</p>

<p>To summarize, programming languages are great engineering tools for assembling black boxes;
they provide functions, classes, and modules, all of which help wrap up code into nice interfaces.
However, when trying to solve problems and design solutions, what you actually want is the math kind of abstraction.
If you try to think at the keyboard, the black boxes available to you will warp your view.</p>

<h2>Problem Representation</h2>

<p>Just as programming languages are rigid in their ability to abstract, they also are rigid in how they represent data.
The very act of implementing an algorithm or data structure is picking <em>just one</em> of the many possible ways to represent
something; along with all the trade-offs that come with it.
It is always easier to make trade-offs when one has use cases in mind and understand the problem well.</p>

<p>For example, graphs (sets of vertices and edges) appear in many programming problems such as internet networks, pathfinding, and social networks.
Despite their simple definition, choosing how to represent them is hard and varies greatly depending on use case:</p>

<p><img src="graph.gif" alt="math graph" /></p>

<ul>
<li><p>The one which most closely matches the definition:<br/>
<code>vertices: vector&lt;NodeData&gt; edges: vector&lt;pair&lt;Int, Int&gt;&gt;</code>
(The vertices can be removed if you only care about connectivity.)</p></li>
<li><p>If you want to traverse a node&rsquo;s neighbors quickly, then you probably want a node structure:<br/>
<code>Node { id: Int, neighbors: vector&lt;Node*&gt; }</code></p></li>
<li><p>You could use an <a href="https://en.wikipedia.org/wiki/Adjacency_matrix">adjacency matrix</a>. Where each row stores the neighbors of a particular node:
<code>connectivity: vector&lt;vector&lt;int&gt;&gt;</code> and the nodes themselves are implicit.</p></li>
<li><p>Pathfinding algorithms often work on graphs implicitly from a board of cells:<br/>
<code>walls: vector&lt;vector&lt;bool&gt;&gt;</code>.</p></li>
<li><p>In a peer-to-peer network, each computer is a vertex and each socket is an edge.
The entire graph isn&rsquo;t even accessible from one machine!</p></li>
</ul>


<p>Math allows you to reason about the graph itself, solve the problem, and then choose an appropriate representation.
If you think in a programming language, you cannot delay this decision as your first line of code commits to a particular representation.</p>

<p>Note that the graph representations are too diverse to wrapped up in a polymorphic interface.
(Consider again the graph representing a computer network, like the entire internet.)
So creating a completely reusable library is impractical.
It can only work on a few types, or force all graphs into an inappropriate representation.
That doesn&rsquo;t mean libraries or interfaces aren&rsquo;t useful.
Similar representations are needed again and again (like <code>std::vector</code>),
but you cannot write a library which encapsulates the concept of &ldquo;graph&rdquo; once and for all.
A simple generic or interface with a few types in mind is appropriate.</p>

<p>As a corollary, programming languages should focus primarily on being useful implementation tools,
rather than theoretical tools.
A good example of modern language feature which does this is async/await.
It&rsquo;s not hiding away complex details or introducing new conceptual theory.
It takes a common practical problem and makes it easier to write.</p>

<p>Thinking in math also makes the &ldquo;C style&rdquo; of programming more appealing.
When you understand a problem well, you don&rsquo;t have to build up layers of framework and abstraction
in anticipation of &ldquo;what if&rdquo;.
You can write a program tailor made to the problem, with carefully chosen trade-offs.</p>

<h2>Example Project</h2>

<p>So what does thinking in math look like?
For this section you may have to read a bit more slowly and carefully.
Recently, I worked on an API at work for pricing cryptocurrency for merchants.
It takes into account recent price changes and recommends that merchants charge a higher price during volatile times.</p>

<p>Although we did some homework on the theory, we wanted to empirically test it to see how it performed during various market conditions.
To do so, I designed a bot to simulate a merchant doing business with our API, to see how it performs.</p>

<p><strong>BTC/USD (1 day)</strong></p>

<p><img src="btc-usd.gif" alt="btc usd" /></p>

<h3>Preliminaries</h3>

<p><strong>Definition:</strong> The <strong>exchange rate</strong> <code>r(t)</code> is the market rate of <code>fiat/crypto</code>.</p>

<p><strong>Definition:</strong> The <strong>merchant rate</strong> <code>r'(t)</code> is the modified exchange rate which the merchant is advised to charge customers.</p>

<p><strong>Definition:</strong> When a customer buys an item, we call that event a <strong>purchase</strong>.
A purchase consists of the price in fiat and a time. <code>p = (f, t)</code>.</p>

<p><strong>Theorem:</strong> The amount of crypto for a purchase is found by applying the modified exchange rate
<code>t(p) = p(1) / r'(p(2))</code>.</p>

<p><strong>Proof:</strong> <code>p(1) / r'(p(2)) = fiat / (fiat/crypto) = fiat * crypto/fiat = crypto</code></p>

<p><strong>Definition:</strong> When the merchant sells their crypto holdings, we call that event a <strong>sale</strong>.
A sale consists of an amount in crypto and a timestamp. <code>s = (c, t)</code>.</p>

<p><strong>Theorem:</strong> The amount of fiat the merchant obtained from a sale is found by applying the exchange rate to the sale <code>g(s) = s(1) * r(s(2))</code>.</p>

<p><strong>Proof:</strong> <code>s(1) * r(s(2)) = crypto * (fiat/crypto) = fiat</code></p>

<p><strong>Definition:</strong> The <strong>balance</strong> of a set of purchases and sales is the difference between all purchase crypto amounts and all sale crypto amounts.
 <code>b(P, S) = sum from i to N of t(p_i) - sum from j to M of s_j(1)</code></p>

<p>Note that <code>b(P, S) &gt;= 0</code> must always hold.</p>

<p><strong>Definition:</strong> The <strong>earnings</strong> of a set of purchases and sales is the difference between sale fiat amounts and purchase fiat amounts.
<code>e(P, S) = sum from j to M of g(s_j(1)) - sum from i to N of p_i(1) &gt;= 0</code>.</p>

<h3>Objective</h3>

<p><strong>Definition:</strong> We say that the merchant rate is <strong>favorable</strong> iff the earnings are non-negative for <em>most</em> sets of <em>typical</em> purchases and sales.
<code>r'(t) is favorable iff e(P, S) &gt;= 0</code>.</p>

<p>In a favorable case, the merchant didn&rsquo;t lose any fiat by accepting crypto.</p>

<p><em>most</em> and <em>typical</em> will not be rigorously defined.</p>

<p>As part of <em>typical</em>, we can assume that merchants will sell their crypto in a timely manner.
So assume <code>s_i(2) - s_j(2) &lt; W</code> for <code>i,j in {1.. M}</code> for some bound <code>W</code>.
Purchase amounts should be randomly distributed within a reasonable range that commerce is done. Perhaps $10-100.</p>

<p><strong>The goal of the bot is to verify that <code>r'(t)</code> is favorable.</strong></p>

<p>Note that this definition is only one measure of quality.
Perhaps protecting against the worst case is more important than being favorable.
In that case, we would be concerned about the ability to construct a set of purchases with very negative earnings.</p>

<h3>Algorithm</h3>

<p>Repeat many times:</p>

<ol>
<li>Randomly choose a time range <code>[t0, t1]</code>.</li>
<li><p>Generate a set of <strong>purchases</strong> at random times within <code>[t0, t1]</code>.
The price should fall within a range <code>[p0, p1</code>] of <em>typical</em> prices.</p></li>
<li><p>Generate a set of <strong>sales</strong> at evenly spaced times (perhaps with slight random noise) within <code>[t0, t1]</code>.
Each sale should be for the full <strong>balance</strong> at that time.</p></li>
<li>Calculate the <strong>earnings</strong> for these sets.</li>
<li>Record the earnings.</li>
</ol>


<p>After:</p>

<ol>
<li>Report how many earnings were negative and non-negative. Show a percentage for each.</li>
<li>Identify the minimum and maximum earnings and report them.</li>
</ol>


<h3>Conclusion</h3>

<p>As you read this example, I think your tendency may be to think that its statements are obvious.
Certainly, none of these steps are hard.
However, it was surprising to me how many of my assumptions were corrected and how difficult it was to choose an objective definition of a <strong>favorable</strong> outcome.
This process helped me become aware of assumptions I would not have even considered if I had started by simply writing code.
Perhaps the greatest benefit was that after writing it, I was able to quickly review it with a co-worker and make corrections which were easy on paper, but would have been difficult to change in code.</p>

<p>I hope that thinking in the language of math will bring similar benefits to your projects!
Note that this example is only one style of utilizing mathematical thinking.</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 12 May 2019 00:00:00 +0000</pubDate>
<title>Notes on Vector Libraries</title>
<guid>https://www.jmeiners.com/vector-libs/</guid>
<link>https://www.jmeiners.com/vector-libs/</link>
<description>
<![CDATA[
<h1>Notes on Vector Libraries</h1>

<p><strong>05/12/2019</strong></p>

<p>A good vector math library is essential for graphics
and simulation programming.
However, implementing one that is flexible, efficient,
and easy to use is difficult.
Due to so many choices, experienced
programmers tend to write their own to accommodate their preference.</p>

<p>In this article I will survey a few of the most popular techniques and offer some design advice.
I will specifically focus on math theory and C implementations.</p>

<h2>Math</h2>

<p>Before diving into the code.
It&rsquo;s helpful to review some of the math
to understand what we are aiming for. One thing to watch for
is operations that can be defined in terms of each other.
Rarely do I see libraries take advantage of this.</p>

<p><strong>Vector Operations</strong></p>

<p>On vectors in <code>R^N</code></p>

<ul>
<li>addition <code>v + w</code></li>
<li>subtraction <code>v - w</code>. Defined by addition: <code>a - b = a + (-b)</code></li>
<li>multiplication <code>v * w</code></li>
<li>scaling <code>a * v</code></li>
<li>normalization. Defined by length and scaling: <code>1/|v| * v</code></li>
</ul>


<p>From <code>R^N -&gt; R</code></p>

<ul>
<li>dot product <code>&lt;v, w&gt;</code></li>
<li>length <code>|v|</code>. Defined by dot product <code>sqrt(&lt;v,v&gt;)</code></li>
<li>angle. Defined by dot product and length <code>acos(&lt;a,b&gt;/|a||b|)</code></li>
</ul>


<p>Only on specific dimension, such as <code>R^2</code> or <code>R^3</code></p>

<ul>
<li>cross product <code>a X b</code></li>
<li>angle (in the plane)</li>
</ul>


<p><strong>Matrix Operations</strong></p>

<p>On all matrices <code>M(n x m)</code></p>

<ul>
<li>addition <code>A + B</code></li>
<li>subtraction <code>A - B</code>
Defined by addition <code>A - B = A + (-B)</code></li>
<li>scaling <code>bA</code></li>
<li>multiplication <code>AB</code></li>
</ul>


<p>On square matrices <code>M(n x n)</code></p>

<ul>
<li>determinant <code>det(A)</code></li>
<li>inverse <code>A^-1</code></li>
</ul>


<p>Between vectors and matrices</p>

<ul>
<li>multiplication <code>Av</code></li>
</ul>


<p>Most programs use 2, 3, and 4
element vectors, and only a few operations
are specific to a given dimension.
So a lot of code can be condensed by writing algorithms
on N dimensional vectors.</p>

<p>Matrix operations are also very general.
But a few should be kept to a specific
dimension (usually 3x3 or 4x4).
You do not want to implement a
general inverse or determinant function.</p>

<h2>1. Simple Structs</h2>

<pre><code>typedef struct
{
    float x, y, z;
} vec3;

vec3 vec3_add(vec3 a, b)
{
    vec3 r;
    r.x = a.x + b.x;
    r.y = a.y + b.y;
    r.z = a.z + b.z;
    return r;  
}
</code></pre>

<p>This works well for smaller programs.
The best part is that expressions look nice (<code>a + 2.0*(b-d)</code>):</p>

<pre><code>vec3_add(a, vec3_scale(2.0, vec_sub(b, c)));
</code></pre>

<p>But, we have to copy this definition for every dimension.
We also have to avoid any algorithms that use
index or iteration.
Matrix vector multiplication gets ugly.</p>

<p>If you only have a few functions that need
indexing and you can index into a pointer to the first member:</p>

<pre><code>vec3 a;
float* v = &amp;a.x;
v[0];
</code></pre>

<p><strong>Examples</strong></p>

<ul>
<li><p><a href="https://github.com/justinmeiners/pre-rendered-backgrounds/blob/master/source/engine/core/vec_math.h">vec math</a></p></li>
<li><p><a href="https://github.com/nothings/obbg/blob/master/src/stb_vec.h">stb vec</a></p></li>
</ul>


<h2>2. Arrays</h2>

<p>For <code>N</code> dimensional vectors
we might try to write functions which
operate on arrays of floats.
This is nice because it does not
introduce another data structure, so
other functions and vector libraries play nice with each other.</p>

<p>Unfortunately, C does not allow you to return
an array from the stack. You can only return a pointer
which must point to some valid region.
So either we do something horrible like <code>malloc</code> in each operation,
or pass in arrays for the return value.
Passing in arrays works, but it destroys the ability
to comfortably write simple expressions such as <code>a + 2.0*(b-d)</code>:</p>

<pre><code>void vecn_add(int n, float* a, float* b, float* ret);

// intermediate results everywhere
float temp[3];
vecn_sub(3, b, d, temp);

float temp2[3];
vecn_scale(3, 2.0, temp, temp2);

float final[3];
vecn_add(3, a, temp2, final);
</code></pre>

<p>Plain arrays may be appropriate for matrices since they are not typically
involved in complex expressions.
Matrices and large vectors, which would be inefficient to copy around
would also be a good use case.</p>

<p>Depending on the application you may not want
to sacrifice performance by introducing loops and branching
into every operation. As long as the dimensions
are input as a literals or macros, the small loops
should be unrolled at compile time.</p>

<p><strong>Examples:</strong></p>

<ul>
<li><a href="https://developer.apple.com/documentation/accelerate/vdsp">Accelerate</a></li>
<li><a href="https://github.com/datenwolf/linmath.h">linmath</a></li>
</ul>


<h2>3. Struct + Union</h2>

<p>A workaround to return an array from a function is to include it in a struct.
The tradeoff is that the size must be fixed and element access is a bit
uglier as it requires at least an extra letter.</p>

<pre><code>typedef struct
{
    float e[3];
} vec3;

vec3 v;
v.e[0] = 1;
</code></pre>

<p>The access syntax can be cleaned up with a union
but, <a href="https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html">anonymous structs/unions</a>
are a GCC extension and are non-standard.</p>

<pre><code>typedef union
{
    float v[3];
    struct
    {
        float x;
        float y;
        float z; 
    }; 
} vec3;
</code></pre>

<p>This gives you safe iterative access and nice named members,
but it is hard to combine with generic functions.
Either you use functions which operate on the internal arrays
and deal with the intermediate results.
Or, define fixed dimension functions which wrap
the generic ones:</p>

<pre><code>vec3 vec3_add(vec3 a, vec3 b);
{
    vec3 temp;
    vecn_add(3, a.v, b.v, temp.v);
    return temp;
}
</code></pre>

<p>I don&rsquo;t love this option.
If I need to write wrapper functions I might as well go back to method 1
and copy implementations around.</p>

<p><strong>Examples:</strong></p>

<ul>
<li><a href="https://github.com/arkanis/single-header-file-c-libs/blob/master/math_3d.h">Math 3D</a> (See Matrices)</li>
</ul>


<h2>4. Macros</h2>

<p>Some clever macros can help you get the best of both worlds, and
parameterize the scalar types. This can be combined with
an array or union data structure.
But, writing multi-line macros isn&rsquo;t very fun.</p>

<pre><code>#define DEFINE_VEC(T, N, SUF) \
\
void vec##N####SUF##_add(const T *a, const T *b,  T *r) \
{ \
    for (int i = 0; i &lt; N; ++i) \
        r[i] = a[i] + b[i]; \
} \
</code></pre>

<p>Then define the types you need:</p>

<pre><code>DEFINE_VEC(float, 2, f);
DEFINE_VEC(float, 3, f);
DEFINE_VEC(float, 4, f);
</code></pre>

<p>Usage:</p>

<pre><code>vec3f_add(a, b);
</code></pre>

<p>Functions which only apply to a specific dimension
can be defined outside of the macro:</p>

<pre><code>void vec3f_cross(const float* a, const float* b, float* r)
{
    // ...
}
</code></pre>

<p><strong>Examples:</strong></p>

<ul>
<li><a href="https://github.com/datenwolf/linmath.h">linmath</a></li>
</ul>


<h2>Closing Thoughts</h2>

<p>In typical C fashion, I believe it is misguided to try to write
the <em>one true</em> vector library to serve all purposes.
These libraries are bloated and must choose tradeoffs which
don&rsquo;t fit your use case. Instead use the examples
above to write to tailor make vector functions as needed.</p>

<p>For further reading, see <a href="http://www.reedbeta.com/blog/2013/12/28/on-vector-math-libraries/">On Vector Math Libraries</a>.
It focuses on C++ and has a few other handy tips.
You can also read a <a href="https://github.com/arkanis/single-header-file-c-libs/issues/3">discussion</a>
which led to these notes.</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 14 Apr 2019 00:00:00 +0000</pubDate>
<title>Foundation of Math Reading List</title>
<guid>https://www.jmeiners.com/foundations-of-math-reading/</guid>
<link>https://www.jmeiners.com/foundations-of-math-reading/</link>
<description>
<![CDATA[
<h2>Foundation of Math Reading List</h2>

<p><strong>04/13/2019</strong></p>

<p>One of my favorite courses in college was
philosophy of language.
Along with interesting philosphy
it introduced me to the foundations of math project
which has since become one of my
favorite subjects to learn about.</p>

<p>Some of my favorite books of all time come out of this interest.
I wanted to organize a few of these
into a list for others who are interested in the topic.
Note that many good books were left out in favor of the very best.</p>

<p>You will notice a theme in my commentary.
The books I like most are those that don&rsquo;t
shy away from hard technical knowledge, but also
explore the philosophical ideas behind them.</p>

<p>The list is arranged in a progressive sequence
that will help prepare you for the next one.</p>

<h3>Logicomix</h3>

<p>By: <a href="https://www.apostolosdoxiadis.com">Apostolos Doxiadis</a></p>

<p><img src="logicomix.jpg" alt="logicomix" /></p>

<p>Logicomix is actually a comic book!
It tells an engaging historical narrative about the search for the foundations of math
and the birth of analytic philosophy, in the early 20th century.</p>

<p>It introduces you to all the major characters
such as Gödel, Russel, Frege, and Wittgenstein and
motivates the kinds of problems they were trying to solve.
The book also explores how these ideas connect to modern computer science.</p>

<p>It is an absolute joy to read and will give you a taste
of whether this is an interesting subject for you.</p>

<h3>Gödel, Escher, Bach</h3>

<p>By: <a href="https://en.wikipedia.org/wiki/Douglas_Hofstadter">Douglas Hofstadter</a></p>

<p><img src="geb.jpg" alt="godel escher bach" /></p>

<p>You probably have seen this work recommended elsewhere.
Gödel, Escher, Bach really deserves all the praise that it gets.</p>

<p>Hofstadter covers an enormous range of topics
including formal systems, Godel&rsquo;s proof, theory of computation,
programming, molecular biology, and artificial intelligence.
Every topic is presented beautifully and with a lot of philosophical discussion.
In many ways it is an introduction to the big ideas in modern science.
It is written for a general audience and assumes no mathematical background.</p>

<h3>Gödel&rsquo;s Proof.</h3>

<p>By: <a href="https://en.wikipedia.org/wiki/Ernest_Nagel)">James Newman</a> &amp; <a href="https://en.wikipedia.org/wiki/James_R._Newman">Ernest Nagel</a></p>

<p><img src="godels_proof.jpg" alt="godel's proof" /></p>

<p>Gödel, Escher, Bach does a good job of introducing the incompleteness theorem
and discussing its ramifications, but if you are like me you probably still won&rsquo;t
completely understand it after a first reading.</p>

<p>This concise book offers another perspective and a clear explanation
of the mathematics of the proof, its general strategy, and the
historical context surrounding the incompleteness problem.</p>

<h3>Descartes Dream</h3>

<p>By: <a href="https://en.wikipedia.org/wiki/Philip_J._Davis">Phillip Davis</a> &amp; <a href="https://en.wikipedia.org/wiki/Reuben_Hersh">Reuben Hersch</a></p>

<p><img src="descartes_dream.jpg" alt="descartes dream" /></p>

<p>In the 17th century Descartes had a dream in which he saw
a future world driven by mathematical calculations and logical systems.
The theme of this book is how this dream has become a reality.</p>

<p>The book explores how mathematics and computer science work together,
surveys several interesting fields, and examines ethical issues in the technological world.
This book is not technical, and should be appropriate for anyone interested in science
or technology.</p>

<p>If you like this book, the authors wrote another called <em>The Mathematical Experience</em>
which is focused more on pure mathematics.</p>

<h3>Computation: Finite &amp; Infinite</h3>

<p>By: <a href="https://en.wikipedia.org/wiki/Marvin_Minsky">Marvin Minsky</a></p>

<p><img src="computation.jpg" alt="computation finite &amp; infinite" /></p>

<p>Marvin Minsky is an incredibly clear and deep writer.
In this work he provides a mathematical framework
for thinking about mechanical machines and develops the
theory of computation.</p>

<p>This book teaches you all you need to know about Turing machines, finite state, and neural networks.
My project: <a href="https://www.jmeiners.com/neural-nets-sim/">McCulloch &amp; Pitts Neural Net Simulator</a>
is based on this book.</p>

<p>To read this book, you should understand some logic and basic set theory
such as that taught in an introductory proofs course.</p>

<p>Unfortunately, it is out of print and may be difficult to obtain (for a reasonable
amount of money).
I read it from my university&rsquo;s library. If that is not an option, I recommend you <em>find it online</em>.
If anyone knows of a place where I can reasonably purchase this book, let me know.</p>

<h3>Structure and Interpretation of Computer Programs</h3>

<p>By: <a href="https://en.wikipedia.org/wiki/Gerald_Jay_Sussman">Gerald Sussman</a> &amp; <a href="https://en.wikipedia.org/wiki/Hal_Abelson">Hal Abelson</a></p>

<p><img src="sicp.jpg" alt="sicp" /></p>

<p><a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book.html)">Read Online</a></p>

<p>This classic text is designed to teach programming to MIT students
who have some technical background in another areas of math and science.
It is a hard read, but it assumes no programming knowledge and teaches Scheme (a Lisp dialect) and
its full inter-workings from the ground up.</p>

<p>If you want to be a professional programmer,
this may be the only book you need to study.
What other book teaches you to write a symbolic differentiator,
interpreter, circuit simulator, and compiler?</p>

<p>Most of the material is mixed in the <a href="https://github.com/justinmeiners/excercises/tree/master/sicp">excercises</a>
so don&rsquo;t skip them!</p>

<p>But, this is not just a programming book.
It belongs in this list because it teaches the fundamental concepts of computation.
See the section <a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-26.html#%_sec_4.1.5">data as programs</a> for an example.</p>

<h3>Logical Foundations of Mathematics and Computational Complexity</h3>

<p>By: <a href="http://users.math.cas.cz/~pudlak/">Pavel Pudlak</a></p>

<p><img src="logical_foundations.jpg" alt="logical foundations of math" /></p>

<p>This book is a massive and dense survey of topics including
formal systems, set theory, abstract algebra, computability theory,
analysis of algorithms, and quantum computing.
The first chapter covered almost everything I had learned about
algebra and meta-mathematics in my entire undergraduate degree!</p>

<p>Pudlak does a fantastic job of balancing technical
information with philosophical discussion.
I can&rsquo;t recommend this book enough.</p>

<p>Reading this book definitely requires some mathematical maturity.
The author does his best to explains every concept in the book
but it would be hard for me to read about a &ldquo;group&rdquo; for the first time
and really understand what he means.</p>

<p>If you read through the other books, and have technical knowledge
you should be well prepared.</p>
]]>
</description>
</item>
<item>
<pubDate>Fri, 22 Feb 2019 00:00:00 +0000</pubDate>
<title>The Skills Poor Programmers Lack</title>
<guid>https://www.jmeiners.com/the-skills-programmers-lack/</guid>
<link>https://www.jmeiners.com/the-skills-programmers-lack/</link>
<description>
<![CDATA[
<h2>The Skills Poor Programmers Lack</h2>

<p><strong>02/22/2019</strong></p>

<p>Updated: <strong>04/27/2020</strong></p>

<p>A friend and I had a discussion about the basic skills that are often lacking in experienced programmers. How can a programmer work for ten or twenty years and never learn to write good code? Too often they need close supervision to ensure they go down the right path, and can never be trusted to take technical leadership on larger tasks. It seems they are just good enough to get by in their job, but they never become <em>effective</em>.</p>

<p>We thought about our experiences and came up with three fundamental skills that we find are most often missing. Note that these are not skills which take a considerable amount of talent or unique insight. Nor are they &ldquo;trends&rdquo; or &ldquo;frameworks&rdquo; to help you get a new job. They are basic fundamentals which are prerequisites to being a successful programmer.</p>

<h2>Understand how the language works</h2>

<p>Programmers cannot write good code unless they understand what they are typing. At the most basic level, this means they need to understand the rules of their programming language well. It is obvious when a programmer doesn&rsquo;t because they solve problems in indirect ways and litter the code with unnecessary statements that they are clueless as to what they actually do. Their mental model of the program does not match with the actual behavior of the code.</p>

<p>You may have seen code which misunderstands how expressions work: (1)</p>

<pre><code>if isDelivered and isNotified:
    isDone = True
else:
    isDone = false;
</code></pre>

<p>Instead of:</p>

<pre><code>isDone = isDelivered and isNotified
</code></pre>

<p>In JavaScript, this is often indicated by <code>new Promise</code> inside a <code>.then()</code>. In C++, it is attaching <code>virtual</code> to every method and destructor and creating every object with <code>new</code>.</p>

<p>Debugging is also extremely difficult if you don&rsquo;t understand the language. You may add a line of code because it fixes a bug for reasons you don&rsquo;t understand. Bugs are mysteries that seem to appear organically, like dust on the shelves. The code has a mind of its own.</p>

<p>Understand the code you write. Know what every line does and why you put it there.</p>

<p>Once you understand the language well, its important to know about implementation; what goes on <em>inside</em> the computer or library? Do you know how the code gets to <a href="http://inst.eecs.berkeley.edu/~cs61c/sp15/">assembly</a>? Do you know how a <a href="https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-21.html#%_sec_3.2">closure captures variables</a>? Do you know how the <a href="https://en.wikipedia.org/wiki/Cheney%27s_algorithm">garbage collector</a> works? Do you know how a <a href="http://opendatastructures.org/ods-python/">map/dictionary</a> works? Do you know how an HTTP request is made?</p>

<p>Modern software and computers are too complex to know everything (2).
The idea is not not to be too clever, but to avoid doing silly things.
Silly mistakes result in sluggish code that is wasteful of system resources, or just does unexpected things.
Removing an item from the front of a C++ <code>vector</code> requires copying the entire vector which is worth thinking about in large cases.
Writing <code>map&lt;string, map&lt;string, ...&gt;&gt;</code> in C++ (a dictionary of dictionaries) creates a a self-balancing tree in which every node is a self-balancing tree, a data structure nobody would intentionally design. (3)</p>

<p>A muddy understanding of how things work is typical of beginners, but it is all too often a problem with experienced programmers if they are not curious and do not take time to learn how things work beyond their immediate job’s needs.
Learn just a bit more about the stuff you use most works.</p>

<h2>Anticipate problems</h2>

<p>To write reliable code, you must be able to anticipate problems, not just patch individual use cases. I am shocked by the number of times I see code that puts the program in a broken state when a very likely error happens.</p>

<p>I recently reviewed some code that made an HTTP request to notify a server of a state change in which the programmer assumed the HTTP request would always succeed. If it failed, (and we know how often HTTP requests fail), a database record was put into an invalid state. The questions they should have asked when writing this code are: What happens if this fails? Is there another opportunity to send the notification? When is the correct time to record the state change? Careful programmers think through the possible states and transitions of their program.</p>

<p>Using <code>sleep()</code>, cron jobs, or <code>setTimeout</code> is almost always wrong because it typically means you are waiting for a task to finish and don’t know how long it will take. What if it takes longer than you expect? What if the scheduler gives resources to another program? Will that break your program? It may take a little bit of effort to rig a proper event, but it is always worth it.</p>

<p>Another common mistake I see is generating a random file or identifier and hoping that collisions will never happen (4). It is reasonable for an unlikely event to cause an error, but it is not ok if that puts your program in an unusable state. For example, if a successful login generates a session token and it collides with another token, you could reject the login and have the user try again. It is a freak accident that slightly inconveniences the user. On the other hand, what if you generate storage files with random names and you have a collision? You just lost someone’s data! “This probably won’t happen” is not a strategy for writing reliable code.</p>

<p>Unit testing can’t solve this problem either. It can help you stop and think about some inputs to write a test, but more than likely, the cases that you write tests are the ones you anticipated when you wrote the code! Unit testing cannot transform fragile code into reliable code.</p>

<p>Fragile code is often caused by a lack of experience regarding things that can go wrong, but it can also be the result of a long career of maintaining existing codebases. When working on a large existing system, you typically fix individual bugs and aren’t rewarded by your bosses for improving the system as a whole. You learn that programming is a never-ending patch. Increasing the <code>sleep()</code> time may fix the bug today, but never solve the underlying issue.</p>

<h2>Organize and design systems</h2>

<p>Even when armed with the other two skills, it&rsquo;s hard to be effective unless you can organize code into a system that makes sense. I believe OOP and relational database get a lot of flack because programmers tend to be bad at design, not because they are broken paradigms. You simply can&rsquo;t create rigid classes, schemas, and hierarchies without thinking them through. Design itself is too broad a topic to explore in this article (read <a href="https://en.wikipedia.org/wiki/Fred_Brooks">Fred Brooks</a>), so I want to focus on a few specific attributes that well-designed software tends to have.</p>

<p>You may have heard a rule like <a href="http://number-none.com/blow/blog/programming/2014/09/26/carmack-on-inlined-code.html">&ldquo;don&rsquo;t make functions or classes too long&rdquo;</a>. However, the real problem is writing code that mixes unrelated ideas. Poorly designed software lacks conceptual integrity. Its concepts and division of responsibilities are not well defined. It usually looks like a giant Rube Goldberg machine that haphazardly sets state and triggers events.</p>

<p>Accordingly, good software is built from well-defined concepts with clear responsibilities. Mathematicians and <a href="https://en.wikipedia.org/wiki/Categories_(Aristotle)">philosophers</a> spend a lot of time discussing definitions because a good definition allows them to capture and understand some truth about the world. Programmers should think similarly and spend a comparable amount of effort grappling with ideas before writing code.</p>

<p>Good programmers ask questions like:</p>

<ul>
<li>&ldquo;What is this function&rsquo;s purpose?&rdquo;</li>
<li>&ldquo;What does this data structure represent?&rdquo;</li>
<li>&ldquo;Does this function actually represent two separate tasks?&rdquo;</li>
<li>&ldquo;What is the responsibility of this portion of code? What shouldn&rsquo;t it &lsquo;know about&rsquo;?&rdquo;</li>
<li>&ldquo;What is necessary to be in the public interface?&rdquo;</li>
</ul>


<p>Luckily the field is ripe with strategies to help you design code. <a href="https://www.oodesign.com">Design patterns</a> and <a href="https://en.wikipedia.org/wiki/SOLID">SOLID</a> can give you guidelines for designing classes. Functional programming encourages writing pure functions (input -> output and no side effects) and maintaining as little state as possible. <a href="https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html">Model view controller</a> aims to separate UI and storage concerns from program logic. On the other hand, React components form conceptual units by combining the HTML, CSS, and JS into a single component. Unix rejects categories and says <a href="https://en.wikipedia.org/wiki/Everything_is_a_file">everything is a file</a>. All of these seemingly contradictory ideas are valid. The important thing is that the concepts make sense and map closely to the problem you are solving.</p>

<p>Software that is well-designed is also software that is easy to change. Of course, it&rsquo;s too much to ask it to satisfy requirements that contradict its original intent. But, it should accommodate changes that are natural evolutions. A common mistake I see is solving a problem for a few cases, instead of N cases. (If you have a variable called <code>button3</code>.) Another is treating everything as a special case using <code>switch</code> statements instead of using polymorphism. (5)</p>

<p>I think the best way to learn about design is to write and study a lot of programs. Programmers who work only on old programs never learn to write new ones. The studying part is key too. Programmers who only work on small temporary projects (like an agency) may get by without ever improving how to design programs. Good design comes gradually with experience, but only if you think about it and try to improve.</p>

<p>There are no tricks or rules that you can follow to guarantee you will write good software. As Alex Stepanov said, &ldquo;think, and then the code will be good.&rdquo;</p>

<ol>
<li><p>There may be some cases where the previous style is preferred.
This example is only an illustration.</p></li>
<li><p>I was shocked when I wrote some multithreaded code and first faced bugs due to
<a href="https://en.wikipedia.org/wiki/Cache_coherence">Cache coherence</a> and <a href="https://preshing.com/20120625/memory-ordering-at-compile-time/">instruction reordering</a>!</p></li>
<li><p>A reader corrected me about the performance of modern <code>map</code> implementations.
Map of map is just as good as alternatives, like map of pair.
I think it is a good illustration of code being suprising,
but perhaps I am doing a bit too much early optimization :)
See his <a href="https://gist.github.com/Dobiasd/fa27e3efb8b08fc81791d7f8e51ac5ca">benchmark</a>.</p></li>
<li><p>There are ways to do this sort of thing correctly using cryptographic hashes.</p></li>
<li><p>Once again, this is just an example. Switching on type may be perfectly appropriate.</p></li>
</ol>

]]>
</description>
</item>
<item>
<pubDate>Sun, 13 Jan 2019 00:00:00 +0000</pubDate>
<title>McCulloch &amp; Pitts Neural Net Simulator</title>
<guid isPermaLink="true">https://www.jmeiners.com/neural-nets-sim/</guid>
</item>
<item>
<pubDate>Sat, 05 Jan 2019 00:00:00 +0000</pubDate>
<title>An Adventure in Pre-Rendered Backgrounds</title>
<guid isPermaLink="true">https://www.jmeiners.com/pre-rendered-backgrounds/</guid>
</item>
<item>
<pubDate>Sun, 16 Dec 2018 00:00:00 +0000</pubDate>
<title>Write your Own Virtual Machine</title>
<guid isPermaLink="true">https://www.jmeiners.com/lc3-vm/</guid>
<description>Write your own virtual machine for the LC-3 computer!</description>
</item>
<item>
<pubDate>Thu, 19 Apr 2018 00:00:00 +0000</pubDate>
<title>Lisp Interpreter</title>
<guid isPermaLink="true">https://github.com/justinmeiners/lisp-interpreter</guid>
</item>
<item>
<pubDate>Sat, 27 Jan 2018 00:00:00 +0000</pubDate>
<title>Spherical Harmonics</title>
<guid isPermaLink="true">https://github.com/justinmeiners/spherical-harmonics</guid>
</item>
<item>
<pubDate>Thu, 01 Jun 2017 00:00:00 +0000</pubDate>
<title>Shamans: A 3D Turn-based Strategy Game</title>
<guid isPermaLink="true">https://www.jmeiners.com/shamans/</guid>
</item>
<item>
<pubDate>Mon, 01 May 2017 00:00:00 +0000</pubDate>
<title>Modern OpenGL</title>
<guid>https://www.jmeiners.com/modern-opengl/</guid>
<link>https://www.jmeiners.com/modern-opengl/</link>
<description>
<![CDATA[
<h2>Modern OpenGL</h2>

<p>These are notes sent to a friend, not a formal article.
I thought they might be useful for others as well.</p>

<p><strong>05/01/2017</strong></p>

<p>If you&rsquo;re looking for an easy way to do 3D its probably <a href="https://developer.apple.com/documentation/scenekit">SceneKit</a> or Unity,
but I assume you want to learn how things work.</p>

<p>Everything you know and love in OpenGL is gone. <code>glTranslate</code>, <code>glLookAt</code>, <code>glRotate</code>, <code>glVertex</code>, <code>glLight</code>, etc.
The reasoning is that these all describe a specific way of doing things, and OpenGL wanted to be as general as possible so that you can make whatever you want.</p>

<p>For example <code>glLight</code> has a built in algorithm for lighting. What if you want to make your own? You can’t.</p>

<p>The solution is to make everything programmable. Instead of having fixed GPU procedures, the GPU becomes flexible so you can write code which runs on the GPU that replaces the fixed procedures.
These programs are called shaders.</p>

<h2>Shaders</h2>

<p>There are two kinds of shaders you need to worry about.</p>

<p><strong>Vertex Shader:</strong> takes input data, outputs vertex information (position, color, etc)</p>

<p>The outputs from this vertex shader are interpolated across the triangle (or line) you are drawing, and the results are inputed into the fragment shader.</p>

<p><strong>Fragment Shader:</strong> takes input data, and interpolated vertex information, and outputs a color.</p>

<p>Shaders are written in a C like language and compiled into native GPU code.
I would say the first thing you need to do is practice writing some shaders, so you can get an idea of what data you need to give them.</p>

<p>The modern OpenGL API has been totally stripped down. It basically consists of creating shaders, providing them with data, and executing them.
That is it. There is nothing else in OpenGL.</p>

<h2>Data</h2>

<p>So here is the kind of data you need to prepare for OpenGL. This is done in your main code.</p>

<h3>vertex positions, vertex colors, vertex normals.</h3>

<p>You use vertex buffers to upload this data to the GPU. Basically you can make a vertex struct:</p>

<p><code>
struct vertex
{
    Vec3 position, normal, color
}
</code></p>

<p>and  then describe its structure, and then upload an array of them. You could make one vertex buffer for your sphere and then reuse it for each ball.</p>

<h3>Textures</h3>

<p>You upload images using <code>glTexImage</code>. This APIs has stayed mostly the same as old OpenGL.</p>

<h3>Matrices</h3>

<p>Since OpenGL has no translate, rotate, etc. You need to create your own transformation matrices for every object in the scene.</p>

<p>This has a few components:</p>

<ul>
<li><strong>model matrix</strong> - this is the translation/rotation for each individual model.</li>
<li><strong>view matrix</strong> - this describes the camera in the scene (<code>gluLookAt</code>)</li>
<li><strong>projection matrix</strong> - this is the “3D lense” which projects 3D coordinates onto the 2D screen.</li>
</ul>


<p>Basically you have to calculate all of these yourself, pass them to your vertex shader, and then use them to translate the vertex positions.</p>

<p>Usually the projection and matrices are constant for one draw of the scene, you create them at the beginning and pass them with everything.
Then for each model you need to construct a new model matrix, describing its current state.</p>

<h3>Recommended Resources</h3>

<ul>
<li><a href="https://learnopengl.com/">Learn OpenGL</a></li>
<li><a href="https://paroj.github.io/gltut/">Learning Modern 3D Graphics Programming</a></li>
</ul>

]]>
</description>
</item>
<item>
<pubDate>Thu, 10 Nov 2016 00:00:00 +0000</pubDate>
<title>HoloLens First Impressions</title>
<guid>https://www.jmeiners.com/hololens-impressions/</guid>
<link>https://www.jmeiners.com/hololens-impressions/</link>
<description>
<![CDATA[
<h2>HoloLens First Impressions</h2>

<p><strong>11/10/2016</strong></p>

<p><img src="hl_2.jpg" alt="HoloLens" /></p>

<p>At work, I recently started on a new medical application for the <a href="https://www.microsoft.com/microsoft-hololens/en-us">Microsoft HoloLens</a>. I don&rsquo;t follow popular technology news, and rarely get excited about new gadgets, but I feel that the HoloLens is a robust platform, with real substance beyond the usual VR gimmicks. In this article I will talk a little bit about my experience with the hardware and development environment, as well as outline some its shortcomings. As the current release is a &ldquo;Developer Edition&rdquo; I hope some of the items will be addressed in the consumer release.</p>

<p>Where the HoloLens succeeds most, is in offering an entirely distinct experience from VR headsets such as the Vive and Occulus. Everyone I have spoken to, who has tried both, immediately agrees the two are like apples and oranges. There is no question that the HTC Vive offers the most immersive graphical experience, but I get the feeling I could actually use the HoloLens for work, education, and other tasks beyond entertainment. The crisp display, is clear and readable, and since it doesn&rsquo;t overwhelm your vision it doesn&rsquo;t feel nauseating. The likelihood, of me setting up a full Vive room setup, to look at a piece of anatomy or the solar system is small, but quickly putting on the HoloLens to view a models from a true 3D perspective is helpful.</p>

<p>Microsoft recommends using Unity to get started with HoloLens development, while also providing native C++ and Direct 3D. Initially. using Unity didn&rsquo;t excite me, but the it ends up working fairly well. Unity has a specific version of its engine adapted for HoloLens. This includes APIs and components for accessing the room scanning, world anchors, gestures, and voice controls. Once a build is exported from Unity, you can run, debug, and write code all in Visual Studio, until you need to modify the scene. The HoloLens can connect directly through USB or the WiFi for debugging. Microsoft has solid <a href="https://developer.microsoft.com/en-us/windows/holographic/documentation">documentation</a> and tutorials to help you figure everything out.</p>

<p>The voice controls are excellent, and easy to develop for. While in my quiet office, I have never had it mistake me for simple commands such as &ldquo;back&rdquo; and &ldquo;select&rdquo;. I&rsquo;ll even admit to working with food stuffed in my mouth, and it still recognized my commands about half the time. Speaking commands to yourself is still as embarrassing as it sounds (less so than shouting at your phone), but the technology is solid, and I believe there is potential here. Development for voice controls is a pleasant process as well. In Unity you can simply register phrases you would like to listen for, and receive callbacks when they are spoken.</p>

<p>The most noticeable limitation is the small field of view. Even though the glasses surround almost your whole vision, the displayable portion takes up only a small rectangular box at the front of your vision. This means that any objects larger than a basketball get chopped off while standing only a few feet away. This ugliness is most noticeable when a large model fills the whole viewing rectangle, leaving everything outside blank. It looks as if you are looking at the world through an open cereal box. Unfortunately, I can&rsquo;t show you what this looks like in a screenshot.</p>

<p><img src="cutoff_screen.jpg" alt="viewport" /></p>

<p>The gesture controls aren&rsquo;t terrible, but still feel clunky. It takes a little bit of time to master, and then it&rsquo;s sort of like having a mouse that fails to click every tenth time. They are made worse when other people are nearby to distract the sensor.</p>

<p>Since the entire system is contained within the headset, its GPU is more comparable to a mobile phone than a desktop machine. While not weak, the hardware feels a bit under powered. The frame rate cuts to about 30 frames, with roughly 50k triangles across 25 draw calls. I don&rsquo;t expect a ton here, but a bit faster would be nice. In my experience an iPad 2 has better GPU performance, but probably does a lot less background work. Given that I only tested in Unity, it is possible that using native C++ and Direct X would be a dramatic improvement. If you are using Unity be sure to use the optimized shaders found in <a href="https://github.com/Microsoft/HoloToolkit-Unity">Microsoft&rsquo;s Holokit</a>, and be conscious of batches.</p>

<p>The shortcomings above can hopefully be addressed in future iterations of the hardware. In its current form, it is still a fundamentally innovative platform and I am excited to continue developing for it.</p>
]]>
</description>
</item>
<item>
<pubDate>Sun, 30 Oct 2016 00:00:00 +0000</pubDate>
<title>3D Paint</title>
<guid>https://www.jmeiners.com/3d-paint/</guid>
<link>https://www.jmeiners.com/3d-paint/</link>
<description>
<![CDATA[
<h2>3D Paint </h2>

<p><strong>10/30/16</strong></p>

<p>In 2012 I came across the paper <a href="http://zurich.disneyresearch.com/OverCoat/">OverCoat: An Implicit Canvas for 3D Painting</a>
which describes a technique for creating 3D models using traditional painting methods.
At the time I didn&rsquo;t have sufficient mathematical knowledge
to understand all of the technical details described, but I picked up the general idea and wrote my own rough implementation.
This article explains how my program was constructed and some of what I learned in the process.</p>

<p><img src="anim.gif" alt="3d paint gif" /></p>

<p>The basic idea is to paint 3d strokes onto a rough 3D model which acts as a canvas.
The model is simply rotated to a desired orientation, and drawn upon, as if one was painting ontop of a flat a picture.
The difference is that the strokes are projected into 3D space giving them their own 3D form.</p>

<p>The model is only a placeholder which is eventually removed, leaving only the painting made up of strokes.
To position the nodes which define a stroke, my program simply performed a ray-triangle test between the mouse ray and the mesh, and offset the intersection point by the face normal.
The paper describes a sophisticated optimization method which evenly distributes stroke nodes, even across harshes changes in depth.</p>

<p><img src="screen1.jpg" alt="screen 1" /></p>

<p>The image above shows several strokes projected onto the surface of the model.
Along with the node positions, information such as a color and brush size are stored for each stroke.</p>

<p>I used the following data structures:</p>

<pre><code>typedef struct
{
    Vec4_t color;
    int brush;
    float pressure;
} StrokeInfo_t;

typedef struct
{
    Vec3_t pos;
    float radius;
} StrokeNode3D_t;

typedef struct
{
    int nodeCount;
    StrokeNode3D_t nodes[MAX_STROKE_NODES];
    Vec4_t color;
    // used for depth sorting
    Vec3_t center;
    StrokeInfo_t info;
} Stroke3D_t;

typedef struct
{
    int strokeCount;
    Stroke3D_t strokes[MAX_STROKES];
    int dirty;
} Canvas3D_t;
</code></pre>

<p><img src="screen2.jpg" alt="screenshot 2" /></p>

<p>To render the strokes, each node position is transformed from 3D onto the 2D screen, using the camera matrix. The brush image is then rendered onto the framebuffer at each of the 2D node positions on the screen. Even though these screenshots show only a few colors and a single brush, the program supports multiple brush types and RGB colors.</p>

<p><img src="screen4.jpg" alt="screenshot 4" /> <img src="screen3.jpg" alt="screenshot 3" /></p>

<p>As the drawing becomes more dense, the strokes begin to resemble their own shape.
Rendering strokes is a very efficient process because it only involves stamping the brush image in 2D, which is easily parallelized on the GPU.
For the strokes to be drawn in the correct order they must be sorted by depth. This is by far the most computational expensive part of the process.
My program solved this problem by only sorting strokes by their average position, which seemed to be an acceptable alternative to sorting each node.
The order in which the nodes of a stroke are rendered is still important to ensure proper layering. An offline rendering process should sort each node properly.</p>

<p><img src="screen5.jpg" alt="screenshot 5" /> <img src="screen6.jpg" alt="screenshot 6" /></p>

<p>Although my program cannot produce the beautiful paintings found in the original paper, it can still draw some fun pictures.
I think the technique itself is very interesting and has great potential. It would be interesting to make a small game, or animation centered around the technique since the artwork is so easy and natural to produce.
Because it requires no textures, other than the small brushes, its memory usage is also very small, while its vertex requirements are similar to triangle meshes.
The next natural step would be to bind a painting to a skeleton for animation.</p>
]]>
</description>
</item>
<item>
<pubDate>Thu, 15 Oct 2015 00:00:00 +0000</pubDate>
<title>Old Artwork</title>
<guid>https://www.jmeiners.com/old-artwork/</guid>
<link>https://www.jmeiners.com/old-artwork/</link>
<description>
<![CDATA[
<h2>Old Artwork</h2>

<p><strong>10/15/2015</strong></p>

<p>I am not much of a visual artist, but I still enjoy 3D modeling and animation. This page contains pictures of some of my older models I have worked on.</p>

<h3>Moon Rover</h3>

<p><span><img src="rover1.png" alt="moon rover 1" /> <img src="rover2.png" alt="moon rover 2" /></span></p>

<h3>Low-poly Cargo Ship</h3>

<p><span><img src="cargo_ship1.png" alt="cargo ship 1" /> <img src="cargo_ship2.png" alt="cargo ship 2" /></span></p>

<p><span><img src="cargo_ship4.png" alt="cargo ship 4" /> <img src="cargo_ship3.png" alt="cargo ship 3" /></span></p>

<h3>Space Invader Sculpt</h3>

<p>While working at Infuse Medical, I taught a course on 3D programming with OpenGL. As part of my course we created a small space invaders clone. Another developer created the low-poly model for the alien, which I use to create the high resolution sculpt shown below. Occlusion maps were generated from the sculpt for the game.</p>

<p><span><img src="space_invaders1.png" alt="alien 1" /> <img src="space_invaders2.png" alt="alien 2" /></span></p>

<p><span><img src="space_invaders_ipad1.png" alt="space invaders ipad" /> <img src="space_invaders_ipad2.png" alt="space invaders ipad" /></span></p>

<h3>Low-poly Radio</h3>

<p><span><img src="radio1.png" alt="radio 1" /> <img src="radio2.png" alt="radio 2" /> <img src="radio3.png" alt="radio 4" /></span></p>

<h3>Pixel Art</h3>

<p><span>
<img width="200" style="image-rendering: pixelated;" alt="knight pixel art" src="knight_pixel.png"/>
<img width="200" style="image-rendering: pixelated;" alt="alien pixel art" src="alien_pixel.png"/>
<img width="200" style="image-rendering: pixelated;" alt="rocket pixel art" src="rocket_pixel.png"/>
<img width="200" style="image-rendering: pixelated;" alt="owl pixel art" src="owl.png"/>
</span></p>

<h3>Another Ship</h3>

<p><img src="another_ship.png" alt="another ship" /></p>
]]>
</description>
</item>
<item>
<pubDate>Fri, 09 Oct 2015 00:00:00 +0000</pubDate>
<title>Old Games</title>
<guid>https://www.jmeiners.com/old-games/</guid>
<link>https://www.jmeiners.com/old-games/</link>
<description>
<![CDATA[
<h2>Old Games</h2>

<p><strong>10/09/2015</strong></p>

<p>I spent quite a bit of time experimenting with game technology when I was first learning how to program. I played with tons of ideas, many of which turned out to be no good, but I learned a ton about graphics and development in the process.</p>

<p><img src="minecraft.jpg" alt="minecraft clone screenshot" /></p>

<p>An extremely fast minecraft clone. Written in C and OpenGL.</p>

<p><img src="lightmap.jpg" alt="lightmap screenshot" /></p>

<p>I wrote my own lightmapper and UV unwrapper in Objective-C.</p>

<p><img src="asteroids.jpg" alt="asteroids screenshot" /></p>

<p>A small demo for a sci-fi adventure game engine. Written in C and OpenGL.</p>

<p><img src="ocean.jpg" alt="ocean screenshot" /></p>

<p>An adventure game in which players explore the ocean. One feature I like allows the player to take a picture and store it in an album. The game recognizes which fish are in the picture so it can reward them for collecting them all.</p>

<p><img src="platform.jpg" alt="platform screenshot" /></p>

<p>An action platform game where players avoid obstacles by jumping and running up walls.</p>

<p><img src="restock.jpg" alt="restock screenshot" /></p>

<p>A puzzle game I created for a school competition. Written in C++ and OpenGL.</p>

<p><img src="shooter.jpg" alt="shooter screenshot" /></p>

<p>A platform shooter game.</p>

<p><img src="strategy.jpg" alt="strategy screenshot" /></p>

<p>A prototype of a strategy game for iOS.</p>
]]>
</description>
</item>
<item>
<pubDate>Tue, 20 Aug 2013 00:00:00 +0000</pubDate>
<title>C Craft</title>
<guid isPermaLink="true">https://github.com/justinmeiners/c-craft</guid>
</item>
<item>
<pubDate>Tue, 02 Jul 2013 00:00:00 +0000</pubDate>
<title>Image Sequence Streaming</title>
<guid isPermaLink="true">https://github.com/justinmeiners/image-sequence-streaming</guid>
</item>
<item>
<pubDate>Tue, 08 Jan 2013 00:00:00 +0000</pubDate>
<title>iOS Color Wheel</title>
<guid isPermaLink="true">https://github.com/justinmeiners/ios-color-wheel</guid>
</item>
</channel>
</rss>
