<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://michvalwin.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://michvalwin.com/" rel="alternate" type="text/html" /><updated>2025-11-19T21:18:44+01:00</updated><id>https://michvalwin.com/feed.xml</id><title type="html">MichValwin website</title><subtitle>Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.</subtitle><entry xml:lang="en"><title type="html">PC parts shenanigans</title><link href="https://michvalwin.com/opinion/2025/07/17/pc-part-shenanigans.html" rel="alternate" type="text/html" title="PC parts shenanigans" /><published>2025-07-17T19:00:00+02:00</published><updated>2025-07-17T20:44:40+02:00</updated><id>https://michvalwin.com/opinion/2025/07/17/pc-part-shenanigans</id><content type="html" xml:base="https://michvalwin.com/opinion/2025/07/17/pc-part-shenanigans.html"><![CDATA[<script>
	EXECUTE_ON_LOAD = function() {
		
	}
</script>

<h1 id="new-pc-parts-shenanigans">New PC parts shenanigans</h1>
<div class="article-date">Last time modified: 17 Jul, 2025</div>
<p><br />
I f***** hate buying computer parts these days. 
From 8-9 years or so I’ve had a good <strong>i7-6700k</strong> as a cpu. It did well for gaming, programming and so on, but the recent games are just
too much for him. Helldivers puts the cpu usage to 80% always (although with a constant 60fps), MHWilds is heavily bottlenecked by this cpu. I get 30-40fps max.
This is all after disabling windows antivirus, and a lot of services.
<br />
So because of that and since I have enough money I decided to <strong>GO BIG</strong> and buy the latest 9950X3D.
I’ve being waiting 3 months since its release for the problems it has on some Mobas (the Asrock ones and some Asus), but I decided to just buy one and buy every part on discount to build
THE PC.
<br />
<br />
A 9950X3d. An Asus X870E pro art, 2x48GB 6000 1.4V for ram. A freaking full tower case to put two GPU’s someday if I want to run a big LLM or something like that.
1200W of Corsair 80Platinum PSU. And a NH-D15 G2 so I never have to worry about cooling.
But you see, the ram wasn’t in the compatibility list for the moba…
FFS 1 month later and the PC doesn’t shut down. “Weird…” I said. “Well I’ll check if it boots up after forcefully shutting down it…” It never boots up.
The yellow light of the Moba indicates a DRAM problem. “I just need to remove a stick…”, still nothing. “I’ll swap them”, still nothing. “I’ll clear the cmos”, nope. “I’ll remove the battery and wait 1h” Nooope. “I’ll update the bios to the latest one”, also nope. “ILL RMA THE MOBA” <strong>NOOOPE</strong>.
Guess it’s the cpu. (I also know it’s not the RAM because I bought 2 sticks that are compatible with the moba).
<br /></p>
<hr />
<p><br />
And so I’m here waiting for the online store where I bought the cpu to come back online to <strong>RMA</strong> it. I kinda <strong>feel scammed</strong> after buying all of these premium components to just have the cpu dead in a month.
I feel like if I hadn’t spent that much money on a MOBA, CPU and RAM I wouldn’t be here, and also I would have had 600€ more or so. It’s kinda depressing that for every new CPU, GPU on the market we have to wait a full 6-12 months just so they patch everything right. Just look at what happened to the 13th and 14th intel cpu’s, they’re all dying because they clearly didn’t test them well. Or worse yet, they knew that would happened and they just went for it just so they could say that their CPUS were the best for gaming.
Maybe it’s not the case and it’s just me getting ram that is not in the compatibility list for my MOBA. 
<br /> 
<br />
I’m not a systems engineer, nor I work mounting computers. But I’ve never seen a cpu dying on normal use. I even think <strong>you can buy a 10 year old cpu and run it for years</strong>. But I’m not sure of that anymore.
<br />
The first thing that I did to my system was checking the RAM with memtest86+ and checking if the cpu and ram were stable. They were on a 1h run for prime95 and Aida. Then I thought that 5.7Ghz was a bit too much so I went and set the PBO to -500mhz, so the cpu doesn’t go more than 5.2. But yeah probably the 1.4V of ram is just too much for the memory controller of the cpu.
<br />
<br />
This post is just me shouting to the void for my clear mistake and to say that I really hate waiting a year for the drivers/bios/HW fixes that should be present since the product comes out.</p>

<p>Anyway, I’ll update this post when I receive a new CPU, until then my good ‘ol 6700k is going to work overtime.</p>

<p><br /></p>
<hr />
<h4 id="note">Note:</h4>
<p>Also, I tested the new moba with an old PSU that had only one CPU 8pin cable. It’s kinda weird because some of the fans didn’t turn on, but I still got a yellow light after waiting 15 min (waiting for ram training or something like that IDK)</p>

<p><br /></p>]]></content><author><name></name></author><category term="opinion" /><summary type="html"><![CDATA[Hating new shiny pc parts things]]></summary></entry><entry xml:lang="en"><title type="html">Raylib and collision response</title><link href="https://michvalwin.com/devblog/2024/01/27/blog02.html" rel="alternate" type="text/html" title="Raylib and collision response" /><published>2024-01-27T17:00:00+01:00</published><updated>2024-01-28T14:22:37+01:00</updated><id>https://michvalwin.com/devblog/2024/01/27/blog02</id><content type="html" xml:base="https://michvalwin.com/devblog/2024/01/27/blog02.html"><![CDATA[<script>
	EXECUTE_ON_LOAD = function() {
		
	}
</script>

<h1 id="raylib-and-collision-response">Raylib and collision response</h1>
<div class="article-date">Last time modified: 28 Jan, 2024</div>
<p><br />
It’s been more than a month without doing one of these. Anyway lets start<br /></p>

<p>I’ve decided to <strong>ditch</strong> my game engine (or just the rendering and sound part of it), and just use <strong><code class="language-plaintext highlighter-rouge">Raylib</code></strong>.
It’s way better than what I was doing and also it compiles without any problem in linux and windows.<br />
So I scrap everything that I could use for the game into a new project.<br />
And 20 days or so later I have everything drawn on the screen like in the older proyect and with some collisions.</p>

<hr />
<h2 id="collisions-swept-aabb">Collisions (swept AABB)</h2>
<p>For the collisions, I launch a ray that goes from the center of the player and collides with the possible colliders that happen in a given frame.<br />
<br />
The bounds of each collider are expanded according to the width and height of the player’s collisions (Minkowski difference). With this setup, we only need to use the Raylib’s built-in ray collision check and we get the collision point where the player should go.<br />
<br />
But when it comes to response, this falls flat. Because in a 2D platformer we need to conserve our velocity in the X axis when we are walking. This method will anchor the player to the ground.<br />
To get a good response, I check for collisions 2 times. And instead of setting the velocity to 0 in each axis. I only set it when the normal of the collision in that axis is different to 0.<br />
So <strong>When the player collides with the ground (Y axis). I put the velocity of Y to 0 leaving the movement in X unchanged</strong>.<br />
This way we can react to walls and the ground as expected in a 2d platformer.<br />
<br />
But what if there was a corner?. In this case we got a collision in two axis and we must determine what velocity axis we need to zero out. This corner could be on a wall, in which we know we must zero the X axis. But it could also be on a flat ground. Or even on the corner of a wall.<br />
<br />
So, to implement this I make an assumption that the player can continue moving in the X axis. So, I zero out the Y axis and check for collisions again. If the next collision does not occur or occurs at a distance that is more than 0, we know we can continue in this direction. Otherwise, if there is a collision at a distance of 0, It means we cannot go in X direction. Therefore the X velocity needs to be zero.<br />
And after this we can continue with the 2º collision check.<br />
<br /></p>

<p>Though I didn’t check the performance, it’s probably bad because of all the calculations needed to raycast to an AABB. And moreso, doing it 20 times or so per frame. While 
<br /></p>

<p>Anyway, here is a video of the collision response in action. Although there are no physics per se, so the movement is weird.</p>

<div class="flex-center">
	<video controls="">
		<source src="/assets/videos/2024-01-26.webm" type="video/mp4" />
	</video>
</div>
<p><br /></p>]]></content><author><name></name></author><category term="devblog" /><summary type="html"><![CDATA[Collisions]]></summary></entry><entry xml:lang="en"><title type="html">First devlog, part 2. Collision failures</title><link href="https://michvalwin.com/devblog/2023/12/15/blog01.html" rel="alternate" type="text/html" title="First devlog, part 2. Collision failures" /><published>2023-12-15T18:00:00+01:00</published><updated>2023-12-15T19:50:09+01:00</updated><id>https://michvalwin.com/devblog/2023/12/15/blog01</id><content type="html" xml:base="https://michvalwin.com/devblog/2023/12/15/blog01.html"><![CDATA[<script>
	EXECUTE_ON_LOAD = function() {
		
	}
</script>

<h1 id="deadlines-what-deadlines">Deadlines? What deadlines?</h1>
<div class="article-date">Last time modified: 15 Dec, 2023</div>
<p><br />
Hello again. This is going to be a very short one. And you know why.<br />
Naturally, I did not deliver on everything that I said last week.</p>

<div class="flex-center">
	<video controls="">
		<source src="/assets/videos/2023-12-15.webm" type="video/mp4" />
	</video>
</div>
<p><br /></p>

<p>Here you can see a line being draw for every full collision on the map, and also the player bounds.
Some of the map layers are correctly tinted and some aren’t.
And of course, <strong>my collision algorithm doesn’t work</strong>.</p>

<hr />

<p>My Idea for the collision map, is to use 1Byte for each tile to <strong>store the type of collision in each one</strong>.
For now, <strong><code class="language-plaintext highlighter-rouge">0</code></strong> means there is no collision. <br />
<strong><code class="language-plaintext highlighter-rouge">1</code></strong> means full collision.
I’m still unsure on what to do with the types. Probably I’ll use a type alias for this, so I can change the size later.
Because I want to use the minimum amount of space to store the collisions. But to do that, I need at least 4 numbers.
And I don’t think I can cram 4 numbers, even if they are just from 0 to 10 in 7bits.
Here is an example:</p>
<div class="flex-center">
	<img src="/assets/images/posts/2023-12-15_19-17.png" width="400" />
</div>
<p><br />
In this one we have a tile in blue that has two empty pixels on it’s left.<br />
For me this tile has a <strong>negative X offset</strong> of two pixels.
Extending this logic we could have positive offsets in X and also the two in the Y range.
For now, I’m going to map it to each one as an index. Since I don’t think (currently) we are using all of this types.</p>

<p>For the next week I’m planning on just finish the collision and implement the collisions for the non-full blocks.
That should be easy enough to finish it in time, and also, refactor a little bit of the code.</p>]]></content><author><name></name></author><category term="devblog" /><summary type="html"><![CDATA[Failure comes in the most expected ways]]></summary></entry><entry xml:lang="en"><title type="html">First devblog</title><link href="https://michvalwin.com/devblog/2023/12/08/blog00.html" rel="alternate" type="text/html" title="First devblog" /><published>2023-12-08T18:00:00+01:00</published><updated>2023-12-08T19:30:00+01:00</updated><id>https://michvalwin.com/devblog/2023/12/08/blog00</id><content type="html" xml:base="https://michvalwin.com/devblog/2023/12/08/blog00.html"><![CDATA[<script>
	EXECUTE_ON_LOAD = function() {
		
	}
</script>

<h1 id="the-game-engine-and-more">The game, engine and more</h1>
<div class="article-date">Last time modified: 08 Dec, 2023</div>
<p><br />
Hey there!. welcome to my first post of my dev blog thingy.</p>

<p>I’ve been working on a tiny game for like some months now. But because I’m reeeeeeeally lazy I’ve always keep delaying features
for the game. So I’m starting this blogs to make a deadline for myself to deliver at least a little bit of content or just to improve the code week by week
(And also to practice English writing). And of course, what a better day to write them than fridays (Inspired by factorio’s blogs).
So, in summary these blogs are a way for me to keep track of what I’m doing and also keep myself away from laziness.</p>

<p>So this game is just a normal 2D platformer. Nothing more nothing less. It’s the same game than this one: <a href="https://www.youtube.com/watch?v=CGlKr_4GSkI">youtube trailer</a>  That I tried making in Java, and ultimately failed and burn myself
out. Making a game (even a simpler one like a platformer) in java without game knowledge. Only knowing OOP and also not knowing simple programming practices, tricks and patterns
is  <strong><em>bad</em></strong>. At least you’ll need to have a lot of willpower to succeed or plan everything from the beginning.</p>

<p>Anyway, here I am trying to make the same game with as little as possible in C++ and OpenGL.
I am currently using libraries like <strong><code class="language-plaintext highlighter-rouge">stb_image</code></strong> for loading images, <strong><code class="language-plaintext highlighter-rouge">OpenAL</code></strong> for sounds, <strong><code class="language-plaintext highlighter-rouge">freetype</code></strong> to load fonts, <strong><code class="language-plaintext highlighter-rouge">cute_tiled</code></strong> to load maps from “tiled” maps (.tmx from tiled program). And finally <strong><code class="language-plaintext highlighter-rouge">Flecs</code></strong>.
In the beginning I did try to make my own ECS, but I’m clearly not that good. Then I try using and remaking one from a SFML book. But this one was too slow. So in the end I opted for Flecs. I think is good enough and it’s fast enough for my needs (actually is waaay faster than I thought it was). I guess, if I ever need better performance I’ll just hardcode everything in a DOD way.</p>

<div class="flex-center">
	<video controls="">
		<source src="/assets/videos/2023-12-08.webm" type="video/mp4" />
	</video>
</div>

<p>So here you can see the game in action right now. There is only the player and the tiles drawing in the background (notice how it is not drawing some tiles due to a bug in my camera implementation).
For the next friday I want to make the next implementations:</p>
<ul>
  <li><strong>Make the map darker</strong> to resemble night time. –&gt; Add one an ambient color to each layer of the map.</li>
  <li>Add the <strong>collisions</strong> to the player –&gt; Add an array of collisions, probably 1Byte per tile because I could store which type of collision is.</li>
  <li>Create a directory  or a path to get all the <strong>sprites and animations together</strong> so I can add more to a texture pack easily.</li>
</ul>

<p>And that’s it. If I end up implementing something else, then that’s a bonus.</p>

<p>Bye!</p>]]></content><author><name></name></author><category term="devblog" /><summary type="html"><![CDATA[First devblog of my game (Neitin studios game)]]></summary></entry><entry xml:lang="en"><title type="html">Optimizing FizzBuzz to the max</title><link href="https://michvalwin.com/devposts/2023/09/02/ultimate-fizz-Buzz.html" rel="alternate" type="text/html" title="Optimizing FizzBuzz to the max" /><published>2023-09-02T17:00:00+02:00</published><updated>2025-07-17T11:13:54+02:00</updated><id>https://michvalwin.com/devposts/2023/09/02/ultimate-fizz-Buzz</id><content type="html" xml:base="https://michvalwin.com/devposts/2023/09/02/ultimate-fizz-Buzz.html"><![CDATA[<script>
	EXECUTE_ON_LOAD = function() {
		
	}
</script>

<h1 id="optimizing-fizz-buzz">Optimizing Fizz Buzz</h1>
<div class="article-date">Last time modified: 17 Jul, 2025</div>
<p><br /></p>

<p>NOTE:
I’m not a professional C/C++ or assembly programmer so probably the following solutions could be much better.
And a lot of times I’m making uneducated guesses without proper profiling.
All of this programs have been measured in my current computer (i7-6700k - 3200Mhz RAM speed).
And all of them have been compiled with GCC version 13.1.1 using -O3 unless stated otherwise.</p>

<p>I’ll start defining our starting program. One which we know it’s output is completely correct.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;cstdio&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;cstdint&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;functional&gt;</span><span class="cp">
</span>
<span class="k">static</span> <span class="n">constexpr</span> <span class="kt">uint32_t</span> <span class="n">ITERATIONS</span> <span class="o">=</span> <span class="mi">500000000</span><span class="p">;</span> 

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">accum</span><span class="p">;</span>

	<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">ITERATIONS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">if</span><span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">"fizzbuzz "</span><span class="p">;</span>
		<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">"fizz "</span><span class="p">;</span>
		<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">"buzz "</span><span class="p">;</span>
		<span class="p">}</span><span class="k">else</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">" "</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">subs</span> <span class="o">=</span> <span class="n">accum</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">accum</span><span class="p">.</span><span class="n">length</span><span class="p">()</span><span class="o">-</span><span class="mi">20</span><span class="p">,</span> <span class="mi">20</span><span class="p">);</span>
	<span class="n">printf</span><span class="p">(</span><span class="s">"%s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">subs</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
	<span class="cp">#ifdef INFO_MODE
</span>		<span class="n">printf</span><span class="p">(</span><span class="s">"Total size string: %ld</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">accum</span><span class="p">.</span><span class="n">length</span><span class="p">());</span>
		<span class="n">printf</span><span class="p">(</span><span class="s">"HASH: %ld</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">{}(</span><span class="n">accum</span><span class="p">));</span>
	<span class="cp">#endif
</span>
	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>

</code></pre></div></div>
<p>As you see we are printing the last 20 characters of the fizzBuzz.
Also if we declare <strong><code class="language-plaintext highlighter-rouge">INFO_MODE</code></strong> at compile time. It will make a hash of the entire string and print it. This serves me well when checking if the solution is correct in the following iterations. Also, for debugging I set <strong><code class="language-plaintext highlighter-rouge">-fsanitize=address</code></strong> to check for memory errors (It saved me a few times on this journey).</p>

<p>The, first speed up we can make is just by <strong>reserving</strong> memory for our <strong>string</strong>.</p>
<pre><code class="language-C++">accum.reserve(ITERATIONS*8);
</code></pre>
<p>Although I’m wasting a lot of space. This should give us the space necessary to store all of the fizz buzz string.
With this we get a speed <strong>improvement of 8-9%</strong>.</p>

<p><br /></p>

<h3 id="encoding-decision">Encoding decision</h3>
<p>The second thing to optimize is the number of modulo operations and if jumps.
We could try to remove one modulo operation by <strong>encoding</strong> them in one integer variable.</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">ITERATIONS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
		<span class="kt">uint8_t</span> <span class="n">encode</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
		<span class="n">encode</span> <span class="o">+=</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="mi">2</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>

		<span class="k">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">" "</span><span class="p">;</span>
		<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">"fizz "</span><span class="p">;</span>
		<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">"buzz "</span><span class="p">;</span>
		<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">accum</span> <span class="o">+=</span> <span class="s">"fizzbuzz "</span><span class="p">;</span>
		<span class="p">}</span>
	<span class="p">}</span>
</code></pre></div></div>
<p>Not only we remove one modulo operation in the worst case, but also give GCC a lot of hints to optimize this sequence.
Although I couldn’t get a significant speed improvement. Some test show a <strong>2% improvement</strong>. Others show none at all.</p>

<p><br /></p>

<h3 id="custom-string">Custom String</h3>
<p>Next we could consider that the string concatenation is probably very slow. I’m sure the string concatenations checks if it needs more space to store all of the string. We don’t need any checks because we know that everything is going ot fit in our pre-reserved String.
So our next point should be creating a simple <strong><code class="language-plaintext highlighter-rouge">struct</code></strong> to store and concatenate the fizz buzz.</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="nc">CustomString</span> <span class="p">{</span>
	<span class="kt">char</span><span class="o">*</span> <span class="n">string</span><span class="p">;</span>
	<span class="kt">size_t</span> <span class="n">total_size_reserved</span><span class="p">;</span>
	<span class="kt">size_t</span> <span class="n">position_null_char</span><span class="p">;</span> <span class="c1">// End of string</span>

	<span class="kt">void</span> <span class="n">initialize</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">size_bytes</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">string</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="n">size_bytes</span><span class="p">);</span>
		<span class="n">string</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
		<span class="n">total_size_reserved</span> <span class="o">=</span> <span class="n">size_bytes</span><span class="p">;</span>
		<span class="n">position_null_char</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="kt">void</span> <span class="nf">concat</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">str_to_concat</span><span class="p">)</span> <span class="p">{</span>
		<span class="kt">size_t</span> <span class="n">length</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">strlen</span><span class="p">(</span><span class="n">str_to_concat</span><span class="p">);</span>

		<span class="n">memcpy</span><span class="p">(</span><span class="n">string</span><span class="o">+</span><span class="n">position_null_char</span><span class="p">,</span> <span class="n">str_to_concat</span><span class="p">,</span> <span class="n">length</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// length+1 to include null terminator</span>
		<span class="n">position_null_char</span> <span class="o">=</span> <span class="n">position_null_char</span><span class="o">+</span><span class="n">length</span><span class="p">;</span>
	<span class="p">}</span>

	<span class="kt">void</span> <span class="nf">concat</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">str_to_concat</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">length</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">memcpy</span><span class="p">(</span><span class="n">string</span><span class="o">+</span><span class="n">position_null_char</span><span class="p">,</span> <span class="n">str_to_concat</span><span class="p">,</span> <span class="n">length</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// length+1 to include null terminator</span>
		<span class="n">position_null_char</span> <span class="o">=</span> <span class="n">position_null_char</span><span class="o">+</span><span class="n">length</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<p>With this we get a nice <strong>6-8%</strong> improvement in speed.</p>

<h3 id="remove-modulo-operations">Remove modulo operations</h3>
<p>Now we could try to remove those bad modulo operations. The only thing that occurs me right now is to just having <strong>two counters</strong>.
One for <strong>3</strong> and another for <strong>5</strong>. So when we hit ‘3’ in one counter, we know it’s divisible by 3. Same goes for the ‘5’ counter.</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint8_t</span> <span class="n">c3</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">uint8_t</span> <span class="n">c5</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">ITERATIONS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span><span class="p">(</span><span class="n">c3</span> <span class="o">==</span> <span class="mi">3</span> <span class="o">&amp;&amp;</span> <span class="n">c5</span> <span class="o">==</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizzbuzz "</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
		<span class="n">c3</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
		<span class="n">c5</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">c3</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
		<span class="n">c3</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">c5</span> <span class="o">==</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"buzz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
		<span class="n">c5</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
	<span class="p">}</span><span class="k">else</span><span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>
	<span class="n">c3</span><span class="o">++</span><span class="p">;</span>
	<span class="n">c5</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>But again this solution perform more or less equal that our previous solution. Probably because GCC is already optimizing it, or it could be that conditional jumps are more expensive.
So this change is ruled out.</p>

<p><br /></p>

<h3 id="unrolling">Unrolling</h3>
<p>But you know what is faster than making modulo operations and if statements?. Not doing it.
Because we know that Fizz Buzz is a sequence with a length of 15. We can just make those 15 statements, and repeat them until we have cover <strong>(ITERATIONS / 15)</strong>. And Then do the remainder fizz buzz normally until we complete everything.</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint32_t</span> <span class="n">iterToUnroll</span> <span class="o">=</span> <span class="p">((</span><span class="kt">uint32_t</span><span class="p">)(</span><span class="n">ITERATIONS</span> <span class="o">/</span> <span class="mf">15.0f</span><span class="p">))</span> <span class="o">*</span> <span class="mi">15</span><span class="p">;</span>

<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">iterToUnroll</span><span class="p">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">15</span><span class="p">)</span> <span class="p">{</span>
	<span class="c1">// nninuinniuninnf</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 3</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">3</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"buzz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 5</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 6</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">6</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">7</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 9</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"buzz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 10</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">10</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// 12</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">12</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">13</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>

	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizzbuzz "</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span> <span class="c1">// 15</span>
<span class="p">}</span>

<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="n">iterToUnroll</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">ITERATIONS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	<span class="kt">uint8_t</span> <span class="n">encode</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">encode</span> <span class="o">+=</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="mi">2</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>

	<span class="k">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">i</span><span class="p">).</span><span class="n">c_str</span><span class="p">());</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"buzz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizzbuzz "</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This get us an <strong>improvement of 3-4%</strong>. Not much of an improvement. This proves that the compiler was already unrolling the loop.
But It seems this solution gives the compiler more headroom to optimize.</p>

<p><br /></p>

<h3 id="custom-int-to-string">Custom int to String</h3>
<p>After all of this I don’t see anything to optimize for the exclusion of <strong><code class="language-plaintext highlighter-rouge">std::to_string</code></strong>.
Let’s see a flamegraph about the program with the last optimization.</p>

<div style="width:500; overflow-x: hidden;">
	<div style="overflow-x: scroll;">
		<img src="/assets/images/fizzbuzz/perfLoopUnroll.svg" width="4000" />
	</div>
</div>

<p>In this very long flamegraph whe can see that calling <strong><code class="language-plaintext highlighter-rouge">std::to_string</code></strong> Is taking a lot of time.
So we could implement our own, with zero safeguards, and a lot of foot-guns.
For this I’ve created three programs to implement the same behavior. I did it for experimentation and because the first program is very, very ugly.
So here is my thought process.</p>

<p>We want to transform an integer to an array of chars. What is the fastest method?. Of course… It’s not doing it at all.
We could just have a buffer and increment the chars of the buffer as it is a decimal number.</p>

<p>So for the <strong>1º Implementation</strong> this was my though:</p>
<ol>
  <li>Have a initially <strong>reserve buffer</strong> that is long enough for the use in our whole application.</li>
  <li>Put a <strong>‘0’ on the first position</strong> and a <strong>null char ‘\0’ on the second</strong>.
    <div class="flex-center">
     <img src="/assets/images/fizzbuzz/begin.png" alt="custom buffer string with 1" width="400" style="image-rendering: pixelated;" />
 </div>
  </li>
  <li>Record the index position of the null char as the last position.</li>
  <li>We can update the buffer by <strong>updating</strong> the character that is the in <strong>the last-1 position</strong>.
    <div class="flex-center">
     <img src="/assets/images/fizzbuzz/9.png" alt="custom buffer string with 9" width="400" style="image-rendering: pixelated;" />
 </div>
  </li>
  <li>If we surpass ‘9’ we update the number accordingly and <strong>we update the current position-1</strong>.</li>
  <li>If the <strong>position is invalid</strong> (position &lt; 0). We <strong>move the entire string one place to the right</strong> and then put a ‘1’ in the first position.
    <div class="flex-center">
     <img src="/assets/images/fizzbuzz/10.png" alt="custom buffer string with 10 Idk how to make a great alt names. But we can see we moved all of the numbers and we put a 1 at index 0" width="400" style="image-rendering: pixelated;" />
 </div>
  </li>
  <li>We continue like this until we have update the whole buffer.</li>
</ol>

<p>Because we don’t need to update the array with numbers that are grater than 3. We don’t need to worry about updating more than one position at a time.</p>

<p>This algorithm works, and it even outclass (by a really small margin) my two other algorithms for some reason that I can’t understand. It is probably because the characters are aligned at the beginning of the string.</p>

<p>The <strong>2º implementation</strong> is just an algorithm that uses modulo 10 and division to get each character from a unsigned int.</p>

<p>The <strong>3º implementation</strong> is like the first but instead of storing the characters that compose our number at the beginning of the buffer. I <strong>store it at the end</strong>. So we don’t need to displace the characters.</p>

<p>And the results against the loopUnroll (with all the other optimizations) are this:</p>
<ol>
  <li>57.99% improvement</li>
  <li>30.25% improvement</li>
  <li>57.48% improvement
As we can see, the first and third implementation are more or less on par. All benchmarks I’ve done suggest that the first implementation is faster than the third one. But for clarity and because simplicity I’ll choose the third implementation from here on out (also the first one is really ugly and it even uses recursion).</li>
</ol>

<p>Here is the whole third implementation:</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="nc">UintInString</span><span class="p">{</span>
	<span class="kt">char</span><span class="o">*</span> <span class="n">string</span><span class="p">;</span>
	<span class="kt">char</span><span class="o">*</span> <span class="n">init_of_number_string</span><span class="p">;</span>
	<span class="kt">size_t</span> <span class="n">position_null_char</span><span class="p">;</span>
	<span class="kt">size_t</span> <span class="n">length</span><span class="p">;</span>

	<span class="kt">void</span> <span class="n">initialize</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">reserve_size</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">string</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="n">reserve_size</span><span class="p">);</span>
		<span class="k">for</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">reserve_size</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">string</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span><span class="p">;</span>
		<span class="p">}</span>

		<span class="n">position_null_char</span> <span class="o">=</span> <span class="n">reserve_size</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
		<span class="n">string</span><span class="p">[</span><span class="n">position_null_char</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'\0'</span><span class="p">;</span>
		<span class="n">length</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
		<span class="n">init_of_number_string</span> <span class="o">=</span> <span class="n">string</span> <span class="o">+</span> <span class="p">(</span><span class="n">position_null_char</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span>
	
	<span class="kt">void</span> <span class="nf">update_add</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="n">num</span><span class="p">)</span> <span class="p">{</span>
		<span class="c1">// CANT UPDATE WITH NUMBERS THAT ARE greater than 9</span>
		<span class="c1">// '0' --&gt; 48</span>
		<span class="c1">// '9' --&gt; 57</span>
		<span class="kt">uint8_t</span> <span class="n">position_char</span> <span class="o">=</span> <span class="n">position_null_char</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
		<span class="kt">uint8_t</span> <span class="n">total_length</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
		<span class="k">while</span><span class="p">(</span><span class="n">num</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="kt">uint8_t</span> <span class="n">lastChar</span> <span class="o">=</span> <span class="n">string</span><span class="p">[</span><span class="n">position_char</span><span class="p">];</span>
			<span class="k">if</span><span class="p">(</span><span class="n">lastChar</span> <span class="o">+</span> <span class="n">num</span> <span class="o">&gt;</span> <span class="sc">'9'</span><span class="p">)</span> <span class="p">{</span>
				<span class="n">string</span><span class="p">[</span><span class="n">position_char</span><span class="p">]</span> <span class="o">=</span> <span class="n">lastChar</span> <span class="o">+</span> <span class="n">num</span> <span class="o">-</span> <span class="mi">10</span><span class="p">;</span>

				<span class="n">position_char</span><span class="o">--</span><span class="p">;</span>
				<span class="n">num</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>

				<span class="n">total_length</span><span class="o">++</span><span class="p">;</span>
				<span class="k">if</span><span class="p">(</span><span class="n">total_length</span> <span class="o">&gt;</span> <span class="n">length</span><span class="p">)</span> <span class="p">{</span>
					<span class="n">length</span> <span class="o">=</span> <span class="n">total_length</span><span class="p">;</span>
					<span class="n">init_of_number_string</span><span class="o">--</span><span class="p">;</span>
				<span class="p">}</span>
			<span class="p">}</span><span class="k">else</span><span class="p">{</span>
				<span class="n">string</span><span class="p">[</span><span class="n">position_char</span><span class="p">]</span> <span class="o">=</span> <span class="n">lastChar</span> <span class="o">+</span> <span class="n">num</span><span class="p">;</span>
				<span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
			<span class="p">}</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<p>With this, we can initialize the buffer and then use <strong><code class="language-plaintext highlighter-rouge">update_add</code></strong> to add a number no greater than 3. And then use <strong><code class="language-plaintext highlighter-rouge">init_of_number_string</code></strong>, and it’s length to concat the buffer to our custom string.</p>

<p>Here is the flamegraph o the third implementation:</p>
<div style="width:500; overflow-x: hidden;">
	<div style="overflow-x: scroll;">
		<img src="/assets/images/fizzbuzz/perfWString3.svg" width="4000" />
	</div>
</div>

<p>Now, the flamegraph is much more clean. 70+ percent of the graph is just our custom concat function.
I’m not really sure how to be faster than <strong><code class="language-plaintext highlighter-rouge">memcpy</code></strong>. Maybe there is a way, but for now I’m leaving this like it is.</p>

<p><br /></p>

<h3 id="multithreading">Multithreading</h3>
<p>But you know what time it is, right?.
It’s time for boring multithreading optimizations. And oh man I’m really bad at multithreading.</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">uint32_t</span> <span class="n">total_iters_mult_15</span> <span class="o">=</span> <span class="p">((</span><span class="kt">size_t</span><span class="p">)(</span><span class="n">ITERATIONS</span> <span class="o">/</span> <span class="mi">15</span><span class="p">))</span> <span class="o">*</span> <span class="mi">15</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">total_chunks</span> <span class="o">=</span> <span class="n">total_iters_mult_15</span> <span class="o">/</span> <span class="mi">15</span><span class="p">;</span>

<span class="n">UintInString</span> <span class="n">num_string_buffer</span><span class="p">;</span>
<span class="n">num_string_buffer</span><span class="p">.</span><span class="n">initialize</span><span class="p">(</span><span class="mi">12</span><span class="p">);</span>

<span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">total_threads</span> <span class="o">=</span>  <span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="o">::</span><span class="n">hardware_concurrency</span><span class="p">();</span>
<span class="kt">uint32_t</span> <span class="n">num_threads</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">min</span><span class="p">(</span><span class="n">total_threads</span><span class="p">,</span> <span class="n">total_chunks</span><span class="p">);</span>

<span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="o">*</span> <span class="n">threads</span> <span class="o">=</span> <span class="k">new</span> <span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="p">[</span><span class="n">num_threads</span><span class="p">];</span>
<span class="n">CustomString</span><span class="o">*</span> <span class="n">threads_accum</span> <span class="o">=</span> <span class="k">new</span> <span class="n">CustomString</span><span class="p">[</span><span class="n">num_threads</span><span class="p">];</span>

<span class="c1">// Start threads</span>
<span class="kt">size_t</span> <span class="n">chunks_per_thread</span> <span class="o">=</span> <span class="n">total_chunks</span> <span class="o">/</span> <span class="n">num_threads</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">remainder_chunks</span> <span class="o">=</span> <span class="n">total_chunks</span> <span class="o">-</span> <span class="p">(</span><span class="n">chunks_per_thread</span> <span class="o">*</span> <span class="n">num_threads</span><span class="p">);</span>

<span class="kt">size_t</span> <span class="n">from</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">to</span> <span class="o">=</span> <span class="n">chunks_per_thread</span> <span class="o">*</span> <span class="mi">15</span><span class="p">;</span>

<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">num_threads</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">threads_accum</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">CustomString</span><span class="p">();</span>
	<span class="n">threads_accum</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">initialize</span><span class="p">((</span><span class="n">ITERATIONS</span> <span class="o">/</span> <span class="n">num_threads</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">);</span>
	<span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="p">(</span><span class="n">fizzBuzz</span><span class="p">,</span> <span class="n">from</span><span class="p">,</span> <span class="n">to</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">threads_accum</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
	<span class="n">from</span> <span class="o">=</span> <span class="n">to</span><span class="p">;</span>
	<span class="n">to</span> <span class="o">+=</span> <span class="n">chunks_per_thread</span> <span class="o">*</span> <span class="mi">15</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Last thread do the remainder operations</span>
<span class="n">threads_accum</span><span class="p">[</span><span class="n">num_threads</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">CustomString</span><span class="p">();</span>
<span class="n">threads_accum</span><span class="p">[</span><span class="n">num_threads</span><span class="o">-</span><span class="mi">1</span><span class="p">].</span><span class="n">initialize</span><span class="p">((</span><span class="n">ITERATIONS</span> <span class="o">/</span> <span class="n">num_threads</span><span class="p">)</span> <span class="o">*</span> <span class="mi">30</span><span class="p">);</span>
<span class="n">to</span> <span class="o">=</span> <span class="n">to</span><span class="o">+</span><span class="n">remainder_chunks</span><span class="o">*</span><span class="mi">15</span><span class="p">;</span>
<span class="n">threads</span><span class="p">[</span><span class="n">num_threads</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="p">(</span><span class="n">fizzBuzz</span><span class="p">,</span> <span class="n">from</span><span class="p">,</span> <span class="n">to</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">threads_accum</span><span class="p">[</span><span class="n">num_threads</span><span class="o">-</span><span class="mi">1</span><span class="p">]);</span>

<span class="c1">// Wait for every thread to finish</span>
<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">num_threads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">join</span><span class="p">();</span>
<span class="p">}</span>

<span class="c1">// Join all the strings</span>
<span class="kt">size_t</span> <span class="n">total_length</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">num_threads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	<span class="n">total_length</span> <span class="o">+=</span> <span class="n">threads_accum</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">position_null_char</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
	<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">threads_accum</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">string</span><span class="p">);</span>
<span class="p">}</span>

<span class="c1">// Finish remainder operations</span>
<span class="n">num_string_buffer</span><span class="p">.</span><span class="n">set_to_number</span><span class="p">(</span><span class="n">to</span><span class="p">);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="n">to</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">ITERATIONS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	<span class="kt">uint8_t</span> <span class="n">encode</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
	<span class="n">encode</span> <span class="o">+=</span> <span class="p">(</span><span class="n">i</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="mi">2</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span>

	<span class="n">num_string_buffer</span><span class="p">.</span><span class="n">update_add</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
	
	<span class="k">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="n">num_string_buffer</span><span class="p">.</span><span class="n">init_of_number_string</span><span class="p">,</span> <span class="n">num_string_buffer</span><span class="p">.</span><span class="n">length</span><span class="p">);</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"buzz "</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
	<span class="p">}</span><span class="k">else</span> <span class="nf">if</span><span class="p">(</span><span class="n">encode</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">accum</span><span class="p">.</span><span class="n">concat</span><span class="p">(</span><span class="s">"fizzbuzz "</span><span class="p">,</span> <span class="mi">9</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Of course, fizz buzz on multithread is more or less trivial. We just need to divide the work load between all the threads in chunks that are divisible by 15 (to process it in an  unrolled loop like before), leaving the non-divisible portion for the main thread. Or that’s what I have done here.</p>

<p>But after benchmarking it against the other programs, we can see that it’s much slower than the single threaded one.</p>

<p><a href="/assets/images/fizzbuzz/measureFizzFuzz500000000.png">
	<img src="/assets/images/fizzbuzz/measureFizzFuzz500000000.png" alt="fizz buzz benchmark of 500000000 numbers. GCC in a 13.1.1 6700k 3200Mhz DDR4" style="max-width:100%;" />
</a></p>

<p><br /></p>

<p>I’m not sure why. But it’s probably because it does double amount of mallocs. One for each thread. And then we need to concat all of this strings into one. This, probably cause a lot of cache invalidation.</p>

<p>Also, I compiled it with CLANG, but it has shown the same performance metrics.</p>

<p>Anyway. When trying to optimize this simple problem I realized that, this is not really a fizz buzz problem. And actually it’s a <strong>concatenate-and-parse-integers</strong> problem.</p>

<p>The code is available in <a href="https://github.com/MichValwin/OptimizingFizzBuzz">github</a> if you want to see all of this aberration.</p>]]></content><author><name></name></author><category term="devposts" /><summary type="html"><![CDATA[Optimizing fizz buzz in C++]]></summary></entry><entry xml:lang="en"><title type="html">Ray vs AABB collision by the slab method</title><link href="https://michvalwin.com/devposts/2023/04/26/ray-collisions.html" rel="alternate" type="text/html" title="Ray vs AABB collision by the slab method" /><published>2023-04-26T19:00:00+02:00</published><updated>2025-07-17T11:13:54+02:00</updated><id>https://michvalwin.com/devposts/2023/04/26/ray-collisions</id><content type="html" xml:base="https://michvalwin.com/devposts/2023/04/26/ray-collisions.html"><![CDATA[<script>
	class Position {
		constructor(x, y){
			this.x = x;
			this.y = y;
		}
	}

	class Ray {
		constructor(origin, angleDegrees) {
			this.origin = origin;
			this.angleDegrees = angleDegrees;

			let dirVect = calculateRayDir(angleDegrees);
			this.dirX = dirVect[0];
			this.dirY = dirVect[1];
			this.magnitude = 1.0;
		}

		calculateRayDir(angleDegrees) {
			let angleRad = angleDegrees * (Math.PI / 180.0);
			let dirX = Math.cos(angleRad);
			let dirY = Math.sin(angleRad);
			return [dirX, dirY];
		}

		updateAngle(angle) {
			this.angle = angle;
			let dirVect = calculateRayDir(this.angleDegrees);
			this.dirX = dirVect[0];
			this.dirY = dirVect[1];
		}
	}

	class Segment {
		constructor(origin, end) {
			this.origin = origin;
			this.end = end;

			this.calculateRayDir();
		}

		calculateRayDir() {
			let xMag = this.end.x - this.origin.x ;
			let yMag = this.end.y - this.origin.y;

			this.magnitude = Math.sqrt(xMag*xMag + yMag*yMag);

			this.dirX = xMag / this.magnitude;
			this.dirY = yMag / this.magnitude;
		}

		update() {
			this.calculateRayDir();
		}
	}

	class SegmentWithBounds extends Segment {
		constructor(origin, end, radius) {
			super(origin, end);
			this.circleBoundsOrigin = new Circle(origin.x, origin.y, radius);
			this.circleBoundsEnd = new Circle(end.x, end.y, radius);
		}
	}

	class Rectangle {
		constructor(x, y, width, height) {
			this.x = y;
			this.y = y;
			this.width = width;
			this.height = height;
		}

		isInBounds(x, y) {
			if(x >= this.x && x <= this.x+this.width && y >= this.y && y <= this.y+this.height) {
				return true;
			}else{
				return false;
			}
		}
	}

	class Circle {
		constructor(x, y, radius) {
			this.x = x;
			this.y = y;
			this.radius = radius;
		}

		isInBounds(x, y) {
			let distanceEucli = Math.sqrt(Math.pow(this.x-x, 2) + Math.pow(this.y-y, 2));
			if(distanceEucli <= this.radius) {
				return true;
			}else{
				return false;
			}
		}
	}

	function isInBounds(x, y, width, height) {
		if(x >= 0 && x < width && y >= 0 && y < height) {
			return true;
		}else {
			return false;
		}
	}

	class TileMap {
		constructor(width, height) {
			this.width = width;
			this.height = height;
			this.map = [width*height];
			for(let i = 0; i < width*height; i++)this.map[i] = false;
		}
	}

	const CANVAS_ASPECT_RATIO = 640.0/480.0;

	class Canvas {
		constructor(elementCanvas, elementContainer, width, height) {
			this.elementCanvas = elementCanvas;
			this.width = width;
			this.height = height;
			this.elementWidth = (window.innerWidth / 2.0);
			this.elementHeight = ((window.innerWidth / 2.0) / CANVAS_ASPECT_RATIO);

			this.contextDraw = elementCanvas.getContext("2d");

			elementCanvas.width = width;
			elementCanvas.height = height;
			elementCanvas.style.width = "100%";
			elementCanvas.style.height = "100%";
			elementContainer.style.width = this.elementWidth + "px";
			elementContainer.style.height = this.elementHeight + "px";

			this.mouseX = 0;
			this.mouseY = 0;
			this.mousePush = false;
			this.mousePressed = false;


			this.elementCanvas.addEventListener('mousemove', (evt) => {
				let normalizeX = evt.offsetX / this.elementWidth;
				let normalizeY = evt.offsetY / this.elementHeight;
				this.mouseX = normalizeX * this.width;
				this.mouseY = normalizeY * this.height;
				this.mousePressed = false;

				this.update();
				this.draw();
			});

			this.elementCanvas.addEventListener('mousedown', (evt) => {
				this.mousePush = true;
				this.mousePressed = true;
				
				this.update();
				this.draw();
			});

			this.elementCanvas.addEventListener('mouseup', (evt) => {
				this.mousePush = false;
				this.mousePressed = false;
				this.update();
				this.draw();
			});
		}
		
		drawRectangleCentered(x, y, width, height) {
			this.contextDraw.fillRect(x-width/2.0, y-width/2.0, width, height);
		}

		update() {
			
		}

		draw() {
			
		}

		resize() {

		}
	}

	function truncateTo2(floatValue) {
		return Math.trunc(floatValue*100.0) / 100.0;
	}

	class TextForPoints {
		constructor(text, x, y, textColor="white") {
			this.text = text;
			this.x = x;
			this.y = y;
			this.textColor = textColor;
		}
		draw(ctx) {
			ctx.font = "20pt Monospace";
			const textInfo = ctx.measureText(this.text);
			const height = ctx.font.match(/\d+/).pop() || 10;
			const width = textInfo.width;
			ctx.fillStyle = this.textColor;
			ctx.textBaseline = "top";
			ctx.fillText(this.text, this.x - textInfo.width/2.0, this.y - textInfo.actualBoundingBoxDescent-4);
		}
		updateCoords(x, y) {
			this.x = x;
			this.y = y;
		}
	}




	class CanvasTestRay extends Canvas {
		constructor(elementCanvas, elementContainer, width, height, docElementDebug) {
			super(elementCanvas, elementContainer, width, height);
			this.segmentRay = new SegmentWithBounds(new Position(0.1*width, 0.1*height), new Position(0.9*width, 0.9*height), 0.04*width);
			this.originDrag = false;
			this.finalDrag = false;
			this.rectangle = new Rectangle(0.5*width - (0.2*width) / 2.0, 0.5*height - (0.2*width) / 2.0, 0.2*width, 0.2*width);

			this.collisionXMinTime = null;
			this.collisionXMaxTime = null;
			this.collisionYMinTime = null;
			this.collisionYMaxTime = null;

			this.collTime = null;

			this.collNear = 0;
			this.collFar = 0;
			// Debug
			this.docElementDebug = docElementDebug;
			this.textXMin = new TextForPoints("XMin", 10, 10, "white");
			this.textXMax = new TextForPoints("XMax", 10, 10, "white");
			this.textYMin = new TextForPoints("YMin", 10, 10, "white");
			this.textYMax = new TextForPoints("YMax", 10, 10, "white");

			this.textNear = new TextForPoints("tNear", 10, 10, "white");
			this.textFar = new TextForPoints("tFar", 10, 10, "white");
		}

		update() {
			// Drag origin or end
			if(this.mousePressed && this.segmentRay.circleBoundsOrigin.isInBounds(this.mouseX, this.mouseY)) {
				this.originDrag = true;
			}

			if(this.mousePressed && this.segmentRay.circleBoundsEnd.isInBounds(this.mouseX, this.mouseY)) {
				this.finalDrag = true;
			}

			if(!this.mousePush) {
				this.originDrag = false;
				this.finalDrag = false;
			}

			if(this.originDrag && this.finalDrag) {
				this.finalDrag = false;
			}

			// Move if in bounds and drag is true until mouse release
			if(this.mousePush == true) {
				if(this.originDrag == true) {
					this.segmentRay.origin.x = this.mouseX;
					this.segmentRay.origin.y = this.mouseY;
					this.segmentRay.circleBoundsOrigin.x = this.mouseX;
					this.segmentRay.circleBoundsOrigin.y = this.mouseY;
				}
				if(this.finalDrag == true) {
					this.segmentRay.end.x = this.mouseX;
					this.segmentRay.end.y = this.mouseY;
					this.segmentRay.circleBoundsEnd.x = this.mouseX;
					this.segmentRay.circleBoundsEnd.y = this.mouseY;
				}
			}

			this.segmentRay.update();
			this.collision()
		}

		collision() {
			// Calculate collision time to borders of rectangle
			this.collisionXMinTime = (this.rectangle.x - this.segmentRay.origin.x) / this.segmentRay.dirX;
			this.collisionXMaxTime = ((this.rectangle.x+this.rectangle.width) - this.segmentRay.origin.x) / this.segmentRay.dirX;
			this.collisionYMinTime = (this.rectangle.y - this.segmentRay.origin.y) / this.segmentRay.dirY;
			this.collisionYMaxTime = ((this.rectangle.y+this.rectangle.height) - this.segmentRay.origin.y) / this.segmentRay.dirY;

			// Calculate near collision time and far
			let collXNear = Math.min(this.collisionXMinTime, this.collisionXMaxTime);
			let collYNear = Math.min(this.collisionYMinTime, this.collisionYMaxTime);
			let collXFar = Math.max(this.collisionXMinTime, this.collisionXMaxTime);
			let collYFar = Math.max(this.collisionYMinTime, this.collisionYMaxTime);

			let collNear = Math.max(collXNear, collYNear);
			let collFar = Math.min(collXFar, collYFar);

			if(collNear < collFar && collNear >= 0.0) {
				this.collTime = collNear;
			}else{
				this.collTime = null;
			}

			if(this.collTime != null && this.collTime > this.segmentRay.magnitude) {
				this.collTime = null;
			}

			// Debug vars HTML
			this.collNear = collNear;
			this.collFar = collFar;
			this.docElementDebug['xNear'].innerHTML = truncateTo2(collXNear);
			this.docElementDebug['yNear'].innerHTML = truncateTo2(collYNear);
			this.docElementDebug['xFar'].innerHTML = truncateTo2(collXFar);
			this.docElementDebug['yFar'].innerHTML = truncateTo2(collYFar);
			this.docElementDebug['tNear'].innerHTML = truncateTo2(collNear);
			this.docElementDebug['tFar'].innerHTML = truncateTo2(collFar);
		}

		draw() {
			// Clear canvas
			this.contextDraw.fillStyle = "black"; // Clear
			this.contextDraw.fillRect(0, 0, this.width, this.height);


			// Draw ray segment
			this.contextDraw.strokeStyle = "white";
			this.contextDraw.beginPath();
			this.contextDraw.moveTo(this.segmentRay.origin.x, this.segmentRay.origin.y);
			this.contextDraw.lineTo(this.segmentRay.end.x, this.segmentRay.end.y);
			this.contextDraw.closePath();
			this.contextDraw.stroke();

			// Draw ray bounds
			this.contextDraw.strokeStyle = "#888";
			this.contextDraw.beginPath();
			this.contextDraw.arc(this.segmentRay.circleBoundsOrigin.x, this.segmentRay.circleBoundsOrigin.y, this.segmentRay.circleBoundsOrigin.radius, 0, 360, false);
			this.contextDraw.stroke();

			this.contextDraw.beginPath();
			this.contextDraw.arc(this.segmentRay.circleBoundsEnd.x, this.segmentRay.circleBoundsEnd.y, this.segmentRay.circleBoundsEnd.radius, 0, 360, false);
			this.contextDraw.stroke();


			// Draw direction vector
			this.contextDraw.strokeStyle = "red";
			this.contextDraw.beginPath();
			this.contextDraw.moveTo(this.segmentRay.origin.x, this.segmentRay.origin.y);
			this.contextDraw.lineTo(this.segmentRay.dirX*20+this.segmentRay.origin.x, this.segmentRay.dirY*20+this.segmentRay.origin.y);
			this.contextDraw.closePath();
			this.contextDraw.stroke();
		
			// Draw rectangle infinite side lines
			this.contextDraw.strokeStyle = "red";
			//X
			this.contextDraw.strokeStyle = "#666";
			this.contextDraw.beginPath();
			this.contextDraw.moveTo(this.rectangle.x-1000, this.rectangle.y);
			this.contextDraw.lineTo(this.rectangle.x+1000, this.rectangle.y);
			this.contextDraw.closePath();
			this.contextDraw.stroke();

			this.contextDraw.beginPath();
			this.contextDraw.moveTo(this.rectangle.x-1000, this.rectangle.y+this.rectangle.height);
			this.contextDraw.lineTo(this.rectangle.x+1000, this.rectangle.y+this.rectangle.height);
			this.contextDraw.closePath();
			this.contextDraw.stroke();

			//Y
			this.contextDraw.beginPath();
			this.contextDraw.moveTo(this.rectangle.x, this.rectangle.y-1000);
			this.contextDraw.lineTo(this.rectangle.x, this.rectangle.y+1000);
			this.contextDraw.closePath();
			this.contextDraw.stroke();

			this.contextDraw.beginPath();
			this.contextDraw.moveTo(this.rectangle.x+this.rectangle.width, this.rectangle.y-1000);
			this.contextDraw.lineTo(this.rectangle.x+this.rectangle.width, this.rectangle.y+1000);
			this.contextDraw.closePath();
			this.contextDraw.stroke();


			// Draw rectangle collision
			this.contextDraw.strokeStyle = "#fff";
			this.contextDraw.strokeRect(this.rectangle.x, this.rectangle.y, this.rectangle.width, this.rectangle.height);


			// Draw colls
			this.contextDraw.fillStyle = "green";
			if(this.collisionXMinTime != null) {
				this.drawRectangleCentered(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionXMinTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionXMinTime,7,7);
			}
			if(this.collisionXMaxTime != null) {
				this.drawRectangleCentered(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionXMaxTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionXMaxTime,7,7);
			}
			if(this.collisionYMinTime != null) {
				this.drawRectangleCentered(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionYMinTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionYMinTime,7,7);
			}
			if(this.collisionYMaxTime != null) {
				this.drawRectangleCentered(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionYMaxTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionYMaxTime,7,7);
			}


			// Debug text coll sides 
			/*
			this.textXMin.updateCoords(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionXMinTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionXMinTime);
			this.textXMin.draw(this.contextDraw);

			this.textXMax.updateCoords(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionXMaxTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionXMaxTime);
			this.textXMax.draw(this.contextDraw);

			this.textYMin.updateCoords(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionYMinTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionYMinTime);
			this.textYMin.draw(this.contextDraw);

			this.textYMax.updateCoords(this.segmentRay.origin.x + this.segmentRay.dirX*this.collisionYMaxTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collisionYMaxTime);
			this.textYMax.draw(this.contextDraw);
			*/

			// Debug text Near/Far
			this.textNear.updateCoords(this.segmentRay.origin.x + this.segmentRay.dirX*this.collNear,this.segmentRay.origin.y + this.segmentRay.dirY*this.collNear);
			this.textNear.draw(this.contextDraw);

			this.textFar.updateCoords(this.segmentRay.origin.x + this.segmentRay.dirX*this.collFar,this.segmentRay.origin.y + this.segmentRay.dirY*this.collFar);
			this.textFar.draw(this.contextDraw);

			// COLL
			if(this.collTime != null) {
				this.contextDraw.fillStyle = "orange";
				this.drawRectangleCentered(this.segmentRay.origin.x + this.segmentRay.dirX*this.collTime,this.segmentRay.origin.y + this.segmentRay.dirY*this.collTime,7,7);
			}

			//this.contextDraw.fillStyle = "red";
			//this.contextDraw.fillRect(this.mouseX-10, this.mouseY-10, 20, 20);
		}
	}

	

	EXECUTE_ON_LOAD = function() {
		// Ray alone canvas
		const canvasRayAlone = document.getElementById('ray-alone');
		const canvasRayAloneContainer = document.getElementById('container-ray-alone');

		const xNearSpan = document.getElementById('x-near');
		const yNearSpan = document.getElementById('y-near');
		const xFarSpan = document.getElementById('x-far');
		const yFarSpan = document.getElementById('y-far');
		const tNearSpan = document.getElementById('t-near');
		const tFarSpan = document.getElementById('t-far');

		var canvas = new CanvasTestRay(canvasRayAlone, canvasRayAloneContainer, 600, 600, 
			{'xNear': xNearSpan, 'yNear': yNearSpan, 'xFar': xFarSpan, 'yFar': yFarSpan, 'tNear': tNearSpan, 'tFar': tFarSpan});
		canvas.draw();
		canvas.update();
		canvas.draw();
	}

</script>

<h1 id="defining-what-is-a-ray">Defining what is a ray</h1>
<div class="article-date">Last time modified: 17 Jul, 2025</div>
<p><br /></p>

<p>I’m going to define a ray as a point in space with a direction vector, or if your prefer, an angle to know in which direction is looking (although i’ll be using the direction vector in this procedure).</p>
<ul>
  <li>A <strong>position</strong> like <strong><code class="language-plaintext highlighter-rouge">{x, y}</code></strong> for our ray origin.</li>
  <li>A <strong>direction vector</strong> (normalized position between <strong><code class="language-plaintext highlighter-rouge">{-1, -1}</code></strong> to <strong><code class="language-plaintext highlighter-rouge">{1, 1}</code></strong>).
  <br />OR</li>
  <li>An <strong>angle</strong> <strong><code class="language-plaintext highlighter-rouge">[0.0, 360.0]</code></strong> to calculate our ray direction vector.</li>
</ul>

<p>We will be using the parametric equation of the ray with it’s direction; Like this:
<br />
<strong><code class="language-plaintext highlighter-rouge">x = originX + t * directionX</code></strong><br />
<strong><code class="language-plaintext highlighter-rouge">y = originY + t * directionY</code></strong><br /></p>

<p>Here, <strong>t</strong> is referred to as ‘parameter’, which can also be interpreted as ‘distance’ or ‘time’ in this context.</p>

<h1 id="ray-collision-with-aabb-by-the-slab-method">Ray collision with AABB by the slab method</h1>
<p>If you are not familiar with ray collisions, your first take would probably be checking points of the ray sequentially until one of the points ends up inside a figure.
<br />
But we don’t need to do this for rectangles that are aligned to the axis.
<br /></p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRay.png" width="400" />
</div>
<p><br />
During this example i’m going to use numbers so you can follow me with pen and paper.
<br />
Let’s start with a rectangle with origin [3, 2] and width and height of [7, 4].</p>
<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayNumbers.png" width="400" />
</div>
<p><br />
The first step we have to make is to calculate the parameter (distance or time of collision) with each side. Because it’s axis aligned, this is really easy to do.
<br />
For each side that we want to calculate <strong>t</strong> there is always a constant value that we can use. Ex: For the left side we know that all the points need to be in <strong>X = X origin of rectangle</strong>. And for the right side <strong>X = X origin + width of rectangle</strong>.
<br />
<br />
This means we just need to resolve the parametric equation for the X in our rectangle, like this
<br />
<strong><code class="language-plaintext highlighter-rouge">rectangleX = xRayOrigin + t * dirRayX</code></strong>
<br />
Solving for <strong>t</strong> will get us:
<br />
<strong><code class="language-plaintext highlighter-rouge">t = (rectangleX-xRayOrigin) / dirRayX</code></strong>
<br />
In our case <strong>tXMin = 2.44</strong>.
<br /></p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayNumbersSidesTime.png" width="400" />
</div>
<p><br />
The values of the for each side are the following:
<br />
<strong>tXMin = 2.44</strong>
<br />
<strong>tXMax = 10.99</strong>
<br />
<strong>tYMin = 8.72</strong>
<br />
<strong>tYMax = 1.74</strong>
<br /></p>

<p>As you can see some <strong>t</strong> points do not collide with our rectangle, because we are calculating the distance needed to an imaginary infinite side of our rectangle. 
<br />
You can better see it in the next example:</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayNumbersSidesTimeWithGuides.png" width="400" />
</div>
<p><br /></p>

<h2 id="the-procedure">The procedure</h2>
<p>There are two rules that every ray intersecting an AABB follows.</p>
<ol>
  <li>The <strong>segment intersecting</strong> an AABB is <strong>always between the second and third points</strong> of collision with it’s sides (assuming that the sides are infinite).</li>
  <li>If we call <strong><code class="language-plaintext highlighter-rouge">'left'</code></strong> and <strong><code class="language-plaintext highlighter-rouge">'right'</code></strong> sides X and up and down sides Y. The order in which the ray intersect them can’t be two X sides or two Y sides. Specifically, the ray must intersect an X side first, followed by a Y side, or vice versa.</li>
</ol>

<p>We can see the segment of the ray that intersects a rectangle in the following image.</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayLotsRay.png" width="400" />
</div>
<p><br /></p>

<p>If we paint the points in which our rays intersect the rectangle, we can see that <strong>the segment that intersect the rectangle is always between the second and third points</strong> counting from it’s origin.
This concept is illustrated in the following image:</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayTwoWithPoints.png" width="400" />
</div>
<p><br /></p>

<p>At this point, we could solve our problem just by checking if there are two points that overlap with the rectangle; And if it’s colliding we will get two points out of four potential collision points. Then, we can select the point that has the shortest distance between the origin of our ray.
<br />
But there is a better less instruction intensive way.
<br />
<strong>The slab method</strong>
<br /></p>

<p>Okay, but how do we find the second point with math?.
Well, if we keep drawing and label the potential collision points as X1 and X2 for the left and right sides and Y1 and Y2 for bottom and top sides respectively. We conclude that a ray that intersect a rectangle always change it’s axis of collision between the first and second, and the third and fourth points.</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayTwoWithPointsNamed.png" width="400" />
</div>
<p><br /></p>

<p>Now we need to classify this four points in two groups (the nearest and farthest points by axis). The “near” group formed by the smallest X and Y. And the “far” group formed by the biggest X and Y.</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayTwoWithPointsNamedNearFar.png" width="400" />
</div>
<p><br /></p>

<p>And for the final step, we must get the two points that form the intersecting segment. Pick the biggest value of the Near set. And the smallest value of the Far set.</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayTwoWithPointsNamedNearFarResolved.png" width="400" />
</div>
<p><br /></p>

<p>That’s it, as you can see, the ray only collides if the ‘near’ point is smaller that the ‘far’ one.
<br />
So now that we know why and how the slab algorithm works we can go to our example.
<br /></p>

<h2 id="finishing-the-example">Finishing the example</h2>

<p>Now that we have listed the four potential collision points with each side. We need to classify the nearest group of <strong>t</strong> collision by axis and the farthest <strong>t</strong>.
Basically we are swapping the parameter for an axis if <strong>tMin &gt; tMax</strong>.
<br />
This will be something like:
<br />
<strong><code class="language-plaintext highlighter-rouge">tXNear = Min(tXMinSide, tXMaxSide)</code></strong>
<br />
<strong><code class="language-plaintext highlighter-rouge">tXFar = Max(tXMinSide, tXMaxSide)</code></strong>
<br />
The same goes for <strong>YNear</strong> and <strong>YFar</strong>.
<br />
In the example for the <strong>YNear</strong>, it will be our <strong>YMax</strong> since is lower than <strong>YMax</strong>.</p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayNumbersNearFarTimes.png" width="400" />
</div>
<p><br />
The values of the for each near and far parameters are the following:
<br />
<strong>tXNear = 2.44</strong>
<br />
<strong>tYNear = 1.74</strong>
<br />
<strong>tXFar = 8.72</strong>
<br />
<strong>tYFar = 10.99</strong>
<br /></p>

<p><br />
We are going to calculate a <strong>TNEAR</strong> and <strong>TFAR</strong> with the four points that we have.
For this we are going to take the greater time from both <strong>tXNear</strong> and <strong>tYnear</strong>. And the lowest time from <strong>tXFar</strong> and <strong>tYfar</strong>.
<br />
<strong><code class="language-plaintext highlighter-rouge">tNear = Max(tXNear, tYNear)</code></strong>
<br />
<strong><code class="language-plaintext highlighter-rouge">tFar = Min(tXFar, tYFar)</code></strong>
<br /></p>

<div class="flex-center">
	<img src="/assets/images/rayRectangle/squareRayNumbersNearFarTimesSolved.png" width="400" />
</div>
<p><br />
The values of this two <strong>t</strong> are:
<br />
<strong>tNear = 2.44</strong>
<br />
<strong>tFar = 8.72</strong>
<br />
<br />
Now The only step that is left is to compare <strong>tNear</strong> and <strong>tFar</strong>.
<br />
If <strong>tNear</strong> is <strong>smaller</strong> than <strong>tFar</strong> it means we have collision.
<br />
And so, our tNear is our collision parameter.
<br />
<br />
Now we can calculate our point of collision by resolving the parametric equation of the ray for our tNear. This get us:
<br />
<strong>X = 3</strong>
<br />
<strong>Y = 5.597</strong></p>

<p><br /></p>

<h2 id="code">Code</h2>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Calculate collision time/distance with sides of rectangle</span>
<span class="kd">let</span> <span class="nx">tXMin</span> <span class="o">=</span> <span class="p">(</span><span class="nx">rectangle</span><span class="p">.</span><span class="nx">x</span> <span class="o">-</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">origin</span><span class="p">.</span><span class="nx">x</span><span class="p">)</span> <span class="o">/</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">dirX</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">tXMax</span> <span class="o">=</span> <span class="p">((</span><span class="nx">rectangle</span><span class="p">.</span><span class="nx">x</span><span class="o">+</span><span class="nx">rectangle</span><span class="p">.</span><span class="nx">width</span><span class="p">)</span> <span class="o">-</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">origin</span><span class="p">.</span><span class="nx">x</span><span class="p">)</span> <span class="o">/</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">dirX</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">tYMin</span> <span class="o">=</span> <span class="p">(</span><span class="nx">rectangle</span><span class="p">.</span><span class="nx">y</span> <span class="o">-</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">origin</span><span class="p">.</span><span class="nx">y</span><span class="p">)</span> <span class="o">/</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">dirY</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">tYMax</span> <span class="o">=</span> <span class="p">((</span><span class="nx">rectangle</span><span class="p">.</span><span class="nx">y</span><span class="o">+</span><span class="nx">rectangle</span><span class="p">.</span><span class="nx">height</span><span class="p">)</span> <span class="o">-</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">origin</span><span class="p">.</span><span class="nx">y</span><span class="p">)</span> <span class="o">/</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">dirY</span><span class="p">;</span>

<span class="c1">// Organize collisions in two groups, nearest and farthest</span>
<span class="kd">let</span> <span class="nx">tXNear</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">min</span><span class="p">(</span><span class="nx">tXMin</span><span class="p">,</span> <span class="nx">tXMax</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">tXFar</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="nx">tXMin</span><span class="p">,</span> <span class="nx">tXMax</span><span class="p">);</span>

<span class="kd">let</span> <span class="nx">tYNear</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">min</span><span class="p">(</span><span class="nx">tYMin</span><span class="p">,</span> <span class="nx">tYMax</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">tYFar</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="nx">tYMin</span><span class="p">,</span> <span class="nx">tYMax</span><span class="p">);</span>

<span class="c1">// Calculate Nearest and farthest collision of all components</span>
<span class="kd">let</span> <span class="nx">tNear</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">max</span><span class="p">(</span><span class="nx">tXNear</span><span class="p">,</span> <span class="nx">tYNear</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">tFar</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">min</span><span class="p">(</span><span class="nx">tXFar</span><span class="p">,</span> <span class="nx">tYFar</span><span class="p">);</span>

<span class="c1">// If tNear &lt; tFar we have collision</span>
<span class="c1">// Discard negatives since it can't be a collision</span>
<span class="k">if</span><span class="p">(</span><span class="nx">tNear</span> <span class="o">&lt;</span> <span class="nx">tFar</span> <span class="o">&amp;&amp;</span> <span class="nx">tNear</span> <span class="o">&gt;=</span> <span class="mf">0.0</span> <span class="o">&amp;&amp;</span> <span class="nx">tNear</span> <span class="o">&lt;=</span> <span class="nx">segmentRay</span><span class="p">.</span><span class="nx">magnitude</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
	<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Since my code treat the ray as a segment i have another condition in the case the segment does not reach collision time.
<br />
Another thing that this code does <strong>NOT</strong> account for is the possibility that our ray is parallel to an axis. Therefore, one of the component of it’s direction vector will be 0.
<br />
In <code class="language-plaintext highlighter-rouge">JS</code> a division by 0 returns <strong>Infinity</strong> by the float IEEE 754 standard. But <strong>you should control this in other languages</strong>.
<br />
<br />
Here it’s a interactive version. You can click and drag on the circles to move the ray origin/end.
<br /></p>
<div class="flex-center"> <!-- Used to center the div inside-->
	<div id="container-ray-alone">
		<canvas id="ray-alone" style="background-color: #0d1210;"></canvas>
	</div>
</div>

<table>
  <thead>
    <tr>
      <th> </th>
      <th style="text-align: center">X</th>
      <th style="text-align: center">Y</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Near</td>
      <td style="text-align: center"><span id="x-near"></span></td>
      <td style="text-align: center"><span id="y-near"></span></td>
    </tr>
    <tr>
      <td>Far</td>
      <td style="text-align: center"><span id="x-far"></span></td>
      <td style="text-align: center"><span id="y-far"></span></td>
    </tr>
    <tr>
      <td>tNear</td>
      <td style="text-align: center"><span id="t-near"></span></td>
      <td style="text-align: center"> </td>
    </tr>
    <tr>
      <td>tFar</td>
      <td style="text-align: center"><span id="t-far"></span></td>
      <td style="text-align: center"> </td>
    </tr>
  </tbody>
</table>

<h1 id="resources-used">Resources used</h1>
<p><a href="https://www.realtimerendering.com/intersections.html">https://www.realtimerendering.com/intersections.html</a> All types of intersection algorithms</p>

<p><a href="https://gdbooks.gitbooks.io/3dcollisions/content/Chapter3/raycast_aabb.html">https://gdbooks.gitbooks.io/3dcollisions/content/Chapter3/raycast_aabb.html</a> Collision ray vs AABB</p>

<p><a href="https://tavianator.com/2011/ray_box.html">https://tavianator.com/2011/ray_box.html</a> Fast, Branchless Ray/Bounding Box Intersections</p>]]></content><author><name></name></author><category term="devposts" /><summary type="html"><![CDATA[Ray vs AABB collision (Slab method)]]></summary></entry><entry xml:lang="en"><title type="html">Promises on JS</title><link href="https://michvalwin.com/notes/2022/10/24/notes-on-js-promises.html" rel="alternate" type="text/html" title="Promises on JS" /><published>2022-10-24T10:08:55+02:00</published><updated>2023-09-05T10:03:21+02:00</updated><id>https://michvalwin.com/notes/2022/10/24/notes-on-js-promises</id><content type="html" xml:base="https://michvalwin.com/notes/2022/10/24/notes-on-js-promises.html"><![CDATA[<script>
	EXECUTE_ON_LOAD = function() {
		
	}
</script>

<h1 id="notes-on-js-promises">Notes on JS promises</h1>
<div class="article-date">Last time modified: 05 Sep, 2023</div>
<p><br />
(this notes are probably incomplete)</p>

<hr />

<h2 id="create-a-promise">Create a promise</h2>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">new</span> <span class="nc">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">){});</span>
<span class="k">new</span> <span class="nc">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{});</span>

<span class="c1">// Example</span>
<span class="kd">function</span> <span class="nf">divide</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">return</span> <span class="k">new</span> <span class="nc">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span><span class="p">{</span>
		<span class="k">if</span><span class="p">(</span><span class="nx">y</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
			<span class="nf">resolve</span><span class="p">(</span><span class="nx">x</span><span class="o">/</span><span class="nx">y</span><span class="p">);</span>
		<span class="p">}</span><span class="k">else</span><span class="p">{</span>
			<span class="nf">reject</span><span class="p">(</span><span class="nc">Error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Can't divide 0</span><span class="dl">"</span><span class="p">));</span>
		<span class="p">}</span>
	<span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>

<p><br /></p>
<h1 id="execute-and-error-control">Execute and error control</h1>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">doPromiseDivide</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
	<span class="nf">divide</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">)</span>
		<span class="p">.</span><span class="nf">then</span><span class="p">(</span>
			<span class="kd">function</span> <span class="nf">onSuccess</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Result: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">result</span><span class="p">);</span>
				<span class="c1">// throw Error("Error from onSuccess block generated");</span>
			<span class="p">},</span>
			<span class="kd">function</span> <span class="nf">onError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
				<span class="c1">// throw Error("Error from OnError block generated");</span>
			<span class="p">}</span>
		<span class="p">)</span>
		<span class="p">.</span><span class="k">catch</span><span class="p">(</span>
			<span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
			<span class="p">}</span>
		<span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li>If we execute <strong><code class="language-plaintext highlighter-rouge">doPromiseDivide(5,3)</code></strong> the <strong><code class="language-plaintext highlighter-rouge">onSuccess</code></strong> is called and it prints 1.33333…</li>
  <li>If we execute <strong><code class="language-plaintext highlighter-rouge">doPromiseDivide(5,0)</code></strong> the <strong><code class="language-plaintext highlighter-rouge">onError</code></strong> is called and we get ‘Error: Can’t divide 0’</li>
  <li>The catch block executes if there is an error that wasn’t caught. <strong>In this case</strong> it only executes when there is a <strong><code class="language-plaintext highlighter-rouge">throw</code></strong> in the <strong><code class="language-plaintext highlighter-rouge">onSuccess</code></strong> function or <strong><code class="language-plaintext highlighter-rouge">onError</code></strong> function.
But if we delete the <strong><code class="language-plaintext highlighter-rouge">onError</code></strong> function and a error is thrown by dividing by 0 then the catch blocks executes. Example:</li>
</ul>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">doPromiseDivideWithoutOnError</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
	<span class="nf">divide</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">)</span>
		<span class="p">.</span><span class="nf">then</span><span class="p">(</span>
			<span class="kd">function</span> <span class="nf">onSuccess</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Result: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">result</span><span class="p">);</span>
			<span class="p">}</span>
		<span class="p">)</span>
		<span class="p">.</span><span class="k">catch</span><span class="p">(</span>
			<span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Catch block executed because there is not a onError function on then</span><span class="dl">'</span><span class="p">);</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
			<span class="p">}</span>
		<span class="p">);</span>
<span class="p">}</span>

<span class="nf">doPromiseDivideWithoutOnError</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
</code></pre></div></div>
<p>You probably want to catch errors from the promise itself in the <strong><code class="language-plaintext highlighter-rouge">onError</code></strong> block, and errors thrown in the <strong><code class="language-plaintext highlighter-rouge">then</code></strong> with a <strong><code class="language-plaintext highlighter-rouge">catch</code></strong> block.</p>

<p><br /></p>
<h2 id="promise-behavior">Promise behavior</h2>
<p>A promise is executed when is created, even if you don’t pass the params <strong><code class="language-plaintext highlighter-rouge">resolve</code></strong>, <strong><code class="language-plaintext highlighter-rouge">reject</code></strong>.
So even if it doesn’t have a <strong><code class="language-plaintext highlighter-rouge">.then</code></strong> the promise is executed.
And it doesn’t need to execute <strong><code class="language-plaintext highlighter-rouge">resolve</code></strong> neither <strong><code class="language-plaintext highlighter-rouge">reject</code></strong>.
Example:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">alertPromise</span><span class="p">(</span><span class="nx">text</span><span class="p">){</span>
	<span class="k">return</span> <span class="k">new</span> <span class="nc">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=&gt;</span><span class="p">{</span>
		<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">text</span><span class="p">);</span>
	<span class="p">});</span>
<span class="p">}</span>

<span class="nf">alertPromise</span><span class="p">(</span><span class="dl">"</span><span class="s2">This promise never execute resolve or reject</span><span class="dl">"</span><span class="p">);</span>
</code></pre></div></div>

<p>This will execute the <strong><code class="language-plaintext highlighter-rouge">console.log</code></strong></p>

<p><br /></p>
<h2 id="finally-block">Finally block</h2>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nf">doPromiseDivide</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">)</span> <span class="p">{</span>
	<span class="nf">divide</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">)</span>
		<span class="p">.</span><span class="nf">then</span><span class="p">(</span>
			<span class="kd">function</span> <span class="nf">onSuccess</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Result: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">result</span><span class="p">);</span>
				<span class="c1">//throw Error("Error from onSuccess block generated");</span>
			<span class="p">},</span>
			<span class="kd">function</span> <span class="nf">onError</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Error: </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
				<span class="c1">//throw Error("Error from OnError block generated");</span>
			<span class="p">}</span>
		<span class="p">)</span>
		<span class="p">.</span><span class="k">catch</span><span class="p">(</span>
			<span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">error</span><span class="p">.</span><span class="nx">message</span><span class="p">);</span>
			<span class="p">}</span>
		<span class="p">)</span>
		<span class="p">.</span><span class="k">finally</span><span class="p">(</span>
			<span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
				<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">This block is always executed</span><span class="dl">'</span><span class="p">);</span>
			<span class="p">}</span>
		<span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="notes" /><summary type="html"><![CDATA[Notes on JS promises to always remember]]></summary></entry></feed>