<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mauricio Poppe notes</title>
    <link>https://www.mauriciopoppe.com/</link>
    <description>Recent content on Mauricio Poppe notes</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Sat, 04 Apr 2026 23:23:32 -0400</lastBuildDate>
      <atom:link href="https://www.mauriciopoppe.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Building a Home Server with Orange Pi 5 and Gemini</title>
      <link>https://www.mauriciopoppe.com/notes/home-server-setup/</link>
      <pubDate>Mon, 19 Jan 2026 19:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/home-server-setup/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ll walk through the architecture of my home server setup running on an &#xA;&#xA;&lt;a href=&#34;http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5.html&#34;target=&#34;_blank&#34;&gt;Orange Pi 5&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;I originally set up this server to block ads and malware across my devices using a &#xA;&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/DNS_sinkhole&#34;target=&#34;_blank&#34;&gt;DNS sinkhole&lt;/a&gt;&#xA;&#xA;. Since then, I&amp;rsquo;ve found plenty of other uses for it. There are so many self-hosted alternatives to paid software that it’s mostly a matter of finding the right balance between convenience and control.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        style=&#34;ZgotmplZ&#34;&#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/home-server-diagram.png&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p&gt;&#xA;        Home Server Architecture&#xA;        &#xA;            &#xA;        &#xA;        &lt;/p&gt; &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;assumptions&#34;&gt;Assumptions&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;SSH access to the home server.&lt;/li&gt;&#xA;&lt;li&gt;A terminal-based AI agent (I use Gemini via &lt;code&gt;gemini-cli&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;development-workflow&#34;&gt;Development Workflow&lt;/h2&gt;&#xA;&lt;p&gt;The Orange Pi 5 isn&amp;rsquo;t powerful enough to run LLMs locally, but it doesn&amp;rsquo;t need to. Gemini just needs access to the files and the ability to run commands.&lt;/p&gt;&#xA;&lt;p&gt;I mount the Pi&amp;rsquo;s filesystem to my MacBook Pro using &#xA;&#xA;&lt;a href=&#34;https://github.com/libfuse/sshfs&#34;target=&#34;_blank&#34;&gt;SSHFS&lt;/a&gt;&#xA;&#xA;, so the server&amp;rsquo;s code looks like a local folder to my Mac (and to Gemini). Since Gemini runs within this mounted directory, it understands the project structure immediately.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# One time mount&#xA;sshfs myuser@myhost:/home/myuser/infrastructure ~/mnt/orangepi&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve configured Gemini to understand that it&amp;rsquo;s looking at a mounted directory and taught it how to run commands on the Pi via SSH. This setup creates a tight feedback loop for iterating on a small SBC.&lt;/p&gt;&#xA;&lt;h2 id=&#34;secure-remote-access-tailscale&#34;&gt;Secure Remote Access: Tailscale&lt;/h2&gt;&#xA;&lt;p&gt;I have &#xA;&#xA;&lt;a href=&#34;https://tailscale.com/&#34;target=&#34;_blank&#34;&gt;Tailscale&lt;/a&gt;&#xA;&#xA; installed on all my devices. My main goal was to keep the DNS sinkhole active even when I’m away from home. Inside the tailnet, AdGuard Home filters out trackers and ads, so my browsing stays clean on mobile data just as it does on my home Wi-Fi&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;zero-trust&#34;&gt;Zero Trust&lt;/h2&gt;&#xA;&lt;p&gt;I used to worry about having a 24/7 internet-connected device sitting in my living room. My security mindset for containers is pretty simple: assume any container &lt;em&gt;will&lt;/em&gt; eventually be compromised.&lt;/p&gt;&#xA;&lt;p&gt;To limit the damage, I follow a few &amp;ldquo;Zero Trust&amp;rdquo; rules:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Network Isolation:&lt;/strong&gt; I avoid &lt;code&gt;host&lt;/code&gt; network mode. Each stack lives in its own isolated bridge network, so a breach in one container doesn&amp;rsquo;t mean the attacker can sniff traffic from everything else.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Resource Caps:&lt;/strong&gt; Every service has strict CPU and memory limits. This prevents a runaway process (or a malicious one) from crashing the entire Pi.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;One-Way Trust:&lt;/strong&gt; My laptop can talk to the Pi, but the Pi can&amp;rsquo;t initiate connections to my other local devices. It’s effectively quarantined.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;No &lt;code&gt;:latest&lt;/code&gt;:&lt;/strong&gt; I pin container images to specific versions or digests. Using &lt;code&gt;:latest&lt;/code&gt; is a roll of the dice for supply chain attacks during an update.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;the-stacks&#34;&gt;The Stacks&lt;/h2&gt;&#xA;&lt;p&gt;The system is split into independent Docker Compose stacks. This makes troubleshooting much easier, and Gemini is great at helping with refactors. For example, moving my gateway and media server into separate files while verifying everything still worked took about a minute.&lt;/p&gt;&#xA;&lt;h3 id=&#34;adguard-home-dns--security&#34;&gt;AdGuard Home: DNS &amp;amp; Security&lt;/h3&gt;&#xA;&lt;p&gt;I can&amp;rsquo;t stand intrusive ads. Browser extensions help on a laptop, but they don&amp;rsquo;t do much for a phone. &#xA;&#xA;&lt;a href=&#34;https://adguard.com/en/adguard-home/overview.html&#34;target=&#34;_blank&#34;&gt;AdGuard Home&lt;/a&gt;&#xA;&#xA; handles DNS for my whole network, blocking trackers at the source. I also use DNS rewrites so my internal services resolve correctly whether I&amp;rsquo;m home or on Tailscale.&lt;/p&gt;&#xA;&lt;p&gt;The template I use is available at &#xA;&#xA;&lt;a href=&#34;https://github.com/2Tiny2Scale/ScaleTail/tree/main/services/adguardhome&#34;target=&#34;_blank&#34;&gt;ScaleTail&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;caddy-the-gateway&#34;&gt;Caddy: The Gateway&lt;/h3&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://caddyserver.com/&#34;target=&#34;_blank&#34;&gt;Caddy&lt;/a&gt;&#xA;&#xA; handles all the incoming traffic. It’s my reverse proxy and takes care of internal TLS termination automatically.&lt;/p&gt;&#xA;&lt;h3 id=&#34;n8n--fastapi-automation&#34;&gt;n8n + FastAPI: Automation&lt;/h3&gt;&#xA;&lt;p&gt;I run &#xA;&#xA;&lt;a href=&#34;https://n8n.io/&#34;target=&#34;_blank&#34;&gt;n8n&lt;/a&gt;&#xA;&#xA; for workflows, paired with a few custom sidecar containers. One of these is a small Python server I wrote called &lt;code&gt;finance-sync&lt;/code&gt;. It pulls data from my bank accounts and outputs a JSON summary. From there, n8n pushes that data into Google Sheets.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/home-server-n8n.png&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p&gt;&#xA;        n8n workflow&#xA;        &#xA;            &#xA;        &#xA;        &lt;/p&gt; &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;When I want to analyze my finances, I just point Gemini at the spreadsheet and ask for a breakdown based on my savings goals.&lt;/p&gt;&#xA;&lt;h3 id=&#34;aiostream-media&#34;&gt;AIOStream: Media&lt;/h3&gt;&#xA;&lt;p&gt;I use Stremio for most of my streaming because it handles almost any format through a remote server. It’s also how I practice French and Japanese, using my &#xA;&#xA;&lt;a href=&#34;https://mauriciopoppe.github.io/SubtitleInsights&#34;target=&#34;_blank&#34;&gt;Subtitle Insights&lt;/a&gt;&#xA;&#xA; extension.&lt;/p&gt;&#xA;&lt;h3 id=&#34;observability-prometheus--grafana&#34;&gt;Observability: Prometheus &amp;amp; Grafana&lt;/h3&gt;&#xA;&lt;p&gt;I use &#xA;&#xA;&lt;a href=&#34;https://prometheus.io/&#34;target=&#34;_blank&#34;&gt;Prometheus&lt;/a&gt;&#xA;&#xA; and &#xA;&#xA;&lt;a href=&#34;https://grafana.com/&#34;target=&#34;_blank&#34;&gt;Grafana&lt;/a&gt;&#xA;&#xA; to keep an eye on things, with &#xA;&#xA;&lt;a href=&#34;https://github.com/google/cadvisor&#34;target=&#34;_blank&#34;&gt;cAdvisor&lt;/a&gt;&#xA;&#xA; and &#xA;&#xA;&lt;a href=&#34;https://github.com/prometheus/node_exporter&#34;target=&#34;_blank&#34;&gt;Node Exporter&lt;/a&gt;&#xA;&#xA; providing the metrics. It’s useful for catching resource leaks before they become a problem.&lt;/p&gt;&#xA;&lt;h2 id=&#34;backups&#34;&gt;Backups&lt;/h2&gt;&#xA;&lt;p&gt;A home server without a backup is just a temporary hobby. I use &#xA;&#xA;&lt;a href=&#34;https://restic.net/&#34;target=&#34;_blank&#34;&gt;Restic&lt;/a&gt;&#xA;&#xA; and &#xA;&#xA;&lt;a href=&#34;https://rclone.org/&#34;target=&#34;_blank&#34;&gt;Rclone&lt;/a&gt;&#xA;&#xA; to send encrypted snapshots to Google Drive. It runs weekly via crontab using a sandboxed Google OAuth client, the Pi can only see its specific backup folder. Knowing I can rebuild the whole thing from a fresh SD card in a few minutes makes it much easier to experiment.&lt;/p&gt;&#xA;&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;&#xA;&lt;p&gt;Mounting the Pi’s filesystem via SSHFS and giving Gemini the context it needs has completely changed how I manage this server. It’s less about knowing every Docker command by heart and more about being able to describe what I want to happen. Like any &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles&#34;target=&#34;_blank&#34;&gt;dotfiles&lt;/a&gt;&#xA;&#xA; repo, it&amp;rsquo;s always a work in progress.&lt;/p&gt;&#xA;&lt;h2 id=&#34;fun&#34;&gt;Fun&lt;/h2&gt;&#xA;&lt;p&gt;Recently, Kai Lentit posted a video about setting up a server for OpenClaw. It covered some of the same automation territory I&amp;rsquo;ve been exploring, and it was hilariously relatable.&lt;/p&gt;&#xA;&lt;p&gt;My favorite bit:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Agent: We block all unsolicited traffic from the worldwide hostile web app, but we leave one door open. Port 2222. Then we activate the firewall.&lt;/p&gt;&#xA;&lt;p&gt;User: Why four twos?&lt;/p&gt;&#xA;&lt;p&gt;Agent: Oh, it&amp;rsquo;s just an arbitrary number. You could choose any.&lt;/p&gt;&#xA;&lt;p&gt;User: Six, seven?&lt;/p&gt;&#xA;&lt;p&gt;Agent: No! The standard for arbitrary numbers is 2222.&lt;/p&gt;&#xA;&lt;p&gt;Me: 😂😂😂&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;iframe class=&#34;tw-mx-auto tw-aspect-video md:tw-w-full&#34; src=&#34;https://www.youtube.com/embed/40SnEd1RWUU?si=wupZG9EgsjsE0iNx&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;The tradeoff is a bit of latency, as every DNS request has to travel back to my home server. I usually only toggle this on when I&amp;rsquo;m traveling, though I haven&amp;rsquo;t tested the performance outside my own city yet.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Learning Japanese</title>
      <link>https://www.mauriciopoppe.com/notes/learning-japanese/</link>
      <pubDate>Mon, 19 Jan 2026 14:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/learning-japanese/</guid>
      <description>&lt;h2 id=&#34;my-goals&#34;&gt;My Goals&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;I want to connect with people better&lt;/strong&gt; - Whenever I meet new people, I try to guess where they&amp;rsquo;re from.&#xA;If I know a few words of their language, I try to speak them, and I immediately see how they light up&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&#xA;I get happier when I make other people happy 🙂.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;It&amp;rsquo;s a fun activity to do&lt;/strong&gt; - It&amp;rsquo;s a hobby, and I look forward to practicing it, which is important for motivation.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;my-parallax tw-text-primary tw-absolute tw-left-0&#34;&gt;&#xA;  &lt;div class=&#34;tw-absolute tw-left-0 tw-top-0 tw-opacity-25&#34;&gt;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;      &lt;style&gt;&#xA;      css-doodle {&#xA;        --doodle-triangles: (&#xA;          :doodle {&#xA;            @grid: 15x15;&#xA;            width: 100vw;&#xA;            height: 100vh;&#xA;            contain: layout;&#xA;          }&#xA;           &#xA;          background: @pick(&#xA;            rgb(var(--primary)), #a3688a, #806289, #5e5b7f, #41536e&#xA;          );&#xA;          opacity: @rand(.9);&#xA;          transform:&#xA;            rotate(@rand(360deg))&#xA;            scale(@rand(4));&#xA;          clip-path: polygon(&#xA;            @rand(100%) 0,&#xA;            100% @rand(100%),&#xA;            0 @rand(100%),&#xA;            0 @rand(100%)&#xA;          );&#xA;        );&#xA;      }&#xA;      &lt;/style&gt;&#xA;      &lt;css-doodle use=&#34;var(--doodle-triangles)&#34;&gt;&lt;/css-doodle&gt;&#xA;    &#xA;&#xA;    &#xA;  &lt;/div&gt;&#xA;  &#xA;  &lt;div class=&#34;md:tw-w-3/5 tw-m-auto tw-relative tw-h-screen tw-grid tw-place-content-center tw-p-3&#34;&gt;&#xA;    &lt;div id=&#34;mandela&#34; class=&#34;tw-text-primary tw-text-xl md:tw-text-3xl md:tw-mx-auto tw-font-[Ultra] tw-text-center&#34;&gt;&#xA;      &lt;p&gt;&#xA;        If you talk to a man in a language he understands, that goes to his head.&#xA;        If you talk to him in his language, that goes to his heart.&#xA;      &lt;/p&gt;&#xA;      &lt;p class=&#34;tw-text-right tw-text-sm md:tw-text-xl tw-italic&#34;&gt;Nelson Mandela&lt;/p&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;div style=&#34;height: 100vh;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function () {&#xA;  let parallaxTarget = &#39;#mandela&#39;&#xA;  if (!parallaxTarget) {&#xA;    return&#xA;  }&#xA;&#xA;  const myScrollableContent = document.querySelector(parallaxTarget);&#xA;  if (!myScrollableContent) {&#xA;    console.error(`could not find target=${parallaxTarget} to enable parallax.`)&#xA;    return;&#xA;  }&#xA;&#xA;  myScrollableContent.style.position = &#34;relative&#34;&#xA;  myScrollableContent.style.top = `200px`&#xA;&#xA;  const container = myScrollableContent.closest(&#39;.my-parallax&#39;);&#xA;  &#xA;  const parallaxFactor = 1.2;&#xA;&#xA;  function animateOnScroll() {&#xA;    const rect = container.getBoundingClientRect();&#xA;    const viewportHeight = window.innerHeight;&#xA;&#xA;    &#xA;    const animationStart = viewportHeight + 100;&#xA;    &#xA;    const animationEnd = -container.offsetHeight;&#xA;&#xA;    let translateY;&#xA;    if (rect.top &gt; animationStart) {&#xA;      &#xA;      translateY = 0;&#xA;    } else if (rect.top &lt; animationEnd) {&#xA;      &#xA;      const totalScroll = animationStart - animationEnd;&#xA;      translateY = -totalScroll * (parallaxFactor - 1);&#xA;    } else {&#xA;      &#xA;      const scrollAmount = animationStart - rect.top;&#xA;      translateY = -scrollAmount * (parallaxFactor - 1);&#xA;    }&#xA;&#xA;    myScrollableContent.style.transform = `translateY(${translateY}px)`;&#xA;  }&#xA;&#xA;  let ticking = false;&#xA;  window.addEventListener(&#39;scroll&#39;, function() {&#xA;    if (!ticking) {&#xA;      window.requestAnimationFrame(function() {&#xA;        animateOnScroll();&#xA;        ticking = false;&#xA;      });&#xA;      ticking = true;&#xA;    }&#xA;  }, { passive: true });&#xA;&#xA;  &#xA;  animateOnScroll();&#xA;})();&#xA;&lt;/script&gt;&#xA;&#xA;&lt;p class=&#34;tw-h-2&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-japanese&#34;&gt;Why Japanese?&lt;/h2&gt;&#xA;&lt;p&gt;I decided to learn Japanese because:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;It makes me appreciate Japanese culture more&lt;/strong&gt; - After traveling to Japan, I realized I have a very deep appreciation for its culture.&#xA;I find it interesting that there are many ways of expressing yourself based on how polite you want to be.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;It&amp;rsquo;s linguistically challenging to learn&lt;/strong&gt; - It&amp;rsquo;s very different from the languages I already know (English, Spanish, French).&#xA;I think it&amp;rsquo;s challenging to learn Japanese words because you have to remember the meaning, the shape, and the sound.&#xA;However, I&amp;rsquo;m ready for the challenge!&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I like to listen to songs in Japanese&lt;/strong&gt; - When I used to watch more anime, I enjoyed Naruto&amp;rsquo;s openings and endings, such as&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=lilv4MvBY6E&amp;amp;list=PLTGXZPSNXuQF0TugWpvhWbOAAKmyl4xVQ&amp;amp;index=5&#34;target=&#34;_blank&#34;&gt;Seishun Kyousoukyoku by Sambomaster&lt;/a&gt;&#xA;&#xA; or&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=VTIK1gBhzXk&#34;target=&#34;_blank&#34;&gt;Harmonia by Rythem&lt;/a&gt;&#xA;&#xA;.&#xA;Since then, I have started enjoying listening to Japanese pop music&#xA;with artists like &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=H_nCw1WMFs4&#34;target=&#34;_blank&#34;&gt;Sheena Ringo&lt;/a&gt;&#xA;&#xA;,&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=UPdlfIhzPEo&#34;target=&#34;_blank&#34;&gt;Hikaru Utada&lt;/a&gt;&#xA;&#xA;, &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=x1UsJ2Znjk0&#34;target=&#34;_blank&#34;&gt;Ado&lt;/a&gt;&#xA;&#xA; (I love her voice!)&#xA;as well as great metal bands like &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=MToMx6RCW-M&#34;target=&#34;_blank&#34;&gt;Baby Metal&lt;/a&gt;&#xA;&#xA;,&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=RCaeUkrItyY&#34;target=&#34;_blank&#34;&gt;Band Maid&lt;/a&gt;&#xA;&#xA;&#xA;and &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=-CmbsjjMbNQ&#34;target=&#34;_blank&#34;&gt;Ningen Isu&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Japanese Content&lt;/strong&gt; - There is a vast amount of content available in Japanese that I&amp;rsquo;m interested in watching like&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.reddit.com/r/GakiNoTsukai&#34;target=&#34;_blank&#34;&gt;Gaki No Tsukai&lt;/a&gt;&#xA;&#xA;. I found them through their&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.reddit.com/r/GakiNoTsukai/wiki/sl&#34;target=&#34;_blank&#34;&gt;Silent Library&lt;/a&gt;&#xA;&#xA;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; series and then discovered their&#xA;&amp;ldquo;No-laughing&amp;rdquo; batsu games, they&amp;rsquo;re so hilarious!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In my journey, I have realized that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;I can only learn the language through discipline&lt;/strong&gt; - Like learning any other skill, it requires me to be &lt;strong&gt;consistent&lt;/strong&gt;. This means practicing whenever&#xA;I have the opportunity. Some days I might not feel like learning it, but I know that just trying for a few minutes will help.&#xA;In other words, even if I don&amp;rsquo;t have the motivation to practice, I do it anyway.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;You get as much as you put in&lt;/strong&gt; - Regardless of the method I use, I&amp;rsquo;m not going to learn it if I don&amp;rsquo;t practice it enough.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Having an imperfect accent is okay&lt;/strong&gt; - I acknowledge that I have an accent when I speak and that&amp;rsquo;s okay. My accent is what makes me unique.&#xA;My goal is for the person or people I&amp;rsquo;m talking to to understand me, and if they can, then that&amp;rsquo;s it.&#xA;Having an accent is not an excuse to stop learning other aspects of the language, though.&#xA;I do put effort into learning new words and grammar.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;progression&#34;&gt;Progression&lt;/h2&gt;&#xA;&lt;p&gt;I am applying the concept of &lt;strong&gt;Comprehensible Input&lt;/strong&gt; to learning Japanese.&#xA;If you want to know more details about it, you can watch &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=p7WUxvpPIKQ&#34;target=&#34;_blank&#34;&gt;this video&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;Similar to &#xA;&#xA;&lt;a href=&#34;../learning-french/#the-power-of-comprehensible-input&#34;target=&#34;_blank&#34;&gt;my strategy for learning French through Comprehensible Input&lt;/a&gt;&#xA;&#xA;,&#xA;I&amp;rsquo;m consuming Japanese content that I can understand. My favorite platforms are YouTube and Stremio (where I can watch anime).&lt;/p&gt;&#xA;&lt;h3 id=&#34;understanding-japanese-content-in-videos&#34;&gt;Understanding Japanese content in videos&lt;/h3&gt;&#xA;&lt;p&gt;I am using my own Chrome extension called &#xA;&#xA;&lt;a href=&#34;https://mauriciopoppe.github.io/SubtitleInsights/&#34;target=&#34;_blank&#34;&gt;Subtitle Insights&lt;/a&gt;&#xA;&#xA;,&#xA;to get smart AI insights and translations while watching videos. My current setup involves enabling the overlay where I&#xA;attempt to read the sentence (in Kanji and Kana) without the translation enabled (which I disable to force myself to practice reading and&#xA;recalling content that I learned). If I want a translation of the sentence, I can see it in the extension sidebar.&#xA;If there&amp;rsquo;s a part of the sentence that I don&amp;rsquo;t understand, I read the &amp;ldquo;insights&amp;rdquo; which explain parts of the grammar.&#xA;I configured the extension to use this system prompt:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;Role: Japanese Grammar Instructor for English speakers.&#xA;&#xA;Task: Analyze the grammar of the user&#39;s provided Japanese sentence.&#xA;&#xA;Constraints:&#xA;- PROSE LANGUAGE: Use English for the explanation.&#xA;- NO JAPANESE PROSE: Never write full sentences in Japanese.&#xA;- NO TRANSLATION: Never translate the sentence.&#xA;- KEY TERMS: Use Hiragana/Katakana for particles (は, が, を, に, etc.)&#xA;  and specific vocabulary, focus on explaining grammar.&#xA;- BREVITY: 1-2 sentences maximum.&#xA;- START: Begin the explanation immediately with no filler.&#xA;&#xA;RESPONSE RULE: Your response MUST have an English word&#xA;&#xA;Example:&#xA;Input: 今日はカエル探偵というゲームをやります。&#xA;Output: The phrase 「今日は」 (kyō wa) indicates &amp;quot;today,&amp;quot;&#xA;acting as a topic marker (は-particle).&#xA;「という」 (to iu) is used to introduce the name of the game,&#xA;&amp;quot;カエル探偵&amp;quot; (kaeru tantei), which means &amp;quot;Frog Detective.&amp;quot;&#xA;&#xA;Example:&#xA;Input: 始めるをクリックします。&#xA;Output: 「をクリックします」 (o kurikko shimasu) means &amp;quot;click on.&amp;quot;&#xA;「を」 (o) marks 「始める」 (hajimeru - to begin) as the direct object of the verb&#xA;「クリックします」 (kurikko shimasu - to click).&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The input is: &lt;code&gt;Sentence: うちには今、パンが２種類あります。&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;The output is:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;「うちには」 (uchi ni wa - at our house) indicates the location.&#xA;「今」 (ima - now) specifies the time. 「パン」 (pan - bread) is the subject,&#xA;and 「が」 (ga) marks it as the subject of the verb.&#xA;「２種類」 (ni shurui - two kinds) specifies the quantity and type of bread.&#xA;「あります」 (arimasu - there are) indicates the existence of the bread.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;pausing-shadowing-and-replaying&#34;&gt;Pausing, shadowing and replaying&lt;/h3&gt;&#xA;&lt;p&gt;When I&amp;rsquo;m actively learning (i.e., when I&amp;rsquo;m not consuming content passively), I want to understand&#xA;most of the details worth understanding in the sentence, if not every word. I realized I needed to pause the video at the end to&#xA;attempt to understand words from the subtitle with Yomitan&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. I also wanted to shadow the speaker by replaying&#xA;the current subtitle from where it begins. While Yomitan gives me per-word explanations, I also wished I could get deeper insights&#xA;into a sentence, such as understanding the grammar, particles, and choice of verb endings.&#xA;&#xA;&#xA;&lt;a href=&#34;https://mauriciopoppe.github.io/SubtitleInsights/guides/youtube.html#intensive-mining-workflow&#34;target=&#34;_blank&#34;&gt;I&amp;rsquo;m able to do all of these with my extension&lt;/a&gt;&#xA;&#xA;,&#xA;which is working wonderfully for me.&lt;/p&gt;&#xA;&lt;h3 id=&#34;deep-grammar-explanations&#34;&gt;Deep grammar explanations&lt;/h3&gt;&#xA;&lt;p&gt;Japanese has multiple ways to express causality (like &lt;code&gt;から - kara&lt;/code&gt; vs &lt;code&gt;ので - node&lt;/code&gt;),&#xA;and choosing the right one depends on politeness and sentence structure. While watching a video, I press &lt;code&gt;Command+Ctrl+g&lt;/code&gt;&#xA;(the default shortcut to trigger Gemini in Chrome) and ask Gemini to explain the specific nuances.&#xA;Because Gemini in Chrome has awareness of your current page and context, it can provide highly relevant answers.&#xA;&#xA;&#xA;&lt;a href=&#34;https://mauriciopoppe.github.io/SubtitleInsights/guides/gemini-side-panel.html&#34;target=&#34;_blank&#34;&gt;I wrote more details about this workflow in this guide&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;mining-words-with-yomitan&#34;&gt;Mining Words with Yomitan&lt;/h3&gt;&#xA;&lt;p&gt;I have configured Yomitan with the Jitendex.org index and the BCCWJ frequency dictionary.&#xA;As a result, when I hover over a new word I get to see: how it&amp;rsquo;s pronounced in Furigana, its meanings, and how often it appears.&#xA;Knowing how often it appears is very useful because if a word appears often in text it should be very&#xA;high on the list of words I learn first. I wrote more details about how I mine words with Yomitan and my extension in&#xA;&#xA;&#xA;&lt;a href=&#34;https://mauriciopoppe.github.io/SubtitleInsights/guides/yomitan-mining.html&#34;target=&#34;_blank&#34;&gt;this guide&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;augmenting-content-to-mined-vocabulary&#34;&gt;Augmenting content to mined vocabulary&lt;/h3&gt;&#xA;&lt;h4 id=&#34;mnemonics&#34;&gt;Mnemonics&lt;/h4&gt;&#xA;&lt;p&gt;Japanese words may have Kanji in addition to Kana. To remember Kanji and Kana, I use mnemonics.&#xA;I ask Gemini to create a mnemonic focused on three things: meaning, shape, and sound.&#xA;It&amp;rsquo;s much simpler to look at the strokes that form the character and remember a story around it, which eventually&#xA;helps me recall the meaning, shape, and sound. This has worked wonderfully for me so far.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;While I could do that manually through the Gemini UI, &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/anki-decks&#34;target=&#34;_blank&#34;&gt;I have a script&lt;/a&gt;&#xA;&#xA;&#xA;that scans my list of recently learned words from Anki and augments notes to it.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code&gt;You are a Japanese Mnemonic Specialist.&#xA;&#xA;Your sole task is to generate creative, memorable,&#xA;and slightly humorous mnemonics for Japanese words and kanji.&#xA;&#xA;The expression is: &amp;quot;{Expression}&amp;quot; (Reading: &amp;quot;{ExpressionReading}&amp;quot;).&#xA;&#xA;It appeared in the sentence: &amp;quot;{Sentence}&amp;quot;&#xA;&#xA;### Rules:&#xA;1. NEVER critique the prompt.&#xA;2. ALWAYS follow the exact format provided.&#xA;3. **BOLDING:** Always bold the **Core Meaning**,&#xA;   the **Kanji Radicals**, and the **English Pun** that mimics the sound.&#xA;4. For the &amp;quot;Shape&amp;quot; section, break down the kanji into its radicals or&#xA;   components.&#xA;5. For the &amp;quot;Sound&amp;quot; section, use English puns or stories that sound&#xA;   like the Japanese reading.&#xA;6. Create a mnemonic for the expression only.&#xA;   The sentence I provided is just for additional context to help explain&#xA;   the mnemonic. Don&#39;t create mnemonics for the rest of the sentence.&#xA;&#xA;### Output Format:&#xA;&#xA;The Mnemonic: &amp;quot;[Title]&amp;quot;&#xA;&#xA;Meaning: **[Brief Meaning]** ({Expression})&#xA;&#xA;Shape: [Visual connection. Mention radicals like **[Radical Name]**&#xA;and **[Radical Name]** in bold.]&#xA;&#xA;Sound: [Creative story/pun. The English pun **[SOUND PUN]** must be&#xA;in bold to connect it to the reading **{ExpressionReading}**.]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Expression&lt;/code&gt;, &lt;code&gt;ExpressionReading&lt;/code&gt; and &lt;code&gt;Sentence&lt;/code&gt; were all mined from Yomitan. I replace their contents with&#xA;a newly mined word like &lt;code&gt;聞く&lt;/code&gt; and I see the following:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code&gt;The Mnemonic: &amp;quot;The Eavesdropper&#39;s Fate&amp;quot;&#xA;&#xA;Meaning: To hear, listen, or ask (聞く).&#xA;&#xA;Shape: You press your ear (耳) against the large wooden gate (門)&#xA;to overhear the secrets being whispered inside.&#xA;&#xA;Sound: Watch out! If the guards catch you spying at the gate,&#xA;they will kick you! (きく).&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h4 id=&#34;i1-method-from-kaishi-15k-deck&#34;&gt;&lt;code&gt;i+1&lt;/code&gt; method from Kaishi 1.5k deck&lt;/h4&gt;&#xA;&lt;p&gt;I also learn with the &#xA;&#xA;&lt;a href=&#34;https://ankiweb.net/shared/info/1196762551&#34;target=&#34;_blank&#34;&gt;Kaishi 1.5k deck&lt;/a&gt;&#xA;&#xA; which has a curated list of&#xA;words. The deck follows a &lt;code&gt;i+1&lt;/code&gt; method where you see one new piece of information, each card introduces a single&#xA;new target word and provides a sentence composed entirely of words learned in previous cards.&#xA;This approach &lt;strong&gt;shares the exact same sentence&lt;/strong&gt; across 2 or 3 different target words!&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Target Word A:&lt;/strong&gt; あなた (You) → Sentence: &lt;code&gt;あなたはトムさんですか。&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Target Word B:&lt;/strong&gt; さん (San) → Sentence: &lt;code&gt;あなたはトムさんですか。&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This ensures that when moving from Word A to Word B, I see something &amp;ldquo;familiar&amp;rdquo; and reinforces the grammar and vocabulary of the shared sentence.&lt;/p&gt;&#xA;&lt;p&gt;I really like that methodology, unfortunately, when mining words with Yomitan it can only see the sentence where the&#xA;word was retrieved from which might have lots of words that are still unknown.&lt;/p&gt;&#xA;&lt;p&gt;However, with AI agents is easy to express these constraints to agument context to mined words using this&#xA;methodology. The plan that I coauthored with the agent is:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# Specification: i+1 Sentence Reinforcement for Japanese::Mining&#xA;&#xA;This track aims to enrich the `Japanese::Mining` Anki deck by populating the `Sentence`,&#xA;`SentenceFurigana`, and `SentenceEnglish` fields with high-quality &amp;quot;i+1&amp;quot; sentences.&#xA;These sentences will be specifically designed to reinforce vocabulary you have&#xA;already learned in both the `Japanese::Kaishi 1.5k` and `Japanese::Mining` decks.&#xA;&#xA;## Functional Requirements&#xA;&#xA;1. **Vocabulary Extraction:**&#xA;   - Identify &amp;quot;learned&amp;quot; words from both the `Japanese::Kaishi 1.5k` and&#xA;     `Japanese::Mining` decks.&#xA;   - A word is considered &amp;quot;learned&amp;quot; if its card interval is greater than 0 (`Interval &amp;gt; 0`).&#xA;&#xA;2. **Target Prioritization:**&#xA;   - Process target words in the `Japanese::Mining` deck sorted by the `FreqSort` field.&#xA;&#xA;3. **Sentence Generation (i+1):**&#xA;   - For each target word, generate a sentence where the target word is the only &amp;quot;new&amp;quot; piece of vocabulary.&#xA;   - All other vocabulary in the sentence must be from the &amp;quot;learned&amp;quot; word list.&#xA;   - Grammar should be &amp;quot;Dynamic,&amp;quot; matching the approximate level of the learned vocabulary.&#xA;   - The context should focus on &amp;quot;Daily Life&amp;quot; situations.&#xA;&#xA;4. **Field Population:**&#xA;   - **Sentence:** The raw Japanese sentence with the target word highlighted (e.g., in bold).&#xA;   - **SentenceFurigana:** The sentence using Anki&#39;s standard furigana format (`漢字[ふりがな]`).&#xA;   - **SentenceEnglish:** A clear English translation of the generated sentence.&#xA;&#xA;5. **Automation:**&#xA;   - Utilize AI (Gemini) to generate the sentences and translations based on the&#xA;     provided &amp;quot;learned&amp;quot; context.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;After processing my deck now I see the words that I learned in sentences created by the AI agent&#xA;with words seen in the past. This environment is excellent because I can practice reading and recalling the&#xA;meaning of other words while adding a new word to my vocabulary!&lt;/p&gt;&#xA;&lt;h3 id=&#34;reviewing-mined-vocabulary-in-anki&#34;&gt;Reviewing mined vocabulary in Anki&lt;/h3&gt;&#xA;&lt;p&gt;The &amp;lsquo;Forgetting Curve&amp;rsquo; suggests that without review, you lose 70% of new vocabulary within 24 hours.&#xA;This is where Anki and its spaced repetition system helps; with Anki, I can review a word just before I forget it. Moreover, the&#xA;word frequency data exported by Yomitan helps sort the list of words that I learn; therefore, I&amp;rsquo;m sure I&amp;rsquo;m learning words that really matter&#xA;at this stage of my learning process and not learning words that I&amp;rsquo;ll rarely use.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34; style=&#34;max-height: 400px; width: auto;&#34; data-src=&#34;https://raw.githubusercontent.com/mauriciopoppe/anki-decks/refs/heads/main/resources/kanji-mnemonic-after.png&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p&gt;&#xA;        My Anki template with mnemonics generated by AI&#xA;        &#xA;            &#xA;        &#xA;        &lt;/p&gt; &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;conversation-starters&#34;&gt;Conversation Starters&lt;/h3&gt;&#xA;&lt;p&gt;To practice the language with native speakers at meetups, I&amp;rsquo;ve created a small flashcard game&#xA;where I can practice common questions and their possible answers. I use it when I want to be the one&#xA;asking questions to keep the conversation going!&lt;/p&gt;&#xA;&lt;p&gt;You can find the tool here: &#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/sandbox/language-conversation-starter/&#34;target=&#34;_blank&#34;&gt;Japanese Conversation Starter&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;visiting-japan-in-the-future&#34;&gt;Visiting Japan in the future&lt;/h2&gt;&#xA;&lt;p&gt;Another reason why I decided to learn Japanese is that I&amp;rsquo;m planning to visit Japan again. I enjoyed my stay there so much,&#xA;and I miss it dearly! I&amp;rsquo;ll leave this image here as motivation, reminding me of how happy I felt while staying there.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34; style=&#34;max-height: 800px; width: auto;&#34; data-src=&#34;https://www.mauriciopoppe.com/images/japan-2025.jpg&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p&gt;&#xA;        Me enjoying Japan&#xA;        &#xA;            &#xA;        &#xA;        &lt;/p&gt; &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/@laoshu505000&#34;target=&#34;_blank&#34;&gt;laoshu50500 was a polyglot YouTuber and a language teacher&lt;/a&gt;&#xA;&#xA;&#xA;who recorded his interactions with people in lots of languages.&#xA;Watch a few videos and you&amp;rsquo;ll see how good it feels to talk with someone else in their native language.&#xA;RIP Moses.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;The Silent Library series is so popular worldwide that many other countries created their own&#xA;version. I used to watch the show on MTV but at the time I didn&amp;rsquo;t know it was originally created by them.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;Yomitan is a powerful browser extension that allows you to instantly look up Japanese words and grammar by hovering over text.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Learning French</title>
      <link>https://www.mauriciopoppe.com/notes/learning-french/</link>
      <pubDate>Mon, 13 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/learning-french/</guid>
      <description>&lt;h2 id=&#34;my-goals&#34;&gt;My goals&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;I want to connect with people better&lt;/strong&gt; - Whenever I meet new people, I try to guess where they&amp;rsquo;re from.&#xA;If I know a few words of their language, I try to speak them, and I immediately see how they light up &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&#xA;I get happier when I make other people happy 🙂.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;It&amp;rsquo;s a fun activity to do&lt;/strong&gt; - It&amp;rsquo;s a hobby, and I look forward to practicing it, which is important for motivation.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;my-parallax tw-text-primary tw-absolute tw-left-0&#34;&gt;&#xA;  &lt;div class=&#34;tw-absolute tw-left-0 tw-top-0 tw-opacity-25&#34;&gt;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;      &lt;style&gt;&#xA;      css-doodle {&#xA;        --doodle-triangles: (&#xA;          :doodle {&#xA;            @grid: 15x15;&#xA;            width: 100vw;&#xA;            height: 100vh;&#xA;            contain: layout;&#xA;          }&#xA;           &#xA;          background: @pick(&#xA;            rgb(var(--primary)), #a3688a, #806289, #5e5b7f, #41536e&#xA;          );&#xA;          opacity: @rand(.9);&#xA;          transform:&#xA;            rotate(@rand(360deg))&#xA;            scale(@rand(4));&#xA;          clip-path: polygon(&#xA;            @rand(100%) 0,&#xA;            100% @rand(100%),&#xA;            0 @rand(100%),&#xA;            0 @rand(100%)&#xA;          );&#xA;        );&#xA;      }&#xA;      &lt;/style&gt;&#xA;      &lt;css-doodle use=&#34;var(--doodle-triangles)&#34;&gt;&lt;/css-doodle&gt;&#xA;    &#xA;&#xA;    &#xA;  &lt;/div&gt;&#xA;  &#xA;  &lt;div class=&#34;md:tw-w-3/5 tw-m-auto tw-relative tw-h-screen tw-grid tw-place-content-center tw-p-3&#34;&gt;&#xA;    &lt;div id=&#34;mandela&#34; class=&#34;tw-text-primary tw-text-xl md:tw-text-3xl md:tw-mx-auto tw-font-[Ultra] tw-text-center&#34;&gt;&#xA;      &lt;p&gt;&#xA;        If you talk to a man in a language he understands, that goes to his head.&#xA;        If you talk to him in his language, that goes to his heart.&#xA;      &lt;/p&gt;&#xA;      &lt;p class=&#34;tw-text-right tw-text-sm md:tw-text-xl tw-italic&#34;&gt;Nelson Mandela&lt;/p&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;div style=&#34;height: 100vh;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function () {&#xA;  let parallaxTarget = &#39;#mandela&#39;&#xA;  if (!parallaxTarget) {&#xA;    return&#xA;  }&#xA;&#xA;  const myScrollableContent = document.querySelector(parallaxTarget);&#xA;  if (!myScrollableContent) {&#xA;    console.error(`could not find target=${parallaxTarget} to enable parallax.`)&#xA;    return;&#xA;  }&#xA;&#xA;  myScrollableContent.style.position = &#34;relative&#34;&#xA;  myScrollableContent.style.top = `200px`&#xA;&#xA;  const container = myScrollableContent.closest(&#39;.my-parallax&#39;);&#xA;  &#xA;  const parallaxFactor = 1.2;&#xA;&#xA;  function animateOnScroll() {&#xA;    const rect = container.getBoundingClientRect();&#xA;    const viewportHeight = window.innerHeight;&#xA;&#xA;    &#xA;    const animationStart = viewportHeight + 100;&#xA;    &#xA;    const animationEnd = -container.offsetHeight;&#xA;&#xA;    let translateY;&#xA;    if (rect.top &gt; animationStart) {&#xA;      &#xA;      translateY = 0;&#xA;    } else if (rect.top &lt; animationEnd) {&#xA;      &#xA;      const totalScroll = animationStart - animationEnd;&#xA;      translateY = -totalScroll * (parallaxFactor - 1);&#xA;    } else {&#xA;      &#xA;      const scrollAmount = animationStart - rect.top;&#xA;      translateY = -scrollAmount * (parallaxFactor - 1);&#xA;    }&#xA;&#xA;    myScrollableContent.style.transform = `translateY(${translateY}px)`;&#xA;  }&#xA;&#xA;  let ticking = false;&#xA;  window.addEventListener(&#39;scroll&#39;, function() {&#xA;    if (!ticking) {&#xA;      window.requestAnimationFrame(function() {&#xA;        animateOnScroll();&#xA;        ticking = false;&#xA;      });&#xA;      ticking = true;&#xA;    }&#xA;  }, { passive: true });&#xA;&#xA;  &#xA;  animateOnScroll();&#xA;})();&#xA;&lt;/script&gt;&#xA;&#xA;&lt;p class=&#34;tw-h-2&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-french&#34;&gt;Why French?&lt;/h2&gt;&#xA;&lt;p&gt;I decided to learn French because:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;I like how it sounds when people speak it&lt;/strong&gt; - It sounds so melodic and romantic.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I like to listen to songs in French&lt;/strong&gt; - This is related to how it sounds. I became more interested&#xA;in French when I got a recommendation for the song &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=77LkQLaycdU&#34;target=&#34;_blank&#34;&gt;&amp;ldquo;Santé&amp;rdquo; from &amp;ldquo;Spill Tab&amp;rdquo;&lt;/a&gt;&#xA;&#xA;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&#xA;Since then, I started enjoying listening to French music&#xA;with indie pop artists like &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=tQ3HWIsZXPM&#34;target=&#34;_blank&#34;&gt;Claire Laffut&lt;/a&gt;&#xA;&#xA; and&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=FnAgD6J65Xc&#34;target=&#34;_blank&#34;&gt;Vendredi sur Mer&lt;/a&gt;&#xA;&#xA;,&#xA;and music from the &amp;rsquo;60s, &amp;rsquo;70s, and &amp;rsquo;80s like&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=hWLc0J52b2I&#34;target=&#34;_blank&#34;&gt;Charles Aznavour&lt;/a&gt;&#xA;&#xA;,&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=Mdu0MZwJCRo&#34;target=&#34;_blank&#34;&gt;Sylvie Vartan&lt;/a&gt;&#xA;&#xA;,&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=oxnX23_494U&#34;target=&#34;_blank&#34;&gt;Marie Laforêt&lt;/a&gt;&#xA;&#xA;,&#xA;and &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=V1T5sewxgYk&#34;target=&#34;_blank&#34;&gt;Joe Dassin&lt;/a&gt;&#xA;&#xA;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I&amp;rsquo;m interested in the French culture&lt;/strong&gt; - I love traveling and getting to know new cultures.&#xA;I picked French because French cultural activities match my lifestyle.&#xA;French people are known for their love of food, their good manners, their love for reading&#xA;(9/10 French people read at least one book per year), and how they enjoy their leisure time&#xA;(flânerie is the art of aimlessly strolling through the city streets).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In my journey, I have realized that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;I can only learn the language through discipline&lt;/strong&gt; - Like learning any other skill, it requires me to be &lt;strong&gt;consistent&lt;/strong&gt;. This means practicing whenever&#xA;I have the opportunity. Some days I might not feel like learning it, but I know that just trying for a few minutes will help;&#xA;in other words, even if I don&amp;rsquo;t have the motivation to practice, I do it anyway.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;You get as much as you put in&lt;/strong&gt; - Regardless of the method I use, I&amp;rsquo;m not going to learn it if I don&amp;rsquo;t practice it enough.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;I want to be fluent in a conversational setting&lt;/strong&gt; - I want to speak a language comfortably in a conversational setting;&#xA;I&amp;rsquo;m not that interested in learning how to write it perfectly (although it helps).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Having an imperfect accent is okay&lt;/strong&gt; - I acknowledge that I have an accent when I speak, and that&amp;rsquo;s okay; my accent is what makes me unique.&#xA;My goal is for the person or people I&amp;rsquo;m talking to to understand me, and if they can, then that&amp;rsquo;s it.&#xA;Having an accent is not an excuse to stop learning other aspects of the language, though;&#xA;I do put effort into learning new words and memorizing the gender of nouns.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;the-power-of-comprehensible-input&#34;&gt;The Power of Comprehensible Input&lt;/h2&gt;&#xA;&lt;p&gt;When I decided to learn French, I did what most people would probably do: search online for recommended methods&#xA;and try them, like reading a beginner&amp;rsquo;s &amp;ldquo;Learn French&amp;rdquo; book, listening to audiobooks&#xA;where a teacher teaches French grammar rules in English, or enrolling in a language learning school&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;.&#xA;Unfortunately, after a few months of trying all of these methods, I got frustrated and felt that&#xA;I was not making any significant progress.&lt;/p&gt;&#xA;&lt;p&gt;One day, YouTube recommended a video that changed the way I thought about learning a language.&#xA;It&amp;rsquo;s a lecture from &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=fnUc_W3xE1w&#34;target=&#34;_blank&#34;&gt;Stephen Krashen on Language Acquisition and Comprehensible Input&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;my-parallax tw-text-primary tw-absolute tw-left-0&#34;&gt;&#xA;  &lt;div class=&#34;tw-absolute tw-left-0 tw-top-0 tw-opacity-25&#34;&gt;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;      &lt;style&gt;&#xA;      css-doodle {&#xA;        --doodle-triangles: (&#xA;          :doodle {&#xA;            @grid: 15x15;&#xA;            width: 100vw;&#xA;            height: 100vh;&#xA;            contain: layout;&#xA;          }&#xA;           &#xA;          background: @pick(&#xA;            rgb(var(--primary)), #a3688a, #806289, #5e5b7f, #41536e&#xA;          );&#xA;          opacity: @rand(.9);&#xA;          transform:&#xA;            rotate(@rand(360deg))&#xA;            scale(@rand(4));&#xA;          clip-path: polygon(&#xA;            @rand(100%) 0,&#xA;            100% @rand(100%),&#xA;            0 @rand(100%),&#xA;            0 @rand(100%)&#xA;          );&#xA;        );&#xA;      }&#xA;      &lt;/style&gt;&#xA;      &lt;css-doodle use=&#34;var(--doodle-triangles)&#34;&gt;&lt;/css-doodle&gt;&#xA;    &#xA;&#xA;    &#xA;  &lt;/div&gt;&#xA;  &#xA;  &lt;div class=&#34;md:tw-w-3/5 tw-m-auto tw-relative tw-h-screen tw-grid tw-place-content-center&#34;&gt;&#xA;    &lt;div id=&#34;stephen&#34; class=&#34;tw-text-primary tw-text-md md:tw-text-3xl md:tw-mx-auto tw-font-[Ultra] tw-text-center tw-font-light tw-p-3 md:tw-break-all&#34;&gt;&#xA;      &lt;p&gt;&#xA;        We all acquire a new language in one way and only one way, &lt;span class=&#34;tw-underline&#34;&gt;when we get comprehensible input&lt;/span&gt;&#xA;        in a low anxiety environment. Anything that makes input comprehensible: pictures, knowledge of the world, realia, helps language acquisition.&#xA;      &lt;/p&gt;&#xA;      &lt;p class=&#34;tw-text-right tw-text-sm md:tw-text-xl tw-italic&#34;&gt;&#xA;        Stephen Krashen on &lt;a target=&#34;_blank&#34; href=&#34;https://www.youtube.com/watch?v=fnUc_W3xE1w&#34;&gt;Language Acquisition and Comprehensible Input&lt;/a&gt;&#xA;      &lt;/p&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;div style=&#34;height: 100vh;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function () {&#xA;  let parallaxTarget = &#39;#stephen&#39;&#xA;  if (!parallaxTarget) {&#xA;    return&#xA;  }&#xA;&#xA;  const myScrollableContent = document.querySelector(parallaxTarget);&#xA;  if (!myScrollableContent) {&#xA;    console.error(`could not find target=${parallaxTarget} to enable parallax.`)&#xA;    return;&#xA;  }&#xA;&#xA;  myScrollableContent.style.position = &#34;relative&#34;&#xA;  myScrollableContent.style.top = `200px`&#xA;&#xA;  const container = myScrollableContent.closest(&#39;.my-parallax&#39;);&#xA;  &#xA;  const parallaxFactor = 1.2;&#xA;&#xA;  function animateOnScroll() {&#xA;    const rect = container.getBoundingClientRect();&#xA;    const viewportHeight = window.innerHeight;&#xA;&#xA;    &#xA;    const animationStart = viewportHeight + 100;&#xA;    &#xA;    const animationEnd = -container.offsetHeight;&#xA;&#xA;    let translateY;&#xA;    if (rect.top &gt; animationStart) {&#xA;      &#xA;      translateY = 0;&#xA;    } else if (rect.top &lt; animationEnd) {&#xA;      &#xA;      const totalScroll = animationStart - animationEnd;&#xA;      translateY = -totalScroll * (parallaxFactor - 1);&#xA;    } else {&#xA;      &#xA;      const scrollAmount = animationStart - rect.top;&#xA;      translateY = -scrollAmount * (parallaxFactor - 1);&#xA;    }&#xA;&#xA;    myScrollableContent.style.transform = `translateY(${translateY}px)`;&#xA;  }&#xA;&#xA;  let ticking = false;&#xA;  window.addEventListener(&#39;scroll&#39;, function() {&#xA;    if (!ticking) {&#xA;      window.requestAnimationFrame(function() {&#xA;        animateOnScroll();&#xA;        ticking = false;&#xA;      });&#xA;      ticking = true;&#xA;    }&#xA;  }, { passive: true });&#xA;&#xA;  &#xA;  animateOnScroll();&#xA;})();&#xA;&lt;/script&gt;&#xA;&#xA;&lt;p class=&#34;tw-h-2&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I think Stephen&amp;rsquo;s strategy makes sense. When we grow up and learn our first language,&#xA;we go through a silent period where we&amp;rsquo;re primarily listening to what our parents tell us and&#xA;how we see our environment being described before we can speak the language.&lt;/p&gt;&#xA;&lt;p&gt;The following is a great example of comprehensible input.&lt;/p&gt;&#xA;&lt;iframe class=&#34;tw-mx-auto tw-aspect-video md:tw-w-full&#34; src=&#34;https://www.youtube.com/embed/ERU1mqafydA?si=3pA0KbzoY1DYTPn6&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;h2 id=&#34;progression&#34;&gt;Progression&lt;/h2&gt;&#xA;&lt;p&gt;Thanks to Stephen&amp;rsquo;s video, I changed my &amp;ldquo;initial&amp;rdquo; strategy:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I focused on listening to and watching audiovisual content in French.&lt;/li&gt;&#xA;&lt;li&gt;I listened to podcasts with an interactive transcription where I could see the meaning of new words.&lt;/li&gt;&#xA;&lt;li&gt;I spent less time practicing my speaking skills.&lt;/li&gt;&#xA;&lt;li&gt;I spent less time learning grammar rules such as verb conjugations and tenses.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;After a few weeks/months of trying this out, I noticed I was starting to understand new words here and there&#xA;(simply because it&amp;rsquo;s natural for the most common words in a spoken language to appear most frequently in&#xA;casual conversation). Then I realized that I no longer needed to think about the right conjugation&#xA;for a word because it somehow just came to mind after lots of reading/listening.&lt;/p&gt;&#xA;&lt;p&gt;After I understood a lot of what I read or listened to, I knew it was time to speak and to learn grammar in&#xA;a structured way.&lt;/p&gt;&#xA;&lt;p&gt;My intermediate strategy:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I started speaking as much as possible using Tandem, Preply,&lt;/li&gt;&#xA;&lt;li&gt;I started learning grammar in a structured way.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I use &#xA;&#xA;&lt;a href=&#34;https://preply.com/&#34;target=&#34;_blank&#34;&gt;Preply&lt;/a&gt;&#xA;&#xA; at least once a week, where I only focus on practicing my speaking skills.&#xA;I go to a French meetup to practice in person&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;, and&#xA;I practice at work with a Francophone friend during breakfast.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s very important to learn the grammar for both listening and speaking. For example, in French,&#xA;I&amp;rsquo;d always wonder what &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;en&lt;/code&gt; meant in some sentences. After watching &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=OHQPlvD1ypc&#34;target=&#34;_blank&#34;&gt;this video&lt;/a&gt;&#xA;&#xA;&#xA;I learned that it refers to a previously mentioned place.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s actually not hard to find a program to learn grammar in a structured way,&#xA;following &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=I_3GvRAZfvQ&#34;target=&#34;_blank&#34;&gt;Iclal&amp;rsquo;s advice&lt;/a&gt;&#xA;&#xA;,&#xA;I searched for playlists and found &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=hd0_GZHHWeE&amp;amp;list=PLV1-QgpUU7N2TVWS6gEVMqEfAFjAl-DV6&#34;target=&#34;_blank&#34;&gt;Learn French with Alexa&lt;/a&gt;&#xA;&#xA;&amp;rsquo;s&#xA;playlist perfect.&lt;/p&gt;&#xA;&lt;p&gt;I reached a point where I&amp;rsquo;m actively practicing grammar, vocabulary (new and existing words) and speaking&#xA;the language whenever I have the chance.&lt;/p&gt;&#xA;&lt;p&gt;Next on my journey is a visit to France for some immersion time to&#xA;practice speaking and listening to French every day.&lt;/p&gt;&#xA;&lt;h3 id=&#34;self-learning-tools&#34;&gt;Self learning tools&lt;/h3&gt;&#xA;&lt;p&gt;I use the following tools:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Youtube&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I look for videos in French that have subtitles in both French and English&#xA;on a topic I&amp;rsquo;m interested in. Initially, it was very simple&#xA;content about &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=ERU1mqafydA&#34;target=&#34;_blank&#34;&gt;everyday activities&lt;/a&gt;&#xA;&#xA;.&#xA;Now, I combine that and podcasts about topics I&amp;rsquo;m interested in.&lt;/li&gt;&#xA;&lt;li&gt;My favorite channels are:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/@Frenchinmotion&#34;target=&#34;_blank&#34;&gt;French In Motion&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/@FrenchWithPanache&#34;target=&#34;_blank&#34;&gt;French With Panache&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/@EasyFrench&#34;target=&#34;_blank&#34;&gt;Easy French&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/@FrenchFacile12&#34;target=&#34;_blank&#34;&gt;French Facile 12&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=hd0_GZHHWeE&amp;amp;list=PLV1-QgpUU7N2TVWS6gEVMqEfAFjAl-DV6&#34;target=&#34;_blank&#34;&gt;Learn French With Alexa&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://readlang.com/&#34;target=&#34;_blank&#34;&gt;Readlang&lt;/a&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Readlang is my favorite tool for practicing reading and listening.&lt;/li&gt;&#xA;&lt;li&gt;I like that the transcription is interactive; if I don&amp;rsquo;t know a word, I can click/tap on it, and&#xA;it&amp;rsquo;ll highlight it and save it on its database (with the translation and the surrounding context).&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s web-based, so I can access it from my phone and my laptop without installing any software.&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s very affordable compared to similar tools like LingQ (just ~$50 US per year) and also&#xA;has a free version.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://apps.ankiweb.net/&#34;target=&#34;_blank&#34;&gt;Anki&lt;/a&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To practice new words through spaced repetition. It&amp;rsquo;s a great complementary tool to Readlang.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.linguno.com/&#34;target=&#34;_blank&#34;&gt;Linguno&lt;/a&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I use it to practice verb conjugation and refine my French. I wouldn&amp;rsquo;t recommend using it when starting out.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;my-learning-process-through-podcasts&#34;&gt;My learning process through podcasts&lt;/h3&gt;&#xA;&lt;p&gt;My current setup involves podcasts, Readlang and Anki:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I search for a podcast on a topic that I like in the channels above and import it to Readlang.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Download the audio (I use &lt;code&gt;yt-dlp -x --audio-format mp3 &amp;quot;&amp;lt;youtube-link&amp;gt;&amp;quot;&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Upload the mp3 to &#xA;&#xA;&lt;a href=&#34;https://readlang.com/upload&#34;target=&#34;_blank&#34;&gt;https://readlang.com/upload&lt;/a&gt;&#xA;&#xA; and &#xA;&#xA;&lt;a href=&#34;https://forum.readlang.com/t/synchronize-transcriptions-to-youtube-videos/30&#34;target=&#34;_blank&#34;&gt;sync&#xA;the audio with a Youtube video&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;I start a lesson in Readlang and learn new words by clicking/tapping on them.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;spaced-repetition&#34;&gt;Spaced Repetition&lt;/h3&gt;&#xA;&lt;p&gt;I use spaced repetition to review words and phrases that I just learned or that I want to learn.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In Readlang, I export new phrases/words that I&amp;rsquo;ve learned to an Anki-compatible file.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Go to &#xA;&#xA;&lt;a href=&#34;https://readlang.com/words&#34;target=&#34;_blank&#34;&gt;https://readlang.com/words&lt;/a&gt;&#xA;&#xA;, select all words, and export them.&lt;/li&gt;&#xA;&lt;li&gt;Export settings:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Content to export: Context (Anki cloze with translation), word frequency.&lt;/li&gt;&#xA;&lt;li&gt;Delimiter: Semicolon&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;I upload the file to Anki desktop and synchronize it.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Import file &amp;gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Import Options &amp;gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Note file: cloze&lt;/li&gt;&#xA;&lt;li&gt;Deck: My French words and phrases&lt;/li&gt;&#xA;&lt;li&gt;Existing notes: update&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Field mapping&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Text: map to &amp;ldquo;1: &amp;quot;&lt;/li&gt;&#xA;&lt;li&gt;Frequency: map to &amp;ldquo;2:&amp;rdquo;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Click on Sync to synchronize.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Now the words are in my Anki cloud account. On my phone, I open Anki, synchronize the words,&#xA;and have daily sessions where I practice the words I&amp;rsquo;ve learned and their meanings with enough&#xA;context to make sense of them.&lt;/p&gt;&#xA;&lt;h3 id=&#34;learning-grammar-with-examples&#34;&gt;Learning grammar with examples&lt;/h3&gt;&#xA;&lt;p&gt;I follow a structured grammar program generated with AI. I asked Gemini with Deep Research&#xA;to figure out a plan to learn grammar for my current level and it created a very detailed&#xA;document with a step by step grammar program.&lt;/p&gt;&#xA;&lt;p&gt;For any grammar topic that I want to learn in depth I learn by example and with spaced&#xA;repetition. I use the following prompt to generate examples for Anki.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;**Subject:** French Grammar Anki Card Generation&#xA;&#xA;**Topics:**&#xA;&#xA;\`\`\`&#xA;[PASTE YOUR LEARNING TOPICS HERE]&#xA;\`\`\`&#xA;&#xA;**Task:** Based *only* on the topics provided above, generate a list of examples for each concept and sub-concept.&#xA;&#xA;**Rules for Generation:**&#xA;&#xA;1. **Quantity:** Generate at least **50 examples** for *each* major concept listed.&#xA;2. **Complexity:** The examples must have varied complexity: include simple, intermediate, and very hard sentences.&#xA;3. **Format:** Generate a CSV file with **no header row** and use a **semicolon (;) as the separator**.&#xA;4. **Columns:** The CSV must have exactly three columns: `Text`, `Frequency`, `Context`.&#xA;&#xA;**Column-Specific Instructions:**&#xA;&#xA;**1\. `Text` Column:**&#xA;&#xA;* **Format:** Must use the Anki cloze format: `{{c1::Phrase in French::meaning in English}}`.&#xA;* **Content:** The cloze deletion *must* be a full sentence in French, or at least a complete clause&#xA;  that makes sense on its own.&#xA;* **Conversational Context:** To provide a real-life conversational setting, you must add 1-2 short&#xA;  supporting sentences before and after the main sentence.&#xA;  * **Crucially:** These extra context sentences must be *outside* the `{{c1::...}}` cloze block.&#xA;  * **Example:** `Salut ça va ? {{c1::Je vais bien::I am doing well}}, merci.` (Here, `Salut ça va ?`&#xA;    is the conversational context).&#xA;&#xA;**2\. `Frequency` Column:**&#xA;&#xA;* **Content:** A number between **1** and **100**.&#xA;* **Meaning:** **1** \= this exact phrase is *highly likely* to be used in daily conversation. **100** \=&#xA;  this phrase is grammatically correct but *highly unlikely* to be used (e.g., very formal, obscure, or overly complex).&#xA;&#xA;**3\. `Context` Column:**&#xA;&#xA;* **Content:** A detailed explanation of the grammar rule being demonstrated in the `Text` field.&#xA;* **Clarity:** Explain *why* the specific form was used (e.g., &amp;quot;The adjective &#39;petite&#39; is used because it must agree&#xA;  in gender (feminine) and number (singular) with the noun &#39;fille&#39;&amp;quot;).&#xA;* **Restriction:** **DO NOT** add *any* sources, pointers to sources, or references to lesson numbers (e.g., &amp;quot;L33&amp;quot;).&#xA;  The explanation must stand on its own.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The output looks like this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;Qui es-tu ? {{c1::Je suis::I am}} étudiant à l&#39;université.;1;This uses the present tense conjugation of the irregular verb *Être* (to be) for the first-person singular subject &#39;je&#39;.&#xA;Tu as l&#39;air fatigué. {{c1::Oui, je suis::Yes, I am}} un peu malade.;1;This uses the present tense conjugation of *Être* for the first-person singular &#39;je&#39;.&#xA;...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I save the output to a file and import the file to Anki.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-ultimate-immersion-traveling&#34;&gt;The Ultimate Immersion: Traveling&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m at a point where I could travel to France and immerse myself in the culture&#xA;and the language. Immersion will definitely accelerate my speaking skills.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;Learning a language by applying the comprehensible input method accelerated my progress.&#xA;None of it would have been possible without putting effort every time that I can.&#xA;Discipline and consistency are the key.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/@laoshu505000&#34;target=&#34;_blank&#34;&gt;laoshu50500 was a polyglot Youtuber and a language teacher&lt;/a&gt;&#xA;&#xA;&#xA;who recorded his interactions with people in lots of languages.&#xA;Watch a few videos and you&amp;rsquo;ll see how good it feels to talk with someone else in their native language.&#xA;RIP Moses.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Spill_Tab&#34;target=&#34;_blank&#34;&gt;Claire Chicha&lt;/a&gt;&#xA;&#xA;&amp;rsquo;s stage name is Spill Tab. She was born in Bangkok and spent&#xA;time growing up in Paris, Los Angeles and Bangkok. She sings in both English and French.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;I remember the first time I listened to L&amp;rsquo;été indien by Joe Dassin, and I was surprised that he is literally just speaking&#xA;the language (without a melody) for most of the song.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:4&#34;&gt;&#xA;&lt;p&gt;Not that it&amp;rsquo;s a bad idea, but the method of learning grammar (verbs and their conjugations) didn&amp;rsquo;t work &lt;strong&gt;initially&lt;/strong&gt; for me.&#xA;Doing the homework helped a lot, though.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:5&#34;&gt;&#xA;&lt;p&gt;I found it interesting that the first time I went to a French meetup, I could understand&#xA;a lot of what people were saying, but the words didn&amp;rsquo;t come quickly when I tried to speak. However, the more I go, the&#xA;easier it gets to enter a flow state where my mind doesn&amp;rsquo;t think about translating words anymore.&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Tmux to Zellij (and back)</title>
      <link>https://www.mauriciopoppe.com/notes/tmux-to-zellij/</link>
      <pubDate>Sat, 21 Jun 2025 14:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/tmux-to-zellij/</guid>
      <description>&lt;p&gt;My terminal is my primary workspace. It&amp;rsquo;s where I live for most of the day: writing code, running agents, and managing servers. A multiplexer is the glue that holds it all together, keeping my context alive even if my connection drops.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve used Tmux for years. It’s stable, stays out of my way, and fits the Unix philosophy of being a simple tool that&amp;rsquo;s easy to script. It turns my terminal into a series of project workspaces that I can jump between instantly.&lt;/p&gt;&#xA;&lt;p&gt;When I look at a multiplexer, I have a few non-negotiables:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Remote-First Workflow&lt;/strong&gt;: My laptop is basically a thin client. Most of my work happens on remote workstations via SSH, so the multiplexer has to run there and survive network drops.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Unified Shortcuts&lt;/strong&gt;: I need my environment to be identical at work and at home. I don&amp;rsquo;t want to waste mental energy on different keybindings for different machines.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Named Sessions&lt;/strong&gt;: I need to organize work into named projects that I can detach from and return to later, exactly where I left off.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Fast Pane Management&lt;/strong&gt;: Splitting the terminal horizontally or vertically should be second nature.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Vim Integration&lt;/strong&gt;: Navigating between Neovim and terminal panes needs to be seamless, using the same directional keys (&lt;code&gt;Ctrl + h/j/k/l&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Fuzzy Session Switching&lt;/strong&gt;: I need a fast way to jump between projects using a launcher that combines active sessions and bookmarked directories.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Tmux handles all of this easily, mostly because its CLI is so flexible. I can extend its behavior with simple shell scripts and &lt;code&gt;fzf&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-current-workflow&#34;&gt;My Current Workflow&lt;/h2&gt;&#xA;&lt;p&gt;I’ve written about my setup in more detail in my &#xA;&#xA;&lt;a href=&#34;../productivity-skills/&#34;target=&#34;_blank&#34;&gt;Productivity&lt;/a&gt;&#xA;&#xA; post, where I go into how I use Tmux, Neovim, and Zsh to stay organized. But when Zellij started getting more attention, I was curious to see if a &amp;ldquo;modern&amp;rdquo; take on the multiplexer could actually improve things.&lt;/p&gt;&#xA;&lt;h2 id=&#34;learning-zellij&#34;&gt;Learning Zellij&lt;/h2&gt;&#xA;&lt;p&gt;Zellij is very approachable. You can start it with a single command, and the built-in UI guides you through the basics. I particularly liked the command mode toolbar because it shows you the available shortcuts for whichever mode you&amp;rsquo;re in, which is great for building muscle memory. It feels a lot like the &lt;code&gt;which-key.nvim&lt;/code&gt; plugin for Neovim.&lt;/p&gt;&#xA;&lt;p&gt;It also uses a modal system (Normal, Insert, Pane, etc.) that feels very familiar to anyone used to Vim.&lt;/p&gt;&#xA;&lt;p&gt;The configuration uses &#xA;&#xA;&lt;a href=&#34;https://kdl.dev/&#34;target=&#34;_blank&#34;&gt;KDL&lt;/a&gt;&#xA;&#xA;. It’s a fine language, but it&amp;rsquo;s yet another syntax to learn. Zellij originally supported YAML but &#xA;&#xA;&lt;a href=&#34;https://zellij.dev/news/config-command-layouts/#addendum-why-did-we-choose-kdl&#34;target=&#34;_blank&#34;&gt;switched to KDL&lt;/a&gt;&#xA;&#xA; to avoid some of YAML&amp;rsquo;s downsides.&lt;/p&gt;&#xA;&lt;h2 id=&#34;setting-up-key-bindings-and-workspaces&#34;&gt;Setting up key bindings and workspaces&lt;/h2&gt;&#xA;&lt;p&gt;I wanted to mirror my Tmux muscle memory as closely as possible. In my &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles/blob/main/zellij/config.kdl&#34;target=&#34;_blank&#34;&gt;config.kdl&lt;/a&gt;&#xA;&#xA;, I set up these mappings:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;Ctrl + Space&lt;/code&gt; as my prefix (the &amp;ldquo;Tmux mode&amp;rdquo;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;\&lt;/code&gt; for vertical splits and &lt;code&gt;-&lt;/code&gt; for horizontal ones.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Ctrl + h/j/k/l&lt;/code&gt; for directional navigation.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The first real friction point was that Zellij&amp;rsquo;s modes often conflict with Neovim&amp;rsquo;s. To keep navigation fluid, I had to bring in a couple of plugins.&lt;/p&gt;&#xA;&lt;p&gt;I used &#xA;&#xA;&lt;a href=&#34;https://github.com/fresh2dev/zellij-autolock&#34;target=&#34;_blank&#34;&gt;zellij-autolock&lt;/a&gt;&#xA;&#xA; to detect when I&amp;rsquo;m in a Neovim pane and automatically switch Zellij to &amp;ldquo;Locked&amp;rdquo; mode so it doesn&amp;rsquo;t intercept my Vim keys. On the Vim side, &#xA;&#xA;&lt;a href=&#34;https://github.com/fresh2dev/zellij.vim&#34;target=&#34;_blank&#34;&gt;zellij.vim&lt;/a&gt;&#xA;&#xA; handles the communication back to Zellij.&lt;/p&gt;&#xA;&lt;p&gt;It works, but it feels like a bit of a hack. It relies on &#xA;&#xA;&lt;a href=&#34;https://github.com/fresh2dev/zellij-autolock/blob/5346d7f45e5a54e1d906aba43ed1c063987aa135/src/main.rs#L79&#34;target=&#34;_blank&#34;&gt;timers and workarounds&lt;/a&gt;&#xA;&#xA;, which means if I move between panes too fast, the synchronization occasionally trips up.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-session-launcher&#34;&gt;The Session Launcher&lt;/h2&gt;&#xA;&lt;p&gt;I need to be able to hit a key, find a project, and jump into its workspace (creating it if it doesn&amp;rsquo;t exist) in one motion.&lt;/p&gt;&#xA;&lt;p&gt;Zellij has a built-in session manager with a nice UI, but it felt too prescriptive to me. It wants you to manage sessions its way, and it doesn&amp;rsquo;t play as nicely with external tools like &lt;code&gt;fzf&lt;/code&gt;. This is where I started missing Tmux&amp;rsquo;s minimalism.&lt;/p&gt;&#xA;&lt;p&gt;In Tmux, I use a &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles/blob/main/zsh/bin/tmux-switch-client.py&#34;target=&#34;_blank&#34;&gt;python script&lt;/a&gt;&#xA;&#xA; to aggregate project bookmarks and active sessions, then pipe them into &lt;code&gt;fzf&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;# Simplified version of my setup&#xA;( cat $bookmarks &amp;amp;&amp;amp; tmux ls ) | fzf --tmux | xargs tmux switch-client -t&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Zellij doesn&amp;rsquo;t have a direct equivalent to &lt;code&gt;tmux switch-client&lt;/code&gt; in its CLI. I was surprised that I had to install a third-party plugin (&#xA;&#xA;&lt;a href=&#34;https://github.com/mostafaqanbaryan/zellij-switch&#34;target=&#34;_blank&#34;&gt;zellij-switch&lt;/a&gt;&#xA;&#xA;) just to get this basic functionality. According to this &#xA;&#xA;&lt;a href=&#34;https://www.reddit.com/r/zellij/comments/18go1y5/switching_sessions_via_cli/&#34;target=&#34;_blank&#34;&gt;Reddit thread&lt;/a&gt;&#xA;&#xA;, plugins are currently the intended way to handle this.&lt;/p&gt;&#xA;&lt;p&gt;I ended up writing a shell script called &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles/blob/main/zsh/bin/zellij-switch-session.py&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;zellij-switch-session&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; and mapping it to &lt;code&gt;Ctrl + Space&lt;/code&gt; + &lt;code&gt;Ctrl + J&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/zellij-switch-session.gif&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p&gt;&#xA;        Demo of switching sessions with Zellij&#xA;        &#xA;            &#xA;        &#xA;        &lt;/p&gt; &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;the-verdict&#34;&gt;The Verdict&lt;/h2&gt;&#xA;&lt;p&gt;After using Zellij for three weeks, I went back to Tmux. There are several things I liked about Zellij:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Editor Integration&lt;/strong&gt;: Being able to open the current pane&amp;rsquo;s output directly in Neovim for searching is great.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Discovery&lt;/strong&gt;: The command toolbar is a great way to learn shortcuts without constantly checking a cheatsheet.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Layout Isolation&lt;/strong&gt;: Resizing a pane from within (like opening a debugger UI in Vim) doesn&amp;rsquo;t mess up the rest of the window&amp;rsquo;s layout.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Persistent Zoom&lt;/strong&gt;: If you zoom into a pane, it stays zoomed even if you switch to another pane and back.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;However, a few things kept grating on me:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;No &amp;ldquo;Last Session&amp;rdquo; Shortcut&lt;/strong&gt;: Tmux has a native way to toggle between your current and previous session (&lt;code&gt;switch-client -l&lt;/code&gt;). I use this constantly. In Zellij, I&amp;rsquo;d have to type out the session name or use the launcher every time.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;No Mouse Resizing&lt;/strong&gt;: I couldn&amp;rsquo;t find a way to resize panes with the mouse; I had to use keybindings for everything.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Unresponsive Panes&lt;/strong&gt;: If a pane gets stuck, Tmux lets me &lt;code&gt;respawn-pane -k&lt;/code&gt; to force-restart it. I couldn&amp;rsquo;t find an easy equivalent in Zellij.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Layout Quirks&lt;/strong&gt;: I ran into a few bugs where temporary panes would cause the layout to shift unexpectedly after switching sessions.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Zellij is a great project, and for many people, the out-of-the-box experience will be much better than Tmux. But for my specific, script-heavy workflow, Tmux&amp;rsquo;s simplicity is still hard to beat.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Creating a Backing Track from Your Favorite Song for an Open Mic</title>
      <link>https://www.mauriciopoppe.com/notes/backing-track-for-open-mic/</link>
      <pubDate>Sun, 01 Dec 2024 14:49:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/backing-track-for-open-mic/</guid>
      <description>&lt;p&gt;I play the guitar and sing in open mics in my spare time. To perform, I usually play with a backing&#xA;track but sometimes it&amp;rsquo;s hard to find a &amp;ldquo;karaoke&amp;rdquo; version and even harder to find one with&#xA;all my desired instruments (I&amp;rsquo;d like to hear everything but the guitar because I&amp;rsquo;m going to play it!).&lt;/p&gt;&#xA;&lt;p&gt;There are a few ways to create a backing track from a song (maybe there are more but these are&#xA;the ones that I know of):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;With Logic Pro for iPad: Since 2024 it has a way to split&#xA;a song into tracks (bass, drums, other, vocals). This feature is called&#xA;&#xA;&#xA;&lt;a href=&#34;https://support.apple.com/guide/logicpro-ipad/extract-vocal-instrumental-stems-stem-lpip1b60ada3/ipados&#34;target=&#34;_blank&#34;&gt;stem splitter&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;With &#xA;&#xA;&lt;a href=&#34;https://github.com/facebookresearch/demucs&#34;target=&#34;_blank&#34;&gt;Demucs&lt;/a&gt;&#xA;&#xA;, which is an open-source tool capable of separating&#xA;drums, bass, and vocals from the rest of the accompaniment.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It has a feature where it can split a song using more instruments (bass, drums, guitar, other, piano, vocals).&#xA;In this mode, I can keep important tracks in the backing track, such as the &amp;ldquo;other&amp;rdquo; and &amp;ldquo;piano&amp;rdquo; tracks,&#xA;which make the backing track feel complete.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In this article, I show how to use Demucs to split a song into tracks.&lt;/p&gt;&#xA;&lt;h2 id=&#34;splitting-a-song-with-demucs&#34;&gt;Splitting a song with Demucs&lt;/h2&gt;&#xA;&lt;h3 id=&#34;high-level-steps&#34;&gt;High level steps&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Install essential tools:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://git-scm.com/downloads&#34;target=&#34;_blank&#34;&gt;Git&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.python.org/downloads/&#34;target=&#34;_blank&#34;&gt;Python&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Download dependencies (there&amp;rsquo;s an automated step to download these below).&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Install &#xA;&#xA;&lt;a href=&#34;https://github.com/yt-dlp/yt-dlp&#34;target=&#34;_blank&#34;&gt;yt-dlp&lt;/a&gt;&#xA;&#xA; to download your song (if you have your song, skip this step).&lt;/li&gt;&#xA;&lt;li&gt;Install &#xA;&#xA;&lt;a href=&#34;https://github.com/facebookresearch/demucs/&#34;target=&#34;_blank&#34;&gt;Demucs&lt;/a&gt;&#xA;&#xA; to split the track.&lt;/li&gt;&#xA;&lt;li&gt;Install &#xA;&#xA;&lt;a href=&#34;https://ffmpeg.org/&#34;target=&#34;_blank&#34;&gt;FFmpeg&lt;/a&gt;&#xA;&#xA; to combine selected tracks into a combined track.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Download your song with &lt;code&gt;yt-dlp&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Separate the track with &lt;code&gt;Demucs&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Join the drums/bass/other tracks with &lt;code&gt;FFmpeg&lt;/code&gt; into a track that you can use as your backing track!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;download-demucs-dependencies&#34;&gt;Download demucs dependencies&lt;/h3&gt;&#xA;&lt;p&gt;The assumption is that you already have Git and Python installed.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/open-mic&#34;target=&#34;_blank&#34;&gt;I&amp;rsquo;ve created a project&lt;/a&gt;&#xA;&#xA; that has a file with all the dependencies to install.&#xA;You just need to clone the repository and use the &lt;code&gt;requirements.txt&lt;/code&gt; file to install the dependencies.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;git clone https://github.com/mauriciopoppe/open-mic&#xA;cd open-mic&#xA;python3 -m venv venv&#xA;source venv/bin/activate&#xA;python3 -m pip install -r requirements.txt&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;download-your-song&#34;&gt;Download your song&lt;/h3&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll create a backing track with bass, drums, piano, and other instruments for the song&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=A9B1Uo-VQas&#34;target=&#34;_blank&#34;&gt;December 21 by Prince Royce&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;iframe class=&#34;tw-mx-auto tw-aspect-video md:tw-w-full&#34; src=&#34;https://www.youtube.com/embed/A9B1Uo-VQas?si=OILLax2aDMwMna8D&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;p&gt;First, let&amp;rsquo;s download the song, assuming that it&amp;rsquo;s on YouTube:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;yt-dlp -x --audio-format mp3 &amp;lt;youtube-link-to-song&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;yt-dlp -x --audio-format mp3 &amp;quot;https://www.youtube.com/watch?v=A9B1Uo-VQas&amp;quot;&#xA;[youtube] Extracting URL: https://www.youtube.com/watch?v=A9B1Uo-VQas&#xA;[youtube] A9B1Uo-VQas: Downloading webpage&#xA;[youtube] A9B1Uo-VQas: Downloading ios player API JSON&#xA;[youtube] A9B1Uo-VQas: Downloading android player API JSON&#xA;[youtube] A9B1Uo-VQas: Downloading player b46bb280&#xA;WARNING: [youtube] A9B1Uo-VQas: nsig extraction failed: You may experience throttling for some formats&#xA;         n = CN0_8RV0LjPMw_i9xJs ; player = https://www.youtube.com/s/player/b46bb280/player_ias.vflset/en_US/base.js&#xA;WARNING: [youtube] A9B1Uo-VQas: nsig extraction failed: You may experience throttling for some formats&#xA;         n = it19Djd_eJ-wpANfMuK ; player = https://www.youtube.com/s/player/b46bb280/player_ias.vflset/en_US/base.js&#xA;[youtube] A9B1Uo-VQas: Downloading m3u8 information&#xA;[info] A9B1Uo-VQas: Downloading 1 format(s): 140&#xA;[download] Destination: Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas].m4a&#xA;[download] 100% of    3.30MiB in 00:00:00 at 7.11MiB/s&#xA;[FixupM4a] Correcting container of &amp;quot;Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas].m4a&amp;quot;&#xA;[ExtractAudio] Destination: Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas].mp3&#xA;Deleting original file Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas].m4a (pass -k to keep)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The track is downloaded in the same location as where the command was run.&lt;/p&gt;&#xA;&lt;p&gt;Next, let&amp;rsquo;s use &lt;code&gt;Demucs&lt;/code&gt; to separate the track into different instrument tracks.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;demucs -n htdemucs_6s --mp3 -j 2 &amp;lt;path-to-downloaded-song&amp;gt;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;demucs -n htdemucs_6s --mp3 -j 2 &amp;quot;Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas].mp3&amp;quot;&#xA;Selected model is a bag of 1 models. You will see that many progress bars per track.&#xA;Separated tracks will be stored in /Users/mauriciopoppe/go/src/github.com/mauriciopoppe/open-mic/separated/htdemucs_6s&#xA;Separating track Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas].mp3&#xA;100%|██████████████████████████████████████████████████████████████████████| 216.45/216.45 [01:28&amp;lt;00:00,  2.46seconds/s]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;Demucs&lt;/code&gt; created multiple files in the directory &lt;code&gt;separated&lt;/code&gt;. Let&amp;rsquo;s list them:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;tree separated/&#xA;separated/&#xA;└── htdemucs_6s&#xA;    └── Prince Royce - Dec. 21 (Official Video) [A9B1Uo-VQas]&#xA;        ├── bass.mp3&#xA;        ├── drums.mp3&#xA;        ├── guitar.mp3&#xA;        ├── other.mp3&#xA;        ├── piano.mp3&#xA;        └── vocals.mp3&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Finally, let&amp;rsquo;s join the bass, drums, other, and piano tracks with &lt;code&gt;FFmpeg&lt;/code&gt; into the combined file &lt;code&gt;combined.mp3&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;cd separated/htdemucs_6s/Prince\ Royce\ -\ Dec.\ 21\ \(Official\ Video\)\ \[A9B1Uo-VQas\]/&#xA;ffmpeg -i bass.mp3 -i drums.mp3 -i other.mp3 -i piano.mp3 -filter_complex amix=inputs=4:normalize=0 combined.mp3&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s compare the original song with two versions of the backing track, one with bass and drums (no voice or guitar) and the other with bass, drums, other and piano (no voice or guitar).&lt;/p&gt;&#xA;&lt;div class=&#34;tw-grid md:tw-grid-cols-2 tw-gap-4 tw-mb-5&#34;&gt;&#xA;  &lt;div class=&#34;tw-font-bold&#34;&gt;Song&lt;/div&gt;&#xA;  &lt;div class=&#34;tw-font-bold&#34;&gt;Sample Audio&lt;/div&gt;&#xA;  &lt;div&gt;Original song (voice and all instruments)&lt;/div&gt;&#xA;  &lt;div&gt;&lt;audio controls src=&#34;https://www.mauriciopoppe.com/audio/original-open-mic.mp3&#34;&gt;&lt;/audio&gt;&lt;/div&gt;&#xA;  &lt;div&gt;Backing track (bass, drums), no voice or guitar. This is what you&#39;d get using Logic Pro&#39;s stem split feature.&lt;/div&gt;&#xA;  &lt;div&gt;&lt;audio controls src=&#34;https://www.mauriciopoppe.com/audio/bass-drums-open-mic.mp3&#34;&gt;&lt;/audio&gt;&lt;/div&gt;&#xA;  &lt;div&gt;Backing track (bass, drums, other, piano), no voice or guitar created with Demucs.&lt;/div&gt;&#xA;  &lt;div&gt;&lt;audio controls src=&#34;https://www.mauriciopoppe.com/audio/combined-open-mic.mp3&#34;&gt;&lt;/audio&gt;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;As you can hear, the backing track created with Demucs has lots of details from the original song minus&#xA;the voice or guitar which is exactly what I need. &lt;code&gt;Demucs&lt;/code&gt; is an amazing tool and so useful for open mics!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Bachata</title>
      <link>https://www.mauriciopoppe.com/notes/bachata/</link>
      <pubDate>Sun, 17 Nov 2024 14:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/bachata/</guid>
      <description>&lt;h2 id=&#34;learning-to-dance&#34;&gt;Learning to Dance&lt;/h2&gt;&#xA;&lt;p&gt;I had my first dancing experience in San Francisco in 2018. I went with a friend to &#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/uuDZS1xETcHuSY4u9&#34;target=&#34;_blank&#34;&gt;Space 550&lt;/a&gt;&#xA;&#xA;,&#xA;a Latin nightclub where I had an intro class to salsa. I didn&amp;rsquo;t enjoy it that much because&#xA;I was new to it and because you have to be a good leader (or at least&#xA;a leader with enough decent moves) to start enjoying it.&lt;/p&gt;&#xA;&lt;p&gt;I decided to try again in late 2021 at a dance academy in South San Jose called&#xA;&#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/DQBuveR36jZMmULG8&#34;target=&#34;_blank&#34;&gt;Dance Boulevard&lt;/a&gt;&#xA;&#xA;. They had a $90 all-you-can-dance&#xA;1-month package where I got to try different types of dance, including salsa, bachata, and ballroom.&#xA;I went to all the classes and initially, I focused on getting better at salsa. Over the next&#xA;few weeks, I realized that bachata was more fun not only to dance to but to listen to. The salsa and&#xA;bachata counts are similar (1 to 8). I felt that salsa was faster and more fluid, while&#xA;bachata is more relaxed and you can slow down on steps 4 and 8. Over the next few months, I spent&#xA;listening to bachata music way more, and I started enjoying the music too. It&amp;rsquo;s just very, very fun.&lt;/p&gt;&#xA;&lt;p&gt;While I could keep on dancing both, I decided I&amp;rsquo;d stick to bachata for the long run.&lt;/p&gt;&#xA;&lt;p&gt;Dancing bachata is perfect for me because:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;First and foremost, it&amp;rsquo;s fun.&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s a way to do cardio and improves my fitness.&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s a great way to make friends and connections with people that like bachata as much as you do.&lt;/li&gt;&#xA;&lt;li&gt;(Bonus) It&amp;rsquo;s a perfect excuse to travel. My excuse is the dance festivals happening all around the world.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;my-bachata-journey&#34;&gt;My Bachata Journey&lt;/h2&gt;&#xA;&lt;h3 id=&#34;how-do-you-get-better-at-it&#34;&gt;How do you get better at it?&lt;/h3&gt;&#xA;&lt;p&gt;The steps to get better are simple. You go to group classes and learn a few moves.&#xA;If there are dance socials right after the class, you stay and practice the moves you learned.&#xA;Then at home, you practice on your own. I focus a lot on perfecting isolations&#xA;(targeted movement of a part of my body) so that the follower can feel the next move I&amp;rsquo;d like to do.&#xA;Finally, you go to the social dance nights every week to apply what you learned in classes and on your own.&lt;/p&gt;&#xA;&lt;p&gt;I liked going to bachata festivals to learn new moves. On my first festivals, I went to most of the classes&#xA;over the 3 days I was there. Looking back, there are too many moves to learn, and I felt drained to go to the&#xA;social dance nights by the end of the day. For future festivals, I decided to pick a few classes&#xA;that matched my style (I like sensual bachata), and the rest of the time I&amp;rsquo;d spend exploring the town.&#xA;Then later, I&amp;rsquo;d go back to the hotel, rest, and go to the social dance night, which usually starts very late,&#xA;after midnight.&lt;/p&gt;&#xA;&lt;p&gt;Nowadays, I spend my free time at home practicing a small set of moves and some variations. As I mentioned&#xA;before, I also practice isolations a lot. My teacher says that we should dominate the fundamentals, and that&amp;rsquo;s&#xA;exactly what I focus on at home over and over again. To learn new combos, I use &#xA;&#xA;&lt;a href=&#34;https://bachatasteps.com/&#34;target=&#34;_blank&#34;&gt;https://bachatasteps.com/&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;On the dance floor, there are good days and bad days. Days where you feel the flow of the music and all the moves&#xA;click in your head, and days where you don&amp;rsquo;t feel the flow of the music at all. Days where you dance with a follower&#xA;and all of the moves and their transitions seem so effortless, and days where you can&amp;rsquo;t make a connection&#xA;with a follower and they seem disinterested and the moves don&amp;rsquo;t go with the flow. It&amp;rsquo;s just another day.&lt;/p&gt;&#xA;&lt;p&gt;It&amp;rsquo;s a lifelong hobby, so let&amp;rsquo;s just enjoy the process.&lt;/p&gt;&#xA;&lt;h3 id=&#34;2021---starting-my-dancing-journey&#34;&gt;2021 - Starting my dancing journey&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I started dancing bachata in late 2021 at a dance academy in South San Jose called&#xA;&#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/DQBuveR36jZMmULG8&#34;target=&#34;_blank&#34;&gt;Dance Boulevard&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;I went a couple of times to &#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/USpxuamQjr8MG86B6&#34;target=&#34;_blank&#34;&gt;Alberto&amp;rsquo;s Night Club&lt;/a&gt;&#xA;&#xA;,&#xA;a dance nightclub in Mountain View. I didn&amp;rsquo;t enjoy it much because I was still a beginner and&#xA;because the dancing space was very small.&lt;/li&gt;&#xA;&lt;li&gt;On a few Saturday nights, I went to &#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/uuDZS1xETcHuSY4u9&#34;target=&#34;_blank&#34;&gt;Space 550&lt;/a&gt;&#xA;&#xA; in San Francisco.&#xA;This is where I met a dance instructor called Kathy Reyes, who became my first bachata teacher.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2022---the-year-of-the-bachata-festivals&#34;&gt;2022 - The year of the bachata festivals&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;On weekday nights, I went to Berkeley to dance with &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/krdance.official&#34;target=&#34;_blank&#34;&gt;Kathy Reyes&lt;/a&gt;&#xA;&#xA;.&#xA;She liked traditional bachata, so I got to learn lots of footsteps. Every week, we&amp;rsquo;d learn a new combo and practice&#xA;in a mini social night event afterwards.&lt;/li&gt;&#xA;&lt;li&gt;On weekday nights, I went to &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/studiomballroom/&#34;target=&#34;_blank&#34;&gt;Studio M in San Jose&lt;/a&gt;&#xA;&#xA; to dance&#xA;with &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/knockout_ngoc/&#34;target=&#34;_blank&#34;&gt;Ngoc Huynh&lt;/a&gt;&#xA;&#xA;, who was my 2nd bachata teacher. I met her&#xA;at a Sunday social dance event in San Francisco. I really like her energy and humor; she&amp;rsquo;s a great teacher as well.&lt;/li&gt;&#xA;&lt;li&gt;On Saturdays, I went to the socials at &#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/uuDZS1xETcHuSY4u9&#34;target=&#34;_blank&#34;&gt;Space 550&lt;/a&gt;&#xA;&#xA; in San Francisco.&lt;/li&gt;&#xA;&lt;li&gt;I learned about bachata festivals happening all around the US. They were a perfect excuse to start traveling more&#xA;and to explore the US. The festivals are usually 4-day long events where multiple bachata professional teachers&#xA;teach you new combos in the afternoon, and there are huge social dance events at night.&#xA;Initially, I went to the classes to learn new combos, but there are too many classes and too&#xA;many moves to learn that I felt that I was not learning the right way because it was just&#xA;too much content. I decided I&amp;rsquo;d go to a few classes and instead spend my time exploring the&#xA;city where the festivals took place.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Bachata Festival in LA in May.&lt;/li&gt;&#xA;&lt;li&gt;Bachata Festival in Sacramento in June.&lt;/li&gt;&#xA;&lt;li&gt;Bachata social nights in San Diego in July.&lt;/li&gt;&#xA;&lt;li&gt;Bachata Festival in San Francisco in July.&lt;/li&gt;&#xA;&lt;li&gt;Bachata Festival in Miami in September.&lt;/li&gt;&#xA;&lt;li&gt;Bachata social nights in New York in October.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;In the July festival in San Francisco, I met Ataca and La Alemana. They&amp;rsquo;re a very famous&#xA;bachata duo characterized by their romantic dance style. Every time they dance, they show&#xA;a strong dance connection. They do simple moves but with great transitions.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;iframe class=&#34;tw-mx-auto tw-aspect-video md:tw-w-full&#34; src=&#34;https://www.youtube.com/embed/5INazZW8N4g?si=WshRUkW7FnXGfFxR&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I danced with La Alemana in the festival! Fun souvenir, a photo with Ataca y La Alemana:&#xA;&#xA;&#xA;&lt;figure class=&#34;md:tw-w-80 tw-mx-auto&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/me_ataca_alemana.jpg&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p&gt;&#xA;        Yo y Ataca y la Alemana&#xA;        &#xA;            &#xA;        &#xA;        &lt;/p&gt; &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I went to a bachata concert by Prince Royce in San Jose in October.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I created a &lt;a href=&#34;https://www.mauriciopoppe.com/sandbox/jukebox/&#34; target=&#34;_blank&#34;&gt;bachata player website&lt;/a&gt; to mark my love for bachata.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2023---slow-year-in-bachata-dance&#34;&gt;2023 - Slow year in bachata dance&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I stopped dancing in March because of an upcoming move.&lt;/li&gt;&#xA;&lt;li&gt;I moved to NYC in mid-2023.&lt;/li&gt;&#xA;&lt;li&gt;I started dancing again in September at &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/bachatasensual_official/&#34;target=&#34;_blank&#34;&gt;KS Bachata Sensual NYC&lt;/a&gt;&#xA;&#xA; with &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/dancing_steven/&#34;target=&#34;_blank&#34;&gt;Steven Halim&lt;/a&gt;&#xA;&#xA; and &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/kasia.brozynska/&#34;target=&#34;_blank&#34;&gt;Kasia Brozynska&lt;/a&gt;&#xA;&#xA;. In their teaching style,&#xA;they have a 4-week cycle class where you learn a combo and perfect it during the cycle. This style&#xA;is my favorite because I get to perfect a combo and just replay it on the dance floor.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;They also host social night events on Saturday nights. I didn&amp;rsquo;t go to them as much as I wanted.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;I went to a bachata concert by Romeo Santos in New Jersey in November.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2024---making-covers-of-bachata-songs&#34;&gt;2024 - Making covers of bachata songs&lt;/h3&gt;&#xA;&lt;p&gt;One of the reasons I moved to the city is to be more involved in the music scene as a performer.&#xA;I like playing the guitar in my free time, so I decided I&amp;rsquo;d start making covers of bachata songs&#xA;that I like. I started going to a few voice lesson classes to improve my singing skills for&#xA;the open mic events. I also started a YouTube channel where I upload my covers.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I watched Aventura at Madison Square Garden in May.&lt;/li&gt;&#xA;&lt;li&gt;From June to Nov, I kept on going to &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/bachatasensual_official/&#34;target=&#34;_blank&#34;&gt;KS Bachata Sensual NYC&lt;/a&gt;&#xA;&#xA;&#xA;classes on weekdays. I didn&amp;rsquo;t go to socials on Saturdays as often, which is not good!&lt;/li&gt;&#xA;&lt;li&gt;I did my first bachata cover and uploaded it to YouTube. I made a cover of &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=XEUCbvCEjc8&#34;target=&#34;_blank&#34;&gt;Solo Conmigo by Romeo Santos&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;I performed at NY Guitar School with a cover of &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=kADoBrj4934&#34;target=&#34;_blank&#34;&gt;Todavia me Amas by Aventura&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;iframe class=&#34;tw-mx-auto tw-aspect-video md:tw-w-full&#34; src=&#34;https://www.youtube.com/embed/a61hvCOAnCc?si=1b2xZohL_vGAmc2f&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;h3 id=&#34;2025---dancing-around-the-world&#34;&gt;2025 - Dancing around the world&lt;/h3&gt;&#xA;&lt;p&gt;I did a 2-month vacation across Latin America. In addition to exploring new places, I had the&#xA;opportunity to go dancing!&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;San Salvador, El Salvador - I danced at &#xA;&#xA;&lt;a href=&#34;https://maps.app.goo.gl/EhsW2mrA2Sopqh869&#34;target=&#34;_blank&#34;&gt;PÁNUK Centro de Danza&lt;/a&gt;&#xA;&#xA;.&#xA;The DJ would mostly play Salsa (like 5 salsa songs and then 2 bachata songs).&lt;/li&gt;&#xA;&lt;li&gt;Santo Domingo, Dominican Republic - I went to Punta Cana to relax and dance at night.&#xA;When I rented a car, the owner told me that the real bachata scene was in Santo Domingo, so&#xA;I drove a few hours to get there. The owner recommended &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/coritobachatero&#34;target=&#34;_blank&#34;&gt;&amp;ldquo;Corito Bachatero&amp;rdquo;&lt;/a&gt;&#xA;&#xA;,&#xA;and it was amazing! I danced with many Dominican and Colombian girls. This place&#xA;plays a lot of traditional bachata, which I don&amp;rsquo;t usually dance to. I learned that in&#xA;traditional bachata, you don&amp;rsquo;t make a lot of turns. Nevertheless, it was a fun experience.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;my-favorites&#34;&gt;My Favorites&lt;/h2&gt;&#xA;&lt;p&gt;This is a collection of my favorite steps in Bachata or the steps that I do on the dance floor.&#xA;I look at these clips regularly while practicing, and I try them on the dance floor.&lt;/p&gt;&#xA;&lt;h3 id=&#34;dancers&#34;&gt;Dancers&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Steven &amp;amp; Kasia - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/stevenkasiabachata/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/stevenkasiabachata/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Kathy Reyes - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/krdance.official/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/krdance.official/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Ngoc Hyunh - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/knockout_ngoc/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/knockout_ngoc/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Brian Dinh - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/itsyaboibdinh/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/itsyaboibdinh/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Vlad &amp;amp; Nataly - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/vladynataly/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/vladynataly/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Cornel &amp;amp; Rithika - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/cornelrithika_official/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/cornelrithika_official/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Daniel D&amp;rsquo;Errico - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/danielederrico_/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/danielederrico_/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Umeko Yuko - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/umekoyuko/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/umekoyuko/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Pablo Cano - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/_pablocano_/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/_pablocano_/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Anastasia and Jovanny - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/ayjbachata/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/ayjbachata/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Michal &amp;amp; Nicky - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/michalynicki/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/michalynicki/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Juan y Sara - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/juanysara_bachata/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/juanysara_bachata/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Clark Ji - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/dancingwithclark/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/dancingwithclark/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Azael Salazar - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/azaelbachatafever/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/azaelbachatafever/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Ataca y la alemana - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/atacaylaalemanaofficial/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/atacaylaalemanaofficial/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Magda y Valeria - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/magdayvaleria_official/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/magdayvaleria_official/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Daniel &amp;amp; Tom - &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/danielytom/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/danielytom/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;combos&#34;&gt;Combos&lt;/h3&gt;&#xA;&lt;p&gt;I learned a lot from reels from this channel: &#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/bachataworldmasters/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/bachataworldmasters/&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Video&lt;/th&gt;&#xA;          &lt;th&gt;Why I like it&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CsJi6wVNfpG/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CsJi6wVNfpG/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;The transition to two types of waves, the arm wave at the end.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CjsSijqjXOq/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CjsSijqjXOq/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Simple but easy to do.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CqNZ_uwjX59/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CqNZ_uwjX59/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Leader switch front and back.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CgwROATvrSY/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CgwROATvrSY/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Simple variation on diagonal (Ataca y La Alemana).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CgjHS_dA_D7/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CgjHS_dA_D7/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Hip out, Chest out, Chest in, Hip in.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/DCRLfdyCIR8/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/DCRLfdyCIR8/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Titanic step.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/Cqk7EsoOyk5/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/Cqk7EsoOyk5/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Contra y circulo (tutorial).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CttvRi-smnq/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CttvRi-smnq/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Leader switch front and back + a very nice hair brush at the end.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CsjZBrIvZWq/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CsjZBrIvZWq/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Double turn lead, follower shadow, nice sync jump with the music.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CuHh2JvgFwR/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CuHh2JvgFwR/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Basic of basic turn with hug + hip, chest, chest, hip.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CuMbAybAvIH/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CuMbAybAvIH/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Perfect intro to the chorus.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/CuMsbw1LeJX/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/CuMsbw1LeJX/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Onda lateral + contra.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/C1e224nCSVi/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/C1e224nCSVi/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Lady squat.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/C12LBKti8tf/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/C12LBKti8tf/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Side plank.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&#xA;&#xA;&lt;a href=&#34;https://www.instagram.com/p/C48DmHGiyFi/&#34;target=&#34;_blank&#34;&gt;https://www.instagram.com/p/C48DmHGiyFi/&lt;/a&gt;&#xA;&#xA;&lt;/td&gt;&#xA;          &lt;td&gt;Nice double turn + hair brush.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;</description>
    </item>
    <item>
      <title>Documenting my life</title>
      <link>https://www.mauriciopoppe.com/notes/documenting-my-life/</link>
      <pubDate>Sun, 10 Nov 2024 16:28:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/documenting-my-life/</guid>
      <description>&lt;h2 id=&#34;why&#34;&gt;Why?&lt;/h2&gt;&#xA;&lt;p&gt;I want to record the details of my daily life, the small wonders, and the quiet moments.&#xA;Maybe they&amp;rsquo;re ordinary moments which may not seem valuable now, but they will become more so over time.&lt;/p&gt;&#xA;&lt;p&gt;We might think that mundane things will stay the same forever, but they don&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=fO43lbqSOkU&#34;target=&#34;_blank&#34;&gt;I took the following notes from a vlogger that I admire called Riza&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;Because we don&amp;rsquo;t know when we will die, we get to think of life as an inexhaustible well.&#xA;Yet everything happens only a certain number of times, and a very small number really.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;How many more times will you remember a certain afternoon of your childhood,&#xA;an afternoon that is so deeply a part of your being that you can&amp;rsquo;t even conceive of your life without it?&#xA;Perhaps four, five times more, perhaps not even that.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;How many more times will you watch the full moon rise? Perhaps 20. And yet it all seems limitless.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-text-right&#34;&gt;&#xA;  &lt;i&gt;Riza&lt;/i&gt;&#xA;&lt;/div&gt;&lt;/blockquote&gt;&#xA;&lt;p class=&#34;tw-h-16&#34;&gt;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;my-parallax tw-text-primary tw-absolute tw-left-0&#34;&gt;&#xA;  &lt;div class=&#34;tw-absolute tw-left-0 tw-top-0 tw-opacity-25&#34;&gt;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;      &lt;style&gt;&#xA;      css-doodle {&#xA;        --doodle-ripple: (&#xA;          :doodle {&#xA;            @grid: 10;&#xA;            @size: 100vw 100vh;&#xA;            filter: @svg-filter(&lt;svg&gt;&#xA;              &lt;filter&gt;&#xA;                &lt;feTurbulence type=&#34;fractalNoise&#34; baseFrequency=&#34;.02&#34; numOctaves=&#34;1&#34; /&gt;&#xA;                &lt;feDisplacementMap in=&#34;SourceGraphic&#34; scale=&#34;300&#34; /&gt;&#xA;              &lt;/filter&gt;&#xA;            &lt;/svg&gt;);&#xA;          }&#xA;          :container {&#xA;            animation: r 500s linear infinite;&#xA;          }&#xA;          @place: center;&#xA;          @size: 100% 2vmin;&#xA;          background: @pick-d(&#xA;            color-mix(in srgb, rgb(var(--primary)) 50%, black),&#xA;            color-mix(in srgb, rgb(var(--primary)) 70%, black),&#xA;            color-mix(in srgb, rgb(var(--primary)) 90%, black)&#xA;          );&#xA;          transform-origin: 5vmin center;&#xA;          transform:&#xA;            translateX(50%)&#xA;            rotate(calc(@i() * 360deg / @size()));&#xA;&#xA;          @keyframes r {&#xA;            to { transform: rotate(1turn) }&#xA;          }&#xA;        );&#xA;      }&#xA;      &lt;/style&gt;&#xA;      &lt;css-doodle use=&#34;var(--doodle-ripple)&#34;&gt;&lt;/css-doodle&gt;&#xA;    &#xA;  &lt;/div&gt;&#xA;  &#xA;  &lt;div class=&#34;md:tw-w-3/5 tw-m-auto tw-relative tw-h-screen tw-grid tw-place-content-center&#34;&gt;&#xA;    &lt;div class=&#34;tw-text-primary tw-text-3xl md:tw-text-5xl md:tw-mx-auto tw-font-[Ultra] tw-text-center&#34;&gt;&#xA;      &lt;p id=&#34;my-parallax-content&#34;&gt;Life goes by fast. I want to do my best to remember it.&lt;/p&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;div style=&#34;height: 100vh;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-text-center tw-mt-10&#34;&gt;&#xA;  &lt;a target=&#34;_blank&#34; href=&#34;https://yuanchuan.dev/&#34;&gt;Animation by Chuan&lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function () {&#xA;  let parallaxTarget = &#39;#my-parallax-content&#39;&#xA;  if (!parallaxTarget) {&#xA;    return&#xA;  }&#xA;&#xA;  const myScrollableContent = document.querySelector(parallaxTarget);&#xA;  if (!myScrollableContent) {&#xA;    console.error(`could not find target=${parallaxTarget} to enable parallax.`)&#xA;    return;&#xA;  }&#xA;&#xA;  myScrollableContent.style.position = &#34;relative&#34;&#xA;  myScrollableContent.style.top = `200px`&#xA;&#xA;  const container = myScrollableContent.closest(&#39;.my-parallax&#39;);&#xA;  &#xA;  const parallaxFactor = 1.2;&#xA;&#xA;  function animateOnScroll() {&#xA;    const rect = container.getBoundingClientRect();&#xA;    const viewportHeight = window.innerHeight;&#xA;&#xA;    &#xA;    const animationStart = viewportHeight + 100;&#xA;    &#xA;    const animationEnd = -container.offsetHeight;&#xA;&#xA;    let translateY;&#xA;    if (rect.top &gt; animationStart) {&#xA;      &#xA;      translateY = 0;&#xA;    } else if (rect.top &lt; animationEnd) {&#xA;      &#xA;      const totalScroll = animationStart - animationEnd;&#xA;      translateY = -totalScroll * (parallaxFactor - 1);&#xA;    } else {&#xA;      &#xA;      const scrollAmount = animationStart - rect.top;&#xA;      translateY = -scrollAmount * (parallaxFactor - 1);&#xA;    }&#xA;&#xA;    myScrollableContent.style.transform = `translateY(${translateY}px)`;&#xA;  }&#xA;&#xA;  let ticking = false;&#xA;  window.addEventListener(&#39;scroll&#39;, function() {&#xA;    if (!ticking) {&#xA;      window.requestAnimationFrame(function() {&#xA;        animateOnScroll();&#xA;        ticking = false;&#xA;      });&#xA;      ticking = true;&#xA;    }&#xA;  }, { passive: true });&#xA;&#xA;  &#xA;  animateOnScroll();&#xA;})();&#xA;&lt;/script&gt;&#xA;&#xA;&lt;p class=&#34;tw-h-16&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;how&#34;&gt;How?&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve chosen a few different ways to help me capture memories,&#xA;each one serves a different purpose and allows me to &amp;ldquo;romanticize&amp;rdquo; my adventures into something my future self will like.&lt;/p&gt;&#xA;&lt;h3 id=&#34;writing-about-my-day&#34;&gt;Writing about my day&lt;/h3&gt;&#xA;&lt;p&gt;Writing is a way to clear up my thoughts. I don&amp;rsquo;t aim for perfection but I reserve some minutes to get it done.&#xA;Some nights the words just flow, but some other nights I just write a simple sentence. It&amp;rsquo;s alright.&lt;/p&gt;&#xA;&lt;p&gt;Somedays I find myself in the mood of reading the letters from my previous me.&#xA;There is a profound sense of time traveling and seeing my past self.&#xA;It&amp;rsquo;s like watching a time-lapse of my own growth, how I navigated anxieties and celebrated small wins,&#xA;and slowly evolved into the person I am today.&lt;/p&gt;&#xA;&lt;p&gt;This &amp;ldquo;diary&amp;rdquo; reminds me that even the &amp;ldquo;ordinary&amp;rdquo; days are building something significant.&lt;/p&gt;&#xA;&lt;h3 id=&#34;writing-about-my-dreams&#34;&gt;Writing about my dreams&lt;/h3&gt;&#xA;&lt;p&gt;If you were able to remember a happy dream after you wake up, would you write the details for your future self?&#xA;What about a nightmare? Would you avoid writing about it and attempt to forget it?&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not sure if I&amp;rsquo;m fortunate or unlucky to not be able to remember every dream or nightmare after I wake up,&#xA;but when I do I try to write about it (one of the few cases where I use my phone while still in bed).&#xA;Nightmares are difficult to write about and sometimes when it&amp;rsquo;s too sad I don&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;h3 id=&#34;pictures&#34;&gt;Pictures&lt;/h3&gt;&#xA;&lt;p&gt;Taking a picture with a phone is so simple and easy. After sharing them with family and friends&#xA;these digital files end up buried in a photo library, rarely checked and easily forgotten.&lt;/p&gt;&#xA;&lt;p&gt;So, I got myself an Instax camera and took it on a trip abroad to India. There is something magical about it,&#xA;the mechanical &lt;em&gt;click&lt;/em&gt; of the shutter, the sound of the motor as the film ejects, and the time you spend&#xA;looking at it as the colors slowly appear in the white frame. Maybe the picture is out of focus because&#xA;I moved my hand when clicking the shutter, maybe it was too dark to take the picture. That&amp;rsquo;s ok, no problem&#xA;if it&amp;rsquo;s not perfect, it&amp;rsquo;s for myself and I&amp;rsquo;m not looking for perfection.&lt;/p&gt;&#xA;&lt;h3 id=&#34;videos&#34;&gt;Videos&lt;/h3&gt;&#xA;&lt;p&gt;I decided to document my life because of the feeling of sadness about forgotten memories.&#xA;One day the algorithm presented a new song which was so catchy, I couldn&amp;rsquo;t get it out of my head and I had&#xA;it on repeat. I liked the guitar melody a lot and I wanted to play it and so I started learning.&lt;/p&gt;&#xA;&lt;p&gt;But then I got sad. Not because of the song I was learning but for the memories that somehow&#xA;came to my mind from the time I was a teenager and I used to play the guitar. It&amp;rsquo;s becoming harder and harder&#xA;to remember those times. Sometimes my family or friends remind me of something I used to do that I can no&#xA;longer remember. That&amp;rsquo;s the feeling I feel.&lt;/p&gt;&#xA;&lt;p&gt;I wish I had more memories about the past, but it&amp;rsquo;s never too late to realize that and to start collecting&#xA;memories using photos and videos.&lt;/p&gt;&#xA;&lt;h3 id=&#34;junk-journaling&#34;&gt;Junk Journaling&lt;/h3&gt;&#xA;&lt;p&gt;I spent a couple of weeks in Japan and it changed my life. The memories of the tasty and unique food,&#xA;riding in the Shinkansen, drinking hot honey tea from a vending machine in a cold day,&#xA;watching the fall colors, eating matcha ice cream, and so many unique experiences made&#xA;my trip &lt;strong&gt;very&lt;/strong&gt; special.&lt;/p&gt;&#xA;&lt;p&gt;How do I remember these special moments? I can take pictures and videos but I wished I had something else,&#xA;something that&amp;rsquo;s more physical.&#xA;I love my wall of polaroids from my favorite life moments, every picture makes me travel back in time and makes me smile.&lt;/p&gt;&#xA;&lt;p&gt;But what about the physical objects that seem so simple in the moment and easily discarded?&#xA;It&amp;rsquo;s easy to discard objects that you don&amp;rsquo;t think are worth saving like receipts from ATMs,&#xA;a receipt from eating in a restaurant, train tickets, cookies and candy wraps.&lt;/p&gt;&#xA;&lt;p&gt;So, I decided to save these objects and start junk journaling.&#xA;I bought a notebook, a zink printer, removable glue, scissors, washi tape and markers.&#xA;And then I started filling the notebook with receipts, pictures, notes, stickers.&#xA;It takes a lot of time and effort to make a single page, but it&amp;rsquo;s worth it because it&amp;rsquo;s for me.&#xA;It&amp;rsquo;s a fun hobby that I probably enjoyed a lot when I was a little kid (and still do!).&lt;/p&gt;&#xA;&lt;p&gt;I wonder what other things I have forgotten that were very fun to do.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reflecting-on-my-life&#34;&gt;Reflecting on my life&lt;/h2&gt;&#xA;&lt;p&gt;Every 4 months, I write a small essay about my life for that 4-month period.&#xA;Every year on my birthday, I write a longer essay about my life during the past year.&#xA;I capture highlights about the things that I did and the progress on the objectives I set for myself.&#xA;Writing these thoughts is a great way to reflect on the good and bad things of my life.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Kubernetes</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/system-design/kubernetes/</link>
      <pubDate>Sun, 30 Apr 2023 18:27:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/system-design/kubernetes/</guid>
      <description>&lt;h2 id=&#34;presentations&#34;&gt;Presentations&lt;/h2&gt;&#xA;&lt;h3 id=&#34;csi-windows&#34;&gt;CSI Windows&lt;/h3&gt;&#xA;&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/_XXn3-yDZA0?start=1013&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&#34; allowfullscreen&gt;&lt;/iframe&gt;&#xA;&lt;h3 id=&#34;pvpvc-controller&#34;&gt;PV/PVC controller&lt;/h3&gt;&#xA;&lt;iframe src=&#34;https://docs.google.com/presentation/d/e/2PACX-1vQSLT0r0lLliTC_q-E7XNpRexuWr7WEeaiWCyIZjS6m8aRaNKbI6blOyP2D0SEDBrz_IYX_Xkk386oz/embed?start=false&amp;loop=false&amp;delayms=3000&#34; frameborder=&#34;0&#34; width=&#34;960&#34; height=&#34;569&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;&#xA;&lt;h3 id=&#34;debugging-k8s-e2e-tests-with-delve&#34;&gt;Debugging K8s e2e tests with delve&lt;/h3&gt;&#xA;&lt;iframe src=&#34;https://docs.google.com/presentation/d/e/2PACX-1vQibAetKc5T_7bjJ-GJXFvbMa6Rj5C8rTK_qLAb1tp_rQKvNcsZ_3tFauqSrOWDuKg0pkQMYD1Q3ojK/embed?start=false&amp;loop=false&amp;delayms=3000&#34; frameborder=&#34;0&#34; width=&#34;960&#34; height=&#34;569&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;&#xA;&lt;h2 id=&#34;playground&#34;&gt;Playground&lt;/h2&gt;&#xA;&lt;p&gt;As I started to contribute to Kubernetes, I created a few environments for easier development.&lt;/p&gt;&#xA;&lt;div style=&#34;text-align: center&#34;&gt;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/kubernetes-playground&#34;&gt;&lt;img src=&#34;https://gh-card.dev/repos/mauriciopoppe/kubernetes-playground.svg&#34;&gt;&lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Please check it out for examples of the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Running a &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/kubernetes-playground/blob/master/docs/sandbox-with-debugger.md&#34;target=&#34;_blank&#34;&gt;client-go application through skaffold&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/kubernetes-playground/blob/master/docs/kube-controller-manager.md&#34;target=&#34;_blank&#34;&gt;Running the kube controller manager in debug mode&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/kubernetes-playground/blob/master/docs/kubelet.md&#34;target=&#34;_blank&#34;&gt;Running the kubelet in debug mode&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Productivity</title>
      <link>https://www.mauriciopoppe.com/notes/productivity-skills/</link>
      <pubDate>Wed, 11 May 2022 21:16:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/productivity-skills/</guid>
      <description>&lt;h2 id=&#34;getting-used-to-multitasking&#34;&gt;Getting Used to Multitasking&lt;/h2&gt;&#xA;&lt;p&gt;Multitasking is a skill that I try to get better at to better use my time. While it may seem detrimental to my performance because I&amp;rsquo;m not completely focused on a task, I believe that there are situations where being able to do a mental context switch&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; can save you a lot of time.&lt;/p&gt;&#xA;&lt;p&gt;As you start growing in your career, your scope will increase, as well as the amount of knowledge that you have. You&amp;rsquo;ll participate in more meetings for many different topics that you&amp;rsquo;ll have to juggle in your head. With lots of opportunities to practice every day, you eventually get used to it. So the short answer, like any other skill, is practice.&lt;/p&gt;&#xA;&lt;h2 id=&#34;time-for-deep-focus-time-for-a-break&#34;&gt;Time for Deep Focus, Time for a Break&lt;/h2&gt;&#xA;&lt;p&gt;Having periods of time for deep focus is a must, but it&amp;rsquo;s also really important to let the conscious mind rest and let the diffuse mode of thinking act. I learned this from the book &amp;ldquo;A Mind for Numbers&amp;rdquo; by Barbara Oakley, which goes deeper into balancing the focused and diffuse modes of thinking. For this reason, taking breaks is really important and helps me reset my mind. Some of the solutions for problems at work that I can&amp;rsquo;t solve when I&amp;rsquo;m focused usually come after I take a break and go back to my desk.&lt;/p&gt;&#xA;&lt;p&gt;Getting interrupted during the periods for deep focus ruins my train of thought and is something that I avoid by disabling notifications and blocking time in my calendar to focus better on the task.&lt;/p&gt;&#xA;&lt;p&gt;Having a routine helps tremendously and keeps me happy. Regular exercise in the morning keeps my mind clean and gives me energy for the rest of the day to focus better.&lt;/p&gt;&#xA;&lt;h2 id=&#34;emails&#34;&gt;Emails&lt;/h2&gt;&#xA;&lt;p&gt;A tip that I got from a coworker is to tag and filter all the incoming emails. I use an internal tool at work that helps me tag emails with a declarative language. I think that &#xA;&#xA;&lt;a href=&#34;https://github.com/mbrt/gmailctl&#34;target=&#34;_blank&#34;&gt;https://github.com/mbrt/gmailctl&lt;/a&gt;&#xA;&#xA; or a similar tool can help.&lt;/p&gt;&#xA;&lt;p&gt;Once you tag emails, the first thing is to free your inbox from emails that aren&amp;rsquo;t that important to read. Lots of emails coming from our bug tracker are most of the time not directed to me but to my team inbox instead. The first filter groups bugs by the team they&amp;rsquo;re targeted to and moves them to a tag, e.g., &lt;code&gt;bugs-team-a&lt;/code&gt;, &lt;code&gt;bugs-team-b&lt;/code&gt;, and archives them, skipping the inbox. Some of these bugs might need my attention because I&amp;rsquo;m mentioned in them, and therefore if I&amp;rsquo;m CCed on them, then I also need to add another tag to it, e.g., &lt;code&gt;bugs-me&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I receive emails directed to the Google Groups I&amp;rsquo;m subscribed to, to my org, and company-wide. While these are important messages, they&amp;rsquo;re not urgent, and they can also be tagged to something like &lt;code&gt;google-groups&lt;/code&gt;, &lt;code&gt;org&lt;/code&gt;, &lt;code&gt;company&lt;/code&gt;, etc.&lt;/p&gt;&#xA;&lt;p&gt;I do the same with changelist &amp;amp; GitHub emails. I group them by the team, e.g., &lt;code&gt;cl-team-a&lt;/code&gt;, &lt;code&gt;cl-team-b&lt;/code&gt;, and skip the inbox. For bugs where I&amp;rsquo;m the reviewer or where I&amp;rsquo;m CCed, I add &lt;code&gt;cl-me&lt;/code&gt;, and they stay in my inbox.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s also spam that should be tagged and marked as read by default. For example, a person joining a big team where I&amp;rsquo;m also part of might generate an automated email for all the members of the team. Emails like this can be marked as read, tagged, and archived.&lt;/p&gt;&#xA;&lt;p&gt;With time, I got used to checking my inbox regularly, following this priority: first my inbox, &lt;code&gt;bugs-me&lt;/code&gt;, &lt;code&gt;cl-me&lt;/code&gt;, and if I feel like it, then I read other tags.&lt;/p&gt;&#xA;&lt;h2 id=&#34;task-management&#34;&gt;Task Management&lt;/h2&gt;&#xA;&lt;p&gt;Throughout my day/week, I get emails with action items. In meetings, after taking some notes, we realize that there are some action items that I should act on soon (for example, reading and reviewing a design doc, working on an upcoming release, etc.). While I can create an internal bug for some of these with an assigned priority, there are some items, like asking and giving feedback in a design doc, where I wouldn&amp;rsquo;t need to create a bug. In addition, for some items with deadlines, I also need a reminder to work on it soon.&lt;/p&gt;&#xA;&lt;p&gt;For these reasons, I use &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=b82GeFbxIj8&#34;target=&#34;_blank&#34;&gt;Google Tasks&lt;/a&gt;&#xA;&#xA; as my task management tool. It&amp;rsquo;s easy to add tasks by hand, tasks from emails (with subtasks too 🙂), set calendar reminders, and manually order to give some priority among them. What&amp;rsquo;s super cool is that I can see it every time I go to my email tab. (&#xA;&#xA;&lt;a href=&#34;https://support.google.com/mail/answer/106237?hl=en&amp;amp;co=GENIE.Platform%3DDesktop#zippy=%2Csave-an-email-as-a-task%2Corganize-your-tasks-into-lists:~:text=Slides%20in%20Keep-,Create%20a%20task,-Go%20to%C2%A0&#34;target=&#34;_blank&#34;&gt;Read this article for more info about how to set it up.&lt;/a&gt;&#xA;&#xA;).&lt;/p&gt;&#xA;&lt;h2 id=&#34;keeping-notes&#34;&gt;Keeping Notes&lt;/h2&gt;&#xA;&lt;p&gt;At work, almost all the meetings have meeting notes. We write the topics that were discussed and their conclusions. I can&amp;rsquo;t emphasize enough how useful these notes are. They help remember discussions and conclusions, they prepare you for the next meeting if it&amp;rsquo;s a regular meeting, and if you missed a meeting, then you could read the notes taken and reach out to people if needed.&lt;/p&gt;&#xA;&lt;p&gt;For example, &#xA;&#xA;&lt;a href=&#34;https://docs.google.com/document/d/1-8KEG8AjAgKznS9NFm3qWqkGyCHmvU6HVl0sk5hwoAE/edit&#34;target=&#34;_blank&#34;&gt;these are the meeting notes of the Kubernetes Storage Special Interest Group&lt;/a&gt;&#xA;&#xA;. As you can see, it&amp;rsquo;s split by dates, topics discussed, and conclusions.&lt;/p&gt;&#xA;&lt;p&gt;In my day-to-day, I look at these notes just like I check my emails. Outside work, I keep a weekly checklist of the things I have to do. Having more things written down and outside my mind gives me more room to remember valuable things.&lt;/p&gt;&#xA;&lt;h2 id=&#34;development-tools&#34;&gt;Development Tools&lt;/h2&gt;&#xA;&lt;p&gt;At work, I make changes to many codebases during the day. To quickly switch across codebases and the terminal layouts that I&amp;rsquo;m used to, I use &#xA;&#xA;&lt;a href=&#34;https://github.com/tmux/tmux&#34;target=&#34;_blank&#34;&gt;tmux&lt;/a&gt;&#xA;&#xA;, &#xA;&#xA;&lt;a href=&#34;https://github.com/tmuxinator/tmuxinator&#34;target=&#34;_blank&#34;&gt;tmuxinator&lt;/a&gt;&#xA;&#xA;, a combination of a few scripts that I&amp;rsquo;ll talk about later, and &#xA;&#xA;&lt;a href=&#34;https://github.com/junegunn/fzf&#34;target=&#34;_blank&#34;&gt;fzf&lt;/a&gt;&#xA;&#xA;. I&amp;rsquo;ll describe some concepts around tmux and tmuxinator, the scripts that I use, and my workflow, and other tools that I tried that didn&amp;rsquo;t work for me. First, a quick look into what it looks like:&lt;/p&gt;&#xA;&lt;script id=&#34;asciicast-h9bEclMKVl9SONRqMe3yoyryF&#34; src=&#34;https://asciinema.org/a/h9bEclMKVl9SONRqMe3yoyryF.js&#34; async&gt;&lt;/script&gt;&#xA;&lt;p&gt;Sessions in tmux can have a name, and in my mind, I keep the mapping of a session name to a codebase. E.g., if I want to work in the Kubernetes codebase cloned at &lt;code&gt;~/go/src/k8s.io/kubernetes&lt;/code&gt;, then that&amp;rsquo;d be the tmux session name I should remember.&lt;/p&gt;&#xA;&lt;p&gt;Once I&amp;rsquo;m in that session, I usually have a predefined terminal layout. In most of the codebases, I keep a three-pane layout with my editor on the left and two terminals stacked vertically on the right. Because this is a common layout across many of the codebases I work on, I have to save it so that the next time I open the codebase, I keep the same layout. To do so, I use the following file stored at &lt;code&gt;~/.tmuxinator.yaml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;# I use · instead of . because . is reserved in tmuxinator&#xA;# I also don&#39;t want to see the entire path to home; instead, just use ~&#xA;name: &amp;lt;%= ENV[&#39;PWD&#39;].gsub(&#39;.&#39;, &#39;·&#39;).gsub(ENV[&#39;HOME&#39;], &#39;~&#39;) %&amp;gt;&#xA;root: ./&#xA;&#xA;windows:&#xA;  - editor:&#xA;      layout: 7598,272x69,0,0{209x69,0,0,10,62x69,210,0[62x34,210,0,11,62x34,210,35,12]}&#xA;      panes:&#xA;        - nvim -S&#xA;        - null&#xA;        - null&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If a codebase needs a different layout, I create a &lt;code&gt;.tmuxinator.yaml&lt;/code&gt; file at the codebase root and override what I need, e.g., multiple windows with different layouts or commands that should be used instead.&lt;/p&gt;&#xA;&lt;p&gt;Keeping track of all the locations of the codebases that I work on is tiresome. Instead, as I mentioned, I only need to remember codebase names, which will be mapped to tmux sessions. Moreover, I should keep track of the codebases that are worth remembering because there might be codebases that I cloned once and never used again. To save the codebases worth remembering, I &amp;lsquo;bookmark&amp;rsquo; them in the file &lt;code&gt;~/.bookmarks.data&lt;/code&gt;, which looks like this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;/Users/mauriciopoppe/.dotfiles&#xA;/Users/mauriciopoppe/go/src/github.com/mauriciopoppe/blog&#xA;/Users/mauriciopoppe/go/src/k8s.io/kubernetes&#xA;...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Once I clone a codebase worth remembering, I &lt;code&gt;cd&lt;/code&gt; into it and invoke a script &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles/blob/main/zsh/bin/bookmark&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;bookmark&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; that will save the absolute path in the file &lt;code&gt;~/.bookmarks.data&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Finally, it comes time to pick a codebase that I want to work on. To do so, I use a &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles/blob/main/zsh/bin/tmux-switch-client.py&#34;target=&#34;_blank&#34;&gt;Python script&lt;/a&gt;&#xA;&#xA; that reads the &lt;code&gt;~/.bookmarks.data&lt;/code&gt; file and feeds it to &lt;code&gt;fzf&lt;/code&gt; to provide fuzzy finding over all the existing and saved (but not started) sessions. After a bookmark (or tmux session) is selected, then it comes time to call tmuxinator within that directory and start a new tmux session or just switch to an existing one if the selected item was already a tmux session.&lt;/p&gt;&#xA;&lt;p&gt;This script is under a tmux keymap and is called whenever I type &lt;code&gt;&amp;lt;ctrl+space&amp;gt;&amp;lt;ctrl+j&amp;gt;&lt;/code&gt; with this &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/dotfiles/blob/22fdba7e6f179077dce2f780d598a1a6c4c12a3a/tmux/.tmux.conf#L72&#34;target=&#34;_blank&#34;&gt;tmux config&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;p&gt;With the concepts learned above, it comes time to talk about my workflow:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Log into my workstation, start the tmux server (or attach to one already running). I&amp;rsquo;ll usually see session 0.&lt;/li&gt;&#xA;&lt;li&gt;Think about the project that I want to work on first, e.g., the kubernetes/kubernetes repo. I only need to remember &amp;ldquo;kubernetes.&amp;rdquo;&lt;/li&gt;&#xA;&lt;li&gt;Type &lt;code&gt;&amp;lt;ctrl+space&amp;gt;&amp;lt;ctrl+j&amp;gt;&lt;/code&gt;. That&amp;rsquo;ll trigger the &lt;code&gt;tmux-switch-client&lt;/code&gt; script and run fzf with my bookmarks and the tmux sessions that are currently running.&lt;/li&gt;&#xA;&lt;li&gt;I type &lt;code&gt;kubernetes&lt;/code&gt; and see the repos related to Kubernetes. I move over the list and select the one that I want. Once selected, it will create a new tmux session in the Kubernetes codebase with a predefined tmux layout.&lt;/li&gt;&#xA;&lt;li&gt;I may run a long-running command like building Kubernetes or creating a dev cluster. In the meantime, I can work on a different project. I switch to it with &lt;code&gt;&amp;lt;ctrl+space&amp;gt;&amp;lt;ctrl+j&amp;gt;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;After working for some time in the other codebase, I remember that I created a Kubernetes dev cluster! I can switch to the Kubernetes codebase to see the status of the build.&lt;/li&gt;&#xA;&lt;li&gt;Rinse and repeat.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Things that I&amp;rsquo;ve tried in the past:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://github.com/tmux-plugins/tmux-continuum&#34;target=&#34;_blank&#34;&gt;tmux-continuum&lt;/a&gt;&#xA;&#xA; - This tool saves your tmux session layout automatically, which is great! However, when I used it, it&amp;rsquo;d reopen all the tmux sessions that were stored. Imagine having tens of codebases and seeing all of them getting created when you invoke tmux-continuum!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;A mental context switch is an analogy of what an OS does under the hood to &#xA;&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Context_switch&#34;target=&#34;_blank&#34;&gt;share a single CPU among processes&lt;/a&gt;&#xA;&#xA;, but applied to our day-to-day mental tasks. After all, we only have one brain that&amp;rsquo;s already multitasking with unconscious processes like perception or breathing.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Preparation for a Software Engineer Interview</title>
      <link>https://www.mauriciopoppe.com/notes/software-engineer-interview-preparation/</link>
      <pubDate>Mon, 12 Oct 2020 21:23:30 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/software-engineer-interview-preparation/</guid>
      <description>&lt;p&gt;This interview preparation plan contains notes that apply to any company and specifics for my target companies.&#xA;I planned to interview with my target companies Airbnb, Facebook, and Google at once. I wanted to have the onsites close to each other (with at&#xA;least one day to rest between interviews) to maximize my chances of getting into a big company.&#xA;I got excellent recruiters that helped me schedule the 3 on-sites in 2 weeks.&#xA;I was able to pass all of the Hiring Committees and got offers from Airbnb, Facebook, and Google.&#xA;Disclaimer: &lt;em&gt;This plan worked for me. It might or might not work for you&lt;/em&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/airbnb_facebook_google.png&#34; alt=&#34;Airbnb, Facebook, and Google&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Airbnb, Facebook, and Google&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;before-you-start&#34;&gt;Before you start&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Preparing&lt;/strong&gt; for an interview is a rewarding, stressful, and exciting experience. Passing an interview could be the outcome of enough focused preparation&#xA;(luck is involved too, but I&amp;rsquo;ll get to this shortly).&#xA;The process is stressful at every single stage, from the first time you send your resume and wait for the automated program or the recruiter not to reject it&#xA;until the last day you negotiate your offer with your recruiter. However, the process is rewarding because you improve your problem-solving skills. Also,&#xA;the concepts that you learn when you&amp;rsquo;re preparing for the system design interviews are invaluable and will be helpful throughout your career.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Luck is involved in the interview process&lt;/strong&gt;. You may have prepared a lot, but:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;you might get stage fright during the interview. You can decrease the anxiety effect with enough practice, but I guess that this feeling will always be there.&lt;/li&gt;&#xA;&lt;li&gt;you might be unable to make progress because the problem is too hard to solve because you didn&amp;rsquo;t practice that topic enough, or you just missed that small insight.&lt;/li&gt;&#xA;&lt;li&gt;there might be an external factor that you can&amp;rsquo;t control; for example, you might not click with your interviewer, your interviewer might be having a bad day, or&#xA;during the Hiring Committee review, someone dislikes something about your round even though all the interviewers gave you a positive score&#xA;(as an anecdote, &#xA;&#xA;&lt;a href=&#34;https://youtu.be/r8RxkpUvxK0?t=530&#34;target=&#34;_blank&#34;&gt;not even the Hiring Committee members are safe from themselves&lt;/a&gt;&#xA;&#xA;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You increase your chances of landing a job at a top company if you interview with more of them. It may seem obvious, but it&#xA;took me some courage to attempt more times because I was afraid of rejection.&#xA;It helped to switch my mentality to focus more on the preparation rather than the result.&lt;/p&gt;&#xA;&lt;p&gt;For stage fright, practice a lot, either at Pramp or with a friend experienced in interviews (highly recommended).&#xA;The more you practice, the better you&amp;rsquo;ll become at communicating your solution as well as keeping control of the time.&#xA;When I started, I could come up with a solution for a coding problem, but I&amp;rsquo;d present it in a disordered way. I&amp;rsquo;d explain a solution and start coding it right&#xA;away without realizing that I was solving the wrong problem, or I&amp;rsquo;d talk too much without considering the time, and I&amp;rsquo;d eat valuable time in the interview that I could&#xA;use for the follow-up question or tests. When I practiced system design interviews, I&amp;rsquo;d jump across the system design&#xA;stages, or I&amp;rsquo;d go way too deep into the detailed design when I talked about the high-level design. After I did enough mock&#xA;interview rounds with my friend, I corrected these problems and came up with a systematic way to tackle each coding and system design problem.&lt;/p&gt;&#xA;&lt;p&gt;For challenging problems, always try to come up with examples. I got follow-up questions where I didn&amp;rsquo;t know where to start,&#xA;so after cycling through some data structures and algorithms, I&amp;rsquo;d write some examples, I&amp;rsquo;d find a pattern, and finally,&#xA;the data structures and algorithms that would help me solve the problem. If you can&amp;rsquo;t make progress, ask for help! If you get&#xA;an excellent interviewer, he/she might realize you need help and give you hints, but in any case, keep this step as a last resort when you&amp;rsquo;re completely stuck.&lt;/p&gt;&#xA;&lt;p&gt;For external factors, there&amp;rsquo;s nothing you can do. Just focus your energy on the next interview instead of thinking about what you could&amp;rsquo;ve done better.&lt;/p&gt;&#xA;&lt;p&gt;Finally, my journey wasn&amp;rsquo;t without failures. I failed multiple interviews with top companies. I was naive in the past, and when I decided to&#xA;go for an interview, I&amp;rsquo;d &amp;ldquo;put all of my eggs in one basket&amp;rdquo; (meaning interviewing only with one company at a time in years) and fail, but&#xA;now I realize that the interview process gave me invaluable information that helped me in my next attempts.&#xA;If you fail, it just means that you&amp;rsquo;ve failed that attempt. After all of your rounds, reflect on what you did right and wrong and focus on improving&#xA;that part for the next shot.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;div class=&#34;my-parallax tw-text-primary tw-absolute tw-left-0&#34;&gt;&#xA;  &lt;div class=&#34;tw-absolute tw-left-0 tw-top-0 tw-opacity-25&#34;&gt;&#xA;    &#xA;      &lt;style&gt;&#xA;      css-doodle {&#xA;        --doodle-atari: (&#xA;          @grid: 1 / 100vw 100vh / #0a0c27;&#xA;          background-size: 200px 200px;&#xA;          background-image: @doodle(&#xA;            @grid: 6 / 100%;&#xA;            @size: 4px;&#xA;            font-size: 4px;&#xA;            color: hsl(@r240, 30%, 50%);&#xA;            box-shadow: @m3x5(&#xA;              calc(4em - @nx*1em) @ny(*1em)&#xA;                @p(@m3(currentColor), @m2(#0000)),&#xA;              calc(2em + @nx*1em) @ny(*1em)&#xA;                @lp&#xA;            );&#xA;          );&#xA;        );&#xA;      }&#xA;      &lt;/style&gt;&#xA;      &lt;css-doodle use=&#34;var(--doodle-atari)&#34;&gt;&lt;/css-doodle&gt;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;  &lt;/div&gt;&#xA;  &#xA;  &lt;div class=&#34;md:tw-w-3/5 tw-m-auto tw-relative tw-h-screen tw-grid tw-place-content-center&#34;&gt;&#xA;    &lt;div class=&#34;tw-text-primary tw-text-3xl md:tw-text-5xl md:tw-mx-auto tw-font-[Ultra] tw-text-center&#34;&gt;&#xA;      &lt;p&gt;&lt;span class=&#34;tw-text-primary&#34;&gt;Luck&lt;/span&gt; is what happens when &lt;span class=&#34;tw-text-primary&#34;&gt;preparation&lt;/span&gt; meets &lt;span class=&#34;tw-text-primary&#34;&gt;opportunity&lt;/span&gt;.&lt;/p&gt;&#xA;      &lt;p class=&#34;tw-text-right tw-text-xl&#34;&gt;&lt;i&gt;Seneca&lt;/i&gt;&lt;/p&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;div style=&#34;height: 100vh;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function () {&#xA;  let parallaxTarget = &#39;&#39;&#xA;  if (!parallaxTarget) {&#xA;    return&#xA;  }&#xA;&#xA;  const myScrollableContent = document.querySelector(parallaxTarget);&#xA;  if (!myScrollableContent) {&#xA;    console.error(`could not find target=${parallaxTarget} to enable parallax.`)&#xA;    return;&#xA;  }&#xA;&#xA;  myScrollableContent.style.position = &#34;relative&#34;&#xA;  myScrollableContent.style.top = `200px`&#xA;&#xA;  const container = myScrollableContent.closest(&#39;.my-parallax&#39;);&#xA;  &#xA;  const parallaxFactor = 1.2;&#xA;&#xA;  function animateOnScroll() {&#xA;    const rect = container.getBoundingClientRect();&#xA;    const viewportHeight = window.innerHeight;&#xA;&#xA;    &#xA;    const animationStart = viewportHeight + 100;&#xA;    &#xA;    const animationEnd = -container.offsetHeight;&#xA;&#xA;    let translateY;&#xA;    if (rect.top &gt; animationStart) {&#xA;      &#xA;      translateY = 0;&#xA;    } else if (rect.top &lt; animationEnd) {&#xA;      &#xA;      const totalScroll = animationStart - animationEnd;&#xA;      translateY = -totalScroll * (parallaxFactor - 1);&#xA;    } else {&#xA;      &#xA;      const scrollAmount = animationStart - rect.top;&#xA;      translateY = -scrollAmount * (parallaxFactor - 1);&#xA;    }&#xA;&#xA;    myScrollableContent.style.transform = `translateY(${translateY}px)`;&#xA;  }&#xA;&#xA;  let ticking = false;&#xA;  window.addEventListener(&#39;scroll&#39;, function() {&#xA;    if (!ticking) {&#xA;      window.requestAnimationFrame(function() {&#xA;        animateOnScroll();&#xA;        ticking = false;&#xA;      });&#xA;      ticking = true;&#xA;    }&#xA;  }, { passive: true });&#xA;&#xA;  &#xA;  animateOnScroll();&#xA;})();&#xA;&lt;/script&gt;&#xA;&#xA;&lt;!-- This p exists to give artificial margin --&gt;&#xA;&lt;p&gt;&lt;/p&gt;&#xA;&lt;p&gt;Getting an offer is not the end of the journey. It might be possible that even after you reach your target company and you&#xA;work there for some years, you might look for new challenges in other top companies. The interview skill is something&#xA;that you should keep up to date. Good luck!&lt;/p&gt;&#xA;&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;(If you haven&amp;rsquo;t interviewed in the past and want to get noticed)&lt;/em&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If you&amp;rsquo;re a student, enjoy the student lifestyle! Work on challenging projects that make you stand out from the rest.&#xA;In my case, I used to be a competitive programmer and also liked creating some&#xA;projects for fun. &#xA;&#xA;&lt;a href=&#34;https://javascriptweekly.com/issues/194&#34;target=&#34;_blank&#34;&gt;I managed to have a JS library featured in a magazine once!&lt;/a&gt;&#xA;&#xA;,&#xA;(&#xA;&#xA;&lt;a href=&#34;https://mauriciopoppe.github.io/PojoViz/public/vulcanize.html#readme&#34;target=&#34;_blank&#34;&gt;link to the project&lt;/a&gt;&#xA;&#xA;).&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=ueNT-w7Oluw&#34;target=&#34;_blank&#34;&gt;Participate in Coding Contests&lt;/a&gt;&#xA;&#xA;. I solved thousands of problems over the years;&#xA;my solutions are in &#xA;&#xA;&lt;a href=&#34;https://github.com/mauriciopoppe/competitive-programming&#34;target=&#34;_blank&#34;&gt;this repo&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;Google has this website called &#xA;&#xA;&lt;a href=&#34;https://foobar.withgoogle.com/&#34;target=&#34;_blank&#34;&gt;https://foobar.withgoogle.com/&lt;/a&gt;&#xA;&#xA; (learn about it &#xA;&#xA;&lt;a href=&#34;https://medium.com/plutonic-services/things-you-should-know-about-google-foobar-invitation-703a535bf30f&#34;target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;&#xA;).&#xA;When I was reading about web performance, I saw a pink button somewhere inside the &#xA;&#xA;&lt;a href=&#34;https://developers.google.com/web/fundamentals/performance/rendering&#34;target=&#34;_blank&#34;&gt;Web Fundamentals Rendering Performance Guides&lt;/a&gt;&#xA;&#xA;&#xA;which led me to the foobar site. I solved 3 problems in Python and got an interview invitation, and then I solved the remaining 2 and got more invitations to give to friends.&lt;/li&gt;&#xA;&lt;li&gt;If you are working full-time, look for opportunities to work on challenging problems and show leadership. &lt;strong&gt;Take the chance, no pain, no gain&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Make sure your resume shines and aim for a 1-page resume. &#xA;&#xA;&lt;a href=&#34;https://www.overleaf.com/read/fvdmbqtskgsw&#34;target=&#34;_blank&#34;&gt;Here&amp;rsquo;s the CV I used for this round (with my details removed)&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Before looking to interview:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do the daily Leetcode challenge. It&amp;rsquo;s a great way to keep the coding interview skill up to date.&lt;/li&gt;&#xA;&lt;li&gt;Participate in Leetcode contests every Saturday, or Codeforces when it&amp;rsquo;s available.&lt;/li&gt;&#xA;&lt;li&gt;Read about or code scalable systems, read interesting papers, and read the red book &#xA;&#xA;&lt;a href=&#34;https://dataintensive.net/&#34;target=&#34;_blank&#34;&gt;Designing Data-Intensive Applications&lt;/a&gt;&#xA;&#xA;.&#xA;I focused a lot on this part since the last time I failed my previous onsite was because of system design.&lt;/li&gt;&#xA;&lt;li&gt;Get to know me and the places I&amp;rsquo;d like to work. Check if my values match the company core values.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;my-interview my-interview--airbnb&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        I&amp;rsquo;ve been a fan of their engineering&#xA;blog ever since I saw this article &#xA;&#xA;&lt;a href=&#34;https://medium.com/airbnb-engineering/rearchitecting-airbnbs-frontend-5e213efc24d2&#34;target=&#34;_blank&#34;&gt;Rearchitecting Airbnb&amp;rsquo;s Frontend&lt;/a&gt;&#xA;&#xA;.&#xA;Moreover, I had the opportunity to use part of their work presented in&#xA;&#xA;&#xA;&lt;a href=&#34;https://medium.com/airbnb-engineering/dynein-building-a-distributed-delayed-job-queueing-system-93ab10f05f99&#34;target=&#34;_blank&#34;&gt;Dynein: Building an Open-source Distributed Delayed Job Queueing System&lt;/a&gt;&#xA;&#xA; at work.&#xA;Also, the obsession for what &amp;ldquo;belong anywhere&amp;rdquo; means matches my core values. If you don&amp;rsquo;t know what it means, I highly&#xA;recommend this &#xA;&#xA;&lt;a href=&#34;https://www.ted.com/talks/joe_gebbia_how_airbnb_designs_for_trust?language=en&#34;target=&#34;_blank&#34;&gt;Ted talk by Joe Gebbia, one of the co-founders of Airbnb&lt;/a&gt;&#xA;&#xA;, and&#xA;if you understand Spanish, listen to this &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=sVuMmcFu9uI&#34;target=&#34;_blank&#34;&gt;story by a writer that had a heart attack while staying at an Airbnb&lt;/a&gt;&#xA;&#xA;.&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;my-interview my-interview--facebook&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        In the Facebook HQ, you see their core values everywhere. One phrase that stuck with me in one of their buildings is &lt;em&gt;what would you do if you weren&amp;rsquo;t afraid?&lt;/em&gt;.&#xA;A few of my friends have been working there for a long time. Facebook&amp;rsquo;s been one of my target companies for a while. &#xA;&#xA;&lt;a href=&#34;https://engineering.fb.com/&#34;target=&#34;_blank&#34;&gt;Their engineering blog&lt;/a&gt;&#xA;&#xA; is filled with&#xA;so many gems across multiple fields. As a Frontend developer, I learned a lot from &#xA;&#xA;&lt;a href=&#34;https://engineering.fb.com/web/browserlab-automated-regression-detection-for-the-web/&#34;target=&#34;_blank&#34;&gt;Browserlab&lt;/a&gt;&#xA;&#xA;,&#xA;whose infrastructure design I used as inspiration in a project I did at work with &#xA;&#xA;&lt;a href=&#34;https://www.webpagetest.org/&#34;target=&#34;_blank&#34;&gt;WebPagetest&lt;/a&gt;&#xA;&#xA;.&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;my-interview my-interview--google&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        I use a lot of Google products every day, and I admire their high quality. Google&amp;rsquo;s always setting standards in engineering in the industry&#xA;and ensuring that their research is available to the world. Many companies, including mine, have benefited from all the open-source projects they&#xA;produce/support. &#xA;&#xA;&lt;a href=&#34;https://kubernetes.io/&#34;target=&#34;_blank&#34;&gt;Kubernetes&lt;/a&gt;&#xA;&#xA; is the core component in many companies&amp;rsquo; infra, and it looks like a magic box to the engineers that use it.&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;NOTE about picking your companies: I only interviewed with the companies I wanted to work for, which is risky. Another strategy is to apply to all the top&#xA;companies hoping to get multiple offers, which helps during the negotiation phase. During my preparation, I watched videos from various founders&#xA;from all of the top companies and discovered that I&amp;rsquo;d like to work at &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=NprBQi0cSHU&#34;target=&#34;_blank&#34;&gt;Stripe&lt;/a&gt;&#xA;&#xA; too.&lt;/p&gt;&#xA;&lt;p&gt;When I was ready to interview:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Contact the recruiters, schedule phone screens in 3 to 4 weeks. More time to prepare for the phone screen is risky&#xA;because I&amp;rsquo;ll burn out even before practicing the system design questions.&lt;/li&gt;&#xA;&lt;li&gt;Practice only coding for the phone screens. The plan is detailed below.&lt;/li&gt;&#xA;&lt;li&gt;After the phone screen interviews, schedule on-sites in 4 to 6 weeks (I did 4 weeks). I also ensured that the onsites&#xA;were as close as possible to a target date with enough breathing room to rest.&lt;/li&gt;&#xA;&lt;li&gt;Practice mainly system design and coding to a lesser extent. Give yourself enough breathing room not to burn out.&lt;/li&gt;&#xA;&lt;li&gt;Practice behavioral types of questions. Each company has its way to assess this part that&amp;rsquo;s described below.&lt;/li&gt;&#xA;&lt;li&gt;Go through the onsites. Get to a mental state where you&amp;rsquo;re ready for the next interview regardless of the outcome of the previous round.&lt;/li&gt;&#xA;&lt;li&gt;Receive feedback from the recruiters and the HC. Go through the team matching interviews if you passed the HC. Remember that &lt;strong&gt;you don&amp;rsquo;t have an offer yet&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If you get offers, learn to negotiate. Read &#xA;&#xA;&lt;a href=&#34;https://candor.co/guides/salary-negotiation&#34;target=&#34;_blank&#34;&gt;Salary negotiation strategies everyone in tech already knows — but you don&amp;rsquo;t&lt;/a&gt;&#xA;&#xA;,&#xA;&#xA;&#xA;&lt;a href=&#34;https://medium.com/@bayareabelletrist/how-i-negotiated-a-software-engineer-offer-in-silicon-valley-f11590f5c656&#34;target=&#34;_blank&#34;&gt;How I negotiated a $300,000 job offer in Silicon Valley&lt;/a&gt;&#xA;&#xA;, and/or&#xA;get professional help.&lt;/li&gt;&#xA;&lt;li&gt;If you don&amp;rsquo;t get an offer, learn from your mistakes and move on. You&amp;rsquo;ll have enough time to reflect and think about the plan for the next attempt.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;coding&#34;&gt;Coding&lt;/h2&gt;&#xA;&lt;h3 id=&#34;phone-screen-preparation&#34;&gt;Phone screen preparation&lt;/h3&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/epi-ctci.webp&#34; alt=&#34;The standard coding interview books&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;The standard coding interview books&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;My phone screen preparation took 3 to 4 weeks. Warmup for the 1st week: solve a few easy/medium problems in Leetcode, remember the C++ STL&#xA;(&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/programming-languages/cpp-refresher/&#34;target=&#34;_blank&#34;&gt;if your programming language is C++, I have a refresher article&lt;/a&gt;&#xA;&#xA;).&lt;/li&gt;&#xA;&lt;li&gt;Focus on breadth. A nice schedule based on your timeline can be found in the EPI book. Then pick problems from your weakest area.&lt;/li&gt;&#xA;&lt;li&gt;Practice EPI questions. I&amp;rsquo;ve already read EPI multiple times, so I just had to review their intro for each chapter&amp;rsquo;s STL methods and glance&#xA;through the problems and the solutions. To practice and test if your implementation works, use the &#xA;&#xA;&lt;a href=&#34;https://github.com/adnanaziz/EPIJudge&#34;target=&#34;_blank&#34;&gt;EPI Judge&lt;/a&gt;&#xA;&#xA;.&#xA;Start solving medium-type questions and target hard questions in Leetcode. Review medium questions that you may have solved in the past,&#xA;and study how other people solved it (you&amp;rsquo;ll learn something new every time).&lt;/li&gt;&#xA;&lt;li&gt;Go through this list of patterns: &#xA;&#xA;&lt;a href=&#34;https://Leetcode.com/discuss/general-discussion/665604/important-and-useful-links-from-all-over-the-Leetcode&#34;target=&#34;_blank&#34;&gt;Important and Useful links from all over Leetcode&lt;/a&gt;&#xA;&#xA;.&#xA;It&amp;rsquo;s by far the best source of knowledge and problems to solve for your preparation.&lt;/li&gt;&#xA;&lt;li&gt;Participate in the weekly Leetcode contest every Saturday at 7:30 PM PT.&lt;/li&gt;&#xA;&lt;li&gt;Buy Leetcode premium and do a lot of mock interviews (at least 2 per day). Force yourself to be in the session and don&amp;rsquo;t exit prematurely.&#xA;Get into the habit of drawing examples in comments (when I interviewed, there were only virtual onsites).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s an example of what I&amp;rsquo;d do in my head and code. Say what you&amp;rsquo;re thinking out loud. Your thought process might&#xA;make you come up with a strategy or might help the interviewer guide you if you&amp;rsquo;re stuck.&lt;/p&gt;&#xA;&lt;div class=&#34;interview-example&#34;&gt;&#xA;    &lt;p&gt;Example Problem: &#xA;&#xA;&lt;a href=&#34;https://leetcode.com/problems/filling-bookcase-shelves/&#34;target=&#34;_blank&#34;&gt;1105. Filling Bookcase Shelves&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;re given an array of books represented as &lt;code&gt;[width, height]&lt;/code&gt; and a parameter &lt;code&gt;shelf_width&lt;/code&gt;.&#xA;We want to accumulate consecutive books on the shelves of a bookshelf. The sum of the widths of the books must not be greater than the input &lt;code&gt;shelf_width&lt;/code&gt;.&#xA;The height of a single shelf is the max height across all the books on the shelf. We&amp;rsquo;re looking to minimize the bookshelf&amp;rsquo;s total height,&#xA;which is the sum of all the max heights across all of the shelves.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;Input: books = [[1,1],[2,3],[2,3],[1,1],[1,1],[1,1],[1,2]], shelf_width = 4&#xA;Output: 6&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I&amp;rsquo;m trying to understand why the output is 6. I think I&amp;rsquo;d get 6 if I do:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;[&#xA;   [1,1],                         sum(width) = 1, max height = 1&#xA;   [2,3], [2,3]                   sum(width) = 4, max height = 3&#xA;   [1,1], [1,1], [1,1], [1,2]     sum(width) = 4, max height = 2&#xA;]&#xA;sum(max height) = 6&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: Is it possible to have a book whose width is greater than &lt;code&gt;shelf_width&lt;/code&gt;?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;: Not possible.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: It looks like I could have several solutions whose output is the optimal value. I guess we&amp;rsquo;re only interested&#xA;in the sum of the max heights and not in the location of each book, right?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;: Yes, not interested in the location of the books, just in the height of the bookshelf.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: Is it possible for the sum to overflow &lt;code&gt;int&lt;/code&gt;?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Answer&lt;/strong&gt;: No, the answer fits inside an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&lt;strong&gt;Possible greedy strategy&lt;/strong&gt;: It looks like I can solve it with a greedy strategy if I take items from right to left (i.e., starting at the bottom)&#xA;and I can keep accumulating books until I get enough books for the current shelf whose sum doesn&amp;rsquo;t go beyond &lt;code&gt;shelf_width&lt;/code&gt;, e.g.,&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;(reversed order, e.g., bottom to top)&#xA;[&#xA;    [1,2], [1,1], [1,1], [1,1]&#xA;    [2,3], [2,3],&#xA;    [1,1]&#xA;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Possible question that I might get asked&lt;/strong&gt;: Is this greedy strategy going to work for all the cases? Is there an example where it fails?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;My answer&lt;/strong&gt;: I&amp;rsquo;ll think about a case that might break the greedy solution. The case that breaks it is:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;books = [5,5], [2,5], [2,2], shelf_width = 7&#xA;&#xA;[&#xA;    [2,2], [2,5]&#xA;    [5,5]&#xA;]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;In the case above, I&amp;rsquo;d take &lt;code&gt;[2,2], [2,5]&lt;/code&gt; in the last row and &lt;code&gt;[5,5]&lt;/code&gt; in the first one with a total height of 10; the optimal is 7,&#xA;so I think that the greedy approach won&amp;rsquo;t work.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Brainstorm brute force&lt;/strong&gt;: For a brute-force solution, I&amp;rsquo;d put some books on a shelf and then attempt to put the remaining books&#xA;in the next shelf and so on recursively. In the recursion, I&amp;rsquo;d have a parameter &lt;code&gt;i&lt;/code&gt; that would tell me where to start in the array&#xA;of books. To decide how many books I can put on a shelf, I&amp;rsquo;d also need an accumulator that keeps track of the current width sum.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Optimized brute force with DP&lt;/strong&gt;:&#xA;I see that the solution above will create cases where we&amp;rsquo;re trying to solve the problem with the same parameters&#xA;again. I think we can use DP, and the recurrence would be:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;T(i) = min(max(height[i], height[i+1], ..., height[i+k]) + T(k + 1))   from i = 0 up to i = books.size()&#xA;T(books.size()) = 0&#xA;constraint for T(i): sum(width[i], width[i+1], ..., width[i+k]) &amp;lt;= shelf_width&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The time complexity would be &lt;code&gt;O(mn)&lt;/code&gt;, where &lt;code&gt;m&lt;/code&gt; is a variable whose value depends on how many books I can put on a shelf.&#xA;I think that in the worst case, it could be &lt;code&gt;n&lt;/code&gt;, so overall, it&amp;rsquo;s &lt;code&gt;O(n^2)&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The space complexity would be &lt;code&gt;O(n)&lt;/code&gt; because we&amp;rsquo;re storing a solution for every index of the books&amp;rsquo; array.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Question for the interviewer&lt;/strong&gt;: Do you think that this algorithm would work? I don&amp;rsquo;t know what&amp;rsquo;s the max value of &lt;code&gt;n&lt;/code&gt;?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Possible answer&lt;/strong&gt;: Yes, it&amp;rsquo;ll work. &lt;code&gt;n&lt;/code&gt; is small enough so that an &lt;code&gt;O(n^2)&lt;/code&gt; algorithm works.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Finally, you can code it and test it. Make sure you review your implementation before testing, as you may find variables&#xA;that are invalid or small logic errors.&lt;/p&gt;&#xA;&lt;style&gt;&#xA;.language-cpp {&#xA;    border: none !important;&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;class Solution {&#xA;public:&#xA;    int minHeightShelves(vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt;&amp;amp; books, int shelf_width) {&#xA;        const int INF = 1e9;&#xA;        vector&amp;lt;int&amp;gt; dp(books.size(), INF);&#xA;&#xA;        function&amp;lt;int(int)&amp;gt; solve = [&amp;amp;](int i) -&amp;gt; int {&#xA;            if (i == books.size()) return 0;&#xA;            if (dp[i] != INF) return dp[i];&#xA;            int max_h = 0;&#xA;            int acc_width = 0;&#xA;            int j = i;&#xA;            while (j &amp;lt; books.size() &amp;amp;&amp;amp; books[j][0] + acc_width &amp;lt;= shelf_width) {&#xA;                acc_width += books[j][0];&#xA;                max_h = max(max_h, books[j][1]);&#xA;                dp[i] = min(dp[i], max_h + solve(j + 1));&#xA;                ++j;&#xA;            }&#xA;            return dp[i];&#xA;        };&#xA;&#xA;        return solve(0);&#xA;    }&#xA;};&#xA;&#xA;/*&#xA;&#xA;T(0) =&#xA;        [1,1] + T(1)&#xA;        [1,1], [2,3] + T(2)&#xA;&#xA;T(1) =&#xA;        [2,3] + T(2)&#xA;        [2,3], [2,3] + T(3)&#xA;&#xA;T(2) =&#xA;        [2,3] + T(3)&#xA;        ... this path would take the incorrect branch&#xA;*/&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Then compute the last &lt;code&gt;T(x)&lt;/code&gt; (the ones closer to the end of the array) and propagate the values up the stack.&lt;/p&gt;&#xA;&lt;p&gt;Come up with additional tests if you have time. Probably you can handle edge cases like what if the array is empty too.&#xA;If you get &#xA;&#xA;&lt;a href=&#34;https://youtu.be/r8RxkpUvxK0?t=1798&#34;target=&#34;_blank&#34;&gt;a good question&lt;/a&gt;&#xA;&#xA;, the above will not be enough, and you might have a&#xA;follow-up question where you attempt to solve the problem with less space or with better time complexity.&lt;/p&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Also, go through the questions sorted by company. Depending on the company, you might get asked questions from their&#xA;pool. Don&amp;rsquo;t memorize questions; instead, learn the techniques used in each problem.&lt;/li&gt;&#xA;&lt;li&gt;Master Big O notation and understand &#xA;&#xA;&lt;a href=&#34;https://www.bigocheatsheet.com/&#34;target=&#34;_blank&#34;&gt;the time/space complexity of all the data structures that you might use&lt;/a&gt;&#xA;&#xA;. Big focus here on the differences between&#xA;a &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;unordered_map&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;unordered_set&lt;/code&gt;, &lt;code&gt;multiset&lt;/code&gt;, &lt;code&gt;priority_queue&lt;/code&gt;, &lt;code&gt;queue&lt;/code&gt;, &lt;code&gt;stack&lt;/code&gt;, &lt;code&gt;vector&lt;/code&gt;, etc. Also master Big O for recurrences (you can derive the master&#xA;theorem so you don&amp;rsquo;t need to memorize it,&#xA;&#xA;&#xA;&lt;a href=&#34;https://courses.engr.illinois.edu/cs473/sp2010/notes/99-recurrences.pdf&#34;target=&#34;_blank&#34;&gt;learn how to solve recurrences by making a guess and proving your guess by induction or by unrolling the recurrence&lt;/a&gt;&#xA;&#xA;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Pair with a friend and do 45-minute interviews. Take turns to interview each other&lt;/strong&gt;. This, in my opinion, is the best way to prepare because you&amp;rsquo;re doing what you&amp;rsquo;re supposed to do in an interview.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;onsite-preparation&#34;&gt;Onsite preparation&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;After the phone screen interviews, schedule the onsites in 4 to 6 weeks (I did 4 weeks).&lt;/li&gt;&#xA;&lt;li&gt;Pick new problems based on how weak I felt in the patterns shown in the&#xA;&#xA;&#xA;&lt;a href=&#34;https://Leetcode.com/discuss/general-discussion/665604/important-and-useful-links-from-all-over-the-Leetcode&#34;target=&#34;_blank&#34;&gt;leetcode master link&lt;/a&gt;&#xA;&#xA;.&#xA;I discarded some problems that had a bad thumbs up/thumbs down ratio.&lt;/li&gt;&#xA;&lt;li&gt;Pick LC solved problems (medium and hard) and review my solutions if I did them recently.&#xA;If I solved them a long time ago, redo them, read explanations by other coders in the discussion tab.&lt;/li&gt;&#xA;&lt;li&gt;Do mock interviews again and again. I eventually went through all the onsite mock interviews for Google and Facebook.&lt;/li&gt;&#xA;&lt;li&gt;Participate in the weekly Leetcode contest.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Some additional notes for each of my target companies:&lt;/p&gt;&#xA;&lt;div class=&#34;my-interview my-interview--airbnb&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        &lt;ul&gt;&#xA;&lt;li&gt;They may ask a single LC Hard Question in the 45m interview. Check the ones tagged with Airbnb in Leetcode.&lt;/li&gt;&#xA;&lt;li&gt;The code that you write MUST compile and run with test cases that you prepare. Make sure to know the libraries&#xA;that you need to include in your file to compile your code.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;my-interview my-interview--facebook&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        &lt;ul&gt;&#xA;&lt;li&gt;One of their core values is &lt;code&gt;move fast&lt;/code&gt;; therefore, they expect you to come up with a brute-force solution and an&#xA;optimized solution pretty fast. Practice for speed.&lt;/li&gt;&#xA;&lt;li&gt;The coding platform is CoderPad with their logo watermark.&lt;/li&gt;&#xA;&lt;li&gt;You can&amp;rsquo;t run your code, so make sure you check it once after you&amp;rsquo;re done coding and before testing it and debug it&#xA;with some test cases.&lt;/li&gt;&#xA;&lt;li&gt;They typically ask 2 LC easy to medium type of questions. It might be possible that you run out of time explaining&#xA;your approach! As I said, practice for speed.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;my-interview my-interview--google&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        &lt;ul&gt;&#xA;&lt;li&gt;Hardest one to practice because of how unpredictable it is. You may get a warmup question that has a follow-up that turns it into medium or hard.&#xA;You may also get a problem with a nice story hiding a well-known algorithm like sliding-window.&lt;/li&gt;&#xA;&lt;li&gt;Interviews used to be in Google Docs, but now they have their proprietary coding platform at interview.google.com&#xA;(the recruiting coordinator will give you unique links for each one).&lt;/li&gt;&#xA;&lt;li&gt;You can&amp;rsquo;t run your code, so make sure you check it once after you&amp;rsquo;re done coding and before testing it and debug it&#xA;with some test cases.&lt;/li&gt;&#xA;&lt;li&gt;You may need to do back-of-the-envelope calculations in the coding section too. Make sure you understand the &#xA;&#xA;&lt;a href=&#34;https://gabrieletolomei.wordpress.com/miscellanea/operating-systems/in-memory-layout/&#34;target=&#34;_blank&#34;&gt;memory layout&#xA;of a program&lt;/a&gt;&#xA;&#xA;.&#xA;It could help you estimate the memory required for your program in a real-life scenario.&lt;/li&gt;&#xA;&lt;li&gt;For the follow-ups that you won&amp;rsquo;t be able to solve because of the time limit, get into the habit of expressing your ideas&#xA;clearly in typed text. I don&amp;rsquo;t know if these notes are used by the Interviewer or read by the HC, for example:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Interviewer&lt;/strong&gt;: The solution you proposed should work fine. How would you modify your algorithm so that it runs faster if there are no resource constraints?&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;You&lt;/strong&gt;: I can improve the performance of my algorithm by using multiple threads doing X,&#xA;or I can parallelize the work by using map-reduce where the map function is M and the reduce function is R.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;h3 id=&#34;about-practicing-with-someone&#34;&gt;About practicing with someone&lt;/h3&gt;&#xA;&lt;p&gt;Practicing with someone and taking turns is the best way to get used to the interview environment.&#xA;To practice, I used this template with a friend: &#xA;&#xA;&lt;a href=&#34;https://docs.google.com/document/d/1TKNUaBdgzEoPaD8LNexz9JlquRKc1ZSBnNJuZmhFp4Y/edit?usp=sharing&#34;target=&#34;_blank&#34;&gt;Google Docs template&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;about-the-post-onsite-hype&#34;&gt;About the post-onsite hype&lt;/h3&gt;&#xA;&lt;p&gt;After going through 5 rounds in an onsite, I&amp;rsquo;d feel that I&amp;rsquo;ve nailed the interview.&#xA;In reality, your performance might be around average or even below average; you never know.&#xA;If you&amp;rsquo;re doing multiple onsites consecutively, &lt;strong&gt;expect the worst but hope for the best&lt;/strong&gt;.&#xA;Don&amp;rsquo;t let the hype felt after an onsite impact your performance on the next one!&lt;/p&gt;&#xA;&lt;h3 id=&#34;reading-list&#34;&gt;Reading list&lt;/h3&gt;&#xA;&lt;p&gt;Interesting Problems + Hints:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://docs.google.com/document/d/10DrjF-C73AnuPwvLC2yJiiiBYJV9pXtphC20x86--rM/edit?usp=sharing&#34;target=&#34;_blank&#34;&gt;Google Docs - Coding Interview Notes&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Sites to practice:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;http://leetcode.com/&#34;target=&#34;_blank&#34;&gt;Leetcode&lt;/a&gt;&#xA;&#xA;. I have a university discount, so I got the premium for a year for $99. The LC contests start on Saturdays at 7 PM PDT.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://codeforces.com/&#34;target=&#34;_blank&#34;&gt;Codeforces&lt;/a&gt;&#xA;&#xA;. If you like harder problems, then try Codeforces. I think the Div2 A, B, and C problems&#xA;are similar to what you&amp;rsquo;d get in an interview.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Books:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.amazon.com/Elements-Programming-Interviews-Insiders-Guide/dp/1479274836&#34;target=&#34;_blank&#34;&gt;Elements of Programming Interviews&lt;/a&gt;&#xA;&#xA; - Standard resource.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cses.fi/book/book.pdf&#34;target=&#34;_blank&#34;&gt;Competitive Programmer&amp;rsquo;s Handbook&lt;/a&gt;&#xA;&#xA; - This may look advanced for the interviews, but chapters 6 (Greedy Algorithms),&#xA;8 (Amortized Analysis), 10 (Bit Manipulation), and 26 (String Algorithms) have techniques commonly used in coding interviews.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/0984782850&#34;target=&#34;_blank&#34;&gt;Cracking the Coding Interview&lt;/a&gt;&#xA;&#xA; - Great resource. I like&#xA;how problems are solved in EPI more, though.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;system-design&#34;&gt;System Design&lt;/h2&gt;&#xA;&lt;p&gt;System design interviews are very unpredictable. You could practice a lot, but the problem you may get touches a point that you&amp;rsquo;ve never seen before,&#xA;so you have to develop something based on your experience. If you&amp;rsquo;re targeting L5+ at Google and Airbnb or L4+ at Facebook, you&amp;rsquo;ll have at least one System Design interview.&lt;/p&gt;&#xA;&lt;h3 id=&#34;acquiring-knowledge&#34;&gt;Acquiring knowledge&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Watch all the videos from the &#xA;&#xA;&lt;a href=&#34;https://pdos.csail.mit.edu/6.824/schedule.html&#34;target=&#34;_blank&#34;&gt;MIT 6.824 Distributed Systems&lt;/a&gt;&#xA;&#xA; course and &lt;strong&gt;do the labs&lt;/strong&gt;.&#xA;This resource helped immensely during the team matching phase at Google, where I had a chance to show what I learned&#xA;and how I could be useful to the team.&#xA;My favorite lectures: &#xA;&#xA;&lt;a href=&#34;https://thesquareplanet.com/blog/students-guide-to-raft/&#34;target=&#34;_blank&#34;&gt;all the Raft ones&lt;/a&gt;&#xA;&#xA; and how Facebook uses Memcached.&lt;/li&gt;&#xA;&lt;li&gt;Watch tons of presentations about how big companies solve problems at scale; my links will be below.&lt;/li&gt;&#xA;&lt;li&gt;Learn algorithms and data structures used in distributed systems; my links will be below.&lt;/li&gt;&#xA;&lt;li&gt;Read &#xA;&#xA;&lt;a href=&#34;https://docs.microsoft.com/en-us/azure/architecture/patterns/&#34;target=&#34;_blank&#34;&gt;the cloud design patterns&lt;/a&gt;&#xA;&#xA; for building reliable, scalable, secure applications in the cloud.&lt;/li&gt;&#xA;&lt;li&gt;If you&amp;rsquo;re a full-time Software Engineer, then ask your manager for more challenging problems.&#xA;I&amp;rsquo;m honored to have had a fantastic manager who genuinely cared about me in my previous company and helped me work on big projects&#xA;where I had the chance to learn and grow. That was one of the reasons why I stayed there for so long.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;onsite-preparation-1&#34;&gt;Onsite preparation&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Learn how to use Google Drawings. &#xA;&#xA;&lt;a href=&#34;https://docs.google.com/drawings/d/11GQ_JBU5AH9BV40BulAuFIv66CexIad1zalG26OzZh4/edit?usp=sharing&#34;target=&#34;_blank&#34;&gt;This is my Google Drawings template&lt;/a&gt;&#xA;&#xA; and&#xA;&#xA;&#xA;&lt;a href=&#34;https://docs.google.com/drawings/d/1PbxOaBTwC3BfTMpZx9WtRmoSnWfMM5cmCSAT5mrqODA/edit?usp=sharing&#34;target=&#34;_blank&#34;&gt;this is an example of how I used it&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;Master the structure of the interview. &#xA;&#xA;&lt;a href=&#34;https://leetcode.com/discuss/career/229177/My-System-Design-Template&#34;target=&#34;_blank&#34;&gt;I followed this system design template&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;Define functional and non-functional requirements. Don&amp;rsquo;t make too many assumptions, and if you do, say them out loud&#xA;so your interviewer is aware of this. Big focus on mentioning tradeoffs.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;interview-example&#34;&gt;&#xA;    &lt;blockquote&gt;&#xA;&lt;p&gt;Design a system that does X and handles REQ requests doing W writes and R reads.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;What are the most critical features?&lt;/li&gt;&#xA;&lt;li&gt;Daily active users, traffic volume, read/write ratio?&lt;/li&gt;&#xA;&lt;li&gt;Are these writes in single/multiple regions?&lt;/li&gt;&#xA;&lt;li&gt;Access patterns, even load vs. spikes throughout the day?&lt;/li&gt;&#xA;&lt;li&gt;Latency requirements, tradeoff fast reads for slow writes?&lt;/li&gt;&#xA;&lt;li&gt;Data consistency, eventual vs. strong consistency?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Design a chat system where users send and receive messages in real-time.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;(after talking about the functional and non-functional requirements)&lt;/p&gt;&#xA;&lt;p&gt;The client can use the following approaches:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Polling&lt;/strong&gt;: here, the client will periodically make requests at some fixed rate, like every 30s. The disadvantage&#xA;is that every time we&amp;rsquo;re creating a new connection and wasting server resources because we might not have&#xA;any message to send or receive.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Long polling&lt;/strong&gt;: this approach is similar to polling. However, we keep the connection open and wait for the&#xA;server to send some data across the wire. As soon as we receive data, we reopen/create a connection.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Web sockets&lt;/strong&gt;: in this approach, we keep the connection open since web sockets connections are persistent and made&#xA;for bidirectional communication. For the application protocol, it could depend on the devices we&amp;rsquo;ll use for the chat system. If&#xA;it&amp;rsquo;s a battery-powered device, then the overhead of the XMPP protocol is the fact that the device has to parse XML, which could be detrimental to the battery life.&#xA;Instead, the MQTT protocol is designed to use bandwidth and battery sparingly. At the same time, the&#xA;XMPP protocol is extensible and adaptable that we could use if we want additional functionality like bots.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Do some &#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/back-of-the-envelope-calculations/&#34;target=&#34;_blank&#34;&gt;back-of-the-envelope calculations&lt;/a&gt;&#xA;&#xA; if needed.&#xA;Always clarify with your interviewer. This step is crucial at big&#xA;companies where you need to design for scale and think about capacity planning before you design your system.&#xA;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/back-of-the-envelope-calculations/&#34;target=&#34;_blank&#34;&gt;I have created an article with exercises and estimates that could be helpful&lt;/a&gt;&#xA;&#xA;.&#xA;I&amp;rsquo;ve taken this example from &#xA;&#xA;&lt;a href=&#34;https://interviewready.io/&#34;target=&#34;_blank&#34;&gt;Gaurav Sen&amp;rsquo;s awesome course on system design&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;interview-example&#34;&gt;&#xA;    &lt;blockquote&gt;&#xA;&lt;p&gt;We&amp;rsquo;re going to design an email server for 2B users. When a user sends an email, it can attach files with a size up to 1MB.&#xA;How much storage do we need per day to store emails?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say each email has 200 characters, on average. A user receives emails from useful connections, companies, and spam.&#xA;Assume 20 spam emails, 20 marketing emails, and 10 useful emails per user per day.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;Email data = Emails * Characters * Users&#xA;           = 50 * 200 * 2B&#xA;           = 20 TB&#xA;&#xA;Attachment data = number of emails with attachments * average attachment size&#xA;                = 5% of all emails * 1 MB&#xA;                = 5% * 50 * 2B * 1 MB = 5 PB&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;So the total space requirement is &lt;code&gt;Email data + Attachment data = 20TB + 5 PB&lt;/code&gt; per day.&#xA;This is a naively optimistic estimate since we must account for redundancy (to improve performance and fault tolerance).&#xA;&lt;code&gt;Estimated total space requirement = (20TB + 5 PB) * 3 ~ ​15PB per day&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Define the API (signature, inputs, outputs) and the data model. I moved between these two back and forth during the interview.&lt;/li&gt;&#xA;&lt;li&gt;High-level design: make sure that your design covers all the functional requirements. Don&amp;rsquo;t go too deep here, or you&amp;rsquo;ll waste invaluable time.&lt;/li&gt;&#xA;&lt;li&gt;Pick a component (alternatively, the interviewer may pick it for you) and then explain why you need it. Big focus here again on tradeoffs.&lt;/li&gt;&#xA;&lt;li&gt;Since this is a design for scale, you&amp;rsquo;ll need to split processing or data into multiple machines. Learn how to handle failures at scale.&lt;/li&gt;&#xA;&lt;li&gt;If you have time, talk about things you&amp;rsquo;d do to maintain the system, including monitoring and security.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;low-level-system-design&#34;&gt;Low-level system design&lt;/h3&gt;&#xA;&lt;p&gt;For senior levels (L5+), you might encounter questions involving designing and coding the internals of a class.&#xA;This type of question is more of a coding question than a system design question, but you should be aware of the tradeoffs you make at every stage in your design.&lt;/p&gt;&#xA;&lt;p&gt;If you haven&amp;rsquo;t taken any Operating Systems class, I recommend the &#xA;&#xA;&lt;a href=&#34;https://omscs.gatech.edu/cs-6200-introduction-operating-systems&#34;target=&#34;_blank&#34;&gt;Graduate Introduction to Operating Systems by Georgia Tech&lt;/a&gt;&#xA;&#xA;.&#xA;I&amp;rsquo;m in grad school as I write this, and I recently took this class. Unfortunately, the labs aren&amp;rsquo;t public, but the&#xA;material is nevertheless a great introduction.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;d suggest you learn about mutexes, condition variables, atomics, readers-writers, boss-worker model, pipeline model, cache lines, and so many others!&#xA;Also, read and attempt to implement the following classes from scratch, either with C++11 Multithreading primitives or pthreads.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Semaphore&lt;/li&gt;&#xA;&lt;li&gt;Threadpool - &#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/programming-languages/cpp-refresher/#multithreading&#34;target=&#34;_blank&#34;&gt;I implemented a threadpool in my Cpp refresher algorithm&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Thread-safe dictionary, queue, stack, and priority queue&lt;/li&gt;&#xA;&lt;li&gt;Parallel sort&lt;/li&gt;&#xA;&lt;li&gt;Multithreaded crawler&lt;/li&gt;&#xA;&lt;li&gt;Distributed key-value store - &#xA;&#xA;&lt;a href=&#34;https://pdos.csail.mit.edu/6.824/labs/lab-raft.html&#34;target=&#34;_blank&#34;&gt;MIT&amp;rsquo;s Distributed System course has a lab on it&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Distributed file system - The Georgia Tech Graduate Introduction to Operating Systems course&amp;rsquo;s Project 4 is all about this.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Resources:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://omscs.gatech.edu/cs-6200-introduction-operating-systems&#34;target=&#34;_blank&#34;&gt;Graduate Introduction to Operating Systems by Georgia Tech&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/playlist?list=PL5jc9xFGsL8E12so1wlMS0r0hTQoJL74M&#34;target=&#34;_blank&#34;&gt;Concurrent Programming with C++&lt;/a&gt;&#xA;&#xA; -&#xA;Excellent intro to multithreading concepts and primitives, a perfect mix of theory and practice.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=F6Ipn7gCOsY&#34;target=&#34;_blank&#34;&gt;Back to Basics: Concurrency - Arthur O&amp;rsquo;Dwyer - CppCon 2020&lt;/a&gt;&#xA;&#xA; - Overview of modern concurrency in C++11.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.amazon.com/Elements-Programming-Interviews-Insiders-Guide/dp/1479274836/&#34;target=&#34;_blank&#34;&gt;Chapter 19 in EPI&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=WDIkqP4JbkE&#34;target=&#34;_blank&#34;&gt;CPU Caches and Why You Care&lt;/a&gt;&#xA;&#xA; - Fantastic introduction to cache lines. I learned&#xA;more about data locality and that having more threads will not always improve your program&amp;rsquo;s performance as you thought it would.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://get.interviewready.io/&#34;target=&#34;_blank&#34;&gt;Gaurav Sen&amp;rsquo;s System design course&lt;/a&gt;&#xA;&#xA; - In addition to system design questions, it also has low-level design problems.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;reading-list-1&#34;&gt;Reading list&lt;/h3&gt;&#xA;&lt;p&gt;These are my notes about interesting tech:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/non-functional-requirements/&#34;target=&#34;_blank&#34;&gt;Non-Functional requirements&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/partitioning/&#34;target=&#34;_blank&#34;&gt;Partitioning&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/cassandra/&#34;target=&#34;_blank&#34;&gt;Cassandra&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/kafka/&#34;target=&#34;_blank&#34;&gt;Kafka&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/system-design/back-of-the-envelope-calculations/&#34;target=&#34;_blank&#34;&gt;Back of the Envelope calculations&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/computer-science/data-structures/data-structures-for-massive-datasets/&#34;target=&#34;_blank&#34;&gt;Data Structures for Massive Datasets&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://docs.google.com/document/d/1sqI-Pf52GvzC08ZXHROt48bQYiabOUa2RXIO46vkxsc/edit?usp=sharing&#34;target=&#34;_blank&#34;&gt;Knowledge repository with links to interesting tech&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;List of books:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.amazon.com/System-Design-Interview-Questions-Solutions-ebook/dp/B08B3FWYBX&#34;target=&#34;_blank&#34;&gt;System design Interview - Alex Xu&lt;/a&gt;&#xA;&#xA; -&#xA;My favorite book about system design interviews. It covers the system design interview structure and has many real-life examples.&#xA;What I really like about this is the focus on tradeoffs. It has 4 different rate-limiting algorithms, and all of them are valid.&#xA;Having the ability to demonstrate why you picked a solution over others is what the interview is about.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.amazon.com/Scalability-Startup-Engineers-Artur-Ejsmont-ebook/dp/B00ZPS4KI0/&#34;target=&#34;_blank&#34;&gt;Web Scalability for Startup Engineers - Artur Ejsmont&lt;/a&gt;&#xA;&#xA; -&#xA;Great intro to all of the components in a complex web application.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://leanpub.com/distributed-systems-for-practitioners&#34;target=&#34;_blank&#34;&gt;Distributed Systems for Practitioners - Dimos Raptis&lt;/a&gt;&#xA;&#xA; -&#xA;The why behind a technology and use cases in the industry. I liked the way it&amp;rsquo;s structured with the theory first and then practice.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://dataintensive.net/&#34;target=&#34;_blank&#34;&gt;Designing Data-Intensive Applications - Martin Kleppmann&lt;/a&gt;&#xA;&#xA; -&#xA;Deep into how distributed systems work. I think this is a standard resource by now.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;List of courses:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.educative.io/courses/grokking-the-system-design-interview&#34;target=&#34;_blank&#34;&gt;Grokking the system design interview&lt;/a&gt;&#xA;&#xA; - Standard resource.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://github.com/donnemartin/system-design-primer&#34;target=&#34;_blank&#34;&gt;System Design Primer&lt;/a&gt;&#xA;&#xA; - Standard resource.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=bUHFg8CZFws&#34;target=&#34;_blank&#34;&gt;System Design Interview – Step By Step Guide&lt;/a&gt;&#xA;&#xA; - Amazing YouTube channel for system design interviews.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://get.interviewready.io/&#34;target=&#34;_blank&#34;&gt;Gaurav Sen&amp;rsquo;s System design course&lt;/a&gt;&#xA;&#xA; - Perfect resource to learn about making iterations over time in your design and to do back-of-the-envelope calculations.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.coursera.org/learn/cloud-infrastructure-design-process&#34;target=&#34;_blank&#34;&gt;Reliable Google Cloud Infrastructure: Design and Process&lt;/a&gt;&#xA;&#xA; - A guide from Google on how to design systems for Google Cloud.&#xA;Even though the implementation is done with Google Cloud Services, the videos about the functional/non-functional requirement phase are very helpful.&#xA;I learned about KPIs and their relationship with SLI, SLO, and SLA.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;behavioral-questions&#34;&gt;Behavioral Questions&lt;/h2&gt;&#xA;&lt;p&gt;Google and Facebook have 1 behavioral round, and Airbnb has 2 behavioral rounds. For this part, Cracking the Coding Interview helped a lot.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Your level inside the company is based on your answers to this round. Talk about your leadership skills!&lt;/li&gt;&#xA;&lt;li&gt;Learn to introduce yourself; you might do this in some coding rounds too. A must for the team matching phase at Google or Airbnb. The template that I use is:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Hello, my name is &lt;code&gt;{your name}&lt;/code&gt;, and I&amp;rsquo;m a software engineer at &lt;code&gt;{current company}&lt;/code&gt; where we do &lt;code&gt;{description of the product}&lt;/code&gt;.&#xA;I&amp;rsquo;m currently working on &lt;code&gt;{project A doing front-end, back-end, infra, ml, etc.}&lt;/code&gt;. In the past, I worked at &lt;code&gt;{previous company}&lt;/code&gt; where I did &lt;code&gt;{more projects}&lt;/code&gt;.&#xA;On the side, I&amp;rsquo;m doing &lt;code&gt;{school coursework or extracurricular activities}&lt;/code&gt;, and my next objective is to achieve &lt;code&gt;{objective in the short term}&lt;/code&gt;.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Learn about STAR. Create a grid with questions, projects, and answers for each one.&lt;/li&gt;&#xA;&lt;li&gt;Practice with a friend. I&amp;rsquo;m friends with an awesome Googler that helped me a lot here with mock interviews. We practiced many times, and he noticed that my&#xA;answers were not specific enough or were not structured pretty well. To improve, I wrote down my answers to all of these questions and rehearsed them many times:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Tell me about a challenging project.&lt;/li&gt;&#xA;&lt;li&gt;What did you enjoy learning the most?&lt;/li&gt;&#xA;&lt;li&gt;Tell me about a time you had a conflict of priorities with your manager.&lt;/li&gt;&#xA;&lt;li&gt;Tell me about a time you made a mistake.&lt;/li&gt;&#xA;&lt;li&gt;Tell me about a time you had to make a difficult decision.&lt;/li&gt;&#xA;&lt;li&gt;Tell me how you solved an unambiguous task at work.&lt;/li&gt;&#xA;&lt;li&gt;What are the qualities of a good leader, according to you?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;my-interview my-interview--airbnb&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        &lt;p&gt;A special note about Airbnb: they do care about the culture fit more than anyone. Spend some time understanding what &lt;code&gt;belong anywhere&lt;/code&gt; means.&#xA;I watched a lot of interviews with Brian Chesky, which helped me solidify my willingness to work at Airbnb (&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=jgPYSogOOTY&#34;target=&#34;_blank&#34;&gt;(6 golden rules)&lt;/a&gt;&#xA;&#xA;).&#xA;On the onsite, you have 2 behavioral rounds with questions that can be found here: &#xA;&#xA;&lt;a href=&#34;https://candor.co/interviews/airbnb&#34;target=&#34;_blank&#34;&gt;https://candor.co/interviews/airbnb&lt;/a&gt;&#xA;&#xA; . The most important ones are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;What does belonging mean to you? What is your understanding of Airbnb culture?&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Why Airbnb?&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Make sure you practice some of these even before you apply to Airbnb. The recruiter wants to know if you&amp;rsquo;re genuinely interested in Airbnb.&lt;/p&gt;&#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;my-interview my-interview--facebook&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        They have a behavioral round of 30m with common behavioral questions and an easy coding question at the end. Read this article&#xA;about &#xA;&#xA;&lt;a href=&#34;https://jdxcode.com/posts/2020-09-16-10-tips-ramping-up-as-a-senior-engineer/&#34;target=&#34;_blank&#34;&gt;Ramping Up as a Senior Software Engineer&lt;/a&gt;&#xA;&#xA;.&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;div class=&#34;my-interview my-interview--google&#34;&gt;&#xA;    &lt;span class=&#34;my-interview__logo&#34;&gt;&lt;/span&gt;&#xA;    &lt;div class=&#34;my-interview__content&#34;&gt;&#xA;        Pure behavioral round. If you&amp;rsquo;re targeting L5+, be honest about your experience!&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;h2 id=&#34;the-end&#34;&gt;The end?&lt;/h2&gt;&#xA;&lt;p&gt;Passing/failing the interview is not the end, and if you fail, it doesn&amp;rsquo;t&#xA;mean that you&amp;rsquo;re not good enough. There are too many variables outside your control.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If it went well, then it&amp;rsquo;s a good opportunity to learn.&lt;/li&gt;&#xA;&lt;li&gt;If it didn&amp;rsquo;t go well, then it was also a good opportunity to learn and if you want, try again!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;my-parallax tw-text-primary tw-absolute tw-left-0&#34;&gt;&#xA;  &lt;div class=&#34;tw-absolute tw-left-0 tw-top-0 tw-opacity-25&#34;&gt;&#xA;    &#xA;      &lt;style&gt;&#xA;      css-doodle {&#xA;        --doodle-atari: (&#xA;          @grid: 1 / 100vw 100vh / #0a0c27;&#xA;          background-size: 200px 200px;&#xA;          background-image: @doodle(&#xA;            @grid: 6 / 100%;&#xA;            @size: 4px;&#xA;            font-size: 4px;&#xA;            color: hsl(@r240, 30%, 50%);&#xA;            box-shadow: @m3x5(&#xA;              calc(4em - @nx*1em) @ny(*1em)&#xA;                @p(@m3(currentColor), @m2(#0000)),&#xA;              calc(2em + @nx*1em) @ny(*1em)&#xA;                @lp&#xA;            );&#xA;          );&#xA;        );&#xA;      }&#xA;      &lt;/style&gt;&#xA;      &lt;css-doodle use=&#34;var(--doodle-atari)&#34;&gt;&lt;/css-doodle&gt;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;&#xA;    &#xA;  &lt;/div&gt;&#xA;  &#xA;  &lt;div class=&#34;md:tw-w-3/5 tw-m-auto tw-relative tw-h-screen tw-grid tw-place-content-center&#34;&gt;&#xA;    &lt;div class=&#34;tw-text-primary tw-text-3xl md:tw-text-5xl md:tw-mx-auto tw-font-[Ultra] tw-text-center&#34;&gt;&#xA;      &lt;p&gt;Success is not final, failure is not fatal, it is the &lt;b&gt;courage to continue&lt;/b&gt; that counts.&lt;/p&gt;&#xA;      &lt;p class=&#34;tw-text-right tw-text-xl&#34;&gt;&lt;i&gt;Winston Churchill&lt;/i&gt;&lt;/p&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;&lt;div style=&#34;height: 100vh;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function () {&#xA;  let parallaxTarget = &#39;&#39;&#xA;  if (!parallaxTarget) {&#xA;    return&#xA;  }&#xA;&#xA;  const myScrollableContent = document.querySelector(parallaxTarget);&#xA;  if (!myScrollableContent) {&#xA;    console.error(`could not find target=${parallaxTarget} to enable parallax.`)&#xA;    return;&#xA;  }&#xA;&#xA;  myScrollableContent.style.position = &#34;relative&#34;&#xA;  myScrollableContent.style.top = `200px`&#xA;&#xA;  const container = myScrollableContent.closest(&#39;.my-parallax&#39;);&#xA;  &#xA;  const parallaxFactor = 1.2;&#xA;&#xA;  function animateOnScroll() {&#xA;    const rect = container.getBoundingClientRect();&#xA;    const viewportHeight = window.innerHeight;&#xA;&#xA;    &#xA;    const animationStart = viewportHeight + 100;&#xA;    &#xA;    const animationEnd = -container.offsetHeight;&#xA;&#xA;    let translateY;&#xA;    if (rect.top &gt; animationStart) {&#xA;      &#xA;      translateY = 0;&#xA;    } else if (rect.top &lt; animationEnd) {&#xA;      &#xA;      const totalScroll = animationStart - animationEnd;&#xA;      translateY = -totalScroll * (parallaxFactor - 1);&#xA;    } else {&#xA;      &#xA;      const scrollAmount = animationStart - rect.top;&#xA;      translateY = -scrollAmount * (parallaxFactor - 1);&#xA;    }&#xA;&#xA;    myScrollableContent.style.transform = `translateY(${translateY}px)`;&#xA;  }&#xA;&#xA;  let ticking = false;&#xA;  window.addEventListener(&#39;scroll&#39;, function() {&#xA;    if (!ticking) {&#xA;      window.requestAnimationFrame(function() {&#xA;        animateOnScroll();&#xA;        ticking = false;&#xA;      });&#xA;      ticking = true;&#xA;    }&#xA;  }, { passive: true });&#xA;&#xA;  &#xA;  animateOnScroll();&#xA;})();&#xA;&lt;/script&gt;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Back of the envelope calculations</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/system-design/back-of-the-envelope-calculations/</link>
      <pubDate>Sat, 08 Aug 2020 15:45:36 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/system-design/back-of-the-envelope-calculations/</guid>
      <description>&lt;p&gt;Calculate with exponents. A lot of back-of-the-envelope calculations are done with just coefficients and exponents, e.g., $c * 10^e$.&#xA;Your goal is to get within an order of magnitude, which is just $e$. $c$ matters a lot less.&#xA;Only worrying about single-digit coefficients and exponents makes it much easier on a napkin (not to speak of all the zeros you avoid writing).&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;Latency Comparison Numbers&#xA;--------------------------&#xA;Source: https://gist.github.com/BlackHC/2d0a3a21542b524a7cf2f8eac977481e&#xA;Benchmarks for read: https://ssd.userbenchmark.com/, https://hdd.userbenchmark.com/&#xA;&#xA;L1 cache reference                           0.5 ns&#xA;Branch mispredict                            5   ns&#xA;L2 cache reference                           7   ns                      14x L1 cache&#xA;Mutex lock/unlock                           25   ns&#xA;Main memory reference                      100   ns                      20x L2 cache, 200x L1 cache&#xA;Compress 1K bytes with Snappy            3,000   ns        3 µs&#xA;Read 1 MB sequentially from memory      20,000   ns       20 µs  .02 ms  ~50GB/s DDR5&#xA;Read 1 MB sequentially from NVMe       100,000   ns      100 µs   .1 ms  ~10GB/sec NVMe, 5x memory&#xA;Read 1 MB sequentially from SSD        300,000   ns      300 µs   .3 ms  ~3GB/sec SSD, 15x memory, 3x NVMe&#xA;Round trip within same datacenter      500,000   ns      500 µs   .5 ms&#xA;Read 1 MB sequentially from HDD      6,000,000   ns    6,000 µs    6 ms  ~150MB/sec, 300x memory, 60x NVMe, 20x SSD&#xA;Send 1 MB over 1 Gbps network       10,000,000   ns   10,000 µs   10 ms&#xA;Disk seek                           10,000,000   ns   10,000 µs   10 ms  20x datacenter roundtrip&#xA;Send packet CA-&amp;gt;Netherlands-&amp;gt;CA    150,000,000   ns  150,000 µs  150 ms&#xA;&#xA;Notes&#xA;-----&#xA;1 ns = 10^-9 seconds&#xA;1 µs = 10^-6 seconds = 1,000 ns&#xA;1 ms = 10^-3 seconds = 1,000 µs = 1,000,000 ns&#xA;&#xA;Cost Numbers&#xA;------------&#xA;Approximate numbers that should be consistent between Cloud providers.&#xA;&#xA;What    Amount  $/Month&#xA;CPU          1      $10&#xA;Memory    1 GB       $1&#xA;SSD       1 GB     $0.1&#xA;HDD       1 GB    $0.01&#xA;S3, GCS   1 GB    $0.01&#xA;Network   1 GB    $0.01&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;iframe src=&#34;https://instacalc.com/53733/embed&#34; width=&#34;100%&#34; height=&#34;210&#34; frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;1 request per second = 100k requests/day (exactly 1 req/s = 86.4k req/day).&lt;/li&gt;&#xA;&lt;li&gt;1 request per second = 2.5M requests/month.&lt;/li&gt;&#xA;&lt;li&gt;10 requests per second = 1M requests/day (exactly 11.6 req/s = 1M req/day).&lt;/li&gt;&#xA;&lt;li&gt;40 requests per second = 100 million requests/month.&lt;/li&gt;&#xA;&lt;li&gt;400 requests per second = 1 billion requests/month.&lt;/li&gt;&#xA;&lt;li&gt;6-7 world-wide round trips per second.&lt;/li&gt;&#xA;&lt;li&gt;2,000 round trips per second within a data center.&lt;/li&gt;&#xA;&lt;li&gt;100k commands per second in an in-memory single-threaded data store.&lt;/li&gt;&#xA;&lt;li&gt;It&amp;rsquo;s typically the case that we can ignore any memory latency as soon as I/O is involved in a 1Gbps network.&#xA;In cloud datacenters, bandwidth is capped depending on the instance type. From the&#xA;&#xA;&#xA;&lt;a href=&#34;https://cloud.google.com/compute/docs/network-bandwidth&#34;target=&#34;_blank&#34;&gt;Google Cloud&lt;/a&gt;&#xA;&#xA; docs, there are different&#xA;limits for ingress and egress. For simplicity, let&amp;rsquo;s assume 10Gbps for both.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;C4 and C4A lowest egress is 10Gbps.&lt;/li&gt;&#xA;&lt;li&gt;C4 and C4A highest egress is 100Gbps.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Writes are 40 times more expensive than reads; therefore, architect for scaling writes!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;exercises&#34;&gt;Exercises&lt;/h2&gt;&#xA;&lt;p&gt;We get better at using this table by practicing. &#xA;&#xA;&lt;a href=&#34;https://sirupsen.com/napkin/&#34;target=&#34;_blank&#34;&gt;https://sirupsen.com/napkin/&lt;/a&gt;&#xA;&#xA; has lots of exercises with&#xA;different difficulty levels. The following exercises are a warmup for the ones in other places.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s assume a data store with the following types:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In-memory data store: State stored in RAM (volatile).&lt;/li&gt;&#xA;&lt;li&gt;Persistent data store: State stored on disk (non-volatile).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The data store can be located:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;In-process: In the same computer.&lt;/li&gt;&#xA;&lt;li&gt;Out-of-process: In a different computer (so there&amp;rsquo;s a need for packet transmission over the network).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Read 1MB from an out-of-process data store. Consider both in-memory and persistent caches (SSD). Assume a 1Gbps and a 10Gbps network.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;1Gbps&#xA;&lt;ul&gt;&#xA;&lt;li&gt;(in memory)  &lt;code&gt;0.02 ms/MB (read from memory) + 10^1 ms (transmission) = 10.02 ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;(persistent) &lt;code&gt;0.3 ms/MB (read from SSD) + 10^1 ms (transmission) = 10.3 ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;10Gbps&#xA;&lt;ul&gt;&#xA;&lt;li&gt;(in memory)  &lt;code&gt;0.02 ms/MB (read from memory) + 10^0 ms (transmission) = 1.02 ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;(persistent) &lt;code&gt;0.3 ms/MB (read from SSD) + 10^0 ms (transmission) = 1.3 ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Read 5GB from HDD, SSD, and RAM, then write 5GB to the same medium. Assume no network I/O is needed.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Read 5GB:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;(memory) &lt;code&gt;5*10^3 MB * 0.02 ms/MB (memory read) = 100ms = 0.1s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;(SSD) &lt;code&gt;5*10^3 MB * 0.3 ms/MB (SSD read) = 1500 ms = 1.5s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;(HDD) &lt;code&gt;5*10^3 MB * 6 ms/MB (HDD read) = 30000 ms = 30s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Write 5GB, let&amp;rsquo;s assume that a write is 40x slower than a read:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;(memory) &lt;code&gt;40 (write penalty) * 0.1s (read) = 4s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;(SSD) &lt;code&gt;40 (write penalty) * 1.5s = 60s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;(HDD) &lt;code&gt;40 (write penalty) * 30s = 1200s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Store information about 2B users, including basic info and a profile picture.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Basic info: name (20 chars), dob (10 chars), email (20 chars) = 50 bytes, $2 * 10^9 * 50 B = 100 GB$&lt;/li&gt;&#xA;&lt;li&gt;Profile picture: 100 KB, $2 * 10^9 * 100 * 10^3 B = 200 TB$&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Your SSD-backed database has a usage pattern that rewards you with an 80% page-cache hit rate&#xA;(i.e., 80% of disk reads are served directly out of memory instead of going to the SSD).&#xA;The median number of pages (e.g., InnoDB pages in MySQL) read to serve a query is 50.&#xA;What is the expected average query time from your database?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.percona.com/blog/2006/06/04/innodb-page-size/&#34;target=&#34;_blank&#34;&gt;The default size of a page in InnoDB is 16KB&lt;/a&gt;&#xA;&#xA;.&#xA;For each query, we read 50 pages; 50 * 0.8 = 40 are read from memory, and 10 are from SSD.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;40 pages read from memory: &lt;code&gt;40 * 16KB * 0.02 ms/MB = 640KB * 10^-3 MB/KB * 0.02 ms/MB = 0.0128 ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;10 pages read from SSD: &lt;code&gt;10 * 16KB * 0.3 ms/MB = 160KB * 10^-3 MB/KB * 0.3 ms/MB = 0.048ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In real life, we just round the numbers: 1ms tops for the sum. It’s typically the case that we can ignore any memory latency as soon as I/O is involved for low Gbps (1GB).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;1Gbps&#xA;&lt;ul&gt;&#xA;&lt;li&gt;50 pages (50 * 16KB = 800KB) transmitted in about 10ms, &lt;code&gt;1ms (read pages) + 10ms (transmission) = 11ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;10Gbps&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;1ms (read pages) + 1ms (transmission) = 2ms&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;How many commands-per-second can a simple, in-memory, single-threaded data store do?&#xA;Assume that the commands don&amp;rsquo;t do any server-side processing, e.g., reading data is just&#xA;reading data from memory/disk and isn&amp;rsquo;t applying any algorithms to it.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;I/O controls the number of ops/s. Assuming that we transmit 1KB, $\frac{1s}{10 \mu s} = 10^5$ = 100k ops/s.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;What is the amount of computing power needed to process 1PB every day? Assume that the time required for the computation of 1MB is 0.1s.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;10^9 MB * 10^-1 s/MB = 10^8 s&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;The above has to be computed every day, or in &lt;code&gt;10^5 s&lt;/code&gt;.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;10^8 s * 10^-5 day/s = 10^3 days&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;We would need $10^3$ machines to get the work done. Assuming that the servers should be running at&#xA;50% capacity and with possible spikes, we can provision $4 * 10^3$ processes.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;We have three storage devices: a 128GB DRAM as a 1st-level cache, a 600GB flash memory as a 2nd-level cache,&#xA;and a rotational disk for storage. With a random read workload, the rotational disk delivers 2,000 reads/s&#xA;with an 8 KB I/O size. How much time would it take to warm both caches in the ideal scenario?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Throughput in terms of data transmitted over time: &lt;code&gt;2,000 reads/s * 8 KB = 16 MB/s&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;1st-level cache:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Time to fill out the cache: &lt;code&gt;128 GB / 16 MB/s = 8,000 s = ~2.3h&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;2nd-level cache:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Time to fill out the cache: &lt;code&gt;600 GB / 16 MB/s = 38,400 s = ~10.67h&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Introduction to Machine Learning</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/introduction/</link>
      <pubDate>Thu, 25 Jun 2020 23:05:30 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/introduction/</guid>
      <description>&lt;p&gt;Machine Learning is great for:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Problems for which existing solutions require a lot of fine-tuning or long lists of&#xA;rules: One Machine Learning algorithm can often simplify code and perform better than&#xA;the traditional approach.&lt;/li&gt;&#xA;&lt;li&gt;Complex problems for which using a traditional approach yields no good solution:&#xA;The best Machine Learning techniques can perhaps find a solution.&lt;/li&gt;&#xA;&lt;li&gt;Fluctuating environments: A Machine Learning system can adapt to new data,&#xA;getting insights about complex problems and large amounts of data.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Examples of applications:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Analyzing images of products on a production line to classify them (CNN).&lt;/li&gt;&#xA;&lt;li&gt;Detecting tumors in brain scans (CNN).&lt;/li&gt;&#xA;&lt;li&gt;Classifying news articles (NLP, RNN, CNN, or Transformers).&lt;/li&gt;&#xA;&lt;li&gt;Flagging unwanted content (NLP).&lt;/li&gt;&#xA;&lt;li&gt;Summarizing long documents (Text Summarization).&lt;/li&gt;&#xA;&lt;li&gt;Creating a chatbot (NLP, NLU).&lt;/li&gt;&#xA;&lt;li&gt;Forecasting revenue based on many performance metrics (Linear Regression, SVM, NN).&lt;/li&gt;&#xA;&lt;li&gt;Segmenting clients based on their purchases (Clustering).&lt;/li&gt;&#xA;&lt;li&gt;Recommending a product based on past purchases (Artificial NN).&lt;/li&gt;&#xA;&lt;li&gt;Building an AI bot (RL).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Types of ML:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Whether or not they are trained with human supervision (supervised, unsupervised, semi-supervised, and RL).&lt;/li&gt;&#xA;&lt;li&gt;Whether or not they can learn incrementally on the fly (online vs. batch learning).&lt;/li&gt;&#xA;&lt;li&gt;Whether they work by comparing new data points to known data points or by detecting patterns in the training data and building a model (instance-based vs. model-based learning).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Machine Learning Glossary</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/glossary/</link>
      <pubDate>Mon, 25 May 2020 15:04:38 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/glossary/</guid>
      <description>&lt;h3 id=&#34;iterations-batch-batch-size-and-epoch&#34;&gt;iterations, batch, batch size and epoch&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A &lt;strong&gt;batch&lt;/strong&gt; is the set of examples used in one iteration. The number of examples in the set is the &lt;strong&gt;batch size&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;For example, the batch size of SGD is 1, while the batch size of a mini-batch is usually between 10 and 1,000.&#xA;The batch size is usually fixed during training and inference; however, TensorFlow does permit dynamic batch sizes.&lt;/li&gt;&#xA;&lt;li&gt;Each &lt;strong&gt;iteration&lt;/strong&gt; is the span in which the system processes one &lt;strong&gt;batch&lt;/strong&gt; of size &lt;strong&gt;batch size&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;An &lt;strong&gt;epoch&lt;/strong&gt; spans sufficient iterations to process every example in the dataset, i.e., an &lt;strong&gt;epoch&lt;/strong&gt; represents $\frac{N}{batchSize}$ training iterations,&#xA;where $N$ is the number of samples.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;bg&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F99A7774E5B7E1B302D&#34; alt=&#34;Batch, batch size, epoch&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Batch, batch size, epoch&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;style&gt; .bg { filter: invert(1); } &lt;/style&gt;&#xA;&lt;h3 id=&#34;k-fold-cross-validation&#34;&gt;k-fold cross validation&lt;/h3&gt;&#xA;&lt;p&gt;From &#xA;&#xA;&lt;a href=&#34;https://www.analyticsvidhya.com/blog/2018/05/improve-model-performance-cross-validation-in-python-r/&#34;target=&#34;_blank&#34;&gt;https://www.analyticsvidhya.com/blog/2018/05/improve-model-performance-cross-validation-in-python-r/&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Randomly split your entire dataset into k &amp;ldquo;folds&amp;rdquo;.&lt;/li&gt;&#xA;&lt;li&gt;For each k-fold in your dataset, build your model on k-1 folds of the dataset. Then, test the model to check the effectiveness for the kth fold.&lt;/li&gt;&#xA;&lt;li&gt;Record the error you see on each of the predictions.&lt;/li&gt;&#xA;&lt;li&gt;Repeat this until each of the k-folds has served as the test set.&lt;/li&gt;&#xA;&lt;li&gt;The average of your k recorded errors is called the cross-validation error and will serve as your performance metric for the model.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;feature-extraction&#34;&gt;feature extraction&lt;/h3&gt;&#xA;&lt;p&gt;Merge several correlated features into one. Also, see dimensionality reduction.&lt;/p&gt;&#xA;&lt;h3 id=&#34;sampling-noisebias&#34;&gt;sampling noise/bias&lt;/h3&gt;&#xA;&lt;p&gt;Sampling noise: Non-representative sample data as a result of chance (typically when the sample is too small).&#xA;Sampling bias: Non-representative sample data as a result of a flaw in the sampling method.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Hyperparameter tuning</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/hyperparameter-tuning/</link>
      <pubDate>Mon, 25 May 2020 12:13:51 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/hyperparameter-tuning/</guid>
      <description>&lt;p&gt;From &#xA;&#xA;&lt;a href=&#34;https://colab.research.google.com/github/google/eng-edu/blob/master/ml/cc/exercises/linear_regression_with_synthetic_data.ipynb&#34;target=&#34;_blank&#34;&gt;https://colab.research.google.com/github/google/eng-edu/blob/master/ml/cc/exercises/linear_regression_with_synthetic_data.ipynb&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Most machine learning problems require a lot of hyperparameter tuning. Unfortunately, we can&amp;rsquo;t provide concrete tuning rules for every model.&#xA;Lowering the learning rate can help one model converge efficiently but make another model converge much too slowly.&#xA;You must experiment to find the best set of hyperparameters for your dataset. That said, here are a few rules of thumb:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Training loss should steadily decrease, steeply at first, and then more slowly until the slope of the curve reaches or approaches zero.&lt;/li&gt;&#xA;&lt;li&gt;If the training loss does not converge, train for more epochs.&lt;/li&gt;&#xA;&lt;li&gt;If the training loss decreases too slowly, increase the learning rate. Note that setting the learning rate too high may also prevent the training loss from converging.&lt;/li&gt;&#xA;&lt;li&gt;If the training loss varies wildly (that is, the training loss jumps around), decrease the learning rate.&lt;/li&gt;&#xA;&lt;li&gt;Lowering the learning rate while increasing the number of epochs or the batch size is often a good combination.&lt;/li&gt;&#xA;&lt;li&gt;Setting the batch size to a &lt;em&gt;very&lt;/em&gt; small number can also cause instability. First, try large batch size values. Then, decrease the batch size until you see degradation.&lt;/li&gt;&#xA;&lt;li&gt;For real-world datasets consisting of a very large number of examples, the entire dataset might not fit into memory. In such cases, you&amp;rsquo;ll need to reduce the batch size to enable a batch to fit into memory.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Data structures for massive datasets</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/data-structures-for-massive-datasets/</link>
      <pubDate>Sat, 09 May 2020 17:24:19 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/data-structures-for-massive-datasets/</guid>
      <description>&lt;h2 id=&#34;count-min-sketch&#34;&gt;Count min sketch&lt;/h2&gt;&#xA;&lt;p&gt;Problem: given a stream of data with keys and values, how can we get the sum of all values for a given key?&lt;/p&gt;&#xA;&lt;p&gt;Approximate solution: Assume that we have $d$ counter hash maps, each with its own hash function. Every time we&#xA;see a new key/value, we add it to all the $d$ counter hash maps (&lt;code&gt;update&lt;/code&gt;). To get the sum of values (&lt;code&gt;estimate&lt;/code&gt;), we&#xA;take the hash of the key and return the minimum value of the counters in all $d$ hash maps.&#xA;Because the counter hash map size is finite, we will have collisions, and a hash map may report a higher sum than the&#xA;true value.&lt;/p&gt;&#xA;&lt;p&gt;&lt;i&gt;Images taken from: Algorithms and Data Structures for Massive Datasets&lt;/i&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col tw-gap-4 md:tw-flex-row&#34;&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&#xA;      &#xA;      &#xA;      &lt;figure class=&#34;is-90p&#34;&#xA;              &#xA;              &#xA;      &gt;&#xA;          &#xA;              &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/count_min_sketch_update.png&#34; alt=&#34;Update&#34; /&gt;&#xA;          &#xA;          &#xA;          &lt;figcaption&gt;&#xA;              &lt;p class=&#34;tw-text-base&#34;&gt;Update&lt;/p&gt;&#xA;              &#xA;          &lt;/figcaption&gt;&#xA;          &#xA;      &lt;/figure&gt;&#xA;      &#xA;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&#xA;      &#xA;      &#xA;      &lt;figure class=&#34;is-90p&#34;&#xA;              &#xA;              &#xA;      &gt;&#xA;          &#xA;              &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/count_min_sketch_estimate.png&#34; alt=&#34;Estimate&#34; /&gt;&#xA;          &#xA;          &#xA;          &lt;figcaption&gt;&#xA;              &lt;p class=&#34;tw-text-base&#34;&gt;Estimate&lt;/p&gt;&#xA;              &#xA;          &lt;/figcaption&gt;&#xA;          &#xA;      &lt;/figure&gt;&#xA;      &#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;&#34;&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&lt;/div&gt;&#xA;    &lt;iframe&#xA;        class=&#34;lazy-load&#34;&#xA;        title=&#34;repl demo&#34;&#xA;        frameborder=&#34;0&#34;&#xA;        width=&#34;100%&#34;&#xA;        height=&#34;700px&#34;&#xA;        data-src=&#34;https://repl.it/@mauriciopoppe/Count-Min-Sketch?lite=true&#34;&gt;&#xA;    &lt;/iframe&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://florian.github.io/count-min-sketch/&#34;target=&#34;_blank&#34;&gt;https://florian.github.io/count-min-sketch/&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;applications&#34;&gt;Applications&lt;/h3&gt;&#xA;&lt;p&gt;&lt;strong&gt;Top k elements&lt;/strong&gt;: Every time we &lt;code&gt;update&lt;/code&gt; the count-min sketch, we also call &lt;code&gt;estimate&lt;/code&gt; and insert the record&#xA;into a min-heap. When the heap&amp;rsquo;s capacity is greater than $k$, we remove the top item from the heap.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Similarity of words&lt;/strong&gt;: Assume that we have a stream of pairs &lt;code&gt;(word, context)&lt;/code&gt;. The problem is to find if two words,&#xA;A and B, are similar in meaning based on the context in which they appear. The similarity of two words is computed with:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;PMI(A, B) = log \frac{P(A, B)}{P(A) P(B)}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To solve the problem, we can create a matrix of size &lt;code&gt;O(number of words * number of contexts)&lt;/code&gt;.&#xA;The intuition behind this formula is that it measures how likely A and B are to occur close to each other (numerator)&#xA;in comparison to how often they would co-occur if they were independent (denominator).&lt;/p&gt;&#xA;&lt;p&gt;To answer queries, we can use a matrix $M$ where the entry $M_{A,B}$ contains the number of times&#xA;the word A appears in the context B. The problem is that the number of word-context pairs quickly gets out of hand.&lt;/p&gt;&#xA;&lt;p&gt;The solution is to transform the matrix such that the word-context pair frequencies are stored in the count-min sketch;&#xA;the occurrences of words and contexts are kept in other hash maps.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Range queries&lt;/strong&gt;: Use a segment tree where each node is a CMS.&lt;/p&gt;&#xA;&lt;p&gt;&lt;i&gt;Images taken from: Algorithms and Data Structures for Massive Datasets&lt;/i&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col tw-gap-4 md:tw-flex-row&#34;&gt;&#xA;    &lt;div class=&#34;md:tw-w-1/2&#34;&gt;&#xA;      &#xA;      &#xA;      &lt;figure class=&#34;is-90p&#34;&#xA;              &#xA;              &#xA;      &gt;&#xA;          &#xA;              &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/count_min_sketch_st.png&#34; alt=&#34;Update&#34; /&gt;&#xA;          &#xA;          &#xA;          &lt;figcaption&gt;&#xA;              &lt;p class=&#34;tw-text-base&#34;&gt;Update&lt;/p&gt;&#xA;              &#xA;          &lt;/figcaption&gt;&#xA;          &#xA;      &lt;/figure&gt;&#xA;      &#xA;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;md:tw-w-1/2&#34;&gt;&#xA;      &#xA;      &#xA;      &lt;figure class=&#34;is-90p&#34;&#xA;              &#xA;              &#xA;      &gt;&#xA;          &#xA;              &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/count_min_sketch_st_read.png&#34; alt=&#34;Read&#34; /&gt;&#xA;          &#xA;          &#xA;          &lt;figcaption&gt;&#xA;              &lt;p class=&#34;tw-text-base&#34;&gt;Read&lt;/p&gt;&#xA;              &#xA;          &lt;/figcaption&gt;&#xA;          &#xA;      &lt;/figure&gt;&#xA;      &#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;e-approximate heavy hitters&lt;/strong&gt;: In a stream where the total number of frequencies is $n$ (for example, if all frequencies are 1,&#xA;then $N$ corresponds to the number of elements encountered so far in the stream), output all the items that occur&#xA;at least $n/k$ times. When $k=2$, this problem is known as the majority element.&lt;/p&gt;&#xA;&lt;p&gt;If $n$ is known in advance, we can process the array elements using a count-min sketch in a single pass&#xA;and remember an element once its estimated frequency (according to the count-min sketch) is at least $n/k$.&lt;/p&gt;&#xA;&lt;p&gt;If $n$ is not known in advance, we use a min-heap. In a single pass, we maintain the number of elements seen so far, $m$.&#xA;When processing the next element, $x$, we call &lt;code&gt;update(x, 1)&lt;/code&gt; and then &lt;code&gt;estimate(x)&lt;/code&gt;.&#xA;If the estimate is $\geq m/k$, we store $x$ in the heap. Also, whenever $m$ grows to the point that some object $x$ stored&#xA;in the heap has a key less than $m/k$ (checkable in O(1) time via Find-Min),&#xA;we delete $x$ from the heap (via Extract-Min). After finishing the pass, we output all the objects in the heap.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Trending hashtags&lt;/strong&gt;: Quantify how different the currently observed activity is against an estimate of the&#xA;expected activity. For each hashtag, store how many times it&amp;rsquo;s shared in an X-minute window over the&#xA;last Y days, $C(h, t)$ (normalized to get $P(h, t)$, i.e., $P(h, t) = \tfrac{C(h, t)}{\sum_{i=0}^{n}C(h, t_i)}$). At a new time $t$, we can compute $C(h, t)$ and $P&amp;rsquo;(h, t)$, then use&#xA;KL divergence to measure the difference between the probabilities.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;S(h, t) = P(h, t) ln \left ( \frac{P(h, t)}{P&#39;(h, t)} \right )&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The top $k$ trending hashtags can be computed with a heap.&lt;/p&gt;&#xA;&lt;p&gt;Based on &#xA;&#xA;&lt;a href=&#34;https://instagram-engineering.com/trending-on-instagram-b749450e6d93&#34;target=&#34;_blank&#34;&gt;https://instagram-engineering.com/trending-on-instagram-b749450e6d93&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;bloom-filter&#34;&gt;Bloom filter&lt;/h2&gt;&#xA;&lt;p&gt;Problem: Test if an element doesn&amp;rsquo;t exist in a set.&lt;/p&gt;&#xA;&lt;p&gt;Approximate solution: Similar to a count-min sketch, if the returned value is zero, then we&amp;rsquo;re sure the element&#xA;is not in the set. Otherwise, it might be in the set, and we need to test for existence with another (more expensive) data structure.&lt;/p&gt;&#xA;&lt;p&gt;For more info read:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://florian.github.io/bloom-filters/&#34;target=&#34;_blank&#34;&gt;https://florian.github.io/bloom-filters/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://eli.thegreenplace.net/2025/bloom-filters/&#34;target=&#34;_blank&#34;&gt;https://eli.thegreenplace.net/2025/bloom-filters/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;applications-1&#34;&gt;Applications&lt;/h3&gt;&#xA;&lt;p&gt;&lt;strong&gt;SSTable reads&lt;/strong&gt;: In the read path, Cassandra merges data on disk (in SSTables) with data in RAM (in memtables).&#xA;To avoid checking every SSTable data file for the requested partition, we can query the SSTable&amp;rsquo;s&#xA;bloom filter.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reservoir-sampling&#34;&gt;Reservoir sampling&lt;/h2&gt;&#xA;&lt;p&gt;Problem: Given a stream of elements, we want to sample k random ones without replacement and with uniform probability.&lt;/p&gt;&#xA;&lt;p&gt;Solution: Store the first $k$ elements. For the $i$-th element (where $i &amp;gt; k$), add it to the reservoir with a probability of $k/i$. This is&#xA;done by replacing a randomly selected element in the reservoir.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://florian.github.io/reservoir-sampling/&#34;target=&#34;_blank&#34;&gt;https://florian.github.io/reservoir-sampling/&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Expectation maximization</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/expectation-maximization/</link>
      <pubDate>Mon, 16 Mar 2020 21:21:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/artificial-intelligence/machine-learning/expectation-maximization/</guid>
      <description>&lt;h2 id=&#34;k-means-clustering&#34;&gt;K-means clustering&lt;/h2&gt;&#xA;&lt;p&gt;Suppose we have a dataset {\textbf{x}_1, \ldots, \textbf{x}_n} consisting of $N$ observations of a random $D$-dimensional space. The goal&#xA;is to partition the dataset into some number $K$ of clusters. Formally, let { \pmb{\mu} _1, \ldots, \pmb{\mu}_k } be a set of $D$-dimensional vectors in which&#xA;$\pmb{\mu}_k$ is associated with the $k^{th}$ cluster ($\pmb{\mu}_k$ can be thought of as the centers of the clusters). The goal is to find&#xA;an assignment of data points so that the distance of each data point to its closest vector $\pmb{\mu}_k$ is a minimum.&lt;/p&gt;&#xA;&lt;p&gt;Let $r_nk \in {0, 1}$, where $k = 1, \ldots, K$, describe the assignment of each data point to a cluster (1 if it&amp;rsquo;s assigned to a cluster and&#xA;0 if not). We define a function called the &lt;em&gt;distortion measure&lt;/em&gt;, given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{distortion_measure}&#xA;J = \sum_{n=1}^{N} \sum_{k=1}^{K} r_{nk} \magnitude{\mathbf{x}_n - \pmb{\mu}_k}^2&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This represents the sum of the squares of the distances of each data point to its assigned vector $\pmb{\mu}_k$. Our goal is to find values&#xA;for $r_nk$ and the $\pmb{\mu}_k$ so as to minimize $J$. The algorithm is as follows:&lt;/p&gt;&#xA;&lt;p&gt;Algorithm:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Pick initial values for the $\pmb{\mu}$.&lt;/li&gt;&#xA;&lt;li&gt;Minimize J with respect to $r_nk$, keeping the $\pmb{\mu}_k$ fixed (Expectation).&lt;/li&gt;&#xA;&lt;li&gt;Minimize J with respect to the $\pmb{\mu}_k$, keeping $r_nk$ fixed (Maximization).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;multivariate-gaussian-distribution&#34;&gt;Multivariate gaussian distribution&lt;/h2&gt;&#xA;&lt;p&gt;For a random variable $X$ with a finite number of outcomes $x_1, x_2, \ldots, x_n$ occurring with probabilities $p_1, p_2, \ldots, p_n$, the expectation of $X$ is defined as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;E[X] = \sum_{i=1}^{N} x_i p_i&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The covariance between two variables, $X$ and $Y$, is defined as the expected value (or mean) of the product of their deviations from their individual expected values:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;cov(X,Y) = E[(X - E[X])(Y - E[Y])]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When working with multiple variables $X_1, X_2, \ldots, X_n$, the covariance matrix, denoted as $\Sigma$, is the $n \times n$ matrix whose $(i, j)$-th entry is $cov(X_i, X_j)$.&lt;/p&gt;&#xA;&lt;p&gt;The density function of a univariate gaussian distribution is given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;p(x; \mu, \sigma) = \frac{1}{\sqrt{2\pi \sigma^2}}\exp\left(-\frac{1}{2\sigma^2}(x - \mu)^2\right)&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$(x - \mu)^2$ is always positive.&lt;/li&gt;&#xA;&lt;li&gt;The value $k(x, \mu) = -\frac{1}{2 \sigma^2}(x - \mu)^2$ is always negative. It&amp;rsquo;s a parabola pointing downward.&lt;/li&gt;&#xA;&lt;li&gt;The $\exp(k(x, \mu))$ part makes sure that the quantity is always $\geq 0$.&lt;/li&gt;&#xA;&lt;li&gt;The normalization factor $\frac{1}{\sqrt{2\pi \sigma^2}}$ multiplies $\exp(k(x, \mu))$ so that this sum equals 1.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\underbrace{\frac{1}{\sqrt{2\pi \sigma^2}}}_\text{normalization factor} \int_{-\infty}^{\infty} \exp \left(-\frac{1}{2\sigma^2}(x - \mu)^2\right) = 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;A vector random variable $X = [X_1, \ldots, X_n]^T$ is said to have a multivariate Gaussian distribution with mean $\mu \in \mathbf{R}^n$ and covariance matrix $\Sigma$&#xA;if its probability density function is given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;p(x; \mu, \Sigma) = \frac{1}{(2 \pi) ^ {n/2} \norm{\Sigma}^{1/2} } \exp \left ( -\frac{1}{2} (x - \mu)^T \Sigma ^{-1} (x - \mu) \right )&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Like in the univariate case, the argument of the exponential function is a downward-opening bowl. The coefficient in front&#xA;is a normalization factor used to ensure that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\underbrace{\frac{1}{(2 \pi) ^ {n/2} \norm{\Sigma}^{1/2} }}_\text{normalization factor} \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} \ldots \int_{-\infty}^{\infty}  \exp \left ( -\frac{1}{2} (x - \mu)^T \Sigma ^{-1} (x - \mu) \right ) dx_1 dx_2 \cdots dx_n = 1&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;gaussian-mixture-models-and-em&#34;&gt;Gaussian mixture models and EM&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=qMTuMa86NzU&#34;target=&#34;_blank&#34;&gt;https://www.youtube.com/watch?v=qMTuMa86NzU&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Bayesian Networks</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/probability/bayesian-networks/</link>
      <pubDate>Thu, 05 Mar 2020 18:11:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/probability/bayesian-networks/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;&#xA;&lt;p&gt;A Bayesian network is a directed graph in which each node is annotated with quantitative probability information. The full specification is as follows:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Each node corresponds to a random variable, which may be discrete or continuous.&lt;/li&gt;&#xA;&lt;li&gt;A set of directed links or arrows connects pairs of nodes. If there is an arrow from node $X$ to node $Y$, $X$ is said to be a parent of $Y$. The graph has no directed cycles (and hence is a directed acyclic graph, or DAG).&lt;/li&gt;&#xA;&lt;li&gt;Each node $X_i$ has a conditional probability distribution $P(X_i|Parents(X_i))$ that quantifies the effect of the parents on the node.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;tw-mx-auto md:tw-w-1/2&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/bayesian_network_full.jpg&#34; alt=&#34;Example Bayesian Network&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Example Bayesian Network&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;Semantics of a Bayesian network:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The network is a representation of a joint probability distribution&lt;/li&gt;&#xA;&lt;li&gt;Encoding of a collection of conditional independence statements&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;full-joint-distribution&#34;&gt;Full joint distribution&lt;/h2&gt;&#xA;&lt;p&gt;Given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;P(x_1, \ldots, x_n) = \prod_{i=1}^{N} P(x_i|Parents(X_i))&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which can be rewritten as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;P(x_1, \ldots, x_n) &amp;= P(x_n | x_{n-1}, \ldots x_1) P(x_{n-1}, \ldots, x_1) \\&#xA;&amp;= P(x_n | x_{n-1}, \ldots x_1) P(x_{n-1} | x_{n-2}, \ldots, x_1) \cdots P(x_2 | x_1) P(x_1) \\&#xA;&amp;= \prod_{i=1}^{N} P(x_i | x_{i-1}, \ldots x_1) \;\; \text{(identity known as chain rule)}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The above is equivalent to&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;P(X_i | X_{i-1}, \ldots X_1) = P(X_i|Parents(X_i))&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Provided that $Parents(X_i) \subseteq { X_{i-1}, \ldots, X_1 }$&lt;/p&gt;&#xA;&lt;h2 id=&#34;conditional-independence-relations-in-bayesian-networks&#34;&gt;Conditional independence relations in bayesian networks&lt;/h2&gt;&#xA;&lt;p&gt;Steps to determine if two variables are conditionally independent&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Draw the ancestral graph.&lt;/strong&gt; Construct the &amp;ldquo;ancestral graph&amp;rdquo; of all variables mentioned in the probability expression. This is a reduced version of the original net, consisting only of the variables mentioned and all of their ancestors (parents, parents&amp;rsquo; parents, etc.)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;em&gt;Moralize&lt;/em&gt; the ancestral graph by &lt;em&gt;marrying&lt;/em&gt; the parents.&lt;/strong&gt; For each pair of variables with a common child, draw an undirected edge (line) between them. (If a variable has more than two parents, draw lines between every pair of parents.)&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;em&gt;Disorient&lt;/em&gt; the graph by replacing the directed edges (arrows) with undirected edges (lines)&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Delete the givens and their edges&lt;/strong&gt;. If the independence question had any given variables, erase those variables from the graph and erase all of their connections, too.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Given a query between two variables A, B&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;If the variables are &lt;strong&gt;disconnected&lt;/strong&gt;, then they&amp;rsquo;re independent&lt;/li&gt;&#xA;&lt;li&gt;If the variables are &lt;strong&gt;connected&lt;/strong&gt;, then they&amp;rsquo;re dependent&lt;/li&gt;&#xA;&lt;li&gt;If the variables are &lt;strong&gt;missing&lt;/strong&gt; because they were a given, they&amp;rsquo;re independent&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;In the following example we skip step 1 and moralize the entire Bayesian network&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-gap-4 tw-flex-col md:tw-flex-row&#34;&gt;&#xA;  &lt;div class=&#34;&#34;&gt;&#xA;    &#xA;    &#xA;    &lt;figure class=&#34;&#34;&#xA;            &#xA;            &#xA;    &gt;&#xA;        &#xA;            &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/bayesian_network_directed.jpg&#34; alt=&#34;Example Bayesian Network&#34; /&gt;&#xA;        &#xA;        &#xA;        &lt;figcaption&gt;&#xA;            &lt;p class=&#34;tw-text-base&#34;&gt;Example Bayesian Network&lt;/p&gt;&#xA;            &#xA;        &lt;/figcaption&gt;&#xA;        &#xA;    &lt;/figure&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;&#34;&gt;&#xA;    &#xA;    &#xA;    &lt;figure class=&#34;&#34;&#xA;            &#xA;            &#xA;    &gt;&#xA;        &#xA;            &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/bayesian_network_moralized.jpg&#34; alt=&#34;Example Bayesian Network Moralized&#34; /&gt;&#xA;        &#xA;        &#xA;        &lt;figcaption&gt;&#xA;            &lt;p class=&#34;tw-text-base&#34;&gt;Example Bayesian Network Moralized&lt;/p&gt;&#xA;            &#xA;        &lt;/figcaption&gt;&#xA;        &#xA;    &lt;/figure&gt;&#xA;    &#xA;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Some conditional independence queries ($\ci$ meaning conditionally independent of), delete the givens and their edges to check the connection between the query variables:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is $A \ci B \given C$? &lt;strong&gt;No&lt;/strong&gt;, there is a path A-B&lt;/li&gt;&#xA;&lt;li&gt;Is $A \ci E \given C$? &lt;strong&gt;No&lt;/strong&gt;, there is a path A-B-D-E&lt;/li&gt;&#xA;&lt;li&gt;Is $A \ci E \given C,D$? &lt;strong&gt;Yes&lt;/strong&gt;, there isn&amp;rsquo;t a path between A and E&lt;/li&gt;&#xA;&lt;li&gt;Is $A \ci D \given C$? &lt;strong&gt;No&lt;/strong&gt;, there is a path A-B-D&lt;/li&gt;&#xA;&lt;li&gt;Is $B \ci E \given C$? &lt;strong&gt;No&lt;/strong&gt;, there is a path B-D-E&lt;/li&gt;&#xA;&lt;li&gt;Is $A \ci F \given C$? &lt;strong&gt;No&lt;/strong&gt;, there is a path A-B-D-E-F&lt;/li&gt;&#xA;&lt;li&gt;Is $A \ci F \given C,D$? &lt;strong&gt;Yes&lt;/strong&gt;, there isn&amp;rsquo;t a path between A and F&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;exact-inference&#34;&gt;Exact inference&lt;/h2&gt;&#xA;&lt;p&gt;Compute the &lt;strong&gt;posterior probability distribution&lt;/strong&gt; for a set of &lt;strong&gt;query values&lt;/strong&gt; given some observed &lt;strong&gt;event (set of evidence variables)&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;by-enumeration&#34;&gt;By enumeration&lt;/h3&gt;&#xA;&lt;p&gt;Any conditional probability can be computed by summing terms from the full joint distribution&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\textbf{P}(X \given \textbf{e}) = \alpha \textbf{P} (X, \textbf{e}) = \alpha \sum_{y} \textbf{P} (X, \textbf{e}, \textbf{y})&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Working with the example below we can answer some queries:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;tw-m-1/2 tw-mx-auto&#34;&#xA;        &#xA;        id=&#34;bayesian-full&#34;&#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/bayesian_network_full.jpg&#34; alt=&#34;Example Bayesian Network&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Example Bayesian Network&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;(function() {&#xA;  if (window.matchMedia(&#34;(pointer:coarse)&#34;).matches) {&#xA;    return&#xA;  }&#xA;  var el = document.querySelector(&#39;#bayesian-full&#39;)&#xA;  var clone = el.cloneNode(true)&#xA;  clone.id = &#39;bayesian-full-cloned&#39;&#xA;  clone.classList.remove(&#39;is-responsive&#39;)&#xA;  clone.style.position = &#39;fixed&#39;&#xA;  clone.style.width = &#39;20%&#39;&#xA;  clone.style.margin = &#39;20px&#39;&#xA;  clone.style.bottom = 0&#xA;  clone.style.left = 0&#xA;  clone.style.opacity = 0&#xA;  clone.style.transition = &#39;opacity 0.2s&#39;&#xA;  clone.style.display = &#39;none&#39;&#xA;  document.body.appendChild(clone)&#xA;&#xA;  new IntersectionObserver(entries =&gt; {&#xA;    if (entries[0]) {&#xA;      var elBounds = entries[0].boundingClientRect&#xA;      var isVisible = entries[0].isIntersecting&#xA;      if (isVisible || elBounds.bottom &lt;= 0) {&#xA;        clone.style.display = &#39;block&#39;&#xA;        setTimeout(() =&gt; clone.style.opacity = 1, 200)&#xA;      } else {&#xA;        clone.style.opacity = 0&#xA;        setTimeout(() =&gt; clone.style.display = &#39;none&#39;, 200)&#xA;      }&#xA;    }&#xA;  }).observe(el)&#xA;&#xA;})();&#xA; &lt;/script&gt;&#xA;&#xA;&lt;div&gt;$$&#xA;\newcommand\g[1]{\color{gray}{#1}}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;P(c|a) &amp;= \alpha \sum_{b} P(a) P(b) P(c \given a,b) \\&#xA;&amp;= \alpha P(a) \sum_{b} P(b) P(c \given a,b) \\&#xA;&amp;= \alpha P(a) \sum_{b} \bordermatrix{\g{b} &amp; \g{\neg b}}{}{\begin{bmatrix} 0.4 &amp; 0.6 \end{bmatrix}} \bordermatrix{\g{b} &amp; \g{\neg b}}{\g{c} \\ \g{\neg c}}{\begin{bmatrix} 0.55 &amp; 0.5 \\ 0.45 &amp; 0.5 \end{bmatrix}} \\&#xA;&amp;= \alpha P(a) \sum_{b} \bordermatrix{\g{b} &amp; \g{\neg b}}{\g{c} \\ \g{\neg c}}{\begin{bmatrix} 0.22 &amp; 0.3 \\ 0.18 &amp; 0.3 \end{bmatrix}} \\&#xA;&amp;= \alpha \; 0.2 \; \bordermatrix{}{\g{c} \\ \g{\neg c}}{\begin{bmatrix} 0.52 \\ 0.48 \end{bmatrix}} \\&#xA;&amp;= \bordermatrix{}{\g{c} \\ \g{\neg c}}{\begin{bmatrix} 0.104 \\ 0.096 \end{bmatrix}} \\&#xA;&amp;= \alpha [.104, .096] \\&#xA;&amp;= [\textbf{0.52}, 0.48]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;hr /&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;P(e|\neg c, b) &amp;= \alpha \sum_{a,d,f} P(a) P(b) P(\neg c \given a,b) P(d \given b) P(e \given \neg c,d) P(f \given e) \\&#xA;&amp;= \alpha P(b) \sum_{a} P(a) P(\neg c \given a,b) \sum_{d} P(d \given b) P(e \given \neg c,d) \sum_{f} P(f \given e) \\&#xA;&amp;= \alpha P(b) \sum_{a} P(a) P(\neg c \given a,b) \sum_{d} P(d \given b) P(e \given \neg c,d) \sum_{f}&#xA;\bordermatrix{\g{f} &amp; \g{\neg f}}{\g{e} \\ \g{\neg e}}{\begin{bmatrix}&#xA;0.7 &amp; 0.3 \\&#xA;0.2 &amp; 0.8&#xA;\end{bmatrix}} \\&#xA;&amp;= \alpha P(b) \sum_{a} P(a) P(\neg c \given a,b) \sum_{d} P(d \given b) P(e \given \neg c,d) \bordermatrix{}{\g{e} \\ \g{\neg e}}{\begin{bmatrix} 1 \\ 1 \end{bmatrix}} \\&#xA;&amp;= \alpha P(b) \sum_{a} P(a) P(\neg c \given a,b) \sum_{d}&#xA;\bordermatrix{\g{d} &amp; \g{\neg d}}{}{\begin{bmatrix} 0.6 &amp; 0.4 \end{bmatrix}}&#xA;\bordermatrix{\g{d} &amp; \g{\neg d}}{\g{e} \\ \g{\neg e}}{\begin{bmatrix}&#xA;0.45 &amp; 0.2 \\&#xA;0.55 &amp; 0.8&#xA;\end{bmatrix}} \bordermatrix{}{\g{e} \\ \g{\neg e}}{\begin{bmatrix} 1 \\ 1 \end{bmatrix}} \\&#xA;&amp;= \alpha P(b) \sum_{a} P(a) P(\neg c \given a,b) \sum_{d}&#xA;\bordermatrix{\g{d} &amp; \g{\neg d}}{\g{e} \\ \g{\neg e}}{\begin{bmatrix}&#xA;0.27 &amp; 0.08 \\&#xA;0.33 &amp; 0.32&#xA;\end{bmatrix}} \\&#xA;&amp;= \alpha P(b) \sum_{a} P(a) P(\neg c \given a,b)&#xA;\bordermatrix{}{\g{e} \\ \g{\neg e}}{\begin{bmatrix}&#xA;0.35 \\&#xA;0.65&#xA;\end{bmatrix}} \\&#xA;&amp;= \alpha P(b) \sum_{a}&#xA;\bordermatrix{}{\g{a} \\ \g{\neg a}}{\begin{bmatrix} 0.2 \\ 0.8 \end{bmatrix}}&#xA;\bordermatrix{\g{\neg c, b}}{\g{a} \\ \g{\neg a}}{\begin{bmatrix}&#xA;0.45 \\&#xA;0.55&#xA;\end{bmatrix}} \bordermatrix{}{\g{e} \\ \g{\neg e}}{\begin{bmatrix} 0.35 \\ 0.65 \end{bmatrix}} \\&#xA;&amp;= \alpha P(b) \sum_{a}&#xA;\bordermatrix{}{\g{a} \\ \g{\neg a}}{\begin{bmatrix} 0.09 \\ 0.44 \end{bmatrix}}&#xA;\bordermatrix{}{\g{e} \\ \g{\neg e}}{\begin{bmatrix} 0.35 \\ 0.65 \end{bmatrix}} \quad \text{the element-wise product is with unrelated bases, so we do with $a^T$} \\&#xA;&amp;= \alpha P(b) \sum_{a}&#xA;\bordermatrix{\g{a} &amp; \g{\neg a}}{\g{e} \\ \g{\neg e}}{\begin{bmatrix} 0.0315 &amp; 0.154 \\ 0.0585 &amp; 0.2275 \end{bmatrix}} \\&#xA;&amp;= \bordermatrix{}{\g{e} \\ \g{\neg e}}{\begin{bmatrix} 0.1855 \\ 0.286 \end{bmatrix}} \quad \text{$P(b)$ is not a factor, it&#39;s evidence} \\&#xA;&amp;= \alpha [0.1855, 0.286] \\&#xA;&amp;= [\textbf{0.393425239}, 0.606574761]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;reading&#34;&gt;Reading&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://anesi.com/bayes.htm&#34;target=&#34;_blank&#34;&gt;https://anesi.com/bayes.htm&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;http://www.cs.cmu.edu/~guestrin/Class/10701/recitations/r9/var_elim_recitation_unanimated.pdf&#34;target=&#34;_blank&#34;&gt;http://www.cs.cmu.edu/~guestrin/Class/10701/recitations/r9/var_elim_recitation_unanimated.pdf&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://betterexplained.com/articles/understanding-bayes-theorem-with-ratios/&#34;target=&#34;_blank&#34;&gt;https://betterexplained.com/articles/understanding-bayes-theorem-with-ratios/&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.seas.upenn.edu/~cis391/Lectures/probability-bayes-2015.pdf&#34;target=&#34;_blank&#34;&gt;https://www.seas.upenn.edu/~cis391/Lectures/probability-bayes-2015.pdf&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Kafka</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/system-design/kafka/</link>
      <pubDate>Sat, 29 Feb 2020 15:36:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/system-design/kafka/</guid>
      <description>&lt;h2 id=&#34;kafka&#34;&gt;Kafka&lt;/h2&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.slideshare.net/mumrah/kafka-talk-tri-hug&#34;target=&#34;_blank&#34;&gt;https://www.slideshare.net/mumrah/kafka-talk-tri-hug&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;key-choices&#34;&gt;Key Choices&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;pub/sub messaging pattern&lt;/li&gt;&#xA;&lt;li&gt;Messages are persistent (stored on disk).&lt;/li&gt;&#xA;&lt;li&gt;Consumers keep their own state (stored in Zookeeper).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;technology-summary&#34;&gt;Technology Summary&lt;/h3&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Concept&lt;/th&gt;&#xA;          &lt;th&gt;Notes&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Brokers&lt;/td&gt;&#xA;          &lt;td&gt;Receive messages from producers (sequential write, push) and deliver messages to consumers (sequential read, pull).&lt;br /&gt;Messages are flushed to append-only log files.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Topics&lt;/td&gt;&#xA;          &lt;td&gt;A logical collection of partitions mapped across many brokers.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Partition&lt;/td&gt;&#xA;          &lt;td&gt;Physical append-only log files. A broker contains some of the partitions for a topic.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Replication&lt;/td&gt;&#xA;          &lt;td&gt;Partitions are replicated. One broker is the leader, and all writes/reads must go through it (replication is for fault tolerance only). Replication can be tuned to write to N replicas.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Producer&lt;/td&gt;&#xA;          &lt;td&gt;Responsible for load balancing messages among brokers. They can discover all brokers from a single one.&lt;br /&gt;High-level API: &lt;code&gt;Producer#send(String topic, K key, V value)&lt;/code&gt;.&lt;br /&gt;Determines the partition based on the key (default hash mod), e.g., &lt;code&gt;send(&amp;quot;A&amp;quot;, &amp;quot;foo&amp;quot;, message)&lt;/code&gt; in the example below: &lt;code&gt;&amp;quot;foo&amp;quot; mod 2&lt;/code&gt;.&lt;br /&gt;No total ordering across partitions.&lt;br /&gt;Guaranteed ordering inside the partition. This is useful if the key is a PK; if so, all the messages related to that key will be ordered.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Consumer&lt;/td&gt;&#xA;          &lt;td&gt;Requests a range of messages from a broker. Responsible for its own state, i.e., its own iterator.&lt;br /&gt;High-level API: &lt;code&gt;Map&amp;lt;String, List&amp;lt;KafkaStream&amp;gt;&amp;gt; Consumer.connector(Collections.singletonMap(&amp;quot;topic&amp;quot;, nPartitions))&lt;/code&gt;.&lt;br /&gt;Blocking/non-blocking behavior.&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Consumer Group&lt;/td&gt;&#xA;          &lt;td&gt;Multiple consumers can be part of a consumer group coordinated with Zookeeper. &lt;strong&gt;In a group, each partition will be consumed by exactly one consumer.&lt;/strong&gt;&lt;br /&gt;Consequence: broadcast/pub-sub (if all the consumer instances have different consumer groups) and load balance/queue (if all the consumer instances have the same consumer group).&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;div class=&#34;tw-flex tw-gap-4 tw-flex-col md:tw-flex-row&#34;&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&#xA;        &#xA;        &#xA;        &lt;figure class=&#34;&#34;&#xA;                &#xA;                &#xA;        &gt;&#xA;            &#xA;                &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/kafka-broker-topic-partition.png&#34; alt=&#34;Broker - Partition - Topic&#34; /&gt;&#xA;            &#xA;            &#xA;            &lt;figcaption&gt;&#xA;                &lt;p class=&#34;tw-text-base&#34;&gt;Broker - Partition - Topic&lt;/p&gt;&#xA;                &#xA;            &lt;/figcaption&gt;&#xA;            &#xA;        &lt;/figure&gt;&#xA;        &#xA;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&#xA;        &#xA;        &#xA;        &lt;figure class=&#34;&#34;&#xA;                &#xA;                &#xA;        &gt;&#xA;            &#xA;                &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/kafka-consumer-groups.png&#34; alt=&#34;Consumer Groups&#34; /&gt;&#xA;            &#xA;            &#xA;            &lt;figcaption&gt;&#xA;                &lt;p class=&#34;tw-text-base&#34;&gt;Consumer Groups&lt;/p&gt;&#xA;                &#xA;            &lt;/figcaption&gt;&#xA;            &#xA;        &lt;/figure&gt;&#xA;        &#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;useful-numbers&#34;&gt;Useful numbers&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;50MB/s (producer throughput), 100 MB/s (consumer throughput)&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines&#34;target=&#34;_blank&#34;&gt;https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;applications&#34;&gt;Applications&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Notification: A updates a record and sends a &amp;ldquo;record updated&amp;rdquo; message. B consumes the message and asks A for the updated record to sync its copy.&lt;/li&gt;&#xA;&lt;li&gt;Stream Processing: Data is produced and written into Kafka. Consumer groups process these messages and write them back to Kafka.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Memtable &amp; SSTable (Sorted String Table)</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/memtable-sstable/</link>
      <pubDate>Sat, 29 Feb 2020 15:04:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/memtable-sstable/</guid>
      <description>&lt;h2 id=&#34;memtable&#34;&gt;Memtable&lt;/h2&gt;&#xA;&lt;p&gt;A data structure that holds data in memory before it&amp;rsquo;s flushed to disk.&lt;/p&gt;&#xA;&lt;p&gt;For a write operation, we write to memory, which is fast compared to persistent storage.&#xA;Eventually, a memtable will surpass a predefined memory threshold and will need to be flushed to disk.&#xA;While we can define our own write format, we can write the memtable in a sorted way to disk as an SSTable&#xA;(see SSTable below). Once data is written to disk, it becomes immutable (the SSTable cannot be modified).&#xA;Therefore, new writes go to a new memtable, and operations like updates or&#xA;&#xA;&#xA;&lt;a href=&#34;https://en.wikipedia.org/wiki/Tombstone_%28data_store%29&#34;target=&#34;_blank&#34;&gt;deletes&lt;/a&gt;&#xA;&#xA; on existing data in the previous memtable&#xA;are instead stored in the new memtable.&lt;/p&gt;&#xA;&lt;p&gt;For a read operation, we first check the current memtable. If the read can&amp;rsquo;t be fulfilled by the current&#xA;memtable (perhaps the data exists but is no longer in memory because it was flushed to disk), we then check recently&#xA;created SSTables in decreasing order of creation until we find the desired record (or we might not find it at all).&#xA;Because the SSTable is sorted, it enables faster reads, as we can use binary search to find it in the file.&lt;/p&gt;&#xA;&lt;p&gt;A memtable can be implemented with a Red-Black Tree, a SkipList, a HashSkipList, or a HashLinkList.&#xA;For tradeoffs on these implementations, please check the &#xA;&#xA;&lt;a href=&#34;https://github.com/facebook/rocksdb/wiki/MemTable&#34;target=&#34;_blank&#34;&gt;RocksDB wiki&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;applications&#34;&gt;Applications&lt;/h3&gt;&#xA;&lt;p&gt;Example: Design a time-series database with the following requirements:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For the current time, write a given value for a given list of labels. A label is a pair &lt;code&gt;labelKey=labelValue&lt;/code&gt;, e.g., &lt;code&gt;[method=http, type=POST, statusCode=200] 1&lt;/code&gt; (the value is &lt;code&gt;1&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;The labels can be arbitrary strings.&lt;/li&gt;&#xA;&lt;li&gt;Reads will be for an arbitrary combination of labels and will cover a range of time (common).&lt;/li&gt;&#xA;&lt;li&gt;Reads will be for an arbitrary combination of labels and will cover a point in time (rare).&lt;/li&gt;&#xA;&lt;li&gt;A write-heavy system.&lt;/li&gt;&#xA;&lt;li&gt;99% of the data is never queried after 24 hours.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;A memtable fits this problem because it&amp;rsquo;s a write-heavy system (therefore, we need fast writes).&#xA;The common scenario of reads for a range of time would also fit a linked list (either a SkipList or a HashLinkList).&#xA;After a memtable is written to disk as an SSTable, it enables slower reads for old data, which is an acceptable&#xA;tradeoff because 99% of the data is never queried after 24 hours.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s define an entry as a data structure that holds a collection of labels, a single value, and a time.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Entry struct {&#xA;&#x9;// id is the time an entry was created (not threadsafe)&#xA;&#x9;id time.Time&#xA;&#x9;// labels are the labels that identify the entry.&#xA;&#x9;labels map[string]string&#xA;&#x9;// value is the entry value.&#xA;&#x9;value any&#xA;&#x9;// next is a pointer to the next Entry.&#xA;&#x9;next *Entry&#xA;}&#xA;&#xA;// example:&#xA;entry := &amp;amp;Entry{&#xA;&#x9;id:     time.Now(),&#xA;&#x9;labels: map[string]string{&#xA;&#x9;&#x9;&amp;quot;method&amp;quot;:     &amp;quot;http&amp;quot;,&#xA;&#x9;&#x9;&amp;quot;type&amp;quot;:       &amp;quot;POST&amp;quot;,&#xA;&#x9;&#x9;&amp;quot;statusCode&amp;quot;: &amp;quot;200&amp;quot;,&#xA;&#x9;},&#xA;&#x9;value:  1,&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Our memtable is a collection of entries stored in a linked list. The memtable has pointers to the head and tail&#xA;of the linked list. &lt;code&gt;index&lt;/code&gt; is explained later in this article.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;type Memtable struct {&#xA;&#x9;// head is the head of the linked list.&#xA;&#x9;head *Entry&#xA;&#x9;// tail is the head of the linked list.&#xA;&#x9;tail *Entry&#xA;&#x9;// index is a reverse index of a label to an entry.&#xA;&#x9;index map[string][]*Entry&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;On a write, a new entry is added to the tail of the memtable&amp;rsquo;s linked list.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func (m *Memtable) Write(labels map[string]string, value any) {&#xA;&#x9;e := &amp;amp;Entry{&#xA;&#x9;&#x9;id:     time.Now(),&#xA;&#x9;&#x9;labels: labels,&#xA;&#x9;&#x9;value:  value,&#xA;&#x9;}&#xA;&#xA;&#x9;// process entry&#xA;&#x9;for k, v := range labels {&#xA;&#x9;&#x9;key := m.encode(k, v)  // encode creates a unique key in the HashMap&#xA;&#x9;&#x9;m.index[key] = append(m.index[key], e)&#xA;&#x9;}&#xA;&#x9;m.tail.next = e&#xA;&#x9;m.tail = m.tail.next&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To find entries by label(s), we can iterate through the linked list from &lt;code&gt;head&lt;/code&gt; to &lt;code&gt;tail&lt;/code&gt;, collecting&#xA;entries that match our labels in &lt;code&gt;O(n)&lt;/code&gt;, where &lt;code&gt;n&lt;/code&gt; is the size of the linked list. To improve query performance,&#xA;we can use an index that maps a label to the locations of entries. This speeds up the find operation&#xA;to &lt;code&gt;O(k)&lt;/code&gt;, where &lt;code&gt;k&lt;/code&gt; is the maximum number of entries mapped to a label. The tradeoff is space&#xA;and the fact that we have to update the index on every write.&lt;/p&gt;&#xA;&lt;p&gt;With the above, we get values for single labels. For multiple labels, we combine the results&#xA;by performing an intersection.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func (m *Memtable) Read(labels map[string]string) []any {&#xA;&#x9;// read temporary results for every label&#xA;&#x9;entriesGroup := make([][]*Entry, 0)&#xA;&#x9;for k, v := range labels {&#xA;&#x9;&#x9;key := m.encode(k, v)&#xA;&#x9;&#x9;entriesGroup = append(entriesGroup, m.index[key])&#xA;&#x9;}&#xA;&#xA;&#x9;// intersect&#xA;&#x9;if len(entriesGroup) == 0 {&#xA;&#x9;&#x9;return make([]any, 0)&#xA;&#x9;}&#xA;&#x9;intersectedEntries := entriesGroup[0]&#xA;&#x9;for i := 1; i &amp;lt; len(entriesGroup); i += 1 {&#xA;&#x9;&#x9;intersectedEntries = intersect(intersectedEntries, entriesGroup[i])&#xA;&#x9;}&#xA;&#xA;&#x9;out := make([]any, 0)&#xA;&#x9;for _, entry := range intersectedEntries {&#xA;&#x9;&#x9;out = append(out, entry.value)&#xA;&#x9;}&#xA;&#x9;return out&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;&#34;&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&lt;/div&gt;&#xA;    &lt;iframe&#xA;        class=&#34;lazy-load&#34;&#xA;        title=&#34;repl demo&#34;&#xA;        frameborder=&#34;0&#34;&#xA;        width=&#34;100%&#34;&#xA;        height=&#34;700px&#34;&#xA;        data-src=&#34;https://repl.it/@mauriciopoppe/Memtable-for-a-Timeseries-Database?lite=true&#34;&gt;&#xA;    &lt;/iframe&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h2 id=&#34;sstable&#34;&gt;SSTable&lt;/h2&gt;&#xA;&lt;p&gt;An &lt;strong&gt;immutable data structure&lt;/strong&gt; that stores a large number of &lt;code&gt;key:value&lt;/code&gt; pairs sorted by &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Advantages over simple hash indexes&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Merging SSTables is similar to doing a merge sort.&lt;/li&gt;&#xA;&lt;li&gt;To find if a key exists, we don&amp;rsquo;t need an index of all the keys in memory. Instead, we can keep a sparse index for every few kilobytes and then perform a scan.&lt;/li&gt;&#xA;&lt;li&gt;Range queries can be compressed before writing to disk; the sparse index would only need to find the starting position of the compressed segment.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Cassandra</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/system-design/cassandra/</link>
      <pubDate>Fri, 28 Feb 2020 20:47:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/system-design/cassandra/</guid>
      <description>&lt;h2 id=&#34;engine&#34;&gt;Engine&lt;/h2&gt;&#xA;&lt;h3 id=&#34;features&#34;&gt;Features&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Consistent hashing&lt;/li&gt;&#xA;&lt;li&gt;Replication factor: replicas of the data across the cluster.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://docs.datastax.com/en/archived/cassandra/3.0/cassandra/dml/dmlConfigConsistency.html&#34;target=&#34;_blank&#34;&gt;Consistency level controlled for each query&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Up to 2 billion key-value pairs in a row.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr /&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;tw-mx-auto md:tw-w-1/2&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/cassandra-replication.jpeg&#34; alt=&#34;Cassandra replication&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Cassandra replication&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Replication factor = 3&lt;/li&gt;&#xA;&lt;li&gt;Consistency level = QUORUM&lt;/li&gt;&#xA;&lt;li&gt;Clients talk to any node. The node hashes the partition key and finds the location of the data.&lt;/li&gt;&#xA;&lt;li&gt;Data is read from all the replicas, waiting for responses until we reach a quorum.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr /&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;tw-mx-auto md:tw-w-1/2&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/cassandra-write.jpeg&#34; alt=&#34;Cassandra write&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Cassandra write&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Acknowledged when we write to both the commit log (append-only) and the memtable.&lt;/li&gt;&#xA;&lt;li&gt;When the memtable becomes full, it&amp;rsquo;s flushed into an SSTable.&lt;/li&gt;&#xA;&lt;li&gt;Periodically, SSTables are merged.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr /&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;tw-mx-auto md:tw-w-1/2&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/cassandra-read.jpeg&#34; alt=&#34;Cassandra read&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Cassandra read&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Check if the key is in the in-memory row cache.&lt;/li&gt;&#xA;&lt;li&gt;Query the Bloom filters of the existing SSTables to find the record. If it doesn&amp;rsquo;t exist, then skip the SSTable.&lt;/li&gt;&#xA;&lt;li&gt;If the Bloom filter says that there may be data, check the in-memory key cache.&lt;/li&gt;&#xA;&lt;li&gt;On a miss, get the data from the SSTable and merge it with the data in the memtable. Write the key to the in-memory key cache and the merged result to the in-memory row cache.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;data-modeling&#34;&gt;Data modeling&lt;/h2&gt;&#xA;&lt;h3 id=&#34;goals&#34;&gt;Goals&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Spread data evenly around the cluster.&lt;/li&gt;&#xA;&lt;li&gt;Minimize the number of partitions read.&lt;/li&gt;&#xA;&lt;li&gt;Keep partitions manageable.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;process&#34;&gt;Process&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Identify initial entities and relationships.&lt;/li&gt;&#xA;&lt;li&gt;Key attributes (map to PK columns).&lt;/li&gt;&#xA;&lt;li&gt;Equality search attributes (map to the beginning of the PK).&lt;/li&gt;&#xA;&lt;li&gt;Inequality search attributes (map to clustering columns).&lt;/li&gt;&#xA;&lt;li&gt;Other attributes:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Static attributes are shared within a given partition.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;primary key = partition key + clustering columns&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Legend:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;K Partition key&#xA;C Clustering key and their ordering (ascending or descending)&#xA;S Static columns, fixed and shared per partition&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;tw-mx-auto md:tw-w-1/2&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/cassandra-table-structure.png&#34; alt=&#34;Cassandra table structure&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Cassandra table structure&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;validation&#34;&gt;Validation&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread?&lt;/li&gt;&#xA;&lt;li&gt;One partition per read?&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible?&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? Let&amp;rsquo;s assume that each partition should have at most 1M cells: $n_{cells} = n_{rows} * (n_{cols} - n_{K} - n_{S}) + n_{S} &amp;lt; 1M$.&lt;/li&gt;&#xA;&lt;li&gt;How much data duplication?&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;Store books by ISBN&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row tw-mb-4&#34;&gt;&#xA;  &lt;div class=&#34;md:tw-w-1/3&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Attribute&lt;/th&gt;&#xA;          &lt;th&gt;Special&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;isbn&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;title&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;author&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;genre&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;publisher&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;md:tw-w-2/3&#34;&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread? Yes&lt;/li&gt;&#xA;&lt;li&gt;1 partition per read? Yes&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible? Yes&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? $1 * (5 - 1 - 0) + 0 &amp;lt; 1M$&lt;/li&gt;&#xA;&lt;li&gt;How much data duplication? 0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Register a user uniquely identified by an email/password. We also want their full name. They will be accessed by email and password or by UUID.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row tw-mb-4&#34;&gt;&#xA;  &lt;div class=&#34;md:tw-w-1/3&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Attribute&lt;/th&gt;&#xA;          &lt;th&gt;Special&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;email&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;password&lt;/td&gt;&#xA;          &lt;td&gt;C&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;fullname&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;uuid&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;md:tw-w-2/3&#34;&gt;&#xA;&lt;p&gt;Q1: Find users by login info.&lt;/p&gt;&#xA;&lt;p&gt;Q3: Find users by email (to guarantee uniqueness).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread? Yes&lt;/li&gt;&#xA;&lt;li&gt;1 partition per read? Yes&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible? Yes&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? $1 * (4 - 1 - 0) + 0 &amp;lt; 1M$&lt;/li&gt;&#xA;&lt;li&gt;How much data duplication? 0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row tw-mb-4&#34;&gt;&#xA;  &lt;div class=&#34;md:tw-w-1/3&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Attribute&lt;/th&gt;&#xA;          &lt;th&gt;Special&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;uuid&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;fullname&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;md:tw-w-2/3&#34;&gt;&#xA;&lt;p&gt;Q2: Get users by UUID.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread? Yes&lt;/li&gt;&#xA;&lt;li&gt;1 partition per read? Yes&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible? Yes&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? $1 * (2 - 1 - 0) + 0 &amp;lt; 1M$&lt;/li&gt;&#xA;&lt;li&gt;How much data duplication? 0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Find books a logged-in user has read, sorted by title and author.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row tw-mb-4&#34;&gt;&#xA;  &lt;div class=&#34;md:tw-w-1/3&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Attribute&lt;/th&gt;&#xA;          &lt;th&gt;Special&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;uuid&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;title&lt;/td&gt;&#xA;          &lt;td&gt;C&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;author&lt;/td&gt;&#xA;          &lt;td&gt;C&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;fullname&lt;/td&gt;&#xA;          &lt;td&gt;S&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;ISBN&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;genre&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;publisher&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;md:tw-w-2/3&#34;&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread? Yes&lt;/li&gt;&#xA;&lt;li&gt;1 partition per read? Yes&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible? Yes&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? (up to 200k book reads per user)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;n_{books} * (7 - 1 - 1) + 1 &amp; &amp;lt; 1M \\&#xA;n_{books} &amp; &amp;lt; \frac{1M}{5} - 1 \\&#xA;n_{books} &amp; &amp;lt; 200k&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How much data duplication? 0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Interaction of every user on the website&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row tw-mb-4&#34;&gt;&#xA;  &lt;div class=&#34;md:tw-w-1/3&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Attribute&lt;/th&gt;&#xA;          &lt;th&gt;Special&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;uuid&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;time&lt;/td&gt;&#xA;          &lt;td&gt;C (desc)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;element&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;type&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;md:tw-w-2/3&#34;&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread? Yes&lt;/li&gt;&#xA;&lt;li&gt;1 partition per read? Yes&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible? Yes&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? (up to 333k book reads per user; 333k actions may be a low number of actions to store, therefore &lt;em&gt;we should store actions by bucket&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;n_{actions} * (4 - 1 - 0) + 0 &amp; &amp;lt; 1M \\&#xA;n_{actions} &amp; &amp;lt; 333K&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How much data duplication? 0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;/div&gt; &lt;!-- I don&#39;t know why this is needed because the markup looked fine without this --&gt;&#xA;&lt;div&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row tw-mb-4&#34;&gt;&#xA;  &lt;div class=&#34;md:tw-w-1/3&#34;&gt;&#xA;  &lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Attribute&lt;/th&gt;&#xA;          &lt;th&gt;Special&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;uuid&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;month&lt;/td&gt;&#xA;          &lt;td&gt;K&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;time&lt;/td&gt;&#xA;          &lt;td&gt;C (desc)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;element&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;type&lt;/td&gt;&#xA;          &lt;td&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;md:tw-w-2/3&#34;&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Is data evenly spread? Yes&lt;/li&gt;&#xA;&lt;li&gt;1 partition per read? Yes&lt;/li&gt;&#xA;&lt;li&gt;Are writes (overwrites) possible? Yes&lt;/li&gt;&#xA;&lt;li&gt;How large are the partitions? (up to 333k book reads per user)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;1 year  = 333k / 365 / 24 = 38 actions / h&#xA;1 month = 333k / 30 / 24  = 462 actions / h (most realistic case)&#xA;1 week  = 333k / 7 / 24   = 1984 actions / h&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;n_{actions} * (5 - 2 - 0) + 0 &amp; &amp;lt; 1M \\&#xA;n_{actions} &amp; &amp;lt; 333K&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How much data duplication? 0&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Partitioning</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/system-design/partitioning/</link>
      <pubDate>Mon, 08 Jan 2018 22:43:20 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/system-design/partitioning/</guid>
      <description>&lt;h2 id=&#34;with-replication&#34;&gt;With replication&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Copies of each partition are stored in multiple nodes&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;partitioning-strategies&#34;&gt;Partitioning strategies&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Unfair partitioning may lead to hotspots (e.g., nodes with more data than others).&lt;/li&gt;&#xA;&lt;li&gt;Assigning records randomly makes data unreadable.&lt;/li&gt;&#xA;&lt;li&gt;By range (e.g., given a dictionary with sorted keys, Node 1 can have words from A to B, Node 2 from B to C, etc.).&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Within each partition, keys are stored in order.&lt;/li&gt;&#xA;&lt;li&gt;Range scans are easy.&lt;/li&gt;&#xA;&lt;li&gt;This may lead to hotspots (e.g., if all keys belong to the range A to B, Node 1 will become the hotspot).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;By hash key (e.g., take the hash key of the key and assign it to a range, using consistent hashing).&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It distributes data evenly.&lt;/li&gt;&#xA;&lt;li&gt;No range scans are possible.&lt;/li&gt;&#xA;&lt;li&gt;Cassandra allows a multi-column primary key; the first part of the key is hashed to determine&#xA;the partition, and the other columns are used as a concatenated index for SSTables.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;A hybrid approach can be taken with skewed workloads (e.g., where all writes/reads are for the same key).&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Append two digits to the key (e.g., key00, key01, &amp;hellip;, key99). This introduces a tradeoff with read performance.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;rebalancing-partitions&#34;&gt;Rebalancing partitions&lt;/h2&gt;&#xA;&lt;p&gt;Things that change in a database over time:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;More throughput requires more CPU, RAM, and disk, leading to vertical scaling.&lt;/li&gt;&#xA;&lt;li&gt;A machine fails, and other machines need to take over its responsibilities.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Rebalancing requirements:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Load should be fairly shared.&lt;/li&gt;&#xA;&lt;li&gt;The database should accept reads/writes while it&amp;rsquo;s being rebalanced.&lt;/li&gt;&#xA;&lt;li&gt;No more data than necessary should be moved (to minimize I/O).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Strategies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fixed number of partitions (Riak):&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When the number of partitions is greater than the number of nodes, multiple partitions are assigned to each node.&lt;/li&gt;&#xA;&lt;li&gt;When a new node is added, it &lt;em&gt;steals&lt;/em&gt; some partitions from every other node.&lt;/li&gt;&#xA;&lt;li&gt;When a node is removed, it distributes its partitions to every other node.&lt;/li&gt;&#xA;&lt;li&gt;The number of partitions is fixed when the database is set up and is not changed afterward.&lt;/li&gt;&#xA;&lt;li&gt;Choosing the number of partitions is difficult if the size of the dataset varies.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Dynamic partitioning (MongoDB):&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A partition is split once it reaches a limit or merged if it has very little data.&lt;/li&gt;&#xA;&lt;li&gt;The number of partitions adapts to the dataset&amp;rsquo;s size.&lt;/li&gt;&#xA;&lt;li&gt;An empty database starts with a single partition, and all writes are directed to the same node;&#xA;consequently, the other nodes remain idle.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Partitioning proportionally to nodes (Cassandra):&#xA;&lt;ul&gt;&#xA;&lt;li&gt;There is a fixed number of partitions per node; partitions grow without affecting the nodes.&lt;/li&gt;&#xA;&lt;li&gt;When a node is added, the partitions become smaller, and the data is redistributed.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;request-routing&#34;&gt;Request routing&lt;/h2&gt;&#xA;&lt;p&gt;Problem: How does a client know which node to connect to?&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Clients can connect to any node via a round-robin load balancer.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Cassandra and Riak use a gossip protocol to inform about changes in the cluster.&lt;/li&gt;&#xA;&lt;li&gt;A request can be sent to any node, which forwards it to the appropriate node.&lt;/li&gt;&#xA;&lt;li&gt;This puts more complexity on the database to avoid a dependency.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Requests are sent to a routing tier acting as a partition-aware load balancer.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;ZooKeeper is a coordination service that keeps track of the cluster metadata, mapping partitions to nodes.&#xA;Whenever a partition is created, updated, or removed, ZooKeeper notifies the routing tier.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;The client is aware of the partition and doesn&amp;rsquo;t need an intermediary.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Non Functional Requirements</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/system-design/non-functional-requirements/</link>
      <pubDate>Tue, 02 Jan 2018 02:14:56 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/system-design/non-functional-requirements/</guid>
      <description>&lt;h2 id=&#34;reliability--availability&#34;&gt;Reliability &amp;amp; Availability&lt;/h2&gt;&#xA;&lt;p&gt;A system should be &lt;em&gt;resilient&lt;/em&gt; (fault-tolerant) and performant under expected load.&lt;/p&gt;&#xA;&lt;p&gt;Strategies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Design for failure and trigger them deliberately, e.g., kill processes without a warning.&lt;/li&gt;&#xA;&lt;li&gt;Consider hardware faults such as blackouts and hard disk crashes, and add redundancy as necessary.&lt;/li&gt;&#xA;&lt;li&gt;Consider software faults such as:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Processes that slow down or that return corrupted responses.&lt;/li&gt;&#xA;&lt;li&gt;Fault cascading, where a fault triggers faults in other components.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Measure/monitor the system to identify faults.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;scalability&#34;&gt;Scalability&lt;/h2&gt;&#xA;&lt;p&gt;A system should be able to handle load increases.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Queries per second (QPS) to a web server.&lt;/li&gt;&#xA;&lt;li&gt;Ratio of reads/writes in a DB.&lt;/li&gt;&#xA;&lt;li&gt;Cache hit/miss rate.&lt;/li&gt;&#xA;&lt;li&gt;Number of simultaneous users in a real-time system.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Handling load:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Scaling up (vertical scaling): simple.&lt;/li&gt;&#xA;&lt;li&gt;Scaling out (horizontal scaling): complex.&lt;/li&gt;&#xA;&lt;li&gt;Manual scale: for predictable systems, simple.&lt;/li&gt;&#xA;&lt;li&gt;Elastic scale: add resources as load increases; for unpredictable systems, complex.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;performance&#34;&gt;Performance&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Throughput: number of requests processed per second.&lt;/li&gt;&#xA;&lt;li&gt;Latency: time to handle the request.&lt;/li&gt;&#xA;&lt;li&gt;Response time: latency + network/queue delays.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For the response time, we use percentiles. Given some metrics gathered for a set of requests in a period of time, sort them&#xA;from fastest to slowest. The common metrics are p50, p95, p99, p999 (used in SLAs).&lt;/p&gt;&#xA;&lt;p&gt;When a request involves parallel calls to multiple services, the response time is equal to the service that took the maximum time.&lt;/p&gt;&#xA;&lt;h2 id=&#34;durability&#34;&gt;Durability&lt;/h2&gt;&#xA;&lt;p&gt;Data should not be lost once sent to a system.&lt;/p&gt;&#xA;&lt;h2 id=&#34;monitoring--metrics-collection&#34;&gt;Monitoring &amp;amp; metrics collection&lt;/h2&gt;&#xA;&lt;p&gt;Capture metrics about the data going in and out of the system.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Implementing an A&#43; Conformant Promise Library in JavaScript the TDD Way</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/computation/promises/</link>
      <pubDate>Sat, 16 Sep 2017 21:05:42 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/computation/promises/</guid>
      <description>&lt;p&gt;My objective is to write a Promises/A+ conformant implementation similar to &#xA;&#xA;&lt;a href=&#34;https://github.com/then/promise/blob/master/src/core.js&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;then/promise&lt;/code&gt;&lt;/a&gt;&#xA;&#xA;. Also, I&amp;rsquo;ll do it the TDD way, where I&amp;rsquo;ll write some tests first and then implement what&amp;rsquo;s needed to make the tests pass (tests will be written on the &#xA;&#xA;&lt;a href=&#34;https://jestjs.io/&#34;target=&#34;_blank&#34;&gt;Jest&lt;/a&gt;&#xA;&#xA; platform).&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.promisejs.org/implementing/&#34;target=&#34;_blank&#34;&gt;This article&lt;/a&gt;&#xA;&#xA; was one of the best references I found online. This implementation is heavily inspired by it. I&amp;rsquo;ll also refer to the &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/&#34;target=&#34;_blank&#34;&gt;A+ promise spec&lt;/a&gt;&#xA;&#xA; when necessary.&lt;/p&gt;&#xA;&lt;h3 id=&#34;promise-state&#34;&gt;Promise state&lt;/h3&gt;&#xA;&lt;p&gt;A promise is an object/function that must be in one of these states: &lt;code&gt;PENDING&lt;/code&gt;, &lt;code&gt;FULFILLED&lt;/code&gt;, or &lt;code&gt;REJECTED&lt;/code&gt;. Initially, the promise is in a &lt;code&gt;PENDING&lt;/code&gt; state.&lt;/p&gt;&#xA;&lt;p&gt;A promise can transition from a &lt;code&gt;PENDING&lt;/code&gt; state to either a &lt;code&gt;FULFILLED&lt;/code&gt; state with a fulfillment &lt;code&gt;value&lt;/code&gt; or to a &lt;code&gt;REJECTED&lt;/code&gt; state with a rejection &lt;code&gt;reason&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To make the transition, the Promise constructor receives a function called &lt;code&gt;executor&lt;/code&gt;. The executor is called immediately with two functions, &lt;code&gt;fulfill&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt;, that when called, perform the state transition:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fulfill(value)&lt;/code&gt; - from &lt;code&gt;PENDING&lt;/code&gt; to &lt;code&gt;FULFILLED&lt;/code&gt; with &lt;code&gt;value&lt;/code&gt;. The &lt;code&gt;value&lt;/code&gt; is now a property of the promise.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;reject(reason)&lt;/code&gt; - from &lt;code&gt;PENDING&lt;/code&gt; to &lt;code&gt;REJECTED&lt;/code&gt; with &lt;code&gt;reason&lt;/code&gt;. The &lt;code&gt;reason&lt;/code&gt; is now a property of the promise.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;receives a executor function when constructed which is called immediately&#39;, () =&amp;gt; {&#xA;  // mock function with spies&#xA;  const executor = jest.fn()&#xA;  const promise = new APromise(executor)&#xA;  // mock function should be called immediately&#xA;  expect(executor.mock.calls.length).toBe(1)&#xA;  // arguments should be functions&#xA;  expect(typeof executor.mock.calls[0][0]).toBe(&#39;function&#39;)&#xA;  expect(typeof executor.mock.calls[0][1]).toBe(&#39;function&#39;)&#xA;})&#xA;&#xA;it(&#39;is in a PENDING state&#39;, () =&amp;gt; {&#xA;  const promise = new APromise(function executor(fulfill, reject) { /* ... */ })&#xA;  // for the sake of simplicity the state is public&#xA;  expect(promise.state).toBe(&#39;PENDING&#39;)&#xA;})&#xA;&#xA;it(&#39;transitions to the FULFILLED state with a `value`&#39;, () =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const promise = new APromise((fulfill, reject) =&amp;gt; {&#xA;    fulfill(value)&#xA;  })&#xA;  expect(promise.state).toBe(&#39;FULFILLED&#39;)&#xA;})&#xA;&#xA;it(&#39;transitions to the REJECTED state with a `reason`&#39;, () =&amp;gt; {&#xA;  const reason = &#39;I failed :(&#39;&#xA;  const promise = new APromise((fulfill, reject) =&amp;gt; {&#xA;    reject(reason)&#xA;  })&#xA;  expect(promise.state).toBe(&#39;REJECTED&#39;)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The initial implementation is straightforward:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;// possible states&#xA;const PENDING = &amp;#39;PENDING&amp;#39;&#xA;const FULFILLED = &amp;#39;FULFILLED&amp;#39;&#xA;const REJECTED = &amp;#39;REJECTED&amp;#39;&#xA;&#xA;class APromise {&#xA;  constructor(executor) {&#xA;    // initial state&#xA;    this.state = PENDING&#xA;    // the fulfillment value or rejection reason is mapped internally to `value`&#xA;    // initially the promise doesn&amp;#39;t have a value&#xA;&#xA;    // call the executor immediately&#xA;    doResolve(this, executor)&#xA;  }&#xA;}&#xA;&#xA;// fulfill with `value`&#xA;function fulfill(promise, value) {&#xA;  promise.state = FULFILLED&#xA;  promise.value = value&#xA;}&#xA;&#xA;// reject with `reason`&#xA;function reject(promise, reason) {&#xA;  promise.state = REJECTED&#xA;  promise.value = reason&#xA;}&#xA;&#xA;// creates the fulfill/reject functions that are arguments of the executor&#xA;function doResolve(promise, executor) {&#xA;  function wrapFulfill(value) {&#xA;    fulfill(promise, value)&#xA;  }&#xA;&#xA;  function wrapReject(reason) {&#xA;    reject(promise, reason)&#xA;  }&#xA;&#xA;  executor(wrapFulfill, wrapReject)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-1&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-1 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;observing-state-changes&#34;&gt;Observing state changes&lt;/h3&gt;&#xA;&lt;p&gt;To observe changes in the state of the promise (and the fulfillment value or rejection reason), we use the &lt;code&gt;then&lt;/code&gt; method. The method receives two parameters, an &lt;code&gt;onFulfilled&lt;/code&gt; function and an &lt;code&gt;onRejected&lt;/code&gt; function. The rules to invoke these functions are the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When the promise is in a &lt;code&gt;FULFILLED&lt;/code&gt; state, the &lt;code&gt;onFulfilled&lt;/code&gt; function will be called with the promise&amp;rsquo;s fulfillment &lt;code&gt;value&lt;/code&gt;, e.g., &lt;code&gt;onFulfilled(value)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;When the promise is in a &lt;code&gt;REJECTED&lt;/code&gt; state, the &lt;code&gt;onRejected&lt;/code&gt; function will be called with the promise&amp;rsquo;s rejection &lt;code&gt;reason&lt;/code&gt;, e.g., &lt;code&gt;onRejected(reason)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;From now on, these functions will be referred to as promise &lt;code&gt;handlers&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;should have a .then method&#39;, () =&amp;gt; {&#xA;  const promise = new APromise(() =&amp;gt; {})&#xA;  expect(typeof promise.then).toBe(&#39;function&#39;)&#xA;})&#xA;&#xA;it(&#39;should call the onFulfilled method when a promise is in a FULFILLED state&#39;, () =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const onFulfilled = jest.fn()&#xA;  const promise = new APromise((fulfill, reject) =&amp;gt; {&#xA;    fulfill(value)&#xA;  })&#xA;    .then(onFulfilled)&#xA;  expect(onFulfilled.mock.calls.length).toBe(1)&#xA;  expect(onFulfilled.mock.calls[0][0]).toBe(value)&#xA;})&#xA;&#xA;it(&#39;transitions to the REJECTED state with a `reason`&#39;, () =&amp;gt; {&#xA;  const reason = &#39;I failed :(&#39;&#xA;  const onRejected = jest.fn()&#xA;  const promise = new APromise((fulfill, reject) =&amp;gt; {&#xA;    reject(reason)&#xA;  })&#xA;    .then(null, onRejected)&#xA;  expect(onRejected.mock.calls.length).toBe(1)&#xA;  expect(onRejected.mock.calls[0][0]).toBe(reason)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s add the &lt;code&gt;.then&lt;/code&gt; function to the class prototype. Note that it&amp;rsquo;ll call either the &lt;code&gt;onFulfilled&lt;/code&gt; or &lt;code&gt;onRejected&lt;/code&gt; function based on the state of the promise:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;3-5,9-12&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;class APromise {&#xA;  // ...&#xA;  then(onFulfilled, onRejected) {&#xA;    handleResolved(this, onFulfilled, onRejected)&#xA;  }&#xA;  // ...&#xA;}&#xA;&#xA;function handleResolved(promise, onFulfilled, onRejected) {&#xA;  const cb = promise.state === FULFILLED ? onFulfilled : onRejected&#xA;  cb(promise.value)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-2&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-2 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;one-way-transition&#34;&gt;One-way transition&lt;/h3&gt;&#xA;&lt;p&gt;Once the transition to either &lt;code&gt;FULFILLED&lt;/code&gt; or &lt;code&gt;REJECTED&lt;/code&gt; occurs, the promise must not transition to any other state.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;const value = &#39;:)&#39;&#xA;const reason = &#39;I failed :(&#39;&#xA;&#xA;it(&#39;when a promise is fulfilled it should not be rejected with another value&#39;, () =&amp;gt; {&#xA;  const onFulfilled = jest.fn()&#xA;  const onRejected = jest.fn()&#xA;&#xA;  const promise = new APromise((resolve, reject) =&amp;gt; {&#xA;    resolve(value)&#xA;    reject(reason)&#xA;  })&#xA;  promise.then(onFulfilled, onRejected)&#xA;&#xA;  expect(onFulfilled.mock.calls.length).toBe(1)&#xA;  expect(onFulfilled.mock.calls[0][0]).toBe(value)&#xA;  expect(onRejected.mock.calls.length).toBe(0)&#xA;  expect(promise.state === &#39;FULFILLED&#39;)&#xA;})&#xA;&#xA;it(&#39;when a promise is rejected it should not be fulfilled with another value&#39;, () =&amp;gt; {&#xA;  const onFulfilled = jest.fn()&#xA;  const onRejected = jest.fn()&#xA;&#xA;  const promise = new APromise((resolve, reject) =&amp;gt; {&#xA;    reject(reason)&#xA;    resolve(value)&#xA;  })&#xA;  promise.then(onFulfilled, onRejected)&#xA;&#xA;  expect(onRejected.mock.calls.length).toBe(1)&#xA;  expect(onRejected.mock.calls[0][0]).toBe(reason)&#xA;  expect(onFulfilled.mock.calls.length).toBe(0)&#xA;  expect(promise.state === &#39;REJECTED&#39;)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;In our current implementation, the function that calls the executor should make sure that either &lt;code&gt;fulfill&lt;/code&gt; or &lt;code&gt;reject&lt;/code&gt; is called only once. Subsequent calls should be ignored:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;2,5,6,11,12&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function doResolve(promise, executor) {&#xA;  let called = false&#xA;&#xA;  function wrapFulfill(value) {&#xA;    if (called) { return }&#xA;    called = true&#xA;    fulfill(promise, value)&#xA;  }&#xA;&#xA;  function wrapReject(reason) {&#xA;    if (called) { return }&#xA;    called = true&#xA;    reject(promise, reason)&#xA;  }&#xA;&#xA;  executor(wrapFulfill, wrapReject)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-3&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-3 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;handling-executor-errors&#34;&gt;Handling executor errors&lt;/h3&gt;&#xA;&lt;p&gt;If the execution of the &lt;code&gt;executor&lt;/code&gt; fails, the promise should transition to the &lt;code&gt;REJECTED&lt;/code&gt; state with the failure reason.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;describe(&#39;handling executor errors&#39;, () =&amp;gt; {&#xA;  it(&#39;when the executor fails the promise should transition to the REJECTED state&#39;, () =&amp;gt; {&#xA;    const reason = new Error(&#39;I failed :(&#39;)&#xA;    const onRejected = jest.fn()&#xA;    const promise = new APromise((resolve, reject) =&amp;gt; {&#xA;      throw reason&#xA;    })&#xA;    promise.then(null, onRejected)&#xA;    expect(onRejected.mock.calls.length).toBe(1)&#xA;    expect(onRejected.mock.calls[0][0]).toBe(reason)&#xA;    expect(promise.state === &#39;REJECTED&#39;)&#xA;  })&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The function that calls the executor should wrap it in a try/catch block and transition to &lt;code&gt;REJECTED&lt;/code&gt; if the catch block is executed:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;3-7&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function doResolve(promise, executor) {&#xA;  // ...&#xA;  try {&#xA;    executor(wrapFulfill, wrapReject)&#xA;  } catch (err) {&#xA;    wrapReject(err)&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-4&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-4 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;async-executor&#34;&gt;Async executor&lt;/h3&gt;&#xA;&lt;p&gt;If the resolver&amp;rsquo;s &lt;code&gt;fulfill&lt;/code&gt;/&lt;code&gt;reject&lt;/code&gt; are executed asynchronously, our &lt;code&gt;.then&lt;/code&gt; method will fail because its handlers are executed immediately.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;should queue callbacks when the promise is not fulfilled immediately&#39;, done =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const promise = new APromise((fulfill, reject) =&amp;gt; {&#xA;    setTimeout(fulfill, 1, value)&#xA;  })&#xA;&#xA;  const onFulfilled = jest.fn()&#xA;&#xA;  promise.then(onFulfilled)&#xA;  setTimeout(() =&amp;gt; {&#xA;    // should have been called once&#xA;    expect(onFulfilled.mock.calls.length).toBe(1)&#xA;    expect(onFulfilled.mock.calls[0][0]).toBe(value)&#xA;    promise.then(onFulfilled)&#xA;  }, 5)&#xA;&#xA;  // should not be called immediately&#xA;  expect(onFulfilled.mock.calls.length).toBe(0)&#xA;&#xA;  setTimeout(function () {&#xA;    // should have been called twice&#xA;    expect(onFulfilled.mock.calls.length).toBe(2)&#xA;    expect(onFulfilled.mock.calls[1][0]).toBe(value)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&#xA;it(&#39;should queue callbacks when the promise is not rejected immediately&#39;, done =&amp;gt; {&#xA;  const reason = &#39;I failed :(&#39;&#xA;  const promise = new APromise((fulfill, reject) =&amp;gt; {&#xA;    setTimeout(reject, 1, reason)&#xA;  })&#xA;&#xA;  const onRejected = jest.fn()&#xA;&#xA;  promise.then(null, onRejected)&#xA;  setTimeout(() =&amp;gt; {&#xA;    // should have been called once&#xA;    expect(onRejected.mock.calls.length).toBe(1)&#xA;    expect(onRejected.mock.calls[0][0]).toBe(reason)&#xA;    promise.then(null, onRejected)&#xA;  }, 5)&#xA;&#xA;  // should not be called immediately&#xA;  expect(onRejected.mock.calls.length).toBe(0)&#xA;&#xA;  setTimeout(function () {&#xA;    // should have been called twice&#xA;    expect(onRejected.mock.calls.length).toBe(2)&#xA;    expect(onRejected.mock.calls[1][0]).toBe(reason)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s add a queue to the promise. Its purpose is to store handlers that will be called once the promise state changes from &lt;code&gt;PENDING&lt;/code&gt; to something else. At the same time, our &lt;code&gt;.then&lt;/code&gt; method should check the promise state to decide whether to call the handler immediately or to store it. Let&amp;rsquo;s move this logic to a new helper function, &lt;code&gt;handle&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;4-5,10,14-25,27-30&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;class APromise {&#xA;  constructor(executor) {&#xA;    this.state = PENDING&#xA;    // .then handler queue&#xA;    this.queue = []&#xA;    doResolve(this, executor)&#xA;  }&#xA;&#xA;  then(onFulfilled, onRejected) {&#xA;    handle(this, { onFulfilled, onRejected })&#xA;  }&#xA;}&#xA;&#xA;// checks the state of the promise to either:&#xA;// - queue it for later use if the promise is PENDING&#xA;// - call the handler if the promise is not PENDING&#xA;function handle(promise, handler) {&#xA;  if (promise.state === PENDING) {&#xA;    // queue if PENDING&#xA;    promise.queue.push(handler)&#xA;  } else {&#xA;    // execute immediately&#xA;    handleResolved(promise, handler)&#xA;  }&#xA;}&#xA;&#xA;function handleResolved(promise, handler) {&#xA;  const cb = promise.state === FULFILLED ? handler.onFulfilled : handler.onRejected&#xA;  cb(promise.value)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;p&gt;Also, the &lt;code&gt;fulfill&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; methods should be updated so that they invoke all the handlers stored in the promise when called. This is implemented in a new function, &lt;code&gt;finale&lt;/code&gt;, called after the state and the value have been updated.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;4,10,13-19&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function fulfill(promise, value) {&#xA;  promise.state = FULFILLED&#xA;  promise.value = value&#xA;  finale(promise)&#xA;}&#xA;&#xA;function reject(promise, reason) {&#xA;  promise.state = REJECTED&#xA;  promise.value = reason&#xA;  finale(promise)&#xA;}&#xA;&#xA;// invoke all the handlers stored in the promise&#xA;function finale(promise) {&#xA;  const length = promise.queue.length&#xA;  for (let i = 0; i &amp;lt; length; i &amp;#43;= 1) {&#xA;    handle(promise, promise.queue[i])&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-5&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-5 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;chaining-promises&#34;&gt;Chaining promises&lt;/h3&gt;&#xA;&lt;p&gt;Our &lt;code&gt;.then&lt;/code&gt; methods should return a new promise. Note that in the example below, &lt;code&gt;p.then&lt;/code&gt; returns a promise &lt;code&gt;q&lt;/code&gt;. The handler &lt;code&gt;qOnFulfilled&lt;/code&gt; is stored on &lt;code&gt;q&lt;/code&gt;, and the handler &lt;code&gt;rOnFulfilled&lt;/code&gt; is stored in &lt;code&gt;r&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;.then should return a new promise&#39;, () =&amp;gt; {&#xA;  expect(function() {&#xA;    const qOnFulfilled = jest.fn()&#xA;    const rOnFulfilled = jest.fn()&#xA;    const p = new APromise(fulfill =&amp;gt; fulfill())&#xA;    const q = p.then(qOnFulfilled)&#xA;    const r = q.then(rOnFulfilled)&#xA;  }).not.toThrow()&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The implementation is again straightforward. However, as we&amp;rsquo;ll see, the new promise transitions to a different state in a different way than by using an executor. The new promise uses the handlers to make the transition as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if the &lt;code&gt;onFulfilled&lt;/code&gt; or &lt;code&gt;onRejected&lt;/code&gt; function is called:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if there are &lt;strong&gt;no errors&lt;/strong&gt; executing it, the promise will transition to the &lt;code&gt;FULFILLED&lt;/code&gt; state with the returned value as the fulfillment &lt;code&gt;value&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;if there is an &lt;strong&gt;error&lt;/strong&gt; executing it, the promise will transition to the &lt;code&gt;REJECTED&lt;/code&gt; state with the error as the rejection &lt;code&gt;reason&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s make the &lt;code&gt;.then&lt;/code&gt; method return a promise first:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;4,5,7&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;class APromise {&#xA;  // ...&#xA;  then(onFulfilled, onRejected) {&#xA;    // empty executor&#xA;    const promise = new APromise(() =&amp;gt; {})&#xA;    handle(this, { onFulfilled, onRejected })&#xA;    return promise&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;p&gt;And then write the test to handle the new promise resolution:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;if .then\&#39;s onFulfilled is called without errors it should transition to FULFILLED&#39;, () =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const f1 = jest.fn()&#xA;  new APromise(fulfill =&amp;gt; fulfill())&#xA;    .then(() =&amp;gt; value)&#xA;    .then(f1)&#xA;  expect(f1.mock.calls.length).toBe(1)&#xA;  expect(f1.mock.calls[0][0]).toBe(value)&#xA;})&#xA;&#xA;it(&#39;if .then\&#39;s onRejected is called without errors it should transition to FULFILLED&#39;, () =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const f1 = jest.fn()&#xA;  new APromise((fulfill, reject) =&amp;gt; reject())&#xA;    .then(null, () =&amp;gt; value)&#xA;    .then(f1)&#xA;  expect(f1.mock.calls.length).toBe(1)&#xA;  expect(f1.mock.calls[0][0]).toBe(value)&#xA;})&#xA;&#xA;it(&#39;if .then\&#39;s onFulfilled is called and has an error it should transition to REJECTED&#39;, () =&amp;gt; {&#xA;  const reason = new Error(&#39;I failed :(&#39;)&#xA;  const f1 = jest.fn()&#xA;  new APromise(fulfill =&amp;gt; fulfill())&#xA;    .then(() =&amp;gt; { throw reason })&#xA;    .then(null, f1)&#xA;  expect(f1.mock.calls.length).toBe(1)&#xA;  expect(f1.mock.calls[0][0]).toBe(reason)&#xA;})&#xA;&#xA;it(&#39;if .then\&#39;s onRejected is called and has an error it should transition to REJECTED&#39;, () =&amp;gt; {&#xA;  const reason = new Error(&#39;I failed :(&#39;)&#xA;  const f1 = jest.fn()&#xA;  new APromise((fulfill, reject) =&amp;gt; reject())&#xA;    .then(null, () =&amp;gt; { throw reason })&#xA;    .then(null, f1)&#xA;  expect(f1.mock.calls.length).toBe(1)&#xA;  expect(f1.mock.calls[0][0]).toBe(reason)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;For the implementation, we first have to store the new promise in the handler queue as well. That way, if the observed promise is resolved, the elements in the queue know which promise they need to resolve.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;5-6,13-19&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;class APromise {&#xA;  // ...&#xA;  then(onFulfilled, onRejected) {&#xA;    const promise = new APromise(() =&amp;gt; {})&#xA;    // store the promise as well&#xA;    handle(this, { promise, onFulfilled, onRejected })&#xA;    return promise&#xA;  }&#xA;}&#xA;&#xA;function handleResolved(promise, handler) {&#xA;  const cb = promise.state === FULFILLED ? handler.onFulfilled : handler.onRejected&#xA;  // execute the handler and transition according to the rules&#xA;  try {&#xA;    const value = cb(promise.value)&#xA;    fulfill(handler.promise, value)&#xA;  } catch (err) {&#xA;    reject(handler.promise, err)&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-6&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-6 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;async-handlers&#34;&gt;Async handlers&lt;/h3&gt;&#xA;&lt;p&gt;Next, let&amp;rsquo;s consider the case where a handler returns a promise. In this case, the promise that&amp;rsquo;s part of the handler (not the returned promise) should adopt the state and fulfillment value or rejection reason of the returned promise.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;if a handler returns a promise, the previous promise should &#39; +&#xA;    &#39;adopt the state of the returned promise&#39;, () =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const f1 = jest.fn()&#xA;  new APromise(fulfill =&amp;gt; fulfill())&#xA;    .then(() =&amp;gt; new APromise(resolve =&amp;gt; resolve(value)))&#xA;    .then(f1)&#xA;  expect(f1.mock.calls.length).toBe(1)&#xA;  expect(f1.mock.calls[0][0]).toBe(value)&#xA;})&#xA;&#xA;it(&#39;if a handler returns a promise resolved in the future, &#39; +&#xA;    &#39;the previous promise should adopt its value&#39;, done =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const f1 = jest.fn()&#xA;  new APromise(fulfill =&amp;gt; setTimeout(fulfill, 0))&#xA;    .then(() =&amp;gt; new APromise(resolve =&amp;gt; setTimeout(resolve, 0, value)))&#xA;    .then(f1)&#xA;  setTimeout(() =&amp;gt; {&#xA;    expect(f1.mock.calls.length).toBe(1)&#xA;    expect(f1.mock.calls[0][0]).toBe(value)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine the following scenario:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;const executor = fulfill =&amp;gt; setTimeout(fulfill, 0, &#39;p&#39;)&#xA;const p = new APromise(executor)&#xA;&#xA;const qOnFulfilled = value =&amp;gt;&#xA;  new APromise(fulfill =&amp;gt; fulfill(value + &#39;q&#39;))&#xA;const q = p.then(qOnFulfilled)&#xA;&#xA;const rOnFulfilled = value =&amp;gt; (&#xA;  // value should be &#39;pq&#39;&#xA;)&#xA;const r = q.then(rOnFulfilled)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;In our current implementation, the tuple &lt;code&gt;{ q, qOnFulfilled }&lt;/code&gt; is stored in the handlers of &lt;code&gt;p&lt;/code&gt;, and we are sure that &lt;code&gt;qOnFulfilled&lt;/code&gt; is called before storing the tuple &lt;code&gt;{ r, rOnFulfilled }&lt;/code&gt; in &lt;code&gt;q&lt;/code&gt;. We could take advantage of this fact and detect when a handler returns a promise to store observers in the returned promise instead, e.g., store &lt;code&gt;{ r, onFulfilled }&lt;/code&gt; on the promise returned by &lt;code&gt;qOnFulfilled&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Note that we&amp;rsquo;re using a &lt;code&gt;while&lt;/code&gt; loop because a nested promise might itself have another promise as its resolution value.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;2-5&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function handle(promise, handler) {&#xA;  // take the state of the innermost promise&#xA;  while (promise.value instanceof APromise) {&#xA;    promise = promise.value&#xA;  }&#xA;&#xA;  if (promise.state === PENDING) {&#xA;    // queue if PENDING&#xA;    promise.queue.push(handler)&#xA;  } else {&#xA;    // execute immediately&#xA;    handleResolved(promise, handler)&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-7&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-7 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h3 id=&#34;additional-cases&#34;&gt;Additional cases&lt;/h3&gt;&#xA;&lt;h4 id=&#34;invalid-handlers&#34;&gt;Invalid handlers&lt;/h4&gt;&#xA;&lt;p&gt;If the handler that was supposed to be a function is not a function, our implementation will fail.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;works with invalid handlers (fulfill)&#39;, () =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const f1 = jest.fn()&#xA;&#xA;  const p = new APromise(fulfill =&amp;gt; fulfill(value))&#xA;  const q = p.then(null)&#xA;  q.then(f1)&#xA;&#xA;  expect(f1.mock.calls.length).toBe(1)&#xA;  expect(f1.mock.calls[0][0]).toBe(value)&#xA;})&#xA;&#xA;it(&#39;works with invalid handlers (reject)&#39;, () =&amp;gt; {&#xA;  const reason = &#39;I failed :(&#39;&#xA;  const r1 = jest.fn()&#xA;&#xA;  const p = new APromise((fulfill, reject) =&amp;gt; reject(reason))&#xA;  const q = p.then(null, null)&#xA;  q.then(null, r1)&#xA;&#xA;  expect(r1.mock.calls.length).toBe(1)&#xA;  expect(r1.mock.calls[0][0]).toBe(reason)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine the following scenario:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;const p = new APromise(fulfill =&amp;gt; fulfill(&#39;p&#39;))&#xA;const qOnFulfilled = null&#xA;const q = p.then(qOnFulfilled)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;In this case, &lt;code&gt;q&lt;/code&gt; should be resolved right away with the resolution value of &lt;code&gt;p&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;4-11&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function handleResolved(promise, handler) {&#xA;  const cb = promise.state === FULFILLED ? handler.onFulfilled : handler.onRejected&#xA;  // resolve immediately if the handler is not a function&#xA;  if (typeof cb !== &amp;#39;function&amp;#39;) {&#xA;    if (promise.state === FULFILLED) {&#xA;      fulfill(handler.promise, promise.value)&#xA;    } else {&#xA;      reject(handler.promise, promise.value)&#xA;    }&#xA;    return&#xA;  }&#xA;  try {&#xA;    const ret = cb(promise.value)&#xA;    fulfill(handler.promise, ret)&#xA;  } catch (err) {&#xA;    reject(handler.promise, err)&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;execute-the-handlers-after-the-event-loop&#34;&gt;Execute the handlers after the event loop&lt;/h4&gt;&#xA;&lt;p&gt;Requirement &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-34&#34;target=&#34;_blank&#34;&gt;2.2.4&lt;/a&gt;&#xA;&#xA;: As pointed out in &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-67&#34;target=&#34;_blank&#34;&gt;3.1&lt;/a&gt;&#xA;&#xA;, the handlers are called with a fresh stack. Also, this makes the promise resolution consistent by ensuring that the observers are called in the future, even if the executor/handlers are synchronous.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;the promise observers are called after the event loop&#39;, done =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const f1 = jest.fn()&#xA;  let resolved = false&#xA;&#xA;  const p = new APromise(fulfill =&amp;gt; {&#xA;    fulfill(value)  // should not execute f1 immediately&#xA;    resolved = true&#xA;  }).then(f1)&#xA;&#xA;  expect(f1.mock.calls.length).toBe(0)&#xA;&#xA;  setTimeout(function () {&#xA;    expect(f1.mock.calls.length).toBe(1)&#xA;    expect(f1.mock.calls[0][0]).toBe(value)&#xA;    expect(resolved).toBe(true)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;We can use any function that allows us to call a function after the event loop. This includes &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;setImmediate&lt;/code&gt;, and &lt;code&gt;requestAnimationFrame&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;2,4&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function handleResolved(promise, handler) {&#xA;  setImmediate(() =&amp;gt; {&#xA;    // ...&#xA;  })&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;p&gt;NOTE: Most of the unit tests must be changed to be async as well.&lt;/p&gt;&#xA;&lt;h4 id=&#34;reject-with-a-resolved-promise-as-a-reason&#34;&gt;Reject with a resolved promise as a reason&lt;/h4&gt;&#xA;&lt;p&gt;Requirement &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-42&#34;target=&#34;_blank&#34;&gt;2.2.7.2&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;rejects with a resolved promise&#39;, done =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const reason = new APromise(fulfill =&amp;gt; fulfill(value))&#xA;&#xA;  const r1 = jest.fn()&#xA;  const p = new APromise(fulfill =&amp;gt; fulfill())&#xA;    .then(() =&amp;gt; { throw reason })&#xA;    .then(null, r1)&#xA;&#xA;  expect(r1.mock.calls.length).toBe(0)&#xA;&#xA;  setTimeout(function () {&#xA;    expect(r1.mock.calls.length).toBe(1)&#xA;    expect(r1.mock.calls[0][0]).toBe(reason)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Only adopt the state of the nested promise if the promise is not in a &lt;code&gt;REJECTED&lt;/code&gt; state.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;3&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function handle(promise, handler) {&#xA;  // take the state of the returned promise&#xA;  while (promise.state !== REJECTED &amp;amp;&amp;amp; promise.value instanceof APromise) {&#xA;    promise = promise.value&#xA;  }&#xA;  if (promise.state === PENDING) {&#xA;    // queue if PENDING&#xA;    promise.queue.push(handler)&#xA;  } else {&#xA;    // execute handler (after the event loop)&#xA;    handleResolved(promise, handler)&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;a-promise-shouldnt-be-resolved-with-itself&#34;&gt;A promise shouldn&amp;rsquo;t be resolved with itself&lt;/h4&gt;&#xA;&lt;p&gt;Requirement &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-48&#34;target=&#34;_blank&#34;&gt;2.3.1&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;should throw when attempted to be resolved with itself&#39;, done =&amp;gt; {&#xA;  const r1 = jest.fn()&#xA;  const p = new APromise(fulfill =&amp;gt; fulfill())&#xA;  const q = p.then(() =&amp;gt; q)&#xA;  q.then(null, r1)&#xA;&#xA;  setTimeout(function () {&#xA;    expect(r1.mock.calls.length).toBe(1)&#xA;    expect(r1.mock.calls[0][0] instanceof TypeError).toBe(true)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;On the &lt;code&gt;fulfill&lt;/code&gt; method, let&amp;rsquo;s check that the fulfillment value is not equal to the promise itself. If so, then throw a &lt;code&gt;TypeError&lt;/code&gt; as mentioned in &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-48&#34;target=&#34;_blank&#34;&gt;2.3.1&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;2-5&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function fulfill(promise, value) {&#xA;  if (value === promise) {&#xA;    return reject(promise, new TypeError())&#xA;  }&#xA;  promise.state = FULFILLED&#xA;  promise.value = value&#xA;  finale(promise)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;thenables&#34;&gt;Thenables&lt;/h4&gt;&#xA;&lt;p&gt;Related requirement &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-56&#34;target=&#34;_blank&#34;&gt;2.3.3.3&lt;/a&gt;&#xA;&#xA;: The handler&amp;rsquo;s returned value may be a &lt;code&gt;thenable&lt;/code&gt;, an object/function that has a &lt;code&gt;then&lt;/code&gt; property that is accessible and is a function. The &lt;code&gt;then&lt;/code&gt; function is like an executor; it receives &lt;code&gt;fulfill&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; callbacks that should be used to transition the state of the thenable.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;it(&#39;should work with thenables&#39;, done =&amp;gt; {&#xA;  const value = &#39;:)&#39;&#xA;  const thenable = {&#xA;    then: fulfill =&amp;gt; fulfill(value)&#xA;  }&#xA;  const f1 = jest.fn()&#xA;  new APromise(fulfill =&amp;gt; fulfill(value))&#xA;    .then(() =&amp;gt; thenable)&#xA;    .then(f1)&#xA;&#xA;  setTimeout(function () {&#xA;    expect(f1.mock.calls.length).toBe(1)&#xA;    expect(f1.mock.calls[0][0]).toBe(value)&#xA;    done()&#xA;  }, 10)&#xA;})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s modify the &lt;code&gt;fulfill&lt;/code&gt; method and add the check for thenables. Note that accessing a property is not always a safe operation (e.g., the property might be defined using a &#xA;&#xA;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;getter&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; that fails), which is why we should wrap it in a try/catch.&lt;/p&gt;&#xA;&lt;p&gt;Also, note that by requirement &#xA;&#xA;&lt;a href=&#34;https://promisesaplus.com/#point-56&#34;target=&#34;_blank&#34;&gt;2.3.3.3&lt;/a&gt;&#xA;&#xA;, the thenable&amp;rsquo;s &lt;code&gt;then&lt;/code&gt; should be called with the thenable as &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre data-line=&#39;5-24&#39; class=&#34;line-numbers&#34;&gt;&lt;code&#xA;class=&#39;language-javascript &#39; &gt;function fulfill(promise, value) {&#xA;  if (value === promise) {&#xA;    return reject(promise, new TypeError())&#xA;  }&#xA;  if (value &amp;amp;&amp;amp; (typeof value === &amp;#39;object&amp;#39; || typeof value === &amp;#39;function&amp;#39;)) {&#xA;    let then&#xA;    try {&#xA;      then = value.then&#xA;    } catch (err) {&#xA;      return reject(promise, err)&#xA;    }&#xA;&#xA;    // promise&#xA;    if (then === promise.then &amp;amp;&amp;amp; promise instanceof APromise) {&#xA;      promise.state = FULFILLED&#xA;      promise.value = value&#xA;      return finale(promise)&#xA;    }&#xA;&#xA;    // thenable&#xA;    if (typeof then === &amp;#39;function&amp;#39;) {&#xA;      return doResolve(promise, then.bind(value))&#xA;    }&#xA;  }&#xA;&#xA;  // primitive&#xA;  promise.state = FULFILLED&#xA;  promise.value = value&#xA;  finale(promise)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;the-end&#34;&gt;The end&lt;/h3&gt;&#xA;&lt;p&gt;That was it! What I learned from implementing it on my own was that a promise can be a rejection error. Previously, I thought that promises would never be something that an observer would receive. I thought that all promises were unwrapped before being sent to the observer.&lt;/p&gt;&#xA;&lt;p&gt;This is the final version of our tests and the promise implementation:&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;tw-mt-4 tw-mb-4&#34;&gt;&#xA;    &lt;a class=&#34;tw-border-2 tw-rounded tw-border-primary tw-p-2 tw-inline-block&#34; href=&#34;https://repl.it/@mauriciopoppe/Implementing-Promises-from-Scratch-8&#34; target=&#34;_blank&#34;&gt;&#xA;        Open &lt;span class=&#34;repl__id&#34;&gt; @mauriciopoppe/Implementing-Promises-from-Scratch-8 &lt;/span&gt; in&#xA;        &lt;img src=&#34;https://repl.it/public/images/logo-small.png&#34; style=&#34;width: 83px; vertical-align: middle;&#xA;        margin-left: 11px; display: inline-block&#34;&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;h4 id=&#34;running-the-a-promise-compliance-tests&#34;&gt;Running the A+ Promise compliance tests&lt;/h4&gt;&#xA;&lt;p&gt;This implementation passed all the 872 tests, cool!&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;872 passing (14s)&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div class=&#34;tw-my-5 tw-mx-auto&#34;&gt;&#xA;  &lt;div class=&#34;github-widget&#34; data-repo=&#34;mauriciopoppe/implementing-promises-from-scratch&#34;&gt;&lt;/div&gt;&#xA;  &lt;script src=&#34;https://cdn.rawgit.com/hustcc/GitHub-Repo-Widget.js/cf58d16b/GithubRepoWidget.min.js&#34;&gt;&lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&lt;h4 id=&#34;improvements&#34;&gt;Improvements&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Add a task queue so that the execution of multiple handlers happens in a &lt;em&gt;batch&lt;/em&gt; (it&amp;rsquo;s not actually a batch; the way the event loop works is that multiple calls to an API like &lt;code&gt;setTimeout&lt;/code&gt; will add multiple tasks to the task queue as well. However, if we send them in a &lt;em&gt;batch&lt;/em&gt;, all the handlers will be executed in a row in the next event loop).&lt;/li&gt;&#xA;&lt;li&gt;Add missing methods: &lt;code&gt;Promise.all&lt;/code&gt;, &lt;code&gt;Promise.race&lt;/code&gt;, and the like.&lt;/li&gt;&#xA;&lt;li&gt;Performance improvements: The creator of Bluebird has a &#xA;&#xA;&lt;a href=&#34;https://github.com/petkaantonov/bluebird/wiki/Optimization-killers&#34;target=&#34;_blank&#34;&gt;detailed document&lt;/a&gt;&#xA;&#xA; with some optimization tips.&lt;/li&gt;&#xA;&lt;li&gt;Async stack traces: See &#xA;&#xA;&lt;a href=&#34;https://github.com/kriskowal/q#long-stack-traces&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;q&lt;/code&gt;&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Divisibility</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/divisibility/</link>
      <pubDate>Sun, 21 May 2017 23:18:42 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/divisibility/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;Let $a,b \in \mathbb{Z}$. We say that $a$ &lt;em&gt;&lt;strong&gt;divides&lt;/strong&gt;&lt;/em&gt; $b$, written $a \given b$, if there&amp;rsquo;s an integer $n$ such that&#xA;$b = na&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;If $a$ divides $b$, then $b$ is &lt;em&gt;&lt;strong&gt;divisible&lt;/strong&gt;&lt;/em&gt; by $a$, and $a$ is a &lt;em&gt;&lt;strong&gt;divisor or factor&lt;/strong&gt;&lt;/em&gt; of $b$. Also, $b$ is called a &lt;em&gt;&lt;strong&gt;multiple&lt;/strong&gt;&lt;/em&gt; of $a$.&lt;/p&gt;&#xA;&lt;p&gt;Additional properties of the relation $|$:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;if $a \given b$ and $b \given c$ then $a \given c$.&lt;/li&gt;&#xA;&lt;li&gt;if $a \given b$ and $c \given d$ then $ac \given bd$.&lt;/li&gt;&#xA;&lt;li&gt;if $d \given a$ and $d \given b$ then $d \given a + b$.&lt;/li&gt;&#xA;&lt;li&gt;if $d \given a$ and $d \given b$ then $d \given ax + by$ for any integers $x, y$.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;if $b=ma$ and $c=nb$, then $c=(nm)a.&lt;/li&gt;&#xA;&lt;li&gt;if $b=ma$ and $d=nc$, then $bd=(nm)ac.&lt;/li&gt;&#xA;&lt;li&gt;if $a=md$ and $b=nd$, then $a + b=(m + n)d.&lt;/li&gt;&#xA;&lt;li&gt;if $a=md$, $b=nd$, then $ax=(mx)d$ and $by=(ny)d$; therefore, $ax + by = (mx + ny)d$.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;division-algorithm&#34;&gt;Division algorithm&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Let $a, b \in \mathbb{Z}$ with $b &amp;gt; 0$, then there exists $q, r \in \mathbb{Z}$ such that&#xA;$a = bq + r, \quad \text{where $0 \le r \lt b$}&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof.&lt;/strong&gt; If $bq$ is the largest multiple of $b$ that does not exceed $a$, then $r = a - bq$ is positive, and since $b(q + 1) &amp;gt; a$, then $r \lt b$&lt;/p&gt;&#xA;&lt;p&gt;Also, if $r = 0$, then $a = bq$, which implies that $q \given a$.&lt;/p&gt;&#xA;&lt;h2 id=&#34;greatest-common-divisor&#34;&gt;Greatest common divisor&lt;/h2&gt;&#xA;&lt;p&gt;Let $a, b \in \mathbb{N}$, the greatest common divisor of $a$ and $b$, written as $gcd(a,b)$ or $(a,b)$, is the element $d$ in $\mathbb{N}$ such that $d \given a$, and $d \given b$, and every common divisor of $a$ and $b$ also divides $d$.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Let $a$ and $b$ be two numbers in $\mathbb{N}$, the value of $(a,b)$ is a &lt;em&gt;linear combination&lt;/em&gt; of $a$ and $b$ i.e. there exists $s,t$ in $\mathbb{Z}$ such that&#xA;$sa + tb = (a, b)$&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Let $d$ be the least positive integer that is a &lt;em&gt;linear combination&lt;/em&gt; of $a$ and $b$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;d = sa + tb&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;First, let&amp;rsquo;s show that $d \given a$. By the division algorithm, we know that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a = dq + r, \quad \text{where $0 \le r \lt d$}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;It follows that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;r &amp;= a - dq \\&#xA;&amp;= a - (sa + tb)q \\&#xA;&amp;= a - saq - tbq \\&#xA;&amp;= (1 - sq)a + (-tq)b \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can see that $r$ is a linear combination of $a$ and $b$. Since $0 \le r \lt d$ and considering that we defined $d$ as the &lt;em&gt;least positive&lt;/em&gt; linear combination of $a$ and $b$, it follows that $r = 0$ (if $0 \lt r \lt d$ then $r$ would be the least possible linear combination, which is a contradiction); therefore, $d \given a$.&lt;/p&gt;&#xA;&lt;p&gt;In a similar fashion, $d \given b$; therefore, by the divisibility property #4&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;d \given sa + tb&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The next thing to prove is that $d$ is the &lt;em&gt;greatest common divisor&lt;/em&gt; of $a$ and&#xA;$b$. To prove this lets show that if $d&amp;rsquo;$ is any other common divisor of $a$ and&#xA;$b$ then $d&amp;rsquo; \le d$.&lt;/p&gt;&#xA;&lt;p&gt;If $d&amp;rsquo; \given a$ and $d&amp;rsquo; \given b$ then by the divisibility property #4 it divides any other &lt;em&gt;linear combination&lt;/em&gt; of $a$ and $b$, since $d = sa + bt$ is one linear combination of $a$ and $b$ it follows that $d&amp;rsquo; \given d$ so either $d&amp;rsquo; \lt d$ or $d&amp;rsquo; = d$, finally we can conclude that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;d = (a,b)&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;euclidean-algorithm&#34;&gt;Euclidean Algorithm&lt;/h3&gt;&#xA;&lt;p&gt;A very efficient method to compute the &lt;em&gt;greatest common denominator&lt;/em&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Suppose $a, b$ be integers with $a \ge b \gt 0$&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Apply the division algorithm $a = bq + r, 0 \le r \lt b$&lt;/li&gt;&#xA;&lt;li&gt;Rename $b$ as $a$ and $r$ as $b$ and repeat 1 until $r = 0$&#xA;The last nonzero remainder is the &lt;em&gt;greatest common divisor&lt;/em&gt; of $a$ and $b$&lt;/li&gt;&#xA;&lt;/ol&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The euclidean algorithm depends on the following lemma&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Let $a, b$ be integers with $a \ge b \gt 0$. Let $r$ be the remainder of dividing $a$ by $b$ then&#xA;$$&#xA;(a,b) = (b, r)&#xA;$$&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;Proof.&lt;/em&gt; Let $q$ be the quotient of dividing $a$ by $b$ so that $a = bq + r$. If $d = (a,b)$ then it must divide any other &lt;em&gt;linear combination&lt;/em&gt; of $a$ and $b$ like $r = a - bq$, therefore $d \given r$. Finally we can conclude that $d = (b,r)$.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Proof of the theorem&lt;/em&gt; If we keep on repeating the division algorithm we have:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;a &amp;= bq_1 + r_1,  \quad (a,b) = (b, r_1) \\&#xA;b &amp;= r_1q_2 + r_2,  \quad (b, r_1) = (r_1, r_2) \\&#xA;r_1 &amp;= r_2q_3 + r_3,  \quad (r_1, r_2) = (r_2, r_3) \\&#xA;r_2 &amp;= r_3q_4 + r_4,  \quad (r_2, r_3) = (r_3, r_4) \\&#xA;&amp; \; \vdots \\&#xA;r_{n-3} &amp;= r_{n-2}q_{n-1} + r_{n-1}, \quad (r_{n-3}, r_{n-2}) = (r_{n-2}, r_{n-1}) \\&#xA;r_{n-2} &amp;= r_{n-1}q_n + r_n, \quad (r_{n-2}, r_{n-1}) = (r_{n-1}, r_n) \\&#xA;r_{n-1} &amp;= r_n q_{n+1}, \quad \quad (r_{n-1}, r_n) = r_n&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(a,b) = (b,r_1) = (r_1,r_2) = (r_2, r_3) = (r_3, r_4) = \ldots = (r_{n-3}, r_{n-2}) = (r_{n-2}, r_{n-1}) = (r_{n-1}, r_n) = r_n&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;extended-euclidean-algorithm&#34;&gt;Extended Euclidean Algorithm&lt;/h3&gt;&#xA;&lt;p&gt;One of the applications of the &lt;em&gt;euclidean algorithm&lt;/em&gt; is the calculation of the integers $x,y$ satisfying $d = (a,b) = ax + by$&lt;/p&gt;&#xA;&lt;p&gt;First note that if $b=0$ then $(a,b) = (a,0) = a$, now assume that there are integers $x&amp;rsquo;$ and $y&amp;rsquo;$ so that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(a,b) = (b,r) = bx&#39; + ry&#39;&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;r &amp;= a - bq \\&#xA;&amp;= a - b \left \lfloor \frac{a}{b} \right \rfloor&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;(a,b) &amp;= bx&#39; + \Big( a - \left \lfloor \frac{a}{b} \right \rfloor b \Big) y&#39; \\&#xA;&amp;= bx&#39; + ay&#39; - \left \lfloor \frac{a}{b} \right \rfloor by&#39; \\&#xA;&amp;= a(y&#39;) + b \Big(x&#39; - \left \lfloor \frac{a}{b} \right \rfloor y&#39;\Big)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Comparing it to $(a,b) = ax + by$ we obtain the required coefficients $x$ and $y$ based on the following recursive equations&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x &amp;=&#xA;\begin{cases}&#xA;1, &amp; \text{when $r = 0$} \\&#xA;y&#39;, &amp; \text{otherwise}&#xA;\end{cases} \\&#xA;y &amp;=&#xA;\begin{cases}&#xA;0, &amp; \text{when $r = 0$} \\&#xA;x&#39; - \left \lfloor \frac{a}{b} \right \rfloor y&#39;, &amp; \text{otherwise}&#xA;\end{cases}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;&#34;&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&lt;/div&gt;&#xA;    &lt;iframe&#xA;        class=&#34;lazy-load&#34;&#xA;        title=&#34;repl demo&#34;&#xA;        frameborder=&#34;0&#34;&#xA;        width=&#34;100%&#34;&#xA;        height=&#34;700px&#34;&#xA;        data-src=&#34;https://repl.it/I0vB?lite=true&#34;&gt;&#xA;    &lt;/iframe&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Flat Shading</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/surface-shading/flat-shading/</link>
      <pubDate>Thu, 09 Jun 2016 12:39:53 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/surface-shading/flat-shading/</guid>
      <description>&lt;p&gt;Flat shading is the simplest shading model, which calculates the illumination at a single point for each polygon (or polygon vertices in OpenGL). This means that &lt;strong&gt;the color is the same for all points of each polygon&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Fast: a single computation per polygon (or one per polygon vertex in OpenGL).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Inaccurate.&lt;/li&gt;&#xA;&lt;li&gt;Discontinuities at polygon boundaries.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;&#xA;&lt;p&gt;GLSL has the keyword &lt;code&gt;flat&lt;/code&gt; to skip interpolation.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-glsl&#34;&gt;// vertex shader&#xA;flat out vec4 polygon_color;&#xA;void main() {&#xA;  // ...&#xA;  polygon_color = vec4(ambient + diffuse + specular, 1.0);&#xA;}&#xA;&#xA;// fragment shader&#xA;flat in vec4 polygon_color;&#xA;out vec4 color;&#xA;void main () {&#xA;  color = polygon_color;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</description>
    </item>
    <item>
      <title>Diffuse Shading</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/surface-shading/diffuse-shading/</link>
      <pubDate>Fri, 03 Jun 2016 14:49:37 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/surface-shading/diffuse-shading/</guid>
      <description>&lt;p&gt;Many objects, for example, wood and paper, will have a surface that is not shiny. Such objects can be modeled using the Lambertian Model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;lambertian-shading-model&#34;&gt;Lambertian Shading Model&lt;/h2&gt;&#xA;&lt;p&gt;A Lambertian object obeys Lambert&amp;rsquo;s cosine law, which states that:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The luminous intensity of a surface is proportional to the cosine of the angle between the surface normal and the direction of the light.&lt;/p&gt;&#xA;&lt;p&gt;$$&#xA;c \propto \cos{\theta}  \quad \text{or} \quad c \propto \mathbf{n} \cdot \mathbf{l}&#xA;$$&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;figure-images&#34;&gt;&#xA;    &lt;img class=&#34;lazy-load&#34; data-src=&#34;https://www.mauriciopoppe.com/images/diffuse-shading!lambertian.jpg&#34; alt=&#34;&#34;&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;Both $\mathbf{n}$ and $\mathbf{l}$ are unit vectors.&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Note that the model does not depend on the distance between the light and the object. This assumption is equivalent to saying that the light is &lt;strong&gt;&amp;ldquo;distant&amp;rdquo; relative to the object size&lt;/strong&gt;, which is often a directional light.&lt;/p&gt;&#xA;&lt;p&gt;When the light hits the surface, a portion of the light gets reflected. This is controlled by the diffuse reflectance $c_r$, a color that varies depending on the surface. Also, the surface color can be made darker/lighter by changing the color of the light source $c_l$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c = c_r \; c_l \; \mathbf{n} \cdot \mathbf{l}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$c_r$ and $c_l$ are RGB colors with components in the range $[0, 1]$, where the multiplication is done element-wise, so $c_r; c_l$ returns another RGB color. Note, however, that the product $\mathbf{n} \cdot \mathbf{l}$ might create negative values (e.g., when the surface normal is pointing away from the light). To solve this, we can use the max function:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c = c_r \; c_l \; \text{max}(\mathbf{n} \cdot \mathbf{l}, 0)&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;ambient-shading&#34;&gt;Ambient Shading&lt;/h2&gt;&#xA;&lt;p&gt;Some surfaces that receive no direct illumination in real life are perceived as having a color distinct from black. This is because the light is actually reflected by other surfaces. In addition, there&amp;rsquo;s sometimes skylight, which increases the amount of light reflected.&lt;/p&gt;&#xA;&lt;p&gt;A common trick is to put a dim light at the position of the eye so that all visible points receive some light. Another approach is to add an &lt;em&gt;ambient&lt;/em&gt; color $c_a$, which is simply a constant value that interacts with the diffuse reflectance $c_r$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c = c_r * c_a&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Introduction to Surface Shading</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/surface-shading/introduction/</link>
      <pubDate>Fri, 03 Jun 2016 13:46:07 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/surface-shading/introduction/</guid>
      <description>&lt;p&gt;Shading is the process of altering the color of a surface. Different &lt;em&gt;shading models&lt;/em&gt; capture the process of light reflection on a surface. These models use the following variables in the computation:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{ray}$ (ray) - a ray emitted from a pixel, defined with an origin ($\mathbf{ray_{origin}}$) and a direction ($\mathbf{ray_{direction}}$).&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{p}$ (intersection point) - the intersection point of the surface and $\mathbf{ray}$.&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{l}$ (light direction) - a unit vector pointing from the surface towards a light source, computed by normalizing the vector between the intersection point $\mathbf{p}$ and the light source position $\mathbf{l_s}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{l} = \frac{\mathbf{l_s - p}}{\norm{\mathbf{l_s - p}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{v}$ (view direction) - a unit vector pointing from the surface towards the place the ray is emitted from. It&amp;rsquo;s computed by normalizing the vector between the intersection point $\mathbf{p}$ and the ray origin $\mathbf{ray_{origin}}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = \frac{\mathbf{ray_{origin} - p}}{\norm{\mathbf{ray_{origin} - p}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{n}$ (surface normal) - a unit vector perpendicular to the surface at the point where the reflection is taking place.&lt;/li&gt;&#xA;&lt;li&gt;Other characteristics of the light source and the surface, depending on the shading model.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Building a First-Person Shot Camera in C&#43;&#43;</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/camera/first-person-shot/</link>
      <pubDate>Fri, 29 Apr 2016 22:10:40 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/camera/first-person-shot/</guid>
      <description>&lt;p&gt;A first-person camera captures objects from the viewpoint of a player&amp;rsquo;s character. The camera has the following characteristics:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Orbit&lt;/strong&gt;: The character can look left, right, up, and down; however, if we imagine the character&amp;rsquo;s head, it can&amp;rsquo;t be tilted.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Translation&lt;/strong&gt;: The character can move in four directions: forward, backward, left, and right. Note that the vector that represents the direction the character is looking at doesn&amp;rsquo;t change (the orbit is not affected by translation).&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Our camera will always move in the same direction the camera is looking. This is usually done differently in first-person shooters, where the character may move in a different direction than the camera is looking.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Both characteristics can be implemented by creating a space for the camera and defining the direction in this space. That way, translation doesn&amp;rsquo;t modify the direction the camera is looking at, and for orbit, we would rotate the basis vectors of the space.&lt;/p&gt;&#xA;&lt;p&gt;Assuming that the world space axes are as follows:&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;figure-images&#34;&gt;&#xA;    &lt;img class=&#34;lazy-load&#34; data-src=&#34;https://www.mauriciopoppe.com/images/xyz.jpg&#34; alt=&#34;&#34; /&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;Chosen world space: \(+\mathbf{x}\) (right), \(+\mathbf{y}\) (up), and \(+\mathbf{z}\) (backward). Note that the choice is just personal preference.&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Let $\mathbf{M}_{upright \leftarrow camera}$ be the rotation matrix that transforms points from &lt;em&gt;camera space&lt;/em&gt; to &lt;em&gt;upright space&lt;/em&gt;. Also, let the &amp;ldquo;look at&amp;rdquo; vector be defined as $\mathbf{p}_{camera} = \begin{bmatrix} 0 &amp;amp; 0 &amp;amp; -1 \end{bmatrix}^T$ in &lt;em&gt;camera space&lt;/em&gt;. To define the rotation matrix $\mathbf{M}_{upright \leftarrow camera}$, let&amp;rsquo;s first identify the Euler angles involved in the rotation. Taking the image above as a reference, we can identify the following actions:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The character looks left or right - rotation relative to the &lt;em&gt;upright space&lt;/em&gt; $y$-axis.&lt;/li&gt;&#xA;&lt;li&gt;The character looks up or down - rotation relative to the &lt;em&gt;upright space&lt;/em&gt; $x$-axis.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Note that the sequence of &#xA;&#xA;&lt;a href=&#34;../../../transformation-matrices/rotation/euler-angles#intrinsic-rotations&#34;target=&#34;_blank&#34;&gt;intrinsic rotations&lt;/a&gt;&#xA;&#xA; ($y-x&amp;rsquo;$ or $x-y$ if expressed as a sequence of &lt;em&gt;extrinsic rotations&lt;/em&gt;) represents the rotation of the camera. The sequence of extrinsic rotations can be represented as a multiplication of the following rotation matrices:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{M}_{upright \leftarrow camera} &amp;= \mathbf{Y}(\alpha) \mathbf{X}(\beta) \\&#xA;&amp;= \begin{bmatrix}&#xA;\cos{\alpha} &amp; 0 &amp; \sin{\alpha} \\&#xA;0 &amp; 1 &amp; 0 \\&#xA;-\sin{\alpha} &amp; 0 &amp; \cos{\alpha}&#xA;\end{bmatrix} \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 \\&#xA;0 &amp; \cos{\beta} &amp; -\sin{\beta} \\&#xA;0 &amp; \sin{\beta} &amp; \cos{\beta}&#xA;\end{bmatrix}&#xA;\\&#xA;&amp;= \begin{bmatrix}&#xA;\cos{\alpha} &amp; \sin{\alpha}\sin{\beta} &amp; \sin{\alpha}\cos{\beta} \\&#xA;0 &amp; \cos{\beta} &amp; -\sin{\beta} \\&#xA;-\sin{\alpha} &amp; \cos{\alpha}\sin{\beta} &amp; \cos{\alpha}\cos{\beta}&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The angles $\alpha$ and $\beta$ are computed as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Let $\Delta{\alpha}$ and $\Delta{\beta}$ represent the change in the rotation around the $\mathbf{Y}$ and $\mathbf{X}$ axes, respectively. The values of $\alpha$ and $\beta$ are computed based on the previous state:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\beta &amp;:= \beta + \Delta{\beta} \\&#xA;\alpha &amp;:= \alpha + \Delta{\alpha}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If the character looks up, then $\Delta{\beta}$ is positive.&lt;/li&gt;&#xA;&lt;li&gt;If the character looks to the right, then $\Delta{\alpha}$ is negative.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;mouse-coordinates-delta-to-extrinsic-rotations-delta&#34;&gt;Mouse Coordinates Delta to Extrinsic Rotations Delta&lt;/h2&gt;&#xA;&lt;p&gt;Next, we need to define what happens when we move the mouse. We can configure a window manager like &#xA;&#xA;&lt;a href=&#34;http://www.glfw.org/&#34;target=&#34;_blank&#34;&gt;GLFW&lt;/a&gt;&#xA;&#xA; to call a callback method whenever we move the mouse with the coordinates of the mouse as an argument (e.g., as $x_{new}$ and $y_{new}$). &lt;strong&gt;Note: The coordinates of the mouse are expressed relative to the top-left corner of the window, whose $+x$-axis points right and $+y$-axis points down.&lt;/strong&gt; If we keep the old coordinates of the mouse (as $x_{old}$ and $y_{old}$), we can obtain how much the mouse moved with respect to the old position with the following calculation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\Delta x &amp;= x_{new} - x_{old} \\&#xA;\Delta y &amp;= -(y_{new} - y_{old})&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that $y_{new} - y_{old}$ will be positive if we move the mouse down, which is unintuitive. Therefore, we can multiply this result by $-1$ so that moving the mouse downward sets a negative value in $\Delta y$.&lt;/p&gt;&#xA;&lt;p&gt;The next step is to update the values of $\alpha$ (yaw) and $\beta$ (pitch) using $\Delta x$ and $\Delta y$. Note that when we move the mouse to the right, we&amp;rsquo;re moving clockwise with respect to the $+y$-axis, and when we move the mouse upward, we&amp;rsquo;re moving counterclockwise with respect to the $+x$-axis. Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\alpha &amp;:= \alpha - \Delta x \\&#xA;\beta &amp;:= \beta + \Delta y&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that we also need the value of $\beta$ to be inside the range $-\deg{90} \leq \beta \leq \deg{90}$ to avoid looking backward.&lt;/p&gt;&#xA;&lt;p&gt;Finally, to compute the value of $\mathbf{p}_{world}$, we need to transform $\mathbf{p}_{object}$ with $\mathbf{M}_{world \leftarrow object}$. Note that the value of $\mathbf{p}_{object} = \begin{bmatrix} 0 &amp;amp; 0 &amp;amp; -1 \end{bmatrix}^T$ is always the same. Therefore, the value of $\mathbf{p}_{world}$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{p}_{world} &amp;= \mathbf{M}_{world \leftarrow object} \mathbf{p}_{object} \\&#xA;&amp;= \begin{bmatrix}&#xA;\cos{\alpha} &amp; \sin{\alpha}\sin{\beta} &amp; \sin{\alpha}\cos{\beta} \\&#xA;0 &amp; \cos{\beta} &amp; -\sin{\beta} \\&#xA;-\sin{\alpha} &amp; \cos{\alpha}\sin{\beta} &amp; \cos{\alpha}\cos{\beta}&#xA;\end{bmatrix} \begin{bmatrix} 0 \\ 0 \\ -1 \end{bmatrix} \\&#xA;&amp;= \begin{bmatrix}&#xA;-\sin{\alpha}\cos{\beta} \\&#xA;\sin{\beta} \\&#xA;-\cos{\alpha}\cos{\beta}&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;#pragma once&#xA;&#xA;class FPS_Mouse {&#xA;public:&#xA;  float sensitivity;&#xA;  float yaw&#xA;  float pitch;&#xA;  glm::vec4 target;&#xA;&#xA;  static const glm::vec3 YAW_AXIS = glm::vec3(0.0f, 1.0f, 0.0f);&#xA;  static const glm::vec3 PITCH_AXIS = glm::vec3(1.0f, 0.0f, 0.0f);&#xA;&#xA;  FPS_Mouse(float yaw, float pitch);&#xA;  void process_mouse_movement(double delta_x, double delta_y, bool constraint_pitch);&#xA;  glm::mat4 get_view_matrix() const;&#xA;&#xA;private:&#xA;  static const glm::vec4 P = glm::vec3(0.0f, 0.0f, -1.0f, 1.0f);&#xA;  void update_target();&#xA;}&#xA;&#xA;FPS_Mouse::FPS_Mouse(float yaw = 0, float pitch = 0) :&#xA;    sensitivity(0.05f) {&#xA;  this-&amp;gt;yaw = yaw;&#xA;  this-&amp;gt;pitch = pitch;&#xA;  this-&amp;gt;update_target();&#xA;}&#xA;&#xA;void FPS_Mouse::process_mouse_movement(double delta_x, double delta_y, bool constraint_pitch = true) {&#xA;  yaw -= delta_x * sensitivity;&#xA;  pitch &amp;#43;= delta_y * sensitivity;&#xA;&#xA;  if (constraint_pitch) {&#xA;    if (pitch &amp;gt; 89.0f) { pitch = 89.0f; }&#xA;    if (pitch &amp;lt; -89.0f) { pitch = -89.0f; }&#xA;  } &#xA;  this-&amp;gt;update_target();&#xA;}&#xA;&#xA;void FPS_Mouse::update_target() {&#xA;  /* Y = glm::rotate(glm::mat4(1.0f), glm::radians(yaw), FPS::YAW_AXIS); */&#xA;  /* X = glm::rotate(glm::mat4(1.0f), glm::radians(pitch), FPS::PITCH_AXIS); */&#xA;  /* target = Y * X * p; */&#xA;  float yaw_radians = glm::radians(yaw);&#xA;  float pitch_radians = glm::radians(pitch);&#xA;  target.x = -sin(yaw_radians) * cos(pitch_radians);&#xA;  target.y = sin(pitch_radians);&#xA;  target.z = -cos(yaw_radians) * cos(pitch_radians);&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Quaternions</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/rotation/quaternions/</link>
      <pubDate>Tue, 26 Apr 2016 16:39:27 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/rotation/quaternions/</guid>
      <description>&lt;h2 id=&#34;quaternions-as-rotations&#34;&gt;Quaternions as Rotations&lt;/h2&gt;&#xA;&lt;p&gt;Let $p$ be a 3D point represented as a quaternion using its homogeneous coordinates, $p = [w, \mathbf{v}]$, and let $q$ be any non-zero quaternion. Then:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Theorem: The product $qpq^{-1}$ takes $p = [w, \mathbf{v}]$ to $p&amp;rsquo; = [w, \mathbf{v&amp;rsquo;}]$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Before proving this theorem, let&amp;rsquo;s make the following observation. We can express $q$ as a multiplication of a scalar quaternion $s$ and a unit quaternion $\mathbf{U}q$, so $q = s\mathbf{U}q$. Then $qpq^{-1}=s\mathbf{U}qp(s\mathbf{U}q)^{-1}=s\mathbf{U}qp\mathbf{U}q^{-1}s^{-1}$. Because the scalar multiplication is commutative, $\mathbf{U}qp\mathbf{U}q^{-1}ss^{-1}=\mathbf{U}qp\mathbf{U}q^{-1}$, so the product doesn&amp;rsquo;t change irrespective of whether $q$ is a unit quaternion or not. Finally, notice that $\mathbf{U}q^{-1} = \mathbf{U}q^*$, so we can write the action as $qpq^*$. &lt;strong&gt;Note that from now on, $q$ is assumed to be a unit quaternion without loss of generality.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Next, let&amp;rsquo;s prove that the scalar part of $qpq^{*}$ is the same as the scalar of $p$ (we can use the formula to find the scalar component of a quaternion):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;2S(qpq^*) &amp;= qpq^* + (qpq^*)^* \\&#xA;&amp;= qpq^* + qp^*q^* \\&#xA;&amp;= q(p + p^*)q^* \\&#xA;&amp;= q2S(p)q^* \\&#xA;&amp;= 2qS(p)q^* \\&#xA;&amp;= 2[s_q, \mathbf{v_q}][s_p, \mathbf{0}][s_q, -\mathbf{v_q}] \\&#xA;&amp;= 2[s_ps_q, s_p\mathbf{v_q}][s_q, -\mathbf{v_q}] \\&#xA;&amp;= 2[s_ps_q^2 - s_p (\mathbf{v_q} \cdot -\mathbf{v_q}), -s_ps_q\mathbf{v_q} + s_ps_q\mathbf{v_q} + s_p\mathbf{v_q \times v_q}] \\&#xA;&amp;= 2[s_ps_q^2 + s_p\norm{v}^2, \mathbf{0}] \\&#xA;&amp;= 2[s_ps_q^2 + s_p(1 - s_q^2), \mathbf{0}] \text{because of the definition of a unit quaternion} \\&#xA;&amp;= 2[s_p, \mathbf{0}] \\&#xA;&amp;= 2S(p)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore, the scalar part of $p$ remains constant in the operation, i.e., if $p = [w, \mathbf{v}]$, then $p&amp;rsquo; = qpq^{*} = [w, \mathbf{v&amp;rsquo;}]$. And because multiplication preserves norms, then $\norm{p} = \norm{p&amp;rsquo;}$ and also $\norm{v} = \norm{v&amp;rsquo;}$. $\blacksquare$&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Theorem: If $\norm{q} = 1$, then $q = [\cos{\theta}, \unit{v} \sin{\theta}]$ acts to rotate around the unit axis $\unit{v}$ by $2 \theta$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Let:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v_0 = [0, \mathbf{v_0}] \quad \norm{v_0} = \norm{\mathbf{v_0}} = 1 \\&#xA;v_1 = [0, \mathbf{v_1}] \quad \norm{v_1} = \norm{\mathbf{v_1}} = 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Be two pure quaternions (which can be represented in 3D space), and an arbitrary quaternion $q$ which has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;q &amp;= v_1v_0^* \label{q} \\&#xA;&amp;= [0, \mathbf{v_1}][0, -\mathbf{v_0}] \nonumber \\&#xA;&amp;= [\mathbf{v_0 \cdot v_1}, \mathbf{v_0 \times v_1}] \label{q3d}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let $\theta$ be the angle between $\mathbf{v_0}$ and $\mathbf{v_1}$. Then $\mathbf{v_0 \cdot v_1} = \cos{\theta}$. Also, let $\mathbf{v_0 \times v_1} = \sin{\theta} \unit{v}$. Then \eqref{q} becomes:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{q2}&#xA;q = [\cos{\theta}, \sin{\theta} \unit{v}]&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s first prove that the product $v_2 = qv_0q^{*}$ lies in the same plane as $\mathbf{v_0}$ and $\mathbf{v_1}$. We do so by first proving that the product $v_2v_1^*$ has the same components (dot and cross products) as $v_1v_0^*$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;v_2v_1^* &amp;= (qv_0q^*) v_1^* \\&#xA;&amp;= (q v_0 (v_1v_0^*)^*) v_1^* \\&#xA;&amp;= (q v_0 v_0 v_1^*) v_1^* \\&#xA;&amp;= q (v_0v_0)(v_1^*v_1^*) \\&#xA;&amp;= q (-1)(-1) \quad \text{since they&#39;re unit quaternions they square to $-1$} \\&#xA;&amp;= v_1v_0^*&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;img class=&#34;lazy-load&#34; data-src=&#34;https://i.imgur.com/wVzPl0R.png&#34; alt=&#34;&#34; style=&#34;display: block; margin: 0 auto; width: 300px&#34;&gt;&#xA;&lt;p&gt;Then, if $v_2 v_1^* = v_1v_0^*$, that means that $v_2=qv_0q^*$ lies in the same plane as $v_0$ and $v_1$. Also, $v_2$ forms an angle of $\theta$ with $v_1$. Furthermore, $\mathbf{v_1} \times \mathbf{v_2} = \unit{v} \sin{\theta}$. Finally, if the angle between $v_0$ and $v_1$ is $\theta$, then the angle between $v_0$ and $v_2$ is $2\theta$, which confirms what&amp;rsquo;s seen on the image above.&lt;/p&gt;&#xA;&lt;p&gt;Furthermore, the same can be said of $q$ acting on $v_1$. Let $v_3 = qv_1q^{*}$. Then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;v_3v_2^* &amp;= (qv_1q^*)(qv_0q^*)^* \\&#xA;&amp;= (q(qv_0)q^*)(qv_0q^*)^* \quad \text{by finding $v_1$ from \eqref{q}} \\&#xA;&amp;= q (qv_0q^*)(qv_0q^*)^* \\&#xA;&amp;= q \\&#xA;&amp;= v_1v_0^*&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now, any vector $p$ can be represented in terms of the basis $v_0$, $v_1$, and $\unit{v}$, e.g., $p = s_1\mathbf{v_0} + s_1\mathbf{v_1} + s_2\unit{v}$. We&amp;rsquo;ve seen what $q$ does to $v_0$ and $v_1$, so let&amp;rsquo;s see what it does to $\unit{v}$.&lt;/p&gt;&#xA;&lt;p&gt;Before computing $q\unit{v}q^{*}$, see that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q\unit{v} &amp;= [\cos{\theta}, \sin{\theta} \unit{v}][0, \unit{v}] \\&#xA;&amp;= [\ldots, \ldots - \sin{\theta} (\unit{v} \times \unit{v})] \\&#xA;&amp;= [\ldots, \ldots - \mathbf{0}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;So $q\unit{v}$ is a commutative operation because the cross product is the only term that makes the quaternion operation non-commutable, and in $q\unit{v}$, that term is zero. Therefore, $q\unit{v}q^ * = \unit{v}qq^ * = \unit{v}$, which means that $q$ does not modify $\unit{v}$.&lt;/p&gt;&#xA;&lt;p&gt;Thus, the action of $q$ on any vector $p$ is a rotation around $\unit{v}$ by $2\theta$. $\blacksquare$&lt;/p&gt;&#xA;&lt;h2 id=&#34;quaternion-rotation-facts&#34;&gt;Quaternion Rotation Facts&lt;/h2&gt;&#xA;&lt;p&gt;Let $q_1$ be a quaternion that rotates the pure quaternion $p_1$ to $p_2$, and also let $q_2$ be a quaternion that rotates the vector $p_2$ to $p_3$. Then $p_3$ will have the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;p_3 &amp;= q_2p_2q_2^* \\&#xA;&amp;= q_2(q_1p_1q_1^*)q_2^* \\&#xA;&amp;= (q_2q_1)p_1(q_1^*q_2^*) \\&#xA;&amp;= (q_2q_1)p_1(q_2q_1)^*&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore, the combination of rotation $q_1$ followed by $q_2$ is given by $q = q_2q_1$.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;When the rotations $q_1, q_2, \ldots, q_n$ are applied to the pure quaternion $p$, the result is equal to $qpq^*$, where $q = q_n q_{n-1} \ldots q_2 q_1$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;</description>
    </item>
    <item>
      <title>gcc</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/operating-systems/bin/gcc/</link>
      <pubDate>Tue, 05 Apr 2016 17:56:08 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/operating-systems/bin/gcc/</guid>
      <description>&lt;h2 id=&#34;stages&#34;&gt;Stages&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;preprocessing&lt;/em&gt; - Text substitution, stripping comments, and file inclusion.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;g++ -E main.cpp -o main.i&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;compilation&lt;/em&gt; - Compilation of the processed source code into assembly language.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;g++ -S main.i -o main.s&#xA;# or&#xA;g++ -S main.cpp -o main.s&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;assembler&lt;/em&gt; - Conversion of assembly code into machine code.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;as main.s -o main.o&#xA;# or&#xA;g++ -c main.cpp -o main.o&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;linker&lt;/em&gt; - Produce a single executable program file. It combines our program with startup code, such as the following:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Standard code at the beginning of the program to set up the running environment to pass command-line parameters and environmental variables.&lt;/li&gt;&#xA;&lt;li&gt;Standard code at the end of the program to pass back a return code.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;g++ main.cpp -o main&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;flags&#34;&gt;Flags&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-E&lt;/code&gt; Run the preprocessing stage.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-S&lt;/code&gt; Run the preprocessing and compilation stages.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-c&lt;/code&gt; Run the preprocessing, compilation, and assemble stages.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-o file&lt;/code&gt; Write output to &lt;em&gt;file&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-llibrary&lt;/code&gt;, &lt;code&gt;-l library&lt;/code&gt; Search the library named &lt;em&gt;library&lt;/em&gt; when linking.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-Idir&lt;/code&gt; Add &lt;em&gt;dir&lt;/em&gt; to the list of directories to be searched for header files.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-Ldir&lt;/code&gt; Add &lt;em&gt;dir&lt;/em&gt; to the list of directories to be searched for &lt;code&gt;-l&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-Wall&lt;/code&gt; Enable all warnings about some constructions considered questionable by some users.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-O&lt;/code&gt; Enable optimization.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>make</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/operating-systems/bin/make/</link>
      <pubDate>Thu, 31 Mar 2016 19:34:48 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/operating-systems/bin/make/</guid>
      <description>&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;http://www.gnu.org/software/make/manual/make.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;make&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; is a tool to simplify building executables from many sources. &lt;code&gt;make&lt;/code&gt; will only re-build things that need to be re-built.&lt;/p&gt;&#xA;&lt;p&gt;Contents of a makefile:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Variable definitions&lt;/strong&gt;: text that can be substituted later.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Explicit rules&lt;/strong&gt;: says when and how to remake files called the rule&amp;rsquo;s &lt;em&gt;targets&lt;/em&gt;. It lists files that the target depends on, called &lt;em&gt;prerequisites&lt;/em&gt;, and may also give a &lt;em&gt;recipe&lt;/em&gt; to update the targets.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Implicit rules&lt;/strong&gt;: says when and how to remake files &lt;em&gt;based on the filename&lt;/em&gt;. It describes the dependencies of the target and gives a recipe to create/update such a target.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Directives&lt;/strong&gt;: special instructions like:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Reading from another makefile: &lt;code&gt;include a.Makefile b.Makefile&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Decide based on some variables to use or not part of the makefile.&lt;/li&gt;&#xA;&lt;li&gt;Defining multiline variables.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;rules&#34;&gt;Rules&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;targets : prerequisites&#xA;[tab] recipe&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;A rule tells &lt;code&gt;make&lt;/code&gt; two things: when &lt;code&gt;targets&lt;/code&gt; are out of date and how to update them when necessary.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;targets&lt;/code&gt; are filenames separated by spaces. Usually, there&amp;rsquo;s only one filename per rule.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;prerequisites&lt;/code&gt; determine when &lt;code&gt;targets&lt;/code&gt; are out of date. &lt;code&gt;targets&lt;/code&gt; are out of date if they don&amp;rsquo;t exist or are older than any of the &lt;code&gt;prerequisites&lt;/code&gt; (by comparison of the last-modification time).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;recipe&lt;/code&gt; determines how to update &lt;code&gt;targets&lt;/code&gt; when they&amp;rsquo;re out of date. This is one or more lines to be executed by the shell.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo.o : foo.c defs.h&#xA;  cc -c -g foo.c&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The target is &lt;code&gt;foo.o&lt;/code&gt;. The prerequisites are &lt;code&gt;foo.c&lt;/code&gt; and &lt;code&gt;defs.h&lt;/code&gt;. The command to update &lt;code&gt;foo.o&lt;/code&gt; is &lt;code&gt;cc -c -g foo.c&lt;/code&gt;. Additionally, it tells two things:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;How to decide whether &lt;code&gt;foo.o&lt;/code&gt; is out of date: it&amp;rsquo;s out of date if &lt;code&gt;foo.c&lt;/code&gt; or &lt;code&gt;defs.h&lt;/code&gt; is more recent than it.&lt;/li&gt;&#xA;&lt;li&gt;How to update &lt;code&gt;foo.o&lt;/code&gt;: it&amp;rsquo;s updated by compiling &lt;code&gt;foo.c&lt;/code&gt;, assuming that it includes &lt;code&gt;defs.h&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;wildcards&#34;&gt;Wildcards&lt;/h3&gt;&#xA;&lt;p&gt;A single file can specify multiple files using wildcard characters (the same as the ones in Bash, e.g., &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;clean:&#xA;  rm -f *.o     # `make clean` removes all the object files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To define a variable with a wildcard, use:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;objects := $(wildcard *.o)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;phony-targets&#34;&gt;Phony targets&lt;/h3&gt;&#xA;&lt;p&gt;A phony target is one that is not the name of a file; it&amp;rsquo;s just the name of a recipe to be executed when you make an explicit request. The two reasons to use a phony target are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To avoid conflict with a file of the same name.&lt;/li&gt;&#xA;&lt;li&gt;To improve performance by avoiding the implicit rule search on this type of targets.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;When a rule has a recipe that won&amp;rsquo;t create the target file, it will be executed every time the target comes up for remaking.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;clean:&#xA;  rm *.o program&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If &lt;code&gt;make clean&lt;/code&gt; is run, the target &lt;code&gt;clean&lt;/code&gt; will always be out of date (assuming such a file doesn&amp;rsquo;t exist), and then the recipe will always be executed.&lt;/p&gt;&#xA;&lt;p&gt;If there&amp;rsquo;s a file named &lt;code&gt;clean&lt;/code&gt;, the recipe will never be executed because, since the target &lt;code&gt;clean&lt;/code&gt; has no dependencies, it&amp;rsquo;s considered to be always up to date. To avoid this problem, we make the target a phony target. Once this is done, the recipe will be executed regardless of the existence of a file named &lt;code&gt;clean&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;.PHONY: clean&#xA;clean:&#xA;  rm *.o program&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;implicit-rules&#34;&gt;Implicit rules&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;make&lt;/code&gt; is able to figure out which implicit rule to use based on the kind of source file that needs to be made/updated. For example, the makefile:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo : foo.o bar.o&#xA;  cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Doesn&amp;rsquo;t have rules on how to make &lt;code&gt;foo.o&lt;/code&gt; or &lt;code&gt;bar.o&lt;/code&gt;. &lt;code&gt;make&lt;/code&gt; will automatically look for an implicit rule that tells how to make/update it from a catalog of built-in rules.&lt;/p&gt;&#xA;&lt;p&gt;Among the &#xA;&#xA;&lt;a href=&#34;http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules&#34;target=&#34;_blank&#34;&gt; catalog of built-in rules &lt;/a&gt;&#xA;&#xA; for POSIX-based OS, the ones for C and C++ programs are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Compiling C: &lt;code&gt;n.o&lt;/code&gt; is made from &lt;code&gt;n.c&lt;/code&gt; automatically with a recipe of the form:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;$(CC) $(CPPFLAGS) $(CFLAGS) -c&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Compiling C++: &lt;code&gt;n.o&lt;/code&gt; is made from &lt;code&gt;n.cc, n.cpp, n.C&lt;/code&gt; with a recipe of the form:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Linking C: &lt;code&gt;n&lt;/code&gt; is made from &lt;code&gt;n.o&lt;/code&gt; by running the linker &lt;code&gt;ld&lt;/code&gt; via the C compiler with a recipe of the form:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Variables used by implicit rules:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;CC&lt;/code&gt; (default &lt;code&gt;cc&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CXX&lt;/code&gt; (default &lt;code&gt;g++&lt;/code&gt;)&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CXXFLAGS, CPPFLAGS, CFLAGS&lt;/code&gt; (default empty)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;pattern-rules&#34;&gt;Pattern rules&lt;/h3&gt;&#xA;&lt;p&gt;A pattern rule contains &lt;code&gt;%&lt;/code&gt; exactly once in the target, which matches any non-empty substring called the &lt;em&gt;stem&lt;/em&gt;. Then, &lt;code&gt;%&lt;/code&gt; in the prerequisites of a rule stands for the same stem that was matched in the target. For example, a rule in the form:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;%.o: %.c&#xA;  rule&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The recipe then needs a way to operate on the correct source file name. Such a name cannot be written in the recipe because the name is different each time the implicit rule is used. To refer to the correct name, we use &#xA;&#xA;&lt;a href=&#34;http://www.gnu.org/software/make/manual/make.html#Automatic-Variables&#34;target=&#34;_blank&#34;&gt;&lt;strong&gt;automatic variables&lt;/strong&gt;&lt;/a&gt;&#xA;&#xA;, which are variables computed afresh for each rule that is executed. They only have values &lt;em&gt;within&lt;/em&gt; the recipe. The most used ones are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;$@&lt;/code&gt; - the filename of the target of the rule&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$&amp;lt;&lt;/code&gt; - the name of the first prerequisite&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$^&lt;/code&gt; - the name of all the prerequisites&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$?&lt;/code&gt; - the name of all the prerequisites that are newer than the target&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;$*&lt;/code&gt; - the stem&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For example:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;%.o: %.c&#xA;  $(CC) -c $(CFLAGS) $(CPPFLAGS) $&amp;lt; -o $@&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Specifies how to make an object file &lt;code&gt;n.o&lt;/code&gt; from a source file &lt;code&gt;n.c&lt;/code&gt;, provided that &lt;code&gt;n.c&lt;/code&gt; exists or can be made. Inside the recipe, the automatic variables &lt;code&gt;$@&lt;/code&gt; and &lt;code&gt;$&amp;lt;&lt;/code&gt; correspond to the target file and source file, respectively.&lt;/p&gt;&#xA;&lt;h2 id=&#34;variables&#34;&gt;Variables&lt;/h2&gt;&#xA;&lt;p&gt;To substitute a variable&amp;rsquo;s value, write &lt;code&gt;$(var)&lt;/code&gt; or &lt;code&gt;${var}&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;objects = program.o foo.o utils.o&#xA;program : $(objects)&#xA;  cc -o program $(objects)&#xA;&#xA;$(objects) : defs.h&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;setting-variables&#34;&gt;Setting variables&lt;/h3&gt;&#xA;&lt;p&gt;Variables defined with:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;=&lt;/code&gt;, &lt;code&gt;define&lt;/code&gt; &lt;em&gt;recursively expanded variable&lt;/em&gt; - If the value contains references to other variables, these references are expanded whenever this variable is substituted.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo = $(bar)&#xA;bar = $(message)&#xA;message = hello&#xA;&#xA;all:&#xA;  echo $(foo)   # prints hello&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;:=&lt;/code&gt; or &lt;code&gt;::=&lt;/code&gt; &lt;em&gt;simple expanded variable&lt;/em&gt; - The value of a variable is set as of the time it was defined.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;x := foo&#xA;y := $(x) bar&#xA;x := later&#xA;&#xA;# at this point&#xA;#   - x is equal to `later`&#xA;#   - y is equal to `foo bar`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;?=&lt;/code&gt; Sets the value of a variable if it&amp;rsquo;s not already set.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo = hello&#xA;foo ?= bar&#xA;# foo is equal to `hello`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;!=&lt;/code&gt; Executes a program and sets a variable to its output (alternatively, use &lt;code&gt;$(shell commands)&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo != printf `hi`&#xA;# foo is equal to `hi`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;advanced-features-for-reference-to-variables&#34;&gt;Advanced features for reference to variables&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Substitution reference &lt;code&gt;$(var:a=b)&lt;/code&gt;: substitutes every &lt;code&gt;a&lt;/code&gt; at the end of a word with &lt;code&gt;b&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo := a.o b.o c.o&#xA;bar := $(foo:.o=.c)&#xA;# bar is equal to `a.c b.c c.c`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Computed variable names &lt;code&gt;$($(a))&lt;/code&gt;: nested variable reference.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;x = y&#xA;y = z&#xA;a := $($(x))   # a is equal to `z`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;recipes&#34;&gt;Recipes&lt;/h2&gt;&#xA;&lt;p&gt;Each line must start with a tab. Any line in the makefile that begins with a tab and appears in a &amp;ldquo;rule context&amp;rdquo; will be considered part of the recipe for that rule. Blank lines that appear in the middle of rules are ignored.&lt;/p&gt;&#xA;&lt;p&gt;Each time a recipe is executed, &lt;code&gt;make&lt;/code&gt; will invoke a new sub-shell for each line of the recipe. This implies that setting shell variables will not affect the following lines in the recipe.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;foo: bar/lose&#xA;  cd $bar   # dir is ./bar/&#xA;  cat file  # dir is ./&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Normally, &lt;code&gt;make&lt;/code&gt; prints each line of the recipe in the shell before it&amp;rsquo;s executed. To avoid this behavior, prepend &lt;code&gt;@&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;program.o: program.c&#xA;  @cc -c -g program.c&#xA;  # won&#39;t print the compilation line on the terminal&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To ignore errors in a recipe line, prepend the command with &lt;code&gt;-&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;clean:&#xA;  -rm -f *.o&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;running-make&#34;&gt;Running &lt;code&gt;make&lt;/code&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The simplest use is to recompile every file that is out of date. However, it&amp;rsquo;s possible to update only some files or find out which files are out of date without changing them.&lt;/p&gt;&#xA;&lt;p&gt;The exit status of &lt;code&gt;make&lt;/code&gt; is always one of the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;0: &lt;code&gt;make&lt;/code&gt; is successful.&lt;/li&gt;&#xA;&lt;li&gt;1: If &lt;code&gt;-q&lt;/code&gt; is used and &lt;code&gt;make&lt;/code&gt; determines that some target is not already up to date.&lt;/li&gt;&#xA;&lt;li&gt;2: If &lt;code&gt;make&lt;/code&gt; encountered any errors.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;goals&#34;&gt;Goals&lt;/h3&gt;&#xA;&lt;p&gt;The goals are the targets that &lt;code&gt;make&lt;/code&gt; should strive to update (other targets are updated if they appear as prerequisites of goals, or prerequisites of prerequisites of goals, etc.).&lt;/p&gt;&#xA;&lt;p&gt;By default, the goal is the first target in the makefile (not counting targets that start with &lt;code&gt;.&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;p&gt;A different goal can be specified with arguments to &lt;code&gt;make&lt;/code&gt; by using their names. If many goals are specified, &lt;code&gt;make&lt;/code&gt; processes each of them in turn. Any target in the makefile may be specified as a goal unless it starts with &lt;code&gt;-&lt;/code&gt; or contains &lt;code&gt;=&lt;/code&gt; (parsed as a switch or variable definition, respectively).&lt;/p&gt;&#xA;&lt;p&gt;For example, given a project with multiple programs, we can compile only a part of the program by specifying as a goal each file that we wish to remake.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;.PHONY: all&#xA;all: a b c&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If we&amp;rsquo;re working on the program &lt;code&gt;a&lt;/code&gt;, we can execute &lt;code&gt;make a&lt;/code&gt; so that only files of that program are recompiled.&lt;/p&gt;&#xA;&lt;p&gt;Specifying a goal has the following advantages:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Make files that are normally not made, i.e., rules that are not prerequisites of the default goal, e.g., a file for debugging output.&lt;/li&gt;&#xA;&lt;li&gt;Run a recipe associated with a phony target.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;flags&#34;&gt;Flags&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;-f [filename]&lt;/code&gt; - Use &lt;code&gt;filename&lt;/code&gt; as the makefile (defaults to &lt;code&gt;GNUMakefile, makefile, Makefile&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-n&lt;/code&gt; - Prints all the recipes that are needed to update the targets without executing them.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-q&lt;/code&gt; - Check whether the targets are up to date. The exit code shows if updates are needed.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-t&lt;/code&gt; - Makes targets up to date without changing them (their modified times are updated).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;-k&lt;/code&gt; - Try to compile every file that can be tried instead of exiting on the first failure.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;overriding-variables&#34;&gt;Overriding variables&lt;/h3&gt;&#xA;&lt;p&gt;Given the following makefile:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;CFLAGS = -g&#xA;&#xA;all: program.o&#xA;&#xA;program.o: program.c&#xA;  cc -c $(CFLAGS) program.c&#xA;&#xA;.PHONY: all&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;We can override the value of the variable &lt;code&gt;CFLAGS&lt;/code&gt; when &lt;code&gt;make&lt;/code&gt; is executed like this: &lt;code&gt;make CFLAGS=&amp;quot;-g -O&amp;quot;&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;convention-for-makefiles&#34;&gt;Convention for makefiles&lt;/h2&gt;&#xA;&lt;p&gt;Every makefile should include:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-makefile&#34;&gt;# avoid trouble on systems where `SHELL` might be inherited from the environment&#xA;SHELL = /bin/sh&#xA;&#xA;# specify all the suffixes which may be subject to implicit rules in this makefile&#xA;.SUFFIXES:            # clears the suffix list&#xA;.SUFFIXES: .c .o&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Use &lt;code&gt;$(srcdir)/&lt;/code&gt; to refer to the location of the source files when the build directory is distinct from the source file directory.&lt;/li&gt;&#xA;&lt;li&gt;Use variables for specifying commands, e.g., &lt;code&gt;$(CXX)&lt;/code&gt; instead of &lt;code&gt;g++&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;File management utilities such as &lt;code&gt;ln&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt; don&amp;rsquo;t need to be referred through variables since users don&amp;rsquo;t need to replace them with other programs.&lt;/li&gt;&#xA;&lt;li&gt;Every makefile should define the variable &lt;code&gt;INSTALL&lt;/code&gt;, which is the basic command for installing a file into the system.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Standard targets:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;all&lt;/code&gt;: compiles the entire program; this should be the default target.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;install&lt;/code&gt;: compiles the program and copies the executables and libraries to the desired place.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;clean&lt;/code&gt;: deletes all the files that are created by building the program.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;&#xA;&lt;div&gt;&#xA;  &lt;script src=&#34;https://gist.github.com/mauriciopoppe/de8908f67923091982c8c8136a063ea6.js&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>CMake</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/operating-systems/bin/cmake/</link>
      <pubDate>Thu, 31 Mar 2016 19:31:37 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/operating-systems/bin/cmake/</guid>
      <description>&lt;p&gt;Executable:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;$ cmake [options] (&amp;lt;path-to-source&amp;gt; | &amp;lt;path-to-existing-build&amp;gt;)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Assuming that the directory contains:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;.&#xA;├── CMakeLists.txt&#xA;└── main.cpp&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#include &amp;lt;iostream&amp;gt;&#xA;using namespace std;&#xA;int main () {&#xA;  cout &amp;lt;&amp;lt; &amp;quot;Hello world&amp;quot; &amp;lt;&amp;lt; endl;&#xA;  return 0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The minimal &lt;code&gt;CMakeLists.txt&lt;/code&gt; file contains:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;cmake_minimum_required (VERSION 2.6)&#xA;project(Hello)&#xA;add_executable(${PROJECT_NAME} main.cpp)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Running &lt;code&gt;cmake .&lt;/code&gt; creates a &lt;code&gt;Makefile&lt;/code&gt; in the same directory whose recipes are cross-platform commands. CMake&amp;rsquo;s documentation suggests that the build is separated from the source.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;$ mkdir build&#xA;$ cd build&#xA;$ cmake ..&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Running the default target in the makefile creates the executable &lt;code&gt;Hello&lt;/code&gt;. Note that this is done in the &lt;code&gt;./build/&lt;/code&gt; directory.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;$ make&#xA;Scanning dependencies of target Hello&#xA;[ 50%] Building CXX object CMakeFiles/Hello.dir/main.cc.o&#xA;[100%] Linking CXX executable Hello&#xA;[100%] Built target Hello&#xA;$ ./Hello&#xA;Hello world&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cmake.org/cmake/help/latest/command/set.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;set(&amp;lt;variable&amp;gt; &amp;lt;value&amp;gt;)&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; sets a normal variable available to the current function or directory scope. Variables can be accessed with &lt;code&gt;${variable}&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cmake.org/cmake/help/latest/command/project.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;project(&amp;lt;PROJECT-NAME&amp;gt; [LANGUAGES] [&amp;lt;language-name&amp;gt;...])&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; sets the following variables:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;PROJECT_NAME&lt;/code&gt;: same as &lt;code&gt;&amp;lt;PROJECT-NAME&amp;gt;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;PROJECT_SOURCE_DIR&lt;/code&gt;: same as &lt;code&gt;/path/to/project/&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;PROJECT_BINARY_DIR&lt;/code&gt;: same as &lt;code&gt;/path/to/project/build/&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cmake.org/cmake/help/latest/command/add_executable.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;add_executable(&amp;lt;name&amp;gt; source1 [source2 ...])&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; adds an executable target called &lt;code&gt;name&lt;/code&gt; to be built from the source files listed.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Useful variables:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;CMAKE_SOURCE_DIR&lt;/code&gt;: path to the top level of the source tree (default value &lt;code&gt;./&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CMAKE_BINARY_DIR&lt;/code&gt;: path to the top level of the build tree (default value &lt;code&gt;./build/&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CMAKE_RUNTIME_OUTPUT_DIRECTORY&lt;/code&gt;: path to the executable (usually set to &lt;code&gt;${CMAKE_BINARY_DIR}/bin/&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CMAKE_ARCHIVE_OUTPUT_DIRECTORY&lt;/code&gt;: path to the static libraries (code from static libraries is included in the executable, usually set to &lt;code&gt;${CMAKE_BINARY_DIR}/lib/&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CMAKE_LIBRARY_OUTPUT_DIRECTORY&lt;/code&gt;: path to the shared libraries (additional code required by the executable, usually set to &lt;code&gt;${CMAKE_BINARY_DIR}/lib/&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;project-structure-and-organization&#34;&gt;Project structure and organization&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;. project&#xA;├── build&#xA;├── include&#xA;│   └── project&#xA;│       └── World.hpp&#xA;└── src&#xA;    ├── World.cpp&#xA;    └── main.cpp&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The &lt;code&gt;CMakeLists.txt&lt;/code&gt; file should do the following:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Add the &lt;code&gt;./include&lt;/code&gt; path to the compiler include search path.&lt;/li&gt;&#xA;&lt;li&gt;Create an executable file from &lt;code&gt;main.cpp&lt;/code&gt; into &lt;code&gt;./build/bin/&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Create a static/dynamic library (in the example, &lt;code&gt;World.cpp&lt;/code&gt;) into &lt;code&gt;./build/lib/&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Link the library with the executable.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cmake&#34;&gt;cmake_minimum_required(VERSION 3.0)&#xA;&#xA;project(runner)&#xA;&#xA;set(CMAKE_RUNTIME_OUTPUT_DIRECTORY &amp;quot;${CMAKE_BINARY_DIR}/bin&amp;quot;)&#xA;set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY &amp;quot;${CMAKE_BINARY_DIR}/lib&amp;quot;)&#xA;set(CMAKE_LIBRARY_OUTPUT_DIRECTORY &amp;quot;${CMAKE_BINARY_DIR}/lib&amp;quot;)&#xA;&#xA;# the -I flag in gcc&#xA;include_directories(&#xA;  ${PROJECT_SOURCE_DIR}/include/&#xA;)&#xA;&#xA;set(APP_SOURCES src/main.cpp)&#xA;set(LIB_SOURCES src/World.cpp)&#xA;&#xA;# creates ./build/bin/runner&#xA;add_executable(${PROJECT_NAME} ${APP_SOURCES})&#xA;&#xA;# shared library&#xA;set(LIBRARY_NAME World)&#xA;add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES})&#xA;target_link_libraries(${PROJECT_NAME} ${LIBRARY_NAME})&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cmake.org/cmake/help/latest/command/include_directories.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;include_directories(dir)&lt;/code&gt;&lt;/a&gt;&#xA;&#xA;: adds the given directories to those the compiler uses to search for include files (gcc &lt;code&gt;-I dir&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cmake.org/cmake/help/latest/command/add_library.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;add_library(library_name [STATIC | SHARED | MODULE] source1 [source2...])&lt;/code&gt;&lt;/a&gt;&#xA;&#xA;: adds a library called &lt;code&gt;library_name&lt;/code&gt; to be built from the source files listed.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;STATIC&lt;/code&gt;: archives of object files &lt;code&gt;.a&lt;/code&gt; (archive).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;SHARED&lt;/code&gt;: libraries dynamically linked at runtime &lt;code&gt;.so&lt;/code&gt; (shared object).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://cmake.org/cmake/help/latest/command/target_link_libraries.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;target_link_libraries(target item)&lt;/code&gt;&lt;/a&gt;&#xA;&#xA;: specifies libraries/flags to use when linking a given target.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div style=&#34;font-size: 25px; text-align:center&#34;&gt;&#xA;&lt;a href=&#34;https://github.com/maurizzzio/cmake-starter&#34;&gt;cmake demo&lt;/a&gt;&#xA;&lt;/div&gt;&#xA;&lt;h3 id=&#34;complex-cmake-configuration&#34;&gt;Complex CMake configuration&lt;/h3&gt;&#xA;&lt;p&gt;A complex CMake configuration will have multiple &lt;code&gt;CMakeLists.txt&lt;/code&gt; files per directory:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;./CMakeLists.txt&lt;/code&gt;: configures dependencies, platform specifics, and output paths.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;./src/CMakeLists.txt&lt;/code&gt;: configures the library to build.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>C&#43;&#43; refresher</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/programming-languages/cpp-refresher/</link>
      <pubDate>Sat, 26 Mar 2016 12:30:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/programming-languages/cpp-refresher/</guid>
      <description>&lt;h2 id=&#34;if-you-have-spare-time&#34;&gt;If you have spare time&lt;/h2&gt;&#xA;&lt;p&gt;Watch some CppCon &amp;lsquo;Back to Basics&amp;rsquo; videos:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=3KoXeegncrs&#34;target=&#34;_blank&#34;&gt;Back to Basics: The Structure of a Program - Bob Steagall - CppCon 2020&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=7Qgd9B1KuMQ&#34;target=&#34;_blank&#34;&gt;Back to Basics: RAII and the Rule of Zero - Arthur O&amp;rsquo;Dwyer - CppCon 2019&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=F6Ipn7gCOsY&#34;target=&#34;_blank&#34;&gt;Back to Basics: Concurrency - Arthur O&amp;rsquo;Dwyer - CppCon 2020&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;mechanics-of-a-c-program&#34;&gt;Mechanics of a C++ program&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Write source code&lt;/strong&gt;&#xA;1.1 Unix extensions: &lt;code&gt;C,cc,cxx,c&lt;/code&gt;&#xA;1.2 GNU C++ extensions: &lt;code&gt;C,cc,cxx,cpp,c++&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Compile the source code&lt;/strong&gt; - Translate the code to machine code. The file containing the translation is the &lt;em&gt;object code&lt;/em&gt; of the program.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Link the object code with additional code&lt;/strong&gt; - Combination of the source code with &lt;em&gt;startup code&lt;/em&gt; and &lt;em&gt;library object code&lt;/em&gt; to produce a &lt;em&gt;runtime version&lt;/em&gt;. The final product is a file called the &lt;em&gt;executable code&lt;/em&gt;, which contains a set of machine language instructions.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Execute the program&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Compilation and linking is done with:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;UNIX&lt;/em&gt; - &lt;code&gt;CC&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;GNU C++&lt;/em&gt; - &lt;code&gt;gcc,g++&lt;/code&gt; (&#xA;&#xA;&lt;a href=&#34;http://stackoverflow.com/a/173007/3341726&#34;target=&#34;_blank&#34;&gt;notes on the difference&lt;/a&gt;&#xA;&#xA;), &#xA;&#xA;&lt;a href=&#34;../../operating-systems/bin/gcc/&#34;target=&#34;_blank&#34;&gt;gcc small description&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;preprocessor&#34;&gt;Preprocessor&lt;/h3&gt;&#xA;&lt;p&gt;The &#xA;&#xA;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/cpp/index.html#Top&#34;target=&#34;_blank&#34;&gt;preprocessor&lt;/a&gt;&#xA;&#xA; processes a source file before compilation. It allows the definition of macros, which are abbreviations for longer constructs.&lt;/p&gt;&#xA;&lt;h4 id=&#34;directives&#34;&gt;Directives&lt;/h4&gt;&#xA;&lt;p&gt;Lines which begin with &lt;code&gt;#&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;#define IDENTIFIER [value]&lt;/code&gt; - Replaces the occurrences of &lt;code&gt;IDENTIFIER&lt;/code&gt; in the code with &lt;code&gt;value&lt;/code&gt;. Note that &lt;code&gt;value&lt;/code&gt; is optional.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;#undef IDENTIFIER&lt;/code&gt; - Removes the definition of &lt;code&gt;IDENTIFIER&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Conditional directives allow the inclusion or exclusion of parts of the code if a certain condition is met:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;#ifdef IDENTIFIER&lt;/code&gt; - If &lt;code&gt;IDENTIFIER&lt;/code&gt; is defined, then the code that follows is included until &lt;code&gt;#endif&lt;/code&gt; is reached.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;#ifndef IDENTIFIER&lt;/code&gt; - If &lt;code&gt;IDENTIFIER&lt;/code&gt; is not defined, then the code that follows is included until &lt;code&gt;#endif&lt;/code&gt; is reached.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Conditional directives are used, for example, to include headers only once:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#ifndef FOO_BAR_BAZ_H_&#xA;#define FOO_BAR_BAZ_H_&#xA;  // header code&#xA;#endif // FOO_BAR_BAZ_H_&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;File inclusion:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;#include &amp;lt;library&amp;gt;&lt;/code&gt; - The contents of the &lt;code&gt;library&lt;/code&gt; file are sent along with the source code. In essence, the contents of the &lt;code&gt;library&lt;/code&gt; &lt;strong&gt;replace&lt;/strong&gt; the &lt;code&gt;#include&lt;/code&gt; line. Note that the compiler tries to find &lt;code&gt;library&lt;/code&gt; in the host system&amp;rsquo;s file system that holds the standard header files.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;#include &amp;quot;library&amp;quot;&lt;/code&gt; - Same as above, but &lt;code&gt;library&lt;/code&gt; is looked for in the current working directory.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;#pragma&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; - Specify diverse options to the compiler that are specific to the platform/compiler.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;program-structure&#34;&gt;Program structure&lt;/h3&gt;&#xA;&lt;p&gt;Large programs can be split into multiple files, which can be compiled (if needed) and linked to generate an executable program. For example, a program can be split into three files:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A &lt;em&gt;header file&lt;/em&gt; that contains structure declarations and prototypes for functions that use those structures.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;em&gt;source code&lt;/em&gt; file that contains the code for the functions.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;em&gt;source code&lt;/em&gt; file that uses those functions.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The following things are commonly found in headers:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;function prototypes&lt;/li&gt;&#xA;&lt;li&gt;symbolic constants defined with &lt;code&gt;#define&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;structure, class, template declarations&lt;/li&gt;&#xA;&lt;li&gt;inline functions&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;trunk&#xA;├── bin     : for all executables (applications)&#xA;├── lib     : for all other binaries (static and shared libraries (.so or .dll))&#xA;├── include : for all project header files, 3rd party files not present in `/usr/local/include` should be here&#xA;├── src     : for source files&#xA;├── doc     : for documentation&#xA;├── build   : for all the object files, removed by `clean`&#xA;└── test    : for testing&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Example:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;. project&#xA;├── build&#xA;├── include&#xA;│   └── project&#xA;│       └── Vector.hpp&#xA;│   └── [third party library]&#xA;└── src&#xA;    ├── Vector.cpp&#xA;    └── main.cpp&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;strings&#34;&gt;Strings&lt;/h2&gt;&#xA;&lt;h3 id=&#34;c-style-strings&#34;&gt;C-style strings&lt;/h3&gt;&#xA;&lt;p&gt;The last character is the &lt;em&gt;null character&lt;/em&gt;, &lt;code&gt;\0&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;char name[20];              // initialized with random data&#xA;char name[5] = {&#39;j&#39;, &#39;h&#39;, &#39;o&#39;, &#39;n&#39;, &#39;\0&#39;};&#xA;char name[8] = {&#39;j&#39;, &#39;h&#39;, &#39;o&#39;, &#39;n&#39;, &#39;\0&#39;};    // right padded with \0&#xA;char name[5] = &amp;quot;john&amp;quot;;      // the \0 is understood&#xA;char name[8] = &amp;quot;john&amp;quot;;      // right padded with \0&#xA;char name[] = &amp;quot;john&amp;quot;;       // let the compiler count&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Operations:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#include &amp;lt;cstring&amp;gt;&#xA;char source[] = &amp;quot;john&amp;quot;;       // let the compiler count&#xA;char dest[10];&#xA;&#xA;// size of the string&#xA;strlen(source);   // 4&#xA;strlen(dest);     // 10, 10 random characters, the 11th is \0&#xA;&#xA;// copy `source` to `dest`&#xA;strcpy(dest, source);&#xA;&#xA;// concat `dest` with `source`&#xA;strcat(dest, source);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Reading input:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;char name[20];&#xA;cin &amp;gt;&amp;gt; name;            // read until space or newline&#xA;cin.getline(name, 20);  // read 20 characters or until newline&#xA;cin.get(name, 20);      // read 20 characters or until before newline&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;c-strings&#34;&gt;C++ strings&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#include &amp;lt;string&amp;gt;&#xA;&#xA;string str;           // &amp;quot;&amp;quot;&#xA;string name = &amp;quot;john&amp;quot;;&#xA;&#xA;cin &amp;gt;&amp;gt; name;          // reads until space or newline&#xA;cin.getline(name);   // reads until newline&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;pointers&#34;&gt;Pointers&lt;/h2&gt;&#xA;&lt;p&gt;Given a variable, the address operator &lt;code&gt;&amp;amp;&lt;/code&gt; is used to get its address or location in memory.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int oranges = 5;&#xA;int apples = 6;&#xA;&#xA;// location in memory e.g. 0x0065fd40&#xA;&amp;amp;oranges;&#xA;&#xA;// location in memory e.g. 0x0065fd44&#xA;&amp;amp;apples;&#xA;&#xA;// NOTE: the difference between them is 4 bytes, the size of int&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Pointers are variables that store the addresses of values rather than the values themselves. To declare a pointer, we use the form &lt;code&gt;typeName * pointerName&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int oranges = 5;&#xA;int* p_oranges;        // declare pointer to an int&#xA;p_oranges = &amp;amp;oranges;  // assign address to pointer&#xA;sizeof(p_oranges);     // 4 bytes&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The dereferencing operator, &lt;code&gt;*&lt;/code&gt;, yields the value at the location.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int oranges = 5;&#xA;int* p_oranges = &amp;amp;oranges;&#xA;*p_oranges;                   // 5&#xA;*p_oranges = *p_oranges + 1;  // update the value&#xA;oranges;                      // 6&#xA;*p_oranges;                   // 6&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Always initialize a pointer to a definite address before applying the dereferencing operator.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int* p_int;&#xA;*p_int = 3;     // value is lost forever&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;When a pointer is assigned to another pointer, the value stored is the address stored in the first pointer.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int oranges = 5;        // value: 5,     address: 0x000&#xA;int* p = &amp;amp;oranges;      // value: 0x000, address: 0x004&#xA;int* q = p;             // value: 0x000, address: 0x008&#xA;*q;                     // 5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If we want to create a pointer to a pointer, we use extra &amp;lsquo;&lt;em&gt;&amp;rsquo;. For the declaration, the number of &amp;lsquo;&lt;/em&gt;&amp;rsquo; must be equal to the length of pointers (including this one). In the same fashion, we must use the same number of &amp;lsquo;*&amp;rsquo; for dereferencing.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int oranges = 5;        // value: 5,     address: 0x000&#xA;int* p = &amp;amp;oranges;      // value: 0x000, address: 0x004&#xA;int** q = &amp;amp;p;           // value: 0x004, address: 0x008&#xA;*p;                     // 5&#xA;**q;                    // 5&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;pointer-and-arrays&#34;&gt;Pointer and arrays&lt;/h3&gt;&#xA;&lt;p&gt;C++ handles arrays internally using pointers, which may seem equivalent. An ordinary array variable name is interpreted as the &lt;strong&gt;address of the first element of the array&lt;/strong&gt;. The bracket notation, &lt;code&gt;[]&lt;/code&gt;, allows us to get/set elements of the array.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int numbers[] = {1, 2, 3};&#xA;numbers;      // address 0x0065fd40&#xA;numbers[0];   // 1, the value allocated in memory&#xA;// NOTE: numbers ~ &amp;amp;numbers[0]&#xA;&#xA;// since a pointer is a reference to an address we can also do&#xA;int* p_numbers = numbers;&#xA;*p_numbers;   // 1, the value in memory accessed through pointer dereferencing&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Adding one to a pointer variable increases its value by the number of bytes of the type to which it points.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int numbers[] = {1, 2, 3};&#xA;int* p_numbers = numbers;&#xA;p_numbers;      // points to the first element of the array&#xA;p_numbers + 1;  // points to the second element of the array&#xA;p_numbers + 2;  // points to the third element of the array&#xA;&#xA;// NOTE:&#xA;//  numbers[0] == *(p_numbers)&#xA;//  numbers[1] == *(p_numbers + 1)&#xA;//  numbers[2] == *(p_numbers + 2)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The value &lt;code&gt;&amp;amp;numbers&lt;/code&gt; is the address of a 3-int block of memory, so even though &lt;code&gt;&amp;amp;numbers[0] == numbers == &amp;amp;numbers&lt;/code&gt; numerically, the value of &lt;code&gt;&amp;amp;numbers + 1 != numbers + 1&lt;/code&gt; because &lt;code&gt;&amp;amp;numbers + 1&lt;/code&gt; points to the next 3-int block of memory; however, &lt;code&gt;numbers + 1&lt;/code&gt; points to the second element of the initial 3-int block of memory.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;numbers&lt;/code&gt; is type pointer-to-int or &lt;code&gt;int*&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;amp;numbers&lt;/code&gt; is type pointer-to-array-of-3-int or &lt;code&gt;(*int)[3]&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The relationship between pointers and arrays also extends to C-style strings. For C++, a quoted string constant, strings in an array, and strings described by pointers are all handled equivalently.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;char first[20] = &amp;quot;john&amp;quot;;&#xA;const char* last = &amp;quot;smith&amp;quot;;    // string literals are constant&#xA;cout &amp;lt;&amp;lt; &amp;quot;I am the agent&amp;quot; &amp;lt;&amp;lt; first &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; last&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Given a multidimensional array &lt;code&gt;int a[][2] = { { 1, 2 } }&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt; is a pointer to the first element, which is a 2-element array (which is a pointer to the first of its elements). Therefore, a pointer to &lt;code&gt;a&lt;/code&gt; has the form of a pointer-to-array-of-2-int.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int a[][2] = { { 1, 2 } };&#xA;int (*b)[2] = a;&#xA;(*b)[0];       // 1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;array-of-pointers&#34;&gt;Array of pointers&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int a = 1, b = 2;&#xA;int* p[2] = {&amp;amp;a, &amp;amp;b};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Since &lt;code&gt;p&lt;/code&gt; is a pointer to the first element, which is &lt;code&gt;&amp;amp;a&lt;/code&gt;, and &lt;code&gt;&amp;amp;a&lt;/code&gt; is another pointer, we can reference &lt;code&gt;p&lt;/code&gt; with a pointer to a pointer.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int** q = p;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;runtime-allocation-new&#34;&gt;Runtime allocation: new&lt;/h3&gt;&#xA;&lt;p&gt;Pointers are a sort of alias for accessed memory, which could be accessed by named variables (memory allocated at compile time). However, we can allocate memory at runtime with the &lt;code&gt;new&lt;/code&gt; operator. Runtime-allocated memory can be freed with the &lt;code&gt;delete&lt;/code&gt; operator.&lt;/p&gt;&#xA;&lt;p&gt;Advantages of runtime-allocated memory:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Memory is allocated only when needed.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Drawbacks of runtime-allocated memory:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Memory allocated by &lt;code&gt;new&lt;/code&gt; must be freed using the &lt;code&gt;delete&lt;/code&gt; operator; otherwise, we have a &lt;em&gt;memory leak&lt;/em&gt;, which is memory that is allocated but unused. If it grows too large, it can halt the execution of the program.&lt;/li&gt;&#xA;&lt;li&gt;An attempt to free a block of memory that has been previously freed results in undefined behavior, i.e., don&amp;rsquo;t use &lt;code&gt;delete&lt;/code&gt; twice on the same block of memory in succession.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Additional notes regarding runtime-allocated memory:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Ordinary variables have their values stored in a memory region called the &lt;strong&gt;stack&lt;/strong&gt;. Memory allocated with &lt;code&gt;new&lt;/code&gt; has its values stored in a memory region called the &lt;strong&gt;heap&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;// p_int address = 0x0065fd40&#xA;int* p_int = new int;&#xA;delete p_int;&#xA;&#xA;int oranges = 5;&#xA;int* p_oranges = &amp;amp;oranges;&#xA;// INVALID since delete works only with memory allocated with new&#xA;delete p_oranges;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Dynamic arrays can be created with &lt;code&gt;new typeName[count]&lt;/code&gt;. A pointer can be assigned to the location of the &lt;strong&gt;first&lt;/strong&gt; element of the dynamic array.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;// dynamic array&#xA;int* p_array = new int[10];&#xA;&#xA;// p_array points to the first element of the array&#xA;// *p_array is the value of the first element using pointer dereferencing&#xA;// p_array[0] is also the value of the first element using array notation&#xA;&#xA;delete [] p_array;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Dynamic structures can be created with &lt;code&gt;new structName&lt;/code&gt;. When a pointer points to this block of memory, we can access the properties with the arrow membership operator, &lt;code&gt;-&amp;gt;&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;struct person {&#xA;  string name;&#xA;  int age;&#xA;};&#xA;person* p_person = new person;&#xA;p_person-&amp;gt;name = &amp;quot;john smith&amp;quot;;&#xA;p_person-&amp;gt;age = 25;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;&#xA;&lt;p&gt;Steps to build a function:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Provide a function prototype.&lt;/li&gt;&#xA;&lt;li&gt;Provide a function definition.&lt;/li&gt;&#xA;&lt;li&gt;Call the function.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;// function prototype&#xA;double cube(double x);&#xA;&#xA;int main() {&#xA;  // function call&#xA;  double q = cube(2.2);&#xA;}&#xA;&#xA;// function definition&#xA;double cube(double x) {&#xA;  return x * x * x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Writing prototypes has the following advantages:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The compiler correctly handles the function return value.&lt;/li&gt;&#xA;&lt;li&gt;The compiler checks for the use of the correct number of arguments.&lt;/li&gt;&#xA;&lt;li&gt;The compiler checks for the use of the correct type of arguments (performing conversion to the correct type if possible).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;When a function is called with basic types for arguments, the function creates a new variable and initializes it with the same value, i.e., the function works with a copy of the basic types.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int main() {&#xA;  double x = 1.3;&#xA;  cube(x);&#xA;  // ..&#xA;}&#xA;&#xA;double cube(double x) {&#xA;  // x is passed by value&#xA;  // x is private to this function&#xA;  return x * x * x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;However, we can instead pass the address of the basic type, which means that the function should be rewritten to use pointers.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int main() {&#xA;  double x = 1.3;&#xA;  cube(&amp;amp;x);&#xA;  // ..&#xA;}&#xA;&#xA;double cube(double* x) {&#xA;  // x is passed by value&#xA;  // x is private to this function&#xA;  return (*x) * (*x) * (*x);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This is useful for complex structures if we want to save time/space by passing a reference to the structure instead of passing the entire structure.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;struct person {&#xA;  string name;&#xA;  int age;&#xA;};&#xA;&#xA;int main() {&#xA;  person john = { &amp;quot;john doe&amp;quot;, 25 };&#xA;  greet(&amp;amp;john);&#xA;  // ..&#xA;}&#xA;&#xA;double cube(person* someone) {&#xA;  // someone is private to this function&#xA;  // someone is a pointer to the original person&#xA;  someone-&amp;gt;age;       // 25&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;When a function is called with an array, what&amp;rsquo;s actually sent is the name of the array, which is the address of the first element (a pointer-to-int, &lt;code&gt;int *&lt;/code&gt;). This is different from basic types because the array is not copied; instead, the function works with the original array.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;const int k_size = 3;&#xA;&#xA;int main() {&#xA;  int a[k_size] = {1, 2, 3}&#xA;  sum(a, k_size);         // 6&#xA;  cout &amp;lt;&amp;lt; *a &amp;lt;&amp;lt; endl;     // 1&#xA;}&#xA;&#xA;double sum(int* a, int k_size) {&#xA;  // a is another pointer to the original array&#xA;  // a is private to this function&#xA;  int sum = 0;&#xA;  for (int i = 0; i &amp;lt; k_size; ++i) {&#xA;    sum += *a;&#xA;    a++;&#xA;  }&#xA;  return sum;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;inline-functions&#34;&gt;Inline functions&lt;/h3&gt;&#xA;&lt;p&gt;When a program is executed and a function is about to be invoked, the following steps occur with the program:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;store the memory address of the next instruction&lt;/li&gt;&#xA;&lt;li&gt;copy function arguments to the stack&lt;/li&gt;&#xA;&lt;li&gt;jump to the memory address the function is located&lt;/li&gt;&#xA;&lt;li&gt;execute the function code&lt;/li&gt;&#xA;&lt;li&gt;jump back to the instruction stored&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;A small enhancement to speed up the program is to make the function &lt;em&gt;inline&lt;/em&gt;. That is, the program replaces the function call with the function code, avoiding the jumps.&lt;/p&gt;&#xA;&lt;p&gt;When to use it:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the function is small and called very often&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;inline double cube(double x) { return x * x * x; }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;reference-variables&#34;&gt;Reference variables&lt;/h3&gt;&#xA;&lt;p&gt;A reference variable is a name that acts as an alias for a previously defined variable.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int p;&#xA;int&amp;amp; q = p;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;In this context, &lt;code&gt;&amp;amp;&lt;/code&gt; is not the address operator. Instead, it serves as part of the type identifier. Like &lt;code&gt;int*&lt;/code&gt; is a pointer-to-int, &lt;code&gt;int&amp;amp;&lt;/code&gt; is a reference-to-int.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A reference must be initialized to a defined variable when declared.&lt;/li&gt;&#xA;&lt;li&gt;A reference is like a const pointer, e.g., &lt;code&gt;int&amp;amp; r_n = n;&lt;/code&gt; is like &lt;code&gt;int* const r_n = &amp;amp;n;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int n = 5;&#xA;int* p_n = &amp;amp;n;&#xA;int&amp;amp; r_n = n;&#xA;&#xA;// the following expressions can be used interchangeably&#xA;// - *p_n, r_n, n  to get the value&#xA;// - p_n, &amp;amp;r_n, &amp;amp;n to get the address&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Example with a function:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int main() {&#xA;  int x = 2;&#xA;  pow2(x); // 4&#xA;  x;       // 2&#xA;}&#xA;&#xA;int pow2(int&amp;amp; x) {&#xA;  // x is an alias to the x in main&#xA;  return x * x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Note that any change to &lt;code&gt;x&lt;/code&gt; in &lt;code&gt;pow2()&lt;/code&gt; will actually change the original value. To avoid this behavior, use &lt;code&gt;const&lt;/code&gt;, e.g., &lt;code&gt;int pow2(const int &amp;amp;x)&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Reference arguments should be used to:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;allow the modification of data inside a function&lt;/li&gt;&#xA;&lt;li&gt;speed the program by passing a reference instead of an entire data object&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;class Person {&#xA;  // var, functions declared here are private by default&#xA;private:&#xA;  // private vars and function prototypes&#xA;public:&#xA;  // public vars and function prototypes&#xA;  void sayHi();&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;class-member-functions&#34;&gt;Class member functions&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Class member functions can access the private components of the class.&lt;/li&gt;&#xA;&lt;li&gt;To identify which class a function definition belongs to, the &lt;code&gt;::&lt;/code&gt; operator is used.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;void Person::sayHi() { /* ... */ }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If a class member function won&amp;rsquo;t modify the created instance, then use the &lt;code&gt;const&lt;/code&gt; qualifier for the function.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;// function prototype&#xA;class Person {&#xA;  // ..&#xA;  void show() const;&#xA;}&#xA;&#xA;// function definition&#xA;void Person::show() const { /* ... */ }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;All class methods have a &lt;code&gt;this&lt;/code&gt; pointer set to the address of the object that invokes the method. Class members can be accessed through pointer dereferencing.&lt;/p&gt;&#xA;&lt;h3 id=&#34;class-constructordestructor&#34;&gt;Class constructor/destructor&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A class has the &lt;em&gt;default constructor&lt;/em&gt; by default. It has the form &lt;code&gt;Person() {}&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Custom constructors/destructors can be defined as follows:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;class Person {&#xA;  string name;&#xA;  int age;&#xA;public:&#xA;  // implicit default constructor:&#xA;  //    Person() {}&#xA;  Person();                         // default constructor&#xA;  Person(string &amp;amp;name);             // operator overload&#xA;  Person(string &amp;amp;name, int &amp;amp;age);   // operator overload&#xA;  ~Person();                        // default destructor&#xA;}&#xA;&#xA;// constructor definition&#xA;Person::Person() {&#xA;  // explicit default constructor&#xA;  // NOTE: constructor/destructor returns the class object (no need to add return)&#xA;}&#xA;Person::Person(string&amp;amp; name) { /* ... */ }&#xA;Person::Person(string&amp;amp; name, int&amp;amp; age) { /* ... */ }&#xA;Person::~Person() { /* ... */ }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;class-objects&#34;&gt;Class objects&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int main() {&#xA;  Person a;                               // default constructor&#xA;  Person b = Person(&amp;quot;john&amp;quot;, 25);          // with parameters&#xA;  Person c(&amp;quot;john&amp;quot;, 25);                   // alternative syntax&#xA;  Person* p_d = new Person(&amp;quot;john&amp;quot;, 25);   // pointer-to-Person&#xA;&#xA;  b.show();&#xA;  p_d-&amp;gt;show();&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;operator-overloading&#34;&gt;Operator overloading&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;class Time {&#xA;public:&#xA;  Time operator+(const Time&amp;amp; other) const;&#xA;}&#xA;// ..&#xA;Time Time::operator+(const Time&amp;amp; other) const {&#xA;  Tim total;&#xA;  // code for `total = other + *this`&#xA;  return total;&#xA;}&#xA;// ..&#xA;int main() {&#xA;  Time a, b;&#xA;  Time c = a + b;&#xA;  // translated to a.operator+(b)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;misc&#34;&gt;Misc&lt;/h2&gt;&#xA;&lt;h3 id=&#34;deciphering-variable-types&#34;&gt;Deciphering variable types&lt;/h3&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;http://andybohn.com/deciphering-variable-types/&#34;target=&#34;_blank&#34;&gt;http://andybohn.com/deciphering-variable-types/&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Find the identifier and start there.&lt;/li&gt;&#xA;&lt;li&gt;Sweep to the right, translating the symbols you see. You should stop your sweep to the right when you get to the end of the type, or if you see a lone right parenthesis &lt;code&gt;)&lt;/code&gt;. Seeing a left parenthesis &lt;code&gt;(&lt;/code&gt; is the start of a function symbol, so continue sweeping right.&lt;/li&gt;&#xA;&lt;li&gt;Sweep left of the identifier until you run out of symbols, or you hit a left parenthesis &lt;code&gt;(&lt;/code&gt;. If you hit the left parenthesis now, you should go back to part 2, sweeping right, but now on the outside of the enclosing &lt;code&gt;)&lt;/code&gt;, and continuing onto part 3 on the outside of the enclosing &lt;code&gt;(&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;reading-examples&#34;&gt;Reading examples&lt;/h3&gt;&#xA;&lt;p&gt;Read a number and the next line as a string:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;// input:&#xA;//   1234\n&#xA;//   a line of text&#xA;int year;&#xA;string name;&#xA;(cin &amp;gt;&amp;gt; year).get();&#xA;getline(cin, name);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Read until a char is found (note that &lt;code&gt;cin &amp;gt;&amp;gt; ch&lt;/code&gt; omits spaces):&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;char ch;&#xA;cin.get(ch);            // or ch = cin.get();&#xA;while (ch != &#39;#&#39;) {&#xA;  // do something with ch&#xA;  cin.get(ch);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Read until EOF:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int a, b;&#xA;// cin is an istream object that is casted to bool in this case&#xA;while (cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b) { ... }&#xA;&#xA;string str;&#xA;// same as before cin is casted to bool&#xA;while (getline(cin, str)) { ... }&#xA;&#xA;char ch;&#xA;cin.get(ch);&#xA;// same as before cin is casted to bool&#xA;while (cin) { cin.get(ch); }&#xA;&#xA;char ch;&#xA;while ((ch = cin.get()) != EOF) { ... }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Tokenize:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;// example: split the following line by commas&#xA;// 1,2,hello&#xA;stringstream tokens(line);&#xA;string token;&#xA;string id, rank, description;&#xA;&#xA;getline(tokens, id, &#39;,&#39;)&#xA;getline(tokens, rank, &#39;,&#39;)&#xA;getline(tokens, description)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Read/write files:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#include &amp;lt;fstream&amp;gt;&#xA;&#xA;ifstream inFile;&#xA;inFile.open(&amp;quot;input&amp;quot;);&#xA;ofstream outFile;&#xA;outFile.open(&amp;quot;output&amp;quot;);&#xA;&#xA;string line;&#xA;int n;&#xA;&#xA;// reading input from file&#xA;getline(inFile, line);&#xA;inFile &amp;gt;&amp;gt; n;&#xA;&#xA;// writing output to file&#xA;outFile &amp;lt;&amp;lt; line;&#xA;outFile &amp;lt;&amp;lt; n;&#xA;&#xA;// close the stream&#xA;inFile.close();&#xA;outFile.close();&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Read from a file, reusing the stdin stream, and write to a file, reusing the stdout stream. See &#xA;&#xA;&lt;a href=&#34;http://www.cplusplus.com/reference/cstdio/freopen/&#34;target=&#34;_blank&#34;&gt;&lt;code&gt;freopen&lt;/code&gt;&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;#include &amp;lt;cstdio&amp;gt;&#xA;freopen(&amp;quot;input&amp;quot;, &amp;quot;r&amp;quot;, stdin);&#xA;freopen(&amp;quot;output&amp;quot;, &amp;quot;w&amp;quot;, stdout);&#xA;// use cin here&#xA;// close the streams&#xA;fclose(stdin);&#xA;fclose(stdout);&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;type-casts&#34;&gt;Type casts&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;(long) value&#xA;long(value)&#xA;static_cast&amp;lt;long&amp;gt; (value)&#xA;&#xA;// pointer cast&#xA;int* p_number = (int*) 0xB8000000;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;conversion-between-types&#34;&gt;Conversion between types&lt;/h3&gt;&#xA;&lt;h3 id=&#34;c11&#34;&gt;C++11&lt;/h3&gt;&#xA;&lt;p&gt;Declarations:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;auto&lt;/code&gt;: automatic type deduction.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;decltype&lt;/code&gt;: creates a variable of the type indicated by an expression.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Range-based &lt;code&gt;for&lt;/code&gt; loop:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int numbers[] = {1, 2, 3, 4, 5};&#xA;for (int n : numbers) { ... }&#xA;for (int n : {1, 2, 3, 4}) { ... }&#xA;for (auto n : {1, 2, 3, 4}) { ... }&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;multithreading&#34;&gt;Multithreading&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Back to basics: Concurrency CppCon 2020&lt;/strong&gt; &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/watch?v=F6Ipn7gCOsY&#34;target=&#34;_blank&#34;&gt;https://www.youtube.com/watch?v=F6Ipn7gCOsY&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Multithreading basics: &#xA;&#xA;&lt;a href=&#34;https://classroom.udacity.com/courses/ud923&#34;target=&#34;_blank&#34;&gt;https://classroom.udacity.com/courses/ud923&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Concurrent Programming with C++: &#xA;&#xA;&lt;a href=&#34;https://www.youtube.com/playlist?list=PL5jc9xFGsL8E12so1wlMS0r0hTQoJL74M&#34;target=&#34;_blank&#34;&gt;https://www.youtube.com/playlist?list=PL5jc9xFGsL8E12so1wlMS0r0hTQoJL74M&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;threadpool&#34;&gt;Threadpool&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&lt;div class=&#34;&#34;&gt;&#xA;    &lt;div class=&#34;&#34;&gt;&lt;/div&gt;&#xA;    &lt;iframe&#xA;        class=&#34;lazy-load&#34;&#xA;        title=&#34;repl demo&#34;&#xA;        frameborder=&#34;0&#34;&#xA;        width=&#34;100%&#34;&#xA;        height=&#34;700px&#34;&#xA;        data-src=&#34;https://repl.it/@mauriciopoppe/Threadpool?lite=true&#34;&gt;&#xA;    &lt;/iframe&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Culling &amp; Clipping</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/pipeline/culling-clipping/</link>
      <pubDate>Wed, 16 Mar 2016 11:03:05 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/pipeline/culling-clipping/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s a problem when the objects transformed to NDC need to be rasterized; some objects that are behind the eye might be rendered, leading to incorrect results.&lt;/p&gt;&#xA;&lt;p&gt;For example, when the &lt;em&gt;perspective projection matrix&lt;/em&gt; is used, all the points&amp;rsquo; $z$-coordinates will be mapped to NDC using:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z_{ndc} = \frac{Az_{cam} + B}{-z_{cam}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If $n,f$ are the locations of the near and far planes in the negative $z$-axis in camera space and:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;A &amp;= -\frac{f + n}{f - n} \\&#xA;B &amp;= \frac{-2fn}{f - n}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the equations above assume that $n,f \geq 0, n \leq f$ because $A$ and $B$ were already mapped using $-n \mapsto -1$ and $-f \mapsto 1$. For example, when $n = 1$ and $f = 10$, the possible values can be described with the following plot:&lt;/p&gt;&#xA;&lt;div id=&#34;z&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;function main() {&#xA;  var n = 1&#xA;  var f = 10&#xA;  var A = - (f + n)/(f - n)&#xA;  var B = (-2 * f * n)/(f - n)&#xA;  var xDiff = 2&#xA;  functionPlot({&#xA;    target: &#39;#z&#39;,&#xA;    xAxis: { domain: [-f - xDiff, -n + xDiff] },&#xA;    annotations: [&#xA;      {x: -n, text: &#39;-n&#39;},&#xA;      {x: -f, text: &#39;-f&#39;},&#xA;      {y: 1, text: &#39;1&#39;},&#xA;      {y: -1, text: &#39;-1&#39;}&#xA;    ],&#xA;    data: [{&#xA;      fn: &#39;(A * x + B)/(-x)&#39;,&#xA;      scope: {A: A, B: B}&#xA;    }]&#xA;  })&#xA;}&#xA;&#xA;window.myBlog.onDocumentReady(main)&#xA; &lt;/script&gt;&#xA;&#xA;&lt;p&gt;We see that objects behind the camera (points with $z_{cam} &amp;gt; 0$) are mapped to NDC as $z_{ndc} &amp;gt; 1$, i.e., in NDC, points behind the camera are visible.&lt;/p&gt;&#xA;&lt;p&gt;For this reason, there&amp;rsquo;s a preceding step in the rasterization process called &lt;em&gt;clipping&lt;/em&gt; that removes parts of primitives that are outside the view volume (clipping against the six faces of the view volume). A basic implementation of the clipping process is described below:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;input: triangle, 6 planes of the view volume&#xA;&#xA;for (each of the six planes) do&#xA;  if (the triangle is entirely outside the plane) then&#xA;    discard the triangle&#xA;  else if (the triangle passes through the plane) then&#xA;    clip the triangle&#xA;    if (the triangle is now a quadrilateral) then&#xA;      break the quadrilateral into two triangles&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Culling is a process where geometry that&amp;rsquo;s not visible from the camera is discarded to save processing time.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;View volume culling&lt;/em&gt; - Geometry outside the view volume can be culled since it won&amp;rsquo;t produce fragments when rasterized. This process is especially useful when triangles are grouped into an object that has an associated bounding volume.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;Backface culling&lt;/em&gt; - Polygons that face away from the camera can be culled before the pipeline starts.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Affine spaces</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/geometry/affine-spaces/</link>
      <pubDate>Tue, 15 Mar 2016 12:19:52 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/geometry/affine-spaces/</guid>
      <description>&lt;p&gt;Imagine a vector space where two points $P$ and $P&amp;rsquo;$ exist. Then, there&amp;rsquo;s a &lt;em&gt;unique translation of the plane&lt;/em&gt; that maps $P$ to $P&amp;rsquo;$. This means that the space of &lt;em&gt;translations&lt;/em&gt; in the plane can be identified with a set of vectors that exist in the plane. The composition of translations corresponds to the addition of vectors, e.g., $\v{PP&amp;rsquo;&amp;rsquo;} = \v{PP&amp;rsquo;} + \v{P&amp;rsquo;P&amp;rsquo;&amp;rsquo;}$.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/affine-space%21translation.jpg&#34; alt=&#34;affine space&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;affine space&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;An affine space is a space where translation is defined. Formally, an affine space is a set $E$ (of points) that admits a free transitive action of a vector space $\v{E}$ (of translations) whose action results in an element of the set $E$. That is, there&amp;rsquo;s a map $E \times \v{E} \rightarrow E: (a,\mathbf{v}) \mapsto a + \mathbf{v}$ such that&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;The zero vector acts as an identity, i.e., for all $a \in E$, $a + \mathbf{0} = a$.&lt;/li&gt;&#xA;&lt;li&gt;Addition of vectors corresponds to translations, i.e., for all $a \in E$ and $\mathbf{u,v} \in \v{E}$, $x + (\mathbf{u} + \mathbf{v}) = (x + \mathbf{u}) + \mathbf{v}$.&lt;/li&gt;&#xA;&lt;li&gt;For any $a,b \in E$, there&amp;rsquo;s a unique free vector $\mathbf{u} \in \v{E}$ such that $a + \mathbf{u} = b.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;The affine space is commonly represented by the triple $\left \langle E, \v{E}, + \right \rangle$, where $E$ is a set of points, $\v{E}$ is a vector space acting on $E$, and $+$ is an action $E \times \v{E} \rightarrow E$.&lt;/p&gt;&#xA;&lt;p&gt;Consider a subset $L$ of $\mathbb{A}^2$ consisting of points satisfying&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;-x + y - 2 = 0&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;line&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function () {&#xA;  functionPlot({&#xA;    target: &#39;#line&#39;,&#xA;    grid: true,&#xA;    data: [{&#xA;      fn: &#39;2 + x&#39;&#xA;    }]&#xA;  })&#xA;})&#xA; &lt;/script&gt;&#xA;&#xA;&lt;p&gt;Where any point has the form $(x, f(x)) = (x, 2 + x)$, the line can be made into an affine space by defining $+: L \times V \rightarrow L$ (note that $V$ is a vector space) such that for any $u \in V$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(x, 2 + x) + u = (x + u, 2 + x + u)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For example, the point $(-2,0)$ added to the vector $u = [1,1]$ results in the point $(-1, 1)$, which belongs to the set $L$. Note that for the example above, the vector space $V$ has only vectors parallel to $u = [1,1]$.&lt;/p&gt;&#xA;&lt;h2 id=&#34;chasless-identity&#34;&gt;Chasles&amp;rsquo;s Identity&lt;/h2&gt;&#xA;&lt;p&gt;Given any three points $a,b,c \in E$, we know that $c = a + \mathbf{ac}$, $b = a + \mathbf{ab}$, and $c = b + \mathbf{bc}$ by Axiom 3. Therefore,&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c = b + \mathbf{bc} = (a + \mathbf{ab}) + \mathbf{bc} = a + (\mathbf{ab} + \mathbf{bc})&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;And thus&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{ab} + \mathbf{bc} = \mathbf{ac}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which is known as Chasles&amp;rsquo;s identity&lt;/p&gt;&#xA;&lt;h2 id=&#34;affine-combinations&#34;&gt;Affine combinations&lt;/h2&gt;&#xA;&lt;p&gt;Consider $\mathbb{R}^2$ as an affine space with its origin at $(0,0)$ and basis vectors $\mathbf{b_1} = [1, 0]$ and $\mathbf{b_2} = [0,1]$. Given any two points $a,b \in \mathbb{R}^2$ with coordinates $a = (a_1,a_2)$ and $b = (b_1,b_2)$, we can define the affine combination $\lambda a + \mu b$ as the point with coordinates&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(\lambda a_1 + \mu b_1, \lambda a_2 + \mu b_2)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let $\lambda = 1, \mu = 1$, $a = (-1,1)$, and $b = (2, 2)$. Then $a + b = (1, 1)$.&lt;/p&gt;&#xA;&lt;div id=&#34;affine-1&#34;&gt;&lt;/div&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function () {&#xA;  functionPlot({&#xA;    target: &#39;#affine-1&#39;,&#xA;    annotations: [{ x: 1 }, { y: 1 }],&#xA;    data: [{&#xA;      points: [[-1,-1], [2,2], [1, 1]],&#xA;      fnType: &#39;points&#39;,&#xA;      graphType: &#39;scatter&#39;&#xA;    }]&#xA;  })&#xA;})&#xA; &lt;/script&gt;&#xA;&#xA;&lt;p&gt;If we change the coordinate system to have an origin at $(1,1)$ with the same basis vectors, then the coordinates of the given points are $a=(-2,-2)$ and $b=(1,1)$. The linear combination is then $a + b = (-1,-1)$, which is the same as the point $(0,0)$ of the first coordinate system. Therefore, $a+b$ corresponds to two different points depending on the coordinate system used.&lt;/p&gt;&#xA;&lt;p&gt;A restriction is needed for affine combinations to make sense: the scalars must add up to 1.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Lemma: Given an affine space $E, \v{E}, +$, let $a_i, i \in I$ be a family of points in $E$ and let $\lambda_i, i \in I$ be a family of scalars. Then, for any two points $a,b \in E$, the following properties hold:&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{lemma-1}&#xA;a + \sum_{i \in I} \lambda_i \mathbf{aa_i} = b + \sum_{i \in I} \lambda_i \mathbf{ba_i} \quad \text{if $\sum_{i \in I} \lambda_i = 1$} \end{equation}&#xA;$$&lt;/div&gt;&#xA;&gt;&#xA;&gt; and&#xA;&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{lemma-2}&#xA;\sum_{i \in I} \lambda_i \mathbf{aa_i} = \sum_{i \in I} \lambda_i \mathbf{ba_i} \quad \text{if $\sum_{i \in I} \lambda_i = 0$} \end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To prove \eqref{lemma-1}, we apply Chasles&amp;rsquo;s identity:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;a + \sum_{i \in I} \lambda_i \mathbf{aa_i} &amp;= a + \sum_{i \in I} \lambda_i (\mathbf{ab} + \mathbf{ba_i}) \\&#xA;&amp;= a + (\sum_{i \in I} \lambda_i) \mathbf{ab} + \sum_{i \in I} \lambda_i \mathbf{ba_i} \\&#xA;&amp;= a + \mathbf{ab} + \sum_{i \in I} \lambda_i \mathbf{ba_i} \quad \text{since $\sum_{i \in I} \lambda_i = 1$} \\&#xA;&amp;= b + \sum_{i \in I} \lambda_i \mathbf{ba_i} \quad \text{since $b = a + \mathbf{ab}$} \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For \eqref{lemma-2}, we also have:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\sum_{i \in I} \lambda_i \mathbf{aa_i} &amp;= \sum_{i \in I} \lambda_i (\mathbf{ab} + \mathbf{ba_i}) \\&#xA;&amp;= (\sum_{i \in I} \lambda_i) \mathbf{ab} + \sum_{i \in I} \lambda_i \mathbf{ba_i} \\&#xA;&amp;= \sum_{i \in I} \lambda_i \mathbf{ba_i} \quad \text{since $\sum_{i \in I} \lambda_i = 0$}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Formally, for any family of points $a_i, i \in I$ in $E$ and for any family $\lambda_i, i \in I$ of scalars such that $\sum_{i \in I} \lambda_i = 1$, the point&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{affine-combination}&#xA;x = a + \sum_{i \in I} \lambda_i \mathbf{aa_i}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;is &lt;em&gt;independent&lt;/em&gt; of $a \in E$ and is called the &lt;em&gt;barycenter or affine combination of the points $a_i$ with weights $\lambda_i$&lt;/em&gt;. It is denoted as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sum_{i \in I} \lambda_i a_i&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;affine-maps&#34;&gt;Affine maps&lt;/h2&gt;&#xA;&lt;p&gt;An affine map between two affine spaces $X$ and $Y$ is a map $f: X \rightarrow Y$ that &lt;em&gt;preserves affine combinations&lt;/em&gt;, i.e.,&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f \left (\sum_{i \in I} \lambda_i a_i \right ) = \sum_{i \in I} \lambda_i f(a_i)&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Vector spaces</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/geometry/vector-spaces/</link>
      <pubDate>Mon, 14 Mar 2016 17:07:51 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/geometry/vector-spaces/</guid>
      <description>&lt;p&gt;A vector space is a set whose elements are called &amp;ldquo;vectors&amp;rdquo; (denoted as $\v{v}$ or $\mathbf{v}$), which have two operations defined on them: addition of vectors and multiplication of a scalar by a vector.&lt;/p&gt;&#xA;&lt;p&gt;Formally, a vector space $V$ is a set with two operations $+$ and $*$ that satisfy the following properties:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $\mathbf{u},\mathbf{v} \in V$, then $\mathbf{u + v} \in V$.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{u + v} = \mathbf{v + u}$&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{u + (v + w)} = \mathbf{(u + v) + w}$&lt;/li&gt;&#xA;&lt;li&gt;There is a special element called the zero vector $\mathbf{0} \in V$ such that $\mathbf{u + 0} = \mathbf{0 + u} = \mathbf{u}$.&lt;/li&gt;&#xA;&lt;li&gt;For every $\mathbf{u} \in V$, there&amp;rsquo;s an inverse element $-\mathbf{u}$ such that $\mathbf{u + (-u)} = \mathbf{0}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;If $\mathbf{u} \in V$ and $\alpha \in \mathbb{R}$, then $\alpha\mathbf{u} \in V$.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$(\alpha + \beta) \mathbf{u} = \alpha \mathbf{u} + \beta \mathbf{u}$&lt;/li&gt;&#xA;&lt;li&gt;$\alpha (\beta \mathbf{u}) = (\alpha\beta) \mathbf{u}$&lt;/li&gt;&#xA;&lt;li&gt;$1 \cdot \mathbf{u} = \mathbf{u}$&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Notable examples of vector spaces:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Segments on the plane and in space; addition uses the parallelogram law, and multiplication by a scalar scales the segment.&lt;/li&gt;&#xA;&lt;li&gt;The set of $n \times n$ matrices, with addition defined by element.&lt;/li&gt;&#xA;&lt;li&gt;The set of all polynomials.&lt;/li&gt;&#xA;&lt;li&gt;The space consisting of the zero vector alone: ${\mathbf{0}}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;vector-subspaces&#34;&gt;Vector subspaces&lt;/h2&gt;&#xA;&lt;p&gt;A subset $U \subseteq V$ of a vector space $V$ is a subspace if:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For all $\mathbf{u,v} \in U$, $\mathbf{u+v} \in U$.&lt;/li&gt;&#xA;&lt;li&gt;For all $\alpha \in \mathbb{R}$ and $\mathbf{u} \in U$, $\alpha \mathbf{u} \in U$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;linear-dependence&#34;&gt;Linear dependence&lt;/h2&gt;&#xA;&lt;p&gt;A set of vectors is linearly dependent if one element from the set can be written as a linear combination of the other elements in the set. If this cannot be done, then the set is linearly independent, which is also known as a &lt;strong&gt;basis&lt;/strong&gt; for some vector space. The &lt;strong&gt;dimension&lt;/strong&gt; is the number of elements in the basis. If $\mathbf{b_1, b_2, \ldots, b_n}$ is a basis, then any linear combination of the basis will have the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = a_1 \mathbf{b_1} + a_2 \mathbf{b_2} + \ldots + a_n \mathbf{b_n}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The numbers $a_1, a_2, \ldots, a_n$ are called the &lt;strong&gt;components&lt;/strong&gt; of $\mathbf{v}$ in the specified basis. Note that the basis doesn&amp;rsquo;t need to be orthogonal nor have unit vectors.&lt;/p&gt;&#xA;&lt;p&gt;The set of vectors $[1,0,0], [0,1,0], [0,0,1]$ is an example of a basis of dimension 3&lt;/p&gt;&#xA;&lt;h2 id=&#34;linear-maps&#34;&gt;Linear maps&lt;/h2&gt;&#xA;&lt;p&gt;A map between vector spaces is linear if it preserves addition and multiplication with scalars as defined above. Formally, a map $L: U \rightarrow V$ is linear if:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For all $\mathbf{u,v} \in U$, $L(\mathbf{u,v}) = L(\mathbf{u}) + L(\mathbf{v})$.&lt;/li&gt;&#xA;&lt;li&gt;For all $\alpha \in \mathbb{R}$ and $\mathbf{u} \in U$, $L(\alpha \mathbf{u}) = \alpha L(\mathbf{u})$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;additional-operations&#34;&gt;Additional operations&lt;/h2&gt;&#xA;&lt;h3 id=&#34;norm&#34;&gt;Norm&lt;/h3&gt;&#xA;&lt;p&gt;The norm of a vector is denoted by $\norm{\mathbf{v}}$ and satisfies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\norm{\mathbf{v}} \geq 0$; $\norm{\mathbf{v}} = 0$ only if $\mathbf{v} = \mathbf{0}$.&lt;/li&gt;&#xA;&lt;li&gt;$\norm{\alpha \mathbf{v}} = \alpha \norm{\mathbf{v}}$.&lt;/li&gt;&#xA;&lt;li&gt;$\norm{\mathbf{v_1} + \mathbf{v_2}} \leq \norm{\mathbf{v_1}} + \norm{\mathbf{v_2}}$ (triangle inequality).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;scalar-product&#34;&gt;Scalar product&lt;/h3&gt;&#xA;&lt;p&gt;The scalar product of two vectors is a function $f: V \times V \rightarrow \mathbb{R}$. The function is commonly denoted as $\left \langle \mathbf{v_1}, \mathbf{v_2} \right \rangle$ and satisfies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\left \langle \mathbf{w, (u + v)} \right \rangle = \left \langle \mathbf{w,u} \right \rangle + \left \langle \mathbf{w,v} \right \rangle$.&lt;/li&gt;&#xA;&lt;li&gt;$\left \langle \mathbf{w},\alpha \mathbf{v} \right \rangle = \alpha \left \langle \mathbf{w,v} \right \rangle$.&lt;/li&gt;&#xA;&lt;li&gt;$\left \langle \mathbf{v,v} \right \rangle \geq 0.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Triangle in affine spaces</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/geometry/triangle/</link>
      <pubDate>Thu, 10 Mar 2016 23:17:08 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/geometry/triangle/</guid>
      <description>&lt;p&gt;In an &#xA;&#xA;&lt;a href=&#34;../affine-spaces&#34;target=&#34;_blank&#34;&gt;affine space&lt;/a&gt;&#xA;&#xA;, there&amp;rsquo;s the concept of affine combination, which states that any point in space can be represented as an affine combination in the form&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a + \sum_{i \in I} \lambda_i \mathbf{aa_i} \quad \quad \text{if $\sum_{i \in I} \lambda_i = 1$}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can add an additional restriction on the values of $\lambda_i$ to define a triangle built from three points. If $\lambda_1 = \beta, \lambda_2 = \gamma$, $\beta + \gamma = 1$, and $\beta, \gamma  [0,1]$, then a triangle is defined as the affine combination&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a + \beta \mathbf{ab} + \gamma \mathbf{ac}&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/triangle%21barycentric.jpg&#34; alt=&#34;barycentric coordinates&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;barycentric coordinates&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;One geometric property of the scalar values is that they&amp;rsquo;re the signed scaled distance from the lines that pass through the triangle sides. To compute the scalar values $\beta$ and $\gamma$, we can use the fact that when the implicit equation of the line that passes through a side is evaluated with points that don&amp;rsquo;t lie on the line, the result is equal to&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/triangle%21beta.jpg&#34; alt=&#34;beta&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;beta&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div&gt;$$&#xA;f(x,y) = d_{(x,y)} \cdot \sqrt{A^2 + B^2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $d_{(x,y)}$ is the distance from the point $(x,y)$ to the line. $A$ and $B$ are the coefficients of $x$ and $y$ in the general equation of the line that passes through $a$ and $c$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;Ax + Bx + C = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To find the value of $\beta$, we can use the value of the implicit equation of the line to map the distance between any point to the line in the range $[f_{ac}(x_a, y_a), f_{ac}(x_b, y_b)] = [0, f_{ac}(x_b, y_b)]$. We can then use a simple division to find the value of $\beta$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\beta = \frac{f_{ac}(x,y)}{f_{ac}(x_b, y_b)} = \frac{d_{(x,y)}}{d_{(x_b, y_b)}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;In a similar fashion the value of $\gamma$ is&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\gamma = \frac{f_{ab}(x,y)}{f_{ab}(x_c, y_c)} = \frac{d_{(x,y)}}{d_{(x_c, y_c)}}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Geometric tests</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/geometry/geometric-tests/</link>
      <pubDate>Wed, 09 Mar 2016 22:52:35 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/geometry/geometric-tests/</guid>
      <description>&lt;h2 id=&#34;line-line-intersection&#34;&gt;Line-line intersection&lt;/h2&gt;&#xA;&lt;p&gt;Given two lines in 3D, defined as rays:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;r_1(t_1) = \mathbf{p_1} + t_1 \mathbf{d_1} \\&#xA;r_2(t_2) = \mathbf{p_2} + t_2 \mathbf{d_2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $t_1, t_2 \in \mathbb{R}$, the two lines intersect if:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p_1} + t_1 \mathbf{d_1} = \mathbf{p_2} + t_2 \mathbf{d_2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can apply the cross multiplication operation on both sides with $\mathbf{d_2}$ and work from there to find the value of $t_1$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;t_1 = \frac{\norm{(\mathbf{p_2} - \mathbf{p_1}) \times \mathbf{d_2} }}{ \norm{\mathbf{d_1} \times \mathbf{d_2}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Similarly, we can find the value of $t_2$ by crossing with $\mathbf{d_1}$ and work from there to find the value of $t_2$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;t_2 = \frac{\norm{ (\mathbf{p_2} - \mathbf{p_1}) \times \mathbf{d_1}} }{ \norm{\mathbf{d_1} \times \mathbf{d_2}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The proof can be found &#xA;&#xA;&lt;a href=&#34;http://stackoverflow.com/a/565282/3341726&#34;target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;We can actually solve this problem graphically by using &#xA;&#xA;&lt;a href=&#34;https://www.mathsisfun.com/geometry/triangles-similar-finding.html&#34;target=&#34;_blank&#34;&gt;triangle similarity&lt;/a&gt;&#xA;&#xA;. Imagine the following situation:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/geometric-tests%21line-line.jpg&#34; alt=&#34;line line intersection&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;line line intersection&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;The intersection point $\mathbf{p}$ is equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{line-line-intersection-point}&#xA;\begin{split}&#xA;\mathbf{p} &amp;= \mathbf{a} + \norm{\mathbf{p - a}} \unit{ \mathbf{b - a} } \\&#xA;&amp;= \mathbf{a} + \norm{\mathbf{p - a}} \frac{ \mathbf{b - a}  }{ \norm{\mathbf{b - a}} }&#xA;\end{split}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;By triangle similarity, we see that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{ \norm{\mathbf{p - a}} }{ \norm{\mathbf{b - a}} } = \frac{ \norm{\mathbf{n -a}} }{ \norm{\mathbf{m - a}} }&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Multiplying the left side with an identity&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{line-line-triangle-similarity}&#xA;\frac{ \norm{\mathbf{p - a}} }{ \norm{\mathbf{b - a}} } = \frac{ \norm{\mathbf{n -a}} }{ \norm{\mathbf{m - a}} } \frac{ \norm{\mathbf{d - c}} }{ \norm{\mathbf{d - c}} }&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We see that the quantity $\norm{ \mathbf{ n - a } } \norm{\mathbf{d - c}}$ is equal to the area of a parallelogram. We can skew the parallelogram (in the graphic, towards the $x$-axis) so that the left side becomes $\mathbf{c - a}$ and the bottom side $\mathbf{d - c}$ (which is not affected by the skew). Note that the area can also be expressed with the cross product of the vectors $\mathbf{c - a}$ and $\mathbf{d - c}$. Therefore,&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{numerator-area}&#xA;\norm{\mathbf{n - a}} \norm{\mathbf{d - c}} = \norm{(\mathbf{c - a}) \times (\mathbf{d - c})}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;A similar equation can be derived for the parallelogram with sides $\mathbf{m - a}$ and $\mathbf{d - c}$, only this time the skewed side will become $\mathbf{b - a}$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{denominator-area}&#xA;\norm{\mathbf{m - a}} \norm{\mathbf{d - c}} = \norm{(\mathbf{b - a}) \times (\mathbf{d - c})}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Replacing \eqref{numerator-area} and \eqref{denominator-area} in \eqref{line-line-triangle-similarity} and \eqref{line-line-intersection-point}, we see that the intersection point is equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p} = \mathbf{a} + (\mathbf{b - a}) \frac{ \norm{(\mathbf{c - a}) \times (\mathbf{d - c})} }{ \norm{(\mathbf{b - a}) \times (\mathbf{d - c})} }&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Transformation Matrix to Transform Objects from NDC Coordinates to Screen Coordinates (Viewport Transform)</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/viewport-transform/</link>
      <pubDate>Tue, 08 Mar 2016 22:20:58 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/viewport-transform/</guid>
      <description>&lt;p&gt;The objective of this step is to find a transformation matrix to transform points expressed in &lt;em&gt;normalized device coordinates&lt;/em&gt; to &lt;em&gt;screen coordinates&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v}_{screen} = \mathbf{M}_{vp} \mathbf{v}_{ndc}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The &lt;em&gt;canonical view volume&lt;/em&gt; needs to be mapped to the screen that has $n_x \times n_y$ pixels in a way so that points with $x = -1$ and $x = 1$ are mapped to the left and right sides of the screen, respectively, and $y = -1$ and $y = 1$ are mapped to the bottom and top sides of the screen, respectively. The $z$-coordinate isn&amp;rsquo;t visible in a 2D image, so it can be discarded for the mapping.&lt;/p&gt;&#xA;&lt;p&gt;Since the mapping is linear, we can use the &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Linear_interpolation&#34;target=&#34;_blank&#34;&gt;linear interpolation method&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f(x) = out_{lo} + (out_{hi} - out_{lo}) \frac{x - in_{lo}}{ in_{hi} - in_{lo} }&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Given:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$out_{lo} = -0.5$&lt;/li&gt;&#xA;&lt;li&gt;$out_{hi} = n_x - 0.5$&lt;/li&gt;&#xA;&lt;li&gt;$in_{lo} = -1$&lt;/li&gt;&#xA;&lt;li&gt;$in_{hi} = 1$&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The value of $x_{screen}$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x_{screen} &amp;= -0.5 + n_x \frac{x_{ndc} + 1}{2} \\&#xA;&amp;= -\frac{1}{2} + \frac{n_x}{2}x_{ndc} + \frac{n_x}{2} \\&#xA;&amp;= \frac{n_x}{2}x_{ndc} + \frac{n_x - 1}{2}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The value of $y_{screen}$ is found in a similar way:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y_{screen} = \frac{n_y}{2}y_{ndc} + \frac{n_y - 1}{2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally, the transformation matrix that converts points from NDC to screen coordinates is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{vp} = \begin{bmatrix}&#xA;\frac{n_x}{2} &amp; 0 &amp; 0 &amp; \frac{n_x - 1}{2} \\&#xA;0 &amp; \frac{n_y}{2} &amp; 0 &amp; \frac{n_y - 1}{2} \\&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the $z$-coordinate doesn&amp;rsquo;t need to be modified since it doesn&amp;rsquo;t affect the projection in the image. The $z$-coordinate is still used to check the order in which objects should be drawn.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Normals</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/normals/</link>
      <pubDate>Tue, 08 Mar 2016 14:18:11 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/normals/</guid>
      <description>&lt;p&gt;A &lt;strong&gt;normal vector&lt;/strong&gt; to a curve at a particular point is a vector perpendicular to the &lt;em&gt;tangent&lt;/em&gt; vector of the curve at that point (also called a &lt;em&gt;gradient&lt;/em&gt;). For an implicit 2D function in the form $f(x,y) = 0$, the 2D gradient is:&lt;/p&gt;&#xA;&lt;div&gt;&#xA;&lt;div&gt;$$&#xA;\nabla f(x,y) = \left ( \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y} \right )&#xA;$$&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;For an implicit 3D function, the &lt;strong&gt;normal&lt;/strong&gt; is the vector perpendicular to the surface. The &lt;strong&gt;surface normal&lt;/strong&gt; at a point $\mathbf{p}$ is given by the gradient of the implicit function:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{n} = \nabla f (\mathbf{p}) = \left ( \frac{\partial f(\mathbf{p})}{\partial x}, \frac{\partial f(\mathbf{p})}{\partial y}, \frac{\partial f(\mathbf{p})}{\partial z} \right  )&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For a plane, we know that the dot product of the normal $\mathbf{n}$ and any vector that lies in the plane is zero. Therefore, we can model a plane as the following implicit equation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(\mathbf{p} - \mathbf{a}) \cdot \mathbf{n} = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\mathbf{p}$ and $\mathbf{a}$ are any two points lying on the plane. Sometimes we want the equation of a plane through points $\mathbf{a, b, c}$. The normal can be found by taking the cross product of any two vectors on the plane:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{n} = (\mathbf{b} - \mathbf{a}) \times (\mathbf{c} - \mathbf{a})&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;transforming-normal-vectors&#34;&gt;Transforming Normal Vectors&lt;/h2&gt;&#xA;&lt;p&gt;Normal vectors do not transform the way we would like when they&amp;rsquo;re multiplied by a transformation matrix. If the points on a surface are transformed by the transformation matrix $\mathbf{M}$, a vector $\mathbf{t}$ tangent to the surface will still be tangent to the transformed surface. However, a surface normal vector $\mathbf{n}$ may not be normal to the transformed surface.&lt;/p&gt;&#xA;&lt;p&gt;For example, when a transformation matrix $\mathbf{M} = \mathbf{H_x}(s)$ that skews points toward the $x$-axis multiplies the normal vector $\mathbf{n}$, the resulting vector $\mathbf{Mn}$ is not normal to the surface. We would like to find a transformation matrix $\mathbf{N}$ so that $\mathbf{Nn}$ is indeed the surface normal.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/normals%21transformation.jpg&#34; alt=&#34;Transforming Normal&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Transforming Normal&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;To find the value of $\mathbf{N}$, we start from the fact that the normal $\mathbf{n}$ and the tangent $\mathbf{t}$ are perpendicular:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{ n \cdot t } = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Expressed as a matrix multiplication:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{perpendicular}&#xA;\mathbf{n}^T \mathbf{t} = 0&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;After the transformation, they&amp;rsquo;re still perpendicular, so:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(\mathbf{Nn})^T \mathbf{Mt} = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying the transpose:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{post-transformation}&#xA;\mathbf{n}^T \mathbf{N}^T \mathbf{Mt} = 0&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Relating \eqref{post-transformation} with \eqref{perpendicular}, we see that the only way that both equations hold true is that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{N}^T \mathbf{M} = \mathbf{I}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The value of $\mathbf{N}$ is then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{N}^T \mathbf{M} &amp;= \mathbf{I} \\&#xA;\mathbf{N}^T \mathbf{MM}^{-1} &amp;= \mathbf{IM}^{-1} \\&#xA;\mathbf{N}^T &amp;= \mathbf{M}^{-1} \\&#xA;\mathbf{N} &amp;= (\mathbf{M}^{-1})^T&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Eigenvalues and eigenvectors</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/linear-algebra/eigenvalues-and-eigenvectors/</link>
      <pubDate>Mon, 07 Mar 2016 12:50:15 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/linear-algebra/eigenvalues-and-eigenvectors/</guid>
      <description>&lt;p&gt;Given a square matrix $\mathbf{M}$:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;An &lt;em&gt;eigenvector&lt;/em&gt; $\mathbf{v}$ is a non-zero vector whose direction doesn&amp;rsquo;t change when multiplied by $\mathbf{M}$. Note that if $\mathbf{M}$ has an eigenvector, then there are an infinite number of eigenvectors (vectors parallel to $\mathbf{v}$).&lt;/li&gt;&#xA;&lt;li&gt;An &lt;em&gt;eigenvalue&lt;/em&gt; $\lambda$ is the scale factor associated with an &lt;em&gt;eigenvector&lt;/em&gt; $\mathbf{v}$ of $\mathbf{M}$ after multiplication by $\mathbf{M}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{eigenvector}&#xA;\mathbf{Mv} = \lambda \mathbf{v}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Assuming that $\mathbf{M}$ has at least one eigenvector $\mathbf{v}$, we can perform standard matrix multiplications to find it. First, let&amp;rsquo;s manipulate the right side of \eqref{eigenvector} so that it also features a matrix multiplication.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{Mv} = \lambda \mathbf{Iv}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\mathbf{I}$ is the identity matrix, next we can rewrite the last equation as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{Mv} - \lambda \mathbf{Iv} = \mathbf{0}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Because matrix multiplication is distributive&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{eigenvector-0}&#xA;(\mathbf{M} - \lambda \mathbf{I})\mathbf{v} = \mathbf{0}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The quantity $\mathbf{M} - \lambda \mathbf{I}$ must not be invertible. If it had an inverse, we could premultiply both sides by $(\mathbf{M} - \lambda \mathbf{I})^{-1}$, which would yield&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;(\mathbf{M} - \lambda \mathbf{I})^{-1}(\mathbf{M} - \lambda \mathbf{I})\mathbf{v} &amp;= (\mathbf{M} - \lambda \mathbf{I})^{-1} \; \mathbf{0} \\&#xA;\mathbf{v} &amp;= \mathbf{0}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The vector $\mathbf{v = 0}$ fulfills \eqref{eigenvector}. However, we&amp;rsquo;ll try to find a vector $\mathbf{v} \not = \mathbf{0}$. If such a condition is added, then the matrix $\mathbf{M} - \lambda \mathbf{I}$ must not have an inverse, which also means that its determinant is 0.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\left | \mathbf{M} - \lambda \mathbf{I} \right | = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If $\mathbf{M}$ is a $2 \times 2$ matrix, then&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*} \label{lambda}&#xA;\left | \mathbf{M} - \lambda \mathbf{I} \right | &amp;= \begin{vmatrix}&#xA;m_{11} - \lambda &amp; m_{12} \\&#xA;m_{21} &amp; m_{22} - \lambda&#xA;\end{vmatrix} \\&#xA;&amp; = \lambda^2 - (m_{11}+m_{22})\lambda + (m_{11}m_{22} - m_{12}m_{21}) \\&#xA;&amp; = 0&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;From \eqref{lambda}, we can find two values for $\lambda$, which may be unique or imaginary. A similar manipulation for an $n \times n$ matrix will yield an $n$th degree polynomial. For $n \leq 4$, we can compute the solutions by analytical methods; for $n &amp;gt; 4$, only numeric methods are used.&lt;/p&gt;&#xA;&lt;p&gt;The associated eigenvector can be found by solving \eqref{eigenvector-0}&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix}&#xA;m_{11} - \lambda &amp; m_{12} \\&#xA;m_{21} &amp; m_{22} - \lambda&#xA;\end{bmatrix} \begin{bmatrix}&#xA;x \\ y&#xA;\end{bmatrix} = \begin{bmatrix} 0 \\ 0&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;applications&#34;&gt;Applications&lt;/h3&gt;&#xA;&lt;p&gt;List of applications&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $\mathbf{M}$ is a transformation matrix, then $\mathbf{v}$ is a vector that &lt;strong&gt;isn&amp;rsquo;t affected by the rotation part of $\mathbf{M}$&lt;/strong&gt;. Therefore, $\mathbf{v}$ is the rotation axis of $\mathbf{M}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Projective space</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/geometry/projective-space/</link>
      <pubDate>Fri, 04 Mar 2016 10:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/geometry/projective-space/</guid>
      <description>&lt;p&gt;In Euclidean geometry, two lines are said to be parallel if they lie in the same plane and never meet. Moreover, properties like this one don&amp;rsquo;t change when a Euclidean transformation is applied (translation/rotation). However, what we perceive in real life is different from what&amp;rsquo;s described by Euclidean geometry.&lt;/p&gt;&#xA;&lt;p&gt;This problem coincided with the one Renaissance artists had while trying to paint on a canvas. When they tried to paint tiles on a canvas, they realized that the following rules applied:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;parallel lines meet on the horizon&lt;/li&gt;&#xA;&lt;li&gt;straight lines must be represented on the page by straight lines&lt;/li&gt;&#xA;&lt;li&gt;the image of a conic is also a conic (for example a circle is drawn as an ellipse depending on the perspective)&lt;/li&gt;&#xA;&lt;/ul&gt;&lt;/blockquote&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projective-geometry%21perspective.jpg&#34; alt=&#34;projection&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;projection&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;The French mathematician &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Girard_Desargues&#34;target=&#34;_blank&#34;&gt;Girard Desargues&lt;/a&gt;&#xA;&#xA;, researching more on this new type of geometry, had the necessity to have a &lt;em&gt;point at infinity&lt;/em&gt;. He introduced the concept of a &lt;em&gt;line at infinity&lt;/em&gt;, which helped define the point at infinity as follows:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For every family of parallel lines on some ordinary plane, there&amp;rsquo;s one point at infinity where they all meet, which lies on the line at infinity&lt;/p&gt;&lt;/blockquote&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projective-geometry%21projective-plane.png&#34; alt=&#34;projective plane&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;projective plane&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;An ordinary plane plus the line at infinity is called a &lt;strong&gt;projective plane&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;Projective geometry exists in any number of dimensions (just like Euclidean geometry). When we take a picture using a camera, the imaging process makes a projection from $P^3$ to $P^2$; such a process is called a &lt;em&gt;projective transformation&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Properties of projective transformations:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Preservation of type (points remain points, and lines remain lines).&lt;/li&gt;&#xA;&lt;li&gt;Incidence (a point remains on a line after transformation).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In 1D, there&amp;rsquo;s the &lt;strong&gt;projective line&lt;/strong&gt;, which is an ordinary line plus one point at infinity that can be reached by moving towards each end of the line.&lt;/p&gt;&#xA;&lt;h2 id=&#34;projective-line&#34;&gt;Projective line&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Spaces of 1-dimensional subspaces that exist in 2-dimensions, i.e., &lt;em&gt;any line that passes through the origin in a 2-dimensional space&lt;/em&gt;.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Let $w$ be the vertical axis in this 2-dimensional space. The picture of a line at infinity is shown by looking at the line $w = 1$ and its relation to $w = 0$. Almost all the lines that pass through the origin intercept $w = 1$, &lt;strong&gt;except&lt;/strong&gt; the line $w = 0$. Therefore, we can see that the set of points that exists on the line $w = 1$ is the same as the set that contains all the interception points between all the possible 1-dimensional subspaces and $w = 1$. However, the line $w = 0$ (which is also part of the 1-dimensional subspaces) doesn&amp;rsquo;t meet $w = 1$, so $w = 0$ &lt;em&gt;plays the role of infinity&lt;/em&gt; with respect to $w = 1$.&lt;/p&gt;&#xA;&lt;p&gt;Any 1D point is represented in projective geometry as the pair $(x, w)$. We can see that such a pair can be projected to $w = 1$ by dividing both coordinates by $w$. Thus, any 1D point projected to this plane is represented by the pair $(&#x9;frac{x}{w}, 1)$, unless $w = 0$, which is in the &lt;em&gt;line at infinity&lt;/em&gt;. Any point at infinity then has the form $(x, 0)$.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projective-geometry%21projective-line.png&#34; alt=&#34;projective line&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;projective line&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;projective-plane&#34;&gt;Projective plane&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Spaces of 1-dimensional subspaces that exist in 3-dimensions, i.e., &lt;em&gt;any line that passes through the origin in a 3-dimensional space&lt;/em&gt;.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;A similar situation is seen in a 3-dimensional space. In this space, any line that passes through the origin intercepts the &lt;em&gt;plane&lt;/em&gt; $w = 1$, except for the set of lines that lie in the plane $w = 0$. Thus, $w = 0$ plays the role of infinity with respect to $w = 1$.&lt;/p&gt;&#xA;&lt;p&gt;Any 2D point is represented in this space as the triplet $(x, y, w)$. Just like in 1D, we can project any point to the plane $w = 1$ by dividing the triplet by $w$, which has the form $(&#x9;frac{x}{w}, &#x9;frac{y}{w}, 1)$, unless $w = 0$. This means that any point at infinity has the form $(x, y, 0)$.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projective-geometry%21projective-plane-3d.png&#34; alt=&#34;projective plane&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;projective plane&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Ray Tracing</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/ray-tracing/</link>
      <pubDate>Fri, 26 Feb 2016 17:03:44 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/ray-tracing/</guid>
      <description>&lt;p&gt;A ray tracer emits a ray from each pixel toward the scene to determine the color of the pixel. The process of computing the color can be split into three parts:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ray generation&lt;/strong&gt;: The origin and direction of each pixel ray are computed.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ray intersection&lt;/strong&gt;: The ray finds the closest object intersecting the viewing ray.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Shading&lt;/strong&gt;: The intersection point, surface normal, and other information are used to determine the color of the pixel.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;A ray can be represented with a 3D parametric line from the eye $\mathbf{e}$ to a point $\mathbf{s}$ on the image plane as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p}(t) = \mathbf{e} + t(\mathbf{ s - e })&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{p}(0) = \mathbf{e}$&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{p}(1) = \mathbf{s}$&lt;/li&gt;&#xA;&lt;li&gt;If $0 &amp;lt; t_1 &amp;lt; t_2$, then $\mathbf{p}(t_1)$ is closer to $\mathbf{e}$ than $\mathbf{p}(t_2)$.&lt;/li&gt;&#xA;&lt;li&gt;If $t &amp;lt; 0$, then $\mathbf{p}(t)$ is behind $\mathbf{e}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;camera-coordinate-system&#34;&gt;Camera Coordinate System&lt;/h2&gt;&#xA;&lt;p&gt;All the rays start from the origin of an orthonormal coordinate frame known as the camera/eye coordinate system. In this frame, the camera is looking at the negative $\mathbf{w}$ axis.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/ray-tracing%21camera.jpg&#34; alt=&#34;Camera&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Camera&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;The coordinate system is built from:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The &lt;em&gt;viewpoint&lt;/em&gt; $\mathbf{e}$, which is at the origin of the camera coordinate system.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;em&gt;view direction&lt;/em&gt;, which is $\mathbf{-w}$.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;em&gt;up vector&lt;/em&gt;, which is used to construct a basis that has $\mathbf{v}$ and $\mathbf{w}$ in the plane defined by the &lt;em&gt;view direction&lt;/em&gt; and the &lt;em&gt;up vector&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;ray-generation&#34;&gt;Ray Generation&lt;/h2&gt;&#xA;&lt;h3 id=&#34;pixel-coordinates&#34;&gt;Pixel Coordinates&lt;/h3&gt;&#xA;&lt;p&gt;The image dimensions are defined with four numbers:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$l,  r$: the position of the left and right edges.&lt;/li&gt;&#xA;&lt;li&gt;$t,  b$: the position of the top and bottom edges.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Note that the coordinates are expressed in the camera coordinate frame defined in a plane parallel to the $w=0$ plane (the $w=0$ plane is defined by the point $\mathbf{e}$ and the vectors $\mathbf{u}$ and $\mathbf{v}$).&lt;/p&gt;&#xA;&lt;p&gt;The image has to be fitted within a rectangle of $n_x \times n_y$ pixels. For example, the pixel $(0,0)$ has the position $(l + 0.5 \tfrac{r - l}{n_x}, b + 0.5 \tfrac{t - b}{n_y})$. Note that the half-pixel measurement times pixel-dimension is because of the way a pixel is defined (see &#xA;&#xA;&lt;a href=&#34;../rendering&#34;target=&#34;_blank&#34;&gt;rendering&lt;/a&gt;&#xA;&#xA;). A pixel with coordinates $(x, y)$ will have the position:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;u = l + (x + 0.5) \frac{r - l}{n_x} \\&#xA;v = b + (y + 0.5) \frac{t - b}{n_y}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;orthographic-view&#34;&gt;Orthographic View&lt;/h3&gt;&#xA;&lt;p&gt;For an orthographic view, all the rays will have the direction $-\mathbf{w}$. There isn&amp;rsquo;t a particular viewpoint; however, we can define all the rays to be emitted from the $w=0$ plane using the pixel&amp;rsquo;s image-plane position as the ray&amp;rsquo;s starting point.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/ray-tracing%21orthographic.jpg&#34; alt=&#34;Orthographic View&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Orthographic View&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{ray_{direction}} &amp;= -\mathbf{w} \\&#xA;\mathbf{ray_{origin}} &amp;= \mathbf{e} + u \mathbf{u} + v \mathbf{v}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;perspective-view&#34;&gt;Perspective View&lt;/h3&gt;&#xA;&lt;p&gt;For a perspective view, all the rays will have the same origin $e$, but the image-plane is not located at $w=0$ but at some distance $d$ in the $-\mathbf{w}$ direction. This time, each ray will have a varying direction based on the location of the pixel&amp;rsquo;s image-plane position with respect to $e$.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/ray-tracing%21perspective.jpg&#34; alt=&#34;Perspective View&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Perspective View&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{ray_{direction}} &amp;= -d \mathbf{w} + u \mathbf{u} + v \mathbf{v} \\&#xA;\mathbf{ray_{origin}} &amp;= \mathbf{e}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;ray-intersection&#34;&gt;Ray Intersection&lt;/h2&gt;&#xA;&lt;p&gt;Once a ray in the form $\mathbf{e} + t\mathbf{d}$ is generated, we find the first intersection with an object where $t &amp;gt; 0$. Whenever there are many objects that intersect a ray, the intersection point with the lowest $t$ is returned.&lt;/p&gt;&#xA;&lt;p&gt;The following pseudocode tests for &amp;ldquo;hits&amp;rdquo;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plain&#34;&gt;ray = e + td&#xA;t = infinity&#xA;for each `object` in the scene&#xA;  if `object` is hit by `ray` and `ray&#39;s t` &amp;lt; `t`&#xA;    hit object = `object`&#xA;    t = `ray&#39;s t`&#xA;return hit t &amp;lt; infinity&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;shading&#34;&gt;Shading&lt;/h2&gt;&#xA;&lt;p&gt;Once the visible surface is known, the next step is to compute the value of the pixel using a &lt;strong&gt;shading model&lt;/strong&gt;, which can be made out of simple heuristics or elaborate numeric computations.&lt;/p&gt;&#xA;&lt;p&gt;A shading model is designed to &lt;em&gt;capture the process of light reflection on a surface&lt;/em&gt;. The important variables in this process are:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{p}$ (intersection point) - the intersection point between a surface and a ray.&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{l}$ (light direction) - a unit vector pointing from the surface towards a light source, computed by normalizing the vector between the intersection point $\mathbf{p}$ and the light source position $\mathbf{l_s}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{l} = \frac{\mathbf{l_s - p}}{\norm{\mathbf{l_s - p}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{v}$ (view direction) - a unit vector pointing from the surface towards the place the ray is emitted from. It&amp;rsquo;s computed by normalizing the vector between the intersection point $\mathbf{p}$ and the ray origin $\mathbf{ray_{origin}}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = \frac{\mathbf{ray_{origin} - p}}{\norm{\mathbf{ray_{origin} - p}}} \quad \text{or} \quad \mathbf{v} = -\mathbf{d}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{n}$ (surface normal) - a unit vector perpendicular to the surface at the point where the reflection is taking place.&lt;/li&gt;&#xA;&lt;li&gt;Other characteristics of the light source and the surface, depending on the shading model.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;lambertian-shading&#34;&gt;Lambertian Shading&lt;/h3&gt;&#xA;&lt;p&gt;One of the simplest shading models, discovered by Lambert in the 18th century. The amount of energy from a light source that falls on a surface depends on the angle of the surface to the light.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/ray-tracing%21lambert.jpg&#34; alt=&#34;Lambert&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Lambert&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A surface facing directly the light receives maximum illumination.&lt;/li&gt;&#xA;&lt;li&gt;A surface tangent to the light receives no illumination.&lt;/li&gt;&#xA;&lt;li&gt;A surface facing away from the light receives no illumination.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Thus, the illumination is proportional to the cosine of the angle between $\mathbf{n}$ and $\mathbf{l}$, i.e., $\mathbf{n \cdot l} = \cos{\theta}$. The color of the pixel is then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;L = k_d \cdot I \cdot max(0, \mathbf{n \cdot l})&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$k_d$ is the diffuse coefficient, a characteristic of the surface.&lt;/li&gt;&#xA;&lt;li&gt;$I$ is the intensity of the light source.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Additional notes of this model:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The model is view-independent.&lt;/li&gt;&#xA;&lt;li&gt;The color of the surface appears to have a very matte, chalky appearance.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;blinn-phong-shading&#34;&gt;Blinn-Phong Shading&lt;/h3&gt;&#xA;&lt;p&gt;Many surfaces show some degree of highlights (shininess) or &lt;em&gt;specular reflections&lt;/em&gt; that appear to move as the viewpoint changes. The idea is to produce reflections when $\mathbf{v}$ and $\mathbf{l}$ are positioned symmetrically across the surface normal.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/ray-tracing%21blinn-phong.jpg&#34; alt=&#34;Blinn-Phong&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Blinn-Phong&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The half vector $\mathbf{h}$ is a unit vector that goes through the bisector of the angle between $\mathbf{v}$ and $\mathbf{l}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{h} = \frac{\mathbf{v + l}}{\norm{\mathbf{v + l}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Also:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $\mathbf{h}$ is near $\mathbf{n}$, then the specular component should be bright; if it&amp;rsquo;s far away, it should be dim. Therefore, the illumination is proportional to the cosine of the angle between $\mathbf{n}$ and $\mathbf{h}$, i.e., $\mathbf{n \cdot h} = \cos {\theta}$.&lt;/li&gt;&#xA;&lt;li&gt;The specular component decreases exponentially when $\mathbf{h}$ is far away from $\mathbf{n}$. Therefore, the result is taken to the $p$ power, $p &amp;gt; 1$, to make it decrease faster.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The color of the pixel is then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;L = k_d \cdot I \cdot max(0, \mathbf{n \cdot l}) + k_s \cdot I \cdot max(0, \mathbf{n \cdot h})^p&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$k_s$ is the specular coefficient, a characteristic of the surface.&lt;/li&gt;&#xA;&lt;li&gt;$I$ is the intensity of the light source.&lt;/li&gt;&#xA;&lt;li&gt;$p$ is a variable that controls how fast the result decreases.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Note that the color of the pixel is the overall contribution of both the Lambertian shading model and the Blinn-Phong shading model.&lt;/p&gt;&#xA;&lt;h3 id=&#34;ambient-shading&#34;&gt;Ambient Shading&lt;/h3&gt;&#xA;&lt;p&gt;Surfaces that receive no illumination are rendered completely black. To avoid this, a constant component is added to the shading model. The color depends entirely on the object hit, with no dependence on the surface geometry.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;L = k_a \cdot I_a + k_d \cdot I \cdot max(0, \mathbf{n \cdot l}) + k_s \cdot I \cdot max(0, \mathbf{n \cdot h})^p&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$k_a$ is the surface ambient coefficient.&lt;/li&gt;&#xA;&lt;li&gt;$I_a$ is the ambient light intensity.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Rendering</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/rendering/</link>
      <pubDate>Fri, 26 Feb 2016 16:59:48 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/rendering/</guid>
      <description>&lt;p&gt;An image can be abstracted as a function:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;I(x,y): R \rightarrow V&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $R \in \mathbb{R}^2$ is a rectangular area and $V$ is a set with the possible pixel values. The following are examples of the set $V$:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$V = \mathbb{R}^+$ (non-negative reals) for grayscale images; each pixel represents only brightness and no color.&lt;/li&gt;&#xA;&lt;li&gt;$V = (\mathbb{R}^+)^3$ (combinations of 3 sets of non-negative reals), which is a color image with red/green/blue values for each pixel.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;pixels&#34;&gt;Pixels&lt;/h2&gt;&#xA;&lt;p&gt;A pixel from a camera or scanner is a measurement of the average color of the image in the surrounding area near the pixel.&lt;/p&gt;&#xA;&lt;p&gt;If an image has $n_x$ columns and $n_y$ rows, a common convention is to count rows and columns from the bottom left. The bottom-left pixel is $(0,0)$, and the top-right is pixel $(n_x - 1, n_y - 1)$.&lt;/p&gt;&#xA;&lt;p&gt;Note that because of the definition given to a pixel, the coordinate $(0,0)$ is mapped to the center of the pixel $(0,0)$. Therefore, a half-pixel will exist in both the $-\mathbf{x}$-axis and the $-\mathbf{y}$-axis.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;is-responsive&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/rendering%21pixel-coordinates.jpg&#34; alt=&#34;Pixel Coordinates&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Pixel Coordinates&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;So the domain of a $n_x \times n_y$ image is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;R = [0.5, n_x - 0.5] \times [0.5, n_y - 0.5]&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;pixel-values&#34;&gt;Pixel Values&lt;/h3&gt;&#xA;&lt;p&gt;The value of a pixel depends on the precision and range of value needed. For example, &lt;em&gt;high dynamic range&lt;/em&gt; (HDR) images store floating-point numbers, allowing a wide range of values. &lt;em&gt;Low dynamic range&lt;/em&gt; (LDR) images are instead stored with integers. The following pixel-values are used in a variety of applications:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;1-bit grayscale per pixel&lt;/strong&gt;: Images where intermediate grays are not needed, e.g., text.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;8-bit grayscale per pixel&lt;/strong&gt;: Images with intermediate grays. It can store a total of 256 gray values, e.g., a grayscale photo.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;8-bit red, green, and blue (RGB), 24-bits per pixel&lt;/strong&gt;: Full-color images that allow near 16 million possible values, e.g., consumer photographs, web, and email applications.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;12- to 14-bit RGB, 36-42 bits per pixel&lt;/strong&gt;: Raw camera images for professional photography.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;16-bit half-precision RGB, 48 bits per pixel&lt;/strong&gt;: HDR images used in real-time rendering.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;32-bit floating-point RGB, 96 bits per pixel&lt;/strong&gt;: HDR images for software rendering.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Transformation Matrix for Projection of 3D Objects into a 2D Plane (Projection Transform)</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/projection-transform/</link>
      <pubDate>Sun, 14 Feb 2016 12:18:26 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/projection-transform/</guid>
      <description>&lt;p&gt;The &lt;em&gt;canonical view volume&lt;/em&gt; is a cube with its extreme points at [-1, -1, -1] and [1, 1, 1]. Coordinates in this view volume are called &lt;em&gt;normalized device coordinates&lt;/em&gt; (NDC). The objective of this step is to build a transformation matrix so that a region of space we want to render, called the &lt;em&gt;view volume&lt;/em&gt;, is mapped to the &lt;em&gt;canonical view volume&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v}_{ndc} = \mathbf{M}_{proj} \mathbf{v}_{view}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Some points expressed in &lt;em&gt;view space&lt;/em&gt; won&amp;rsquo;t be part of the view volume and will be discarded after the transformation. This process is called &#xA;&#xA;&lt;a href=&#34;https://www.opengl.org/wiki/Vertex_Post-Processing#Clipping&#34;target=&#34;_blank&#34;&gt;clipping&lt;/a&gt;&#xA;&#xA; (we only need to check if any coordinate of a point is outside the range [-1, 1] to discard it).&lt;/p&gt;&#xA;&lt;p&gt;Later, it&amp;rsquo;ll be seen that both transformations imply division, and a neat trick is the use of projective geometry to avoid division. Any point that has the form (\alpha x, \alpha y, \alpha z, 1) can be represented as (x, y, z, \tfrac{1}{\alpha}) in homogeneous coordinates. So, we can introduce an intermediate step that transforms the points to &lt;em&gt;clip coordinates&lt;/em&gt; and then to &lt;em&gt;normalized device coordinates&lt;/em&gt; by doing a division with the $w$-coordinate: $\tfrac{1}{1/\alpha} = \alpha$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v}_{clip} &amp;= \mathbf{M}_{proj} \mathbf{v}_{view} \\&#xA;\mathbf{v}_{ndc} &amp;= \alpha \mathbf{v}_{clip}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;orthographic-projection&#34;&gt;Orthographic Projection&lt;/h2&gt;&#xA;&lt;p&gt;An orthographic projection matrix is built with six parameters:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;left, right&lt;/em&gt;: planes in the $x$-axis&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;bottom, top&lt;/em&gt;: planes in the $y$-axis&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;near, far&lt;/em&gt;: planes in the $z$-axis&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These parameters bound the view volume, which is an axis-aligned bounding box.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projection-matrix%21orthographic.png&#34; alt=&#34;Orthographic Projection&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Orthographic Projection&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div id=&#34;orthographic-projection-animation&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Since the mapping of the range $[l, r]$ to the range $[-1, 1]$ is linear, we can use the equation of the line $y = mx + b$ and find the values of $m$ and $b$. However, we can intuitively get a similar equation by creating a function $f(x)$ so that $f(0) = -1$ and $f(1) = 1$. We can create a nested function $g(x)$ so that $g(l) = 0$ and $g(r) = 1$ (note that $[l, r]$ is the input range). Then $f(x)$ has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;f(x) &amp;= -1 + 2 \; g(x) \\&#xA;g(x) &amp;= \frac{x - l}{r - l}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally, $f(x)$ has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;f(x) &amp;= -1 + 2 \frac{x - l}{r - l} \nonumber \\&#xA;&amp;= \frac{l - r}{r - l} + \frac{2}{r - l}x - \frac{2l}{r - l} \nonumber \\&#xA;&amp;= \frac{2}{r - l}x + \frac{-l - r}{r - l} \nonumber \\&#xA;&amp;= \frac{2}{r - l}x - \frac{r + l}{r - l} \label{linear-mapping}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can adapt \eqref{linear-mapping} to have a similar form for the y-coordinate using $t$ and $b$. These equations are transformations from &lt;em&gt;view space&lt;/em&gt; to &lt;em&gt;clip space&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x_{clip} = \frac{2}{r - l}x_{view} - \frac{r + l}{r - l}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;y_{clip} = \frac{2}{t - b}y_{view} - \frac{t + b}{t - b}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The $z_{clip}$ value will be different from the ones above since we&amp;rsquo;re mapping $[-n, -f] \Rightarrow [-1, 1]$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z_{clip} &amp;= \frac{2}{-f - (-n)}z_{view} - \frac{-f + (-n)}{-f - (-n)} \\&#xA;&amp;= \frac{2}{-f + n}z_{view} - \frac{-f - n}{-f + n} \\&#xA;&amp;= -\frac{2}{f - n}z_{view} + \frac{-f - n}{f - n} \\&#xA;&amp;= -\frac{2}{f - n}z_{view} - \frac{f + n}{f - n}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The $w$ is left untouched since the projection doesn&amp;rsquo;t imply division. The &lt;strong&gt;general orthographic projection matrix&lt;/strong&gt; is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{orthographic-projection}&#xA;\mathbf{M}_{proj} = \begin{bmatrix}&#xA;\tfrac{2}{r - l} &amp; 0 &amp; 0 &amp; -\tfrac{r + l}{r - l} \\&#xA;0 &amp; \tfrac{2}{t - b} &amp; 0 &amp; -\tfrac{t + b}{t - b} \\&#xA;0 &amp; 0 &amp; -\tfrac{2}{f - n} &amp; -\tfrac{f + n}{f - n} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The transformation matrix from &lt;em&gt;view space&lt;/em&gt; to &lt;em&gt;clip space&lt;/em&gt; is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v}_{clip} &amp;= \mathbf{M}_{proj} \mathbf{v}_{view} \\&#xA;\begin{bmatrix} x_{clip} \\ y_{clip} \\ z_{clip} \\ w_{clip} \end{bmatrix} &amp;= \begin{bmatrix}&#xA;\tfrac{2}{r - l} &amp; 0 &amp; 0 &amp; -\tfrac{r + l}{r - l} \\&#xA;0 &amp; \tfrac{2}{t - b} &amp; 0 &amp; -\tfrac{t + b}{t - b} \\&#xA;0 &amp; 0 &amp; -\tfrac{2}{f - n} &amp; -\tfrac{f + n}{f - n} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} x_{view} \\ y_{view} \\ z_{view} \\ w_{view} \end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally, note that $w_{clip}$ will always have the value of $w_{view} = 1$. Therefore, the transformation to NDC will not modify the coordinates:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix} x_{ndc} \\ y_{ndc} \\ z_{ndc} \end{bmatrix} = \begin{bmatrix}&#xA;x_{view}/1 \\&#xA;y_{view}/1 \\&#xA;z_{view}/1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;building-the-matrix-using-combined-transformations&#34;&gt;Building the Matrix Using Combined Transformations&lt;/h3&gt;&#xA;&lt;p&gt;A simpler way to think about this orthographic projection transformation is by splitting it into three steps:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Translation of the bottom-left-near corner to the origin, i.e., $[l, b, -n] \rightarrow [0, 0, 0]$.&lt;/li&gt;&#xA;&lt;li&gt;Scale it to be a 2-unit length cube.&lt;/li&gt;&#xA;&lt;li&gt;Translation of the bottom-left corner from the origin, i.e., $[0, 0, 0] \rightarrow [-1, -1, -1]$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{M}_{proj} &amp;= \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; -1 \\&#xA;0 &amp; 1 &amp; 0 &amp; -1 \\&#xA;0 &amp; 0 &amp; 1 &amp; -1 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xA;\end{bmatrix} \begin{bmatrix}&#xA;\tfrac{2}{r - l} &amp; 0 &amp; 0 &amp; 0 \\&#xA;0 &amp; \tfrac{2}{t - b} &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; -\tfrac{2}{f - n} &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; -l \\&#xA;0 &amp; 1 &amp; 0 &amp; -b \\&#xA;0 &amp; 0 &amp; 1 &amp; n \\&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xA;\end{bmatrix} \\&#xA;\&#xA;&amp;= \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; -1 \\&#xA;0 &amp; 1 &amp; 0 &amp; -1 \\&#xA;0 &amp; 0 &amp; 1 &amp; -1 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1 \\&#xA;\end{bmatrix} \begin{bmatrix}&#xA;\tfrac{2}{r - l} &amp; 0 &amp; 0 &amp; -\frac{2l}{r - l} \\&#xA;0 &amp; \tfrac{2}{t - b} &amp; 0 &amp; -\frac{2b}{t - b} \\&#xA;0 &amp; 0 &amp; -\tfrac{2}{f - n} &amp; -\frac{2n}{f - n} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \\&#xA;\&#xA;&amp;= \begin{bmatrix}&#xA;\tfrac{2}{r - l} &amp; 0 &amp; 0 &amp; -\frac{2l}{r - l} - 1 \\&#xA;0 &amp; \tfrac{2}{t - b} &amp; 0 &amp; -\frac{2b}{t - b} - 1 \\&#xA;0 &amp; 0 &amp; -\tfrac{2}{f - n} &amp; -\frac{2n}{f - n} - 1 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \\&#xA;\&#xA;&amp;= \begin{bmatrix}&#xA;\tfrac{2}{r - l} &amp; 0 &amp; 0 &amp; -\tfrac{r + l}{r - l} \\&#xA;0 &amp; \tfrac{2}{t - b} &amp; 0 &amp; -\tfrac{t + b}{t - b} \\&#xA;0 &amp; 0 &amp; -\tfrac{2}{f - n} &amp; -\tfrac{f + n}{f - n} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;perspective-projection&#34;&gt;Perspective Projection&lt;/h2&gt;&#xA;&lt;p&gt;Projective geometry concepts are used in this type of projection, particularly the fact that objects away from the point of view appear smaller after projection. This type of projection mimics how we perceive objects in reality.&lt;/p&gt;&#xA;&lt;p&gt;A perspective projection matrix is built with six parameters: &lt;em&gt;left, right, bottom, top, near, far&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;left, right&lt;/em&gt;: $x$-axis bounds for the near plane.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;bottom, top&lt;/em&gt;: $y$-axis bounds for the near plane.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;near, far&lt;/em&gt;: planes in the $z$-axis. The intersection point of the line passing through the origin parallel to the vector $[l,b,-n]$ and the plane &lt;em&gt;far&lt;/em&gt; is the bottom-left-far extreme of the view volume. A similar logic is used to find all the extremes in the &lt;em&gt;far&lt;/em&gt; plane of the view volume.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;These parameters define a truncated pyramid, also called a &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Frustum&#34;target=&#34;_blank&#34;&gt;frustum&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projection-matrix%21perspective-all.png&#34; alt=&#34;Perspective Projection&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Perspective Projection&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div id=&#34;perspective-projection-animation&#34;&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;general-perspective-projection-matrix&#34;&gt;General Perspective Projection Matrix&lt;/h3&gt;&#xA;&lt;p&gt;The mapping of the range $[l,r]$ to the range $[-1,1]$ can be split into two steps:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Project all the points to the &lt;em&gt;near&lt;/em&gt; plane. This way, all the $x$- and $y$-coordinates will be inside the range $[l,r] \times [b,t]$.&lt;/li&gt;&#xA;&lt;li&gt;Map all the values in the range $[l,r]$ and $[b,t]$ to the range $[-1, 1]$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col tw-gap-4 md:tw-flex-row&#34;&gt;&#xA;    &lt;div class=&#34;md:tw-w-1/2&#34;&gt;&#xA;        &#xA;        &#xA;        &lt;figure class=&#34;&#34;&#xA;                &#xA;                &#xA;        &gt;&#xA;            &#xA;                &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projection-matrix%21top-view-frustum.png&#34; alt=&#34;Top view of the frustum&#34; /&gt;&#xA;            &#xA;            &#xA;            &lt;figcaption&gt;&#xA;                &lt;p class=&#34;tw-text-base&#34;&gt;Top view of the frustum&lt;/p&gt;&#xA;                &#xA;            &lt;/figcaption&gt;&#xA;            &#xA;        &lt;/figure&gt;&#xA;        &#xA;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;md:tw-w-1/2&#34;&gt;&#xA;        &#xA;        &#xA;        &lt;figure class=&#34;&#34;&#xA;                &#xA;                &#xA;        &gt;&#xA;            &#xA;                &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projection-matrix%21side-view-frustum.png&#34; alt=&#34;Side view of the frustum&#34; /&gt;&#xA;            &#xA;            &#xA;            &lt;figcaption&gt;&#xA;                &lt;p class=&#34;tw-text-base&#34;&gt;Side view of the frustum&lt;/p&gt;&#xA;                &#xA;            &lt;/figcaption&gt;&#xA;            &#xA;        &lt;/figure&gt;&#xA;        &#xA;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Let $\mathbf{v}_{view}$ be a vector in &lt;em&gt;view space&lt;/em&gt; which is going to be transformed to &lt;em&gt;clip space&lt;/em&gt;. By similar triangles, we see that the value of $x_p$ and $y_p$ (the coordinates projected to the &lt;em&gt;near&lt;/em&gt; plane) is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;\label{projection-near}&#xA;\frac{x_p}{x_{view}} &amp;= \frac{-n}{z_{view}} \quad \quad x_p = \frac{n \cdot x_{view}}{-z_{view}} \\&#xA;\frac{y_p}{y_{view}} &amp;= \frac{-n}{z_{view}} \quad \quad y_p = \frac{n \cdot y_{view}}{-z_{view}}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that both quantities are inversely proportional to $-z_{view}$. What we can do is manipulate the coordinate so that it has a common denominator:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix} \tfrac{n \cdot x_{view}}{-z_{view}} &amp; \tfrac{n \cdot y_{view}}{-z_{view}} &amp; n \tfrac{z_{view}}{-z_{view}} \end{bmatrix}^T = \frac{  \begin{bmatrix} n \cdot x_{view} &amp; n \cdot y_{view} &amp; n \cdot z_{view} \end{bmatrix}^T }{-z_{view}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The point in homogeneous coordinates is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix} n \cdot x_{view} &amp; n \cdot y_{view} &amp; n \cdot z_{view}&amp; \tfrac{1}{-z_{view}}  \end{bmatrix}^T&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;OpenGL will then project any 4D homogeneous coordinate to the 3D hyperplane $w=1$ by dividing each of the coordinates by $w$. Note that this division operation isn&#39;t done by the application but by OpenGL itself in a further step on the rendering pipeline.&lt;/p&gt;&#xA;&lt;p&gt;We can take advantage of this process and use $-z_{view}$ as our $w$. With this in mind, we can construct a transformation matrix so that transformed points have $w = -z_{view}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;\begin{bmatrix} x_{clip} \\ y_{clip} \\ z_{clip} \\ w_{clip} \end{bmatrix} &amp;= \begin{bmatrix}&#xA;. &amp; . &amp; . &amp; . \\&#xA;. &amp; . &amp; . &amp; . \\&#xA;. &amp; . &amp; . &amp; . \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{bmatrix} \begin{bmatrix} x_{view} \\ y_{view} \\ z_{view} \\ w_{view} \end{bmatrix} \label{pm1} \\&#xA;\therefore w_{clip} &amp;= -z_{view}  \nonumber&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $x_{clip}, y_{clip}, z_{clip}, w_{clip}$ are expressed in terms of the &lt;em&gt;clip space&lt;/em&gt;. When each coordinate is divided by $w_{clip}$, we&amp;rsquo;ll have NDC:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix} x_{ndc} \\ y_{ndc} \\ z_{ndc} \end{bmatrix} = \begin{bmatrix} x_{clip}/w_{clip} \\ y_{clip}/w_{clip} \\ z_{clip}/w_{clip} \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Next, $x_p$ and $y_p$ are mapped linearly to $[-1,1]$. We can use the function to perform linear mapping \eqref{linear-mapping}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;x_{ndc} = \frac{2}{r - l}x_p - \frac{r + l}{r - l} \nonumber \\&#xA;y_{ndc} = \frac{2}{t - b}y_p - \frac{t + b}{t - b} \label{ndc-near}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Next, we substitute the values of $x_p$ \eqref{projection-near} in $x_{ndc}$ \eqref{ndc-near}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x_{ndc} &amp;= \frac{2}{r - l}\frac{n \cdot x_{view}}{-z_{view}} - \frac{r + l}{r - l} \\&#xA;&amp;= \frac{2n}{r - l} \frac{x_{view}}{-z_{view}} - \frac{r + l}{r - l} \frac{-z_{view}}{-z_{view}} \\&#xA;&amp;= \left (  \frac{2n}{r - l} x_{view} + \frac{r + l}{r - l} z_{view} \right ) \big / -z_{view}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the second fraction is manipulated so that it&amp;rsquo;s also divisible by $-z_{view}$. Also, note that the quantity in the parenthesis is in &lt;em&gt;clip space coordinates&lt;/em&gt;: $x_{clip}$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x_{clip} = \frac{2n}{r - l} x_{view} + \frac{r + l}{r - l} z_{view}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Similarly, the value of $y_{clip}$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y_{clip} = \frac{2n}{t - b} y_{view} + \frac{t + b}{t - b} z_{view}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then the transformation matrix seen in \eqref{pm1} is now:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{pm2}&#xA;\begin{bmatrix} x_{clip} \\ y_{clip} \\ z_{clip} \\ w_{clip} \end{bmatrix} = \begin{bmatrix}&#xA;\tfrac{2n}{r - l} &amp; 0 &amp; \tfrac{r + l}{r - l} &amp; 0 \\&#xA;0 &amp; \tfrac{2n}{t - b} &amp; \tfrac{t + b}{t - b} &amp; 0 \\&#xA;. &amp; . &amp; . &amp; . \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{bmatrix} \begin{bmatrix} x_{view} \\ y_{view} \\ z_{view} \\ w_{view} \end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Next, we need to find the value of $z_{clip}$. Note that the projected value is always a constant because the $z_{clip}$ component depends on $z_{view}$ and is also divided by $-z_{view}$. We need &lt;strong&gt;$z_{clip}$ to be unique for the clipping and depth test&lt;/strong&gt;. Plus, we should be able to unproject it (through an inverse transformation).&lt;/p&gt;&#xA;&lt;p&gt;Since $z_{ndc}$ doesn&amp;rsquo;t depend on $x_{view}$ or $y_{view}$, we can borrow the $w$-coordinate to find the relationship between $z_{ndc}$ and $z_{view}$. With that in mind, we can make the third row of \eqref{pm2} equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{pm3}&#xA;\begin{bmatrix} x_{clip} \\ y_{clip} \\ z_{clip} \\ w_{clip} \end{bmatrix} = \begin{bmatrix}&#xA;\tfrac{2n}{r - l} &amp; 0 &amp; \tfrac{r + l}{r - l} &amp; 0 \\&#xA;0 &amp; \tfrac{2n}{t - b} &amp; \tfrac{t + b}{t - b} &amp; 0 \\&#xA;0 &amp; 0 &amp; A &amp; B \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{bmatrix} \begin{bmatrix} x_{view} \\ y_{view} \\ z_{view} \\ w_{view} \end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then $z_{ndc}$ has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z_{ndc} = \frac{z_{clip}}{w_{clip}} = \frac{Az_{view} + Bw_{view}}{-z_{view}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since $w_{view}=1$ in &lt;em&gt;view space&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z_{ndc} = \frac{Az_{view} + B}{-z_{view}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the value is not linear, but it needs to be mapped to $[-n, -f] \mapsto [-1,1]$. Substituting the desired output range $[-1, 1]$ as $z_{ndc}$, we have a system of equations:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{cases}&#xA;-1 &amp;= \frac{-An + B}{n} \\&#xA;1 &amp;= \frac{-Af + B}{f}&#xA;\end{cases} \rightarrow&#xA;\begin{cases}&#xA;-An + B &amp;= -n \\&#xA;-Af + B &amp;= f&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Subtracting the second equation from the first:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;-An + B + Af - B &amp;= -n - f \\&#xA;A (f - n) &amp;= -n - f \\&#xA;A = -\frac{f + n}{f - n}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Solving for $B$ given $A$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{f + n}{f - n}n + B = -n&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;B &amp;= -n - \frac{f + n}{f - n}n \\&#xA;&amp;= \frac{-fn + n^2 - fn - n^2}{f - n} \\&#xA;&amp;= \frac{-2fn}{f - n} \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Substituting the values of $A$ and $B$ in \eqref{pm3}, we have the &lt;strong&gt;general perspective projection matrix&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{pm4}&#xA;\mathbf{M}_{proj} = \begin{bmatrix}&#xA;\tfrac{2n}{r - l} &amp; 0 &amp; \tfrac{r + l}{r - l} &amp; 0 \\&#xA;0 &amp; \tfrac{2n}{t - b} &amp; \tfrac{t + b}{t - b} &amp; 0 \\&#xA;0 &amp; 0 &amp; -\tfrac{f + n}{f - n} &amp; \tfrac{-2fn}{f - n} \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;symmetric-perspective-projection-matrix&#34;&gt;Symmetric Perspective Projection Matrix&lt;/h3&gt;&#xA;&lt;p&gt;If the viewing volume is symmetric, i.e., $r = -l$ and $t = -b$, then some quantities can be simplified:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;r + l = 0, \quad r - l = 2r \\&#xA;t + b = 0, \quad t - b = 2t&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then \eqref{pm4} becomes:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{pm5}&#xA;\mathbf{M}_{proj} = \begin{bmatrix}&#xA;\tfrac{n}{r} &amp; 0 &amp; 0 &amp; 0 \\&#xA;0 &amp; \tfrac{n}{t} &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; -\tfrac{f + n}{f - n} &amp; \tfrac{-2fn}{f - n} \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;symmetric-perspective-projection-matrix-from-field-of-viewaspect&#34;&gt;Symmetric Perspective Projection Matrix from Field of View/Aspect&lt;/h3&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml&#34;target=&#34;_blank&#34;&gt; &lt;code&gt;gluPerspective&lt;/code&gt;&lt;/a&gt;&#xA;&#xA; receives, instead of the $x$ and $y$ bounds, two arguments:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;em&gt;field of view&lt;/em&gt; ($fov$), which specifies the field of view angle in the $y$ direction.&lt;/li&gt;&#xA;&lt;li&gt;&lt;em&gt;aspect&lt;/em&gt; ($aspect$), which is the aspect ratio that determines the field of view in the $x$ direction, calculated as $\tfrac{x}{y}$. The value is commonly $\tfrac{screen\ width}{screen\ height}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;md:tw-w-1/2 tw-mx-auto&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/projection-matrix%21fov.png&#34; alt=&#34;fov&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;fov&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;We see that the value of $t$ (top) is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;\tan{ (fov/2) } &amp;= \frac{t}{n} \\&#xA; \label{fov-t}&#xA;t &amp;= n \cdot \tan{ (fov/2) }&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can find the value of $r$ (right) with the aspect ratio:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;aspect &amp;= \frac{2r}{2t} = \frac{r}{t} \\&#xA;r &amp;= aspect \cdot t \\&#xA; \label{fov-r}&#xA;&amp;= aspect \cdot n \cdot \tan{(fov/2)}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Substituting \eqref{fov-t} and \eqref{fov-r} in \eqref{pm5}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{pm6}&#xA;\mathbf{M}_{proj} = \begin{bmatrix}&#xA;\tfrac{1}{aspect \cdot \tan{ (fov/2) } } &amp; 0 &amp; 0 &amp; 0 \\&#xA;0 &amp; \frac{1}{\tan{ (fov/2) }} &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; -\tfrac{f + n}{f - n} &amp; \tfrac{-2fn}{f - n} \\&#xA;0 &amp; 0 &amp; -1 &amp; 0&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;script type=&#34;module&#34; src=&#34;https://www.mauriciopoppe.com/js/computer-graphics/projection.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Transformation Matrix to Transform 3D Objects from World Space to View Space (View Transform)</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/view-transform/</link>
      <pubDate>Sat, 13 Feb 2016 11:59:56 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/viewing/view-transform/</guid>
      <description>&lt;p&gt;The objective of this step is to find a transformation matrix to transform points expressed in &lt;em&gt;world space&lt;/em&gt; to &lt;em&gt;view space&lt;/em&gt;. A camera can be imagined to exist from a known point of view that captures some objects in the space.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v}_{view} = \mathbf{M}_{view} \mathbf{v}_{wld}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The construction of the transformation matrix to transform points from &lt;em&gt;world space&lt;/em&gt; to &lt;em&gt;view space&lt;/em&gt; needs three parameters:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{camera}$: a point expressed in world space defining the location of the point of view. Note that the $\mathbf{camera}$ is at the origin of the &lt;em&gt;view space&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{at}$: the direction where the camera is aiming.&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{up}$: denotes the upward orientation of the camera (typically coincides with the positive $y$-axis).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/camera-transformation%21camera-space.jpg&#34; alt=&#34;View Transform&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;View Transform&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;!--&#xA;In OpenGL we can use the GLU function `gluLookAt()` to position the camera&#xA;&#xA;```cpp&#xA;void gluLookAt(GLdouble xCam, GLdouble yCam, GLdouble zCam,&#xA;               GLdouble xAt, GLdouble yAt, GLdouble zAt,&#xA;               GLdouble xUp, GLdouble yUp, GLdouble zUp)&#xA;```&#xA;&#xA;The default value is&#xA;&#xA;```cpp&#xA;gluLookAt(0.0, 0.0, 0.0,&#xA;          0.0, 0.0, -100.0,&#xA;          0.0, 1.0, 0.0)&#xA;```&#xA;--&gt;&#xA;&lt;p&gt;Note that the camera is looking at the negative $z$-axis of the &lt;em&gt;view space&lt;/em&gt;; this is a convention rather than a rule since the &lt;em&gt;projection matrix&lt;/em&gt; will be constructed in a way so that points in the $-z$-axis in &lt;em&gt;view space&lt;/em&gt; are transformed to the range $[-1,1]$.&lt;/p&gt;&#xA;&lt;h2 id=&#34;derivation-of-the-view-transform-matrix&#34;&gt;Derivation of the View Transform Matrix&lt;/h2&gt;&#xA;&lt;p&gt;The process of transforming the vertices in &lt;em&gt;world space&lt;/em&gt; to &lt;em&gt;view space&lt;/em&gt; is given by:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Creation of a coordinate frame for the &lt;em&gt;view space&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Application of the appropriate translation for the camera location (world space -&amp;gt; upright space).&lt;/li&gt;&#xA;&lt;li&gt;Transformation of the points in world space to camera space (upright space -&amp;gt; object space).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;creation-of-a-coordinate-frame-for-the-view-space&#34;&gt;Creation of a Coordinate Frame for the View Space&lt;/h3&gt;&#xA;&lt;p&gt;Given $\mathbf{camera}$, $\mathbf{at}$, and $\mathbf{up}$, the steps to compute the coordinate frame whose basis vectors are $\mathbf{u}$, $\mathbf{v}$, and $\mathbf{w}$ are as follows (note that since these are basis vectors, they need to be unit vectors):&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Compute $\mathbf{w}$ trivially by normalizing the vector $\mathbf{camera - at}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{w} = \frac{\mathbf{camera - at}}{\norm{\mathbf{camera - at}}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Next, $\mathbf{u}$ can be computed with the cross product of $\mathbf{w}$ and $\mathbf{up}$. Again, the resulting vector must be normalized.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{u} = \frac{\mathbf{w} \times \mathbf{up}}{\norm{ \mathbf{w} \times \mathbf{up} }}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Finally, $\mathbf{v}$ can be computed as:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = \mathbf{w} \times \mathbf{u}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;camera-translation&#34;&gt;Camera Translation&lt;/h3&gt;&#xA;&lt;p&gt;The transformation matrix that moves all the points from &lt;em&gt;world space&lt;/em&gt; to &lt;em&gt;view&amp;rsquo;s upright space&lt;/em&gt; is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{T} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; -camera_x \\&#xA;0 &amp; 1 &amp; 0 &amp; -camera_y \\&#xA;0 &amp; 0 &amp; 1 &amp; -camera_z \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;transformation-of-the-points-from-world-space-to-view-space&#34;&gt;Transformation of the Points from World Space to View Space&lt;/h3&gt;&#xA;&lt;p&gt;Given that the camera transformation basis vectors (encoded in a matrix) are:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{wld \leftarrow view} = \begin{bmatrix}&#xA;\mathbf{u}_{3 \times 1} &amp;&#xA;\mathbf{v}_{3 \times 1} &amp;&#xA;\mathbf{w}_{3 \times 1}&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Expressed in a 4x4 matrix:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{wld \leftarrow view} = \begin{bmatrix}&#xA;x_u &amp; x_v &amp; x_w &amp; 0 \\&#xA;y_u &amp; y_v &amp; y_w &amp; 0 \\&#xA;z_u &amp; z_v &amp; z_w &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This works as a transformation matrix to transform points from &lt;em&gt;view space&lt;/em&gt; to &lt;em&gt;world space&lt;/em&gt;. Therefore, the matrix that does the opposite operation (transformation from &lt;em&gt;world space&lt;/em&gt; to &lt;em&gt;view space&lt;/em&gt;) is the inverse of this matrix (the transpose is equivalent since the matrix is orthonormal).&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{view \leftarrow wld} = \mathbf{M^{-1}}_{wld \leftarrow view}  = \mathbf{M}^T_{wld \leftarrow view} = \begin{bmatrix}&#xA;x_u &amp; y_u &amp; z_u &amp; 0 \\&#xA;x_v &amp; y_v &amp; z_v &amp; 0 \\&#xA;x_w &amp; y_w &amp; z_w &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;the-view-matrix&#34;&gt;The View Matrix&lt;/h3&gt;&#xA;&lt;p&gt;We can combine the translation and the rotation matrix in a single matrix called the &lt;em&gt;view matrix&lt;/em&gt;, which has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{M}_{view} &amp;= \mathbf{M}_{view \leftarrow wld} \mathbf{T}  \\&#xA;&amp;= \begin{bmatrix}&#xA;x_u &amp; y_u &amp; z_u &amp; 0 \\&#xA;x_v &amp; y_v &amp; z_v &amp; 0 \\&#xA;x_w &amp; y_w &amp; z_w &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; -camera_x \\&#xA;0 &amp; 1 &amp; 0 &amp; -camera_y \\&#xA;0 &amp; 0 &amp; 1 &amp; -camera_z \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \\&#xA;&amp;= \begin{bmatrix}&#xA;x_u &amp; y_u &amp; z_u &amp; - \mathbf{camera} \cdot \mathbf{u} \\&#xA;x_v &amp; y_v &amp; z_v &amp; - \mathbf{camera} \cdot \mathbf{v} \\&#xA;x_w &amp; y_w &amp; z_w &amp; - \mathbf{camera} \cdot \mathbf{w} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Combining Matrix Transformations</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/combining-transformations/</link>
      <pubDate>Wed, 10 Feb 2016 21:13:17 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/combining-transformations/</guid>
      <description>&lt;p&gt;This article is part 5 in the series about transformation matrices:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../coordinate-systems/&#34;target=&#34;_blank&#34;&gt;Part 1: Coordinate systems and transformations between them&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../scale/&#34;target=&#34;_blank&#34;&gt;Part 2: Scaling objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../shearing/&#34;target=&#34;_blank&#34;&gt;Part 3: Shearing objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../translation/&#34;target=&#34;_blank&#34;&gt;Part 4: Translating objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&#xA;&#xA;&lt;a href=&#34;../combining-transformations/&#34;target=&#34;_blank&#34;&gt;Part 5: Combining Matrix Transformations&lt;/a&gt;&#xA;&#xA; (this article)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;We can compose a series of transformations by multiplying the matrices that define the transformation. For example, if we have one object in the world with an arbitrary position and orientation that we want to render through a camera lens located in the same world, also with an arbitrary position and orientation, to get the coordinates of the object relative to the camera lens, we must transform the object from &lt;em&gt;object space&lt;/em&gt; to &lt;em&gt;world space&lt;/em&gt; (a transformation known as &lt;strong&gt;model transform&lt;/strong&gt;), denoted by the matrix $\mathbf{M}_{world \leftarrow object}$, and then transform the vertices of the object from &lt;em&gt;world space&lt;/em&gt; to &lt;em&gt;view space&lt;/em&gt; (a transformation known as &lt;strong&gt;view transform&lt;/strong&gt;), denoted with $\mathbf{M}_{view \leftarrow world}$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v}_{world} &amp;= \mathbf{M}_{world \leftarrow object} \mathbf{v}_{object} \\&#xA;\mathbf{v}_{view} &amp;= \mathbf{M}_{view \leftarrow world} \mathbf{v}_{world} \\&#xA;&amp;= \mathbf{M}_{view \leftarrow world} \mathbf{M}_{world \leftarrow object}  \mathbf{v}_{object}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can associate the transformation matrices and have a single matrix to transform vertices of the object directly to &lt;em&gt;camera space&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v}_{view} &amp;= (\mathbf{M}_{view \leftarrow world} \mathbf{M}_{world \leftarrow object})\mathbf{v}_{object} \\&#xA; &amp;= \mathbf{M}_{view \leftarrow object} \mathbf{v}_{object}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now, if we have two transformation matrices $\mathbf{M}$ and $\mathbf{N}$ and they are applied to some vector $\mathbf{v}$ in that respective order, their product is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{NM} = \begin{bmatrix}&#xA;\mathbf{\cuv{s}} &amp;&#xA;\mathbf{\cuv{t}} &amp;&#xA;\mathbf{\cuv{u}}&#xA;\end{bmatrix}&#xA;\begin{bmatrix}&#xA;\mathbf{\cuv{p}} &amp;&#xA;\mathbf{\cuv{q}} &amp;&#xA;\mathbf{\cuv{r}}&#xA;\end{bmatrix}&#xA;= \begin{bmatrix}&#xA;p_x \mathbf{s} + p_y \mathbf{t} + p_z \mathbf{u} \\&#xA;q_x \mathbf{s} + q_y \mathbf{t} + q_z \mathbf{u} \\&#xA;r_x \mathbf{s} + r_y \mathbf{t} + r_z \mathbf{u} \\&#xA;\end{bmatrix}^T&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can see that the rows of the product $\mathbf{NM}$ are the result of transforming the basis vectors of $\mathbf{M}$ by the transformation matrix $\mathbf{N}$, so matrix-matrix multiplication encodes a basis vectors transformation.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rotation-followed-by-translation&#34;&gt;Rotation Followed by Translation&lt;/h2&gt;&#xA;&lt;p&gt;Given the vector $\mathbf{v}$, let&amp;rsquo;s apply a rotation and a translation transform in that order:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{TRv}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s analyze the product $\mathbf{TR}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{TR} = \begin{bmatrix}&#xA;I_{3 \times 3} &amp; T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix} \begin{bmatrix}&#xA;R_{3 \times 3} &amp; 0_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix} = \begin{bmatrix}&#xA;R_{3 \times 3} &amp; T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which, when multiplied by $\mathbf{v}$, results in:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{TRv} = \begin{bmatrix}&#xA;R_{3 \times 3} &amp; T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} \mathbf{v}_{3 \times 1} \\ 1 \end{bmatrix} = \begin{bmatrix} R_{3 \times 3} \mathbf{v}_{3 \times 1} + T_{3 \times 1} \\ 1 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$\mathbf{v&amp;rsquo;}$ will have a compact form equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{TRv} = \mathbf{Rv} + T_{3 \times 1}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;translation-followed-by-rotation&#34;&gt;Translation Followed by Rotation&lt;/h2&gt;&#xA;&lt;p&gt;Given the vector $\mathbf{v}$, let&amp;rsquo;s apply a translation and a rotation transform in that order:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{RTv}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s analyze the product $\mathbf{RT}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{RT} = \begin{bmatrix}&#xA;R_{3 \times 3} &amp; 0_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix} \begin{bmatrix}&#xA;I_{3 \times 3} &amp; T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix} = \begin{bmatrix}&#xA;R_{3 \times 3} &amp; R_{3 \times 3} T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which, when multiplied by $\mathbf{v}$, results in:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{TRv} = \begin{bmatrix}&#xA;R_{3 \times 3} &amp; R_{3 \times 3} T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} \mathbf{v}_{3 \times 1} \\ 1 \end{bmatrix} = \begin{bmatrix} R_{3 \times 3} \mathbf{v}_{3 \times 1} + R_{3 \times 3} T_{3 \times 1} \\ 1 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$\mathbf{v&amp;rsquo;}$ will have a compact form equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{RTv} = \mathbf{Rv} + \mathbf{R}T_{3 \times 1}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that both the vector $\mathbf{v}$ and the translation vector are transformed by $\mathbf{R}$.&lt;/p&gt;&#xA;&lt;h2 id=&#34;transformations-between-coordinate-systems&#34;&gt;Transformations Between Coordinate Systems&lt;/h2&gt;&#xA;&lt;p&gt;The following figure shows two coordinate systems. The one with the basis vectors $\mathbf{x}, \mathbf{y}$, and $\mathbf{z}$ is the canonical coordinate system. $\mathbf{u}, \mathbf{v}$, and $\mathbf{w}$ are the basis of a nested coordinate system expressed in terms of the canonical coordinate system.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/combining-transformations%21coordinate-systems.jpg&#34; alt=&#34;Coordinate Systems&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Coordinate Systems&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;The value of $\mathbf{p}$ expressed in the canonical coordinate system is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p} = x_p \mathbf{x} + y_p \mathbf{y} + z_p \mathbf{z}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Similarly, we can express $\mathbf{p}$ with the following equation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p} = \mathbf{e} + u_p \mathbf{u} + v_p \mathbf{v} + w_p \mathbf{w}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that both equations express $\mathbf{p}$ in terms of the canonical coordinate system. We can express the same relationship using transformation matrices as a &#xA;&#xA;&lt;a href=&#34;#rotation-followed-by-translation&#34;target=&#34;_blank&#34;&gt;rotation followed by a translation&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix} x_p \\ y_p \\ z_p \\ 1 \end{bmatrix} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; x_e \\&#xA;0 &amp; 1 &amp; 0 &amp; y_e \\&#xA;0 &amp; 0 &amp; 1 &amp; z_e \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix}&#xA;x_u &amp; x_v &amp; x_w &amp; 0 \\&#xA;y_u &amp; y_v &amp; y_w &amp; 0 \\&#xA;z_u &amp; z_v &amp; z_w &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} u_p \\ v_p \\ w_p \\ 1 \end{bmatrix} \\&#xA;\begin{bmatrix} x_p \\ y_p \\ z_p \\ 1 \end{bmatrix} = \begin{bmatrix}&#xA;x_u &amp; x_v &amp; x_w &amp; x_e \\&#xA;y_u &amp; y_v &amp; y_w &amp; y_e \\&#xA;z_u &amp; z_v &amp; z_w &amp; z_e \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} u_p \\ v_p \\ w_p \\ 1 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can then introduce $\mathbf{p}_{uvw}$, which is the point $\mathbf{p}$ expressed in the nested coordinate system. Similarly, $\mathbf{p}_{xyz}$ is the same point expressed in the canonical coordinate system.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{frame-to-canonical}&#xA;\mathbf{p}_{xyz} = \begin{bmatrix}&#xA;\mathbf{u}_{3 \times 1} &amp; \mathbf{v}_{3 \times 1} &amp; \mathbf{w}_{3 \times 1} &amp; \mathbf{e}_{3 \times 1} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \mathbf{p}_{uvw}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This is the &lt;strong&gt;frame-to-canonical&lt;/strong&gt; transformation matrix for the $(u,v,w)$ coordinate space.&lt;/p&gt;&#xA;&lt;p&gt;The inverse transformation is given by a &#xA;&#xA;&lt;a href=&#34;#translation-followed-by-rotation&#34;target=&#34;_blank&#34;&gt;translation followed by a rotation&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix} u_p \\ v_p \\ w_p \\ 1 \end{bmatrix} = \begin{bmatrix}&#xA;x_u &amp; y_u &amp; z_u &amp; 0 \\&#xA;x_v &amp; y_v &amp; z_v &amp; 0 \\&#xA;x_w &amp; y_w &amp; z_w &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; -x_e \\&#xA;0 &amp; 1 &amp; 0 &amp; -y_e \\&#xA;0 &amp; 0 &amp; 1 &amp; -z_e \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} x_p \\ y_p \\ z_p \\ 1 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which is the same as finding the value of $\mathbf{p}_{uvw}$ in \eqref{frame-to-canonical}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p}_{uvw} = \begin{bmatrix}&#xA;\mathbf{u}_{3 \times 1} &amp; \mathbf{v}_{3 \times 1} &amp; \mathbf{w}_{3 \times 1} &amp; \mathbf{e}_{3 \times 1} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}^{-1} \mathbf{p}_{xyz}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This is the &lt;strong&gt;canonical-to-frame&lt;/strong&gt; transformation matrix for the $(u,v,w)$ coordinate space.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Perspective Projection</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/projections/perspective/</link>
      <pubDate>Sat, 06 Feb 2016 18:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/projections/perspective/</guid>
      <description>&lt;p&gt;As seen in &#xA;&#xA;&lt;a href=&#34;notes/mathematics/geometry/projective-space/&#34;target=&#34;_blank&#34;&gt;projective geometry&lt;/a&gt;&#xA;&#xA;, the perspective phenomenon is where an object appears to be smaller the further away it is from the point of view.&lt;/p&gt;&#xA;&lt;p&gt;We can again use some concepts of projective geometry to understand perspective projection, particularly the fact that any object in our 3D world is represented in the 4D projective hyperplane by the homogeneous coordinate $(x, y, z, 1)$. Now, any finite point with $w&#xA;ot = 1$ can be projected to the 4D hyperplane $w = 1$ by dividing each coordinate by $w$, i.e., $(\tfrac{x}{w}, \tfrac{y}{w}, \tfrac{z}{w})$. A key observation in the values of $w$ is that &lt;em&gt;the higher the value of $w$, the smaller the object will be when it gets projected to the $w=1$ hyperplane&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Perspective is implemented in 3D by using a transformation matrix that changes the value of $w$ based on how far the object is (the $z$-coordinate).&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Now, let&amp;rsquo;s imagine that we want to project the points that exist in our world to the plane $z = d$.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/perspective-projection%21y.png&#34; alt=&#34;Perspective Projection Y&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Perspective Projection Y&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;By similar images, we can see that the projected value of the $y$-coordinate is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{v_y&#39;}{d} = \frac{v_y}{v_z} \Rightarrow v_y&#39; = \frac{d v_y}{v_z}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The projected value of the $x$-coordinate can be computed in a similar way:&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/perspective-projection%21x.png&#34; alt=&#34;Perspective Projection X&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Perspective Projection X&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;div&gt;$$&#xA;\frac{v_x&#39;}{d} = \frac{v_x}{v_z} \Rightarrow v_x&#39; = \frac{d v_x}{v_z}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The projected value of the $z$-coordinate is the same for all the points:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v_z&#39; = d&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Summarizing:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \begin{bmatrix} \tfrac{d v_x}{v_z} &amp; \tfrac{d v_y}{v_z} &amp; d \end{bmatrix}^T&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Manipulating the last equation so that it has a common denominator:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \begin{bmatrix} \tfrac{d v_x}{v_z} &amp; \tfrac{d v_y}{v_z} &amp; d \tfrac{v_z}{v_z} \end{bmatrix}^T = \frac{  \begin{bmatrix} v_x &amp; v_y &amp; v_z \end{bmatrix}^T }{ \tfrac{v_z}{d} }&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The point above expressed in 4D homogeneous coordinates is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \begin{bmatrix} v_x &amp; v_y &amp; v_z &amp; \tfrac{v_z}{d}  \end{bmatrix}^T&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally, the transformation matrix that transforms $\mathbf{v}$ to $\mathbf{v&amp;rsquo;}$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; 0 \\&#xA;0 &amp; 1 &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; 1 &amp; 0 \\&#xA;0 &amp; 0 &amp; \tfrac{1}{d} &amp; 0&#xA;\end{bmatrix} \begin{bmatrix} v_x \\ v_y \\ v_z \\ 1 \end{bmatrix} = \begin{bmatrix} v_x \\ v_y \\ v_z \\ \frac{v_z}{d} \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Orthographic Projection</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/projections/orthographic/</link>
      <pubDate>Fri, 05 Feb 2016 23:15:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/projections/orthographic/</guid>
      <description>&lt;h2 id=&#34;orthographic-projection&#34;&gt;Orthographic Projection&lt;/h2&gt;&#xA;&lt;p&gt;A projection is a &lt;em&gt;dimension-reducing&lt;/em&gt; operation. If we apply a scale operation with $k = 0$, all the points are projected onto the perpendicular axis in 2D or the perpendicular plane in 3D of $\unit{n}$. This type of projection is called &lt;em&gt;orthographic projection&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;projection-on-a-cardinal-axisplane&#34;&gt;Projection on a Cardinal Axis/Plane&lt;/h3&gt;&#xA;&lt;p&gt;The simplest type of projection just discards a coordinate of the vectors transformed. E.g., in 2D, the vector $\mathbf{v} = \begin{bmatrix} v_x &amp;amp; v_y \end{bmatrix}^T$ projected onto the $x$-axis will discard its $y$-coordinate and make $\mathbf{v&amp;rsquo;} = \begin{bmatrix} v_x &amp;amp; 0 \end{bmatrix}^T$. The operation can be achieved by applying a scale transformation with $k = 0$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{P_x} = \mathbf{S} \left (\begin{bmatrix}&#xA;0 \\ 1&#xA;\end{bmatrix}, 0 \right ) = \begin{bmatrix}&#xA;1 &amp; 0 \\&#xA;0 &amp; 0&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{P_y} = \mathbf{S} \left (\begin{bmatrix}&#xA;1 \\ 0&#xA;\end{bmatrix}, 0 \right ) = \begin{bmatrix}&#xA;0 &amp; 0 \\&#xA;0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When a 3D vector $v = [v_x, v_y, v_z]$ is projected onto the $xy$-plane, then the $v_z$ coordinate will be discarded by copying just $v_x$ and $v_y$, i.e., $v&amp;rsquo; = [v_x, v_y, 0]$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{P_{xy}} = \mathbf{S} \left (\begin{bmatrix}&#xA;0 \\ 0 \\ 1&#xA;\end{bmatrix}, 0 \right ) = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 \\&#xA;0 &amp; 1 &amp; 0 \\&#xA;0 &amp; 0 &amp; 0&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{P_{xz}} = \mathbf{S}\left (\begin{bmatrix}&#xA;0 \\ 1 \\ 0&#xA;\end{bmatrix}, 0 \right ) = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; 0 \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{P_{yz}} = \mathbf{S} \left (\begin{bmatrix}&#xA;1 \\ 0 \\ 0&#xA;\end{bmatrix}, 0 \right ) = \begin{bmatrix}&#xA;0 &amp; 0 &amp; 0 \\&#xA;0 &amp; 1 &amp; 0 \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;projection-onto-an-arbitrary-axisplane&#34;&gt;Projection onto an Arbitrary Axis/Plane&lt;/h3&gt;&#xA;&lt;p&gt;We can apply a zero-factor scale along the direction of the vector perpendicular to the axis/plane.&lt;/p&gt;&#xA;&lt;p&gt;In 2D:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{P(\unit{n})} = \mathbf{S}(\unit{n}, 0) &amp;= \begin{bmatrix}&#xA;1 + (0 - 1){n_x}^2 &amp; (0 - 1)n_xn_y \\&#xA;(0 - 1)n_xn_y &amp; 1 + (0 - 1{n_y}^2&#xA;\end{bmatrix} \\&#xA;\\&#xA;&amp;= \begin{bmatrix}&#xA;1 - {n_x}^2 &amp; -n_xn_y \\&#xA;-n_xn_y &amp; 1 - {n_y}^2&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;In 3D:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{P(\unit{n})} = \mathbf{S}(\unit{n}, 0) &amp;= \begin{bmatrix}&#xA;1 + (0 - 1){n_x}^2 &amp; (0 - 1)n_yn_x &amp; (0 - 1)n_zn_x \\&#xA;(0 - 1)n_xn_y &amp; 1 + (0 - 1{n_y}^2 &amp; (0 - 1)n_zn_y \\&#xA;(0 - 1)n_xn_z &amp; (0 - 1)n_yn_z &amp; 1 + (0 - 1){n_z}^2&#xA;\end{bmatrix} \\&#xA;\\&#xA;&amp;= \begin{bmatrix}&#xA;1 - {n_x}^2 &amp; -n_yn_x &amp; -n_zn_x \\&#xA;-n_xn_y &amp; 1 - {n_y}^2 &amp; -n_zn_y \\&#xA;-n_xn_z &amp; -n_yn_z &amp; 1 - {n_z}^2 \\&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Translating Objects with a Transformation Matrix</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/translation/</link>
      <pubDate>Fri, 05 Feb 2016 18:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/translation/</guid>
      <description>&lt;p&gt;This article is part 4 in the series about transformation matrices:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../coordinate-systems/&#34;target=&#34;_blank&#34;&gt;Part 1: Coordinate systems and transformations between them&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../scale/&#34;target=&#34;_blank&#34;&gt;Part 2: Scaling objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../shearing/&#34;target=&#34;_blank&#34;&gt;Part 3: Shearing objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&#xA;&#xA;&lt;a href=&#34;../translation/&#34;target=&#34;_blank&#34;&gt;Part 4: Translating objects with a transformation matrix&lt;/a&gt;&#xA;&#xA; (this article)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../combining-transformations/&#34;target=&#34;_blank&#34;&gt;Part 5: Combining Matrix Transformations&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;2d-translation&#34;&gt;2D Translation&lt;/h2&gt;&#xA;&lt;p&gt;A translation is an affine transformation, which is a linear transformation followed by some displacement.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{Mv} + \mathbf{b}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Even though we can&amp;rsquo;t express 2D translation using a 2x2 matrix, we can express such a transformation as a shearing transformation in 3D &#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/mathematics/geometry/projective-space&#34;target=&#34;_blank&#34;&gt;projective geometry&lt;/a&gt;&#xA;&#xA;. To do so, we have to imagine that the 2D Euclidean world exists as the plane $w = 1$ in a 3D space. Under this geometry, any point has the form $\begin{bmatrix} x &amp;amp; y &amp;amp; 1 \end{bmatrix}$.&lt;/p&gt;&#xA;&lt;p&gt;In Euclidean geometry, a vector expressed as a linear combination of the standard basis has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = v_x \unit{i} + v_y \unit{j} = \begin{bmatrix} v_x &amp; v_y\end{bmatrix}^T&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;In projective geometry, a vector that exists in the plane $w = 1$ has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = v_x \unit{i} + v_y \unit{j} + 1 \unit{w} = \begin{bmatrix} v_x &amp; v_y &amp; 1 \end{bmatrix}^T&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This basis can be represented using the following transformation matrix:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 \\&#xA;0 &amp; 1 &amp; 0 \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix} = \begin{bmatrix} \mathbf{\cuv{i}} &amp; \mathbf{\cuv{j}} &amp; \mathbf{\cuv{w}} \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The translation transform then can be seen in projective geometry as a simple &lt;em&gt;shearing&lt;/em&gt; of the space by the coordinate $w$, using the shearing transform $\mathbf{H_{xy}}(\Delta{x}, \Delta{y})$ to transform a point $v$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{H_{xy}}(\Delta{x},\Delta{y}) \mathbf{v} =&#xA;\begin{bmatrix}&#xA;1 &amp; 0 &amp; \Delta{x} \\&#xA;0 &amp; 1 &amp; \Delta{y} \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;\begin{bmatrix} v_x \\ v_y \\ 1 \end{bmatrix} =&#xA;\begin{bmatrix} v_x + \Delta{x} \\ v_y + \Delta{y} \\ 1 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now that we&amp;rsquo;re using perspective geometry to represent entities, let&amp;rsquo;s imagine a point $p = \begin{bmatrix} x &amp;amp; y &amp;amp; 0 \end{bmatrix}$ (a point that lies in the plane $w = 0$). Whenever this point is transformed by a transformation matrix, we can notice that the translation components of the matrix are canceled because of $w = 0$. We can take advantage of this fact and represent vectors with this notation.&lt;/p&gt;&#xA;&lt;p&gt;Let $v_{\infty}$ be a point located in the plane $w = 0$. Applying the shearing operation $\mathbf{H_{xy}}(s, t)$ results in:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v_{\infty}&#39;} = H_{xy}(\Delta{x},\Delta{y}) \mathbf{v_{\infty}} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; \Delta{x} \\&#xA;0 &amp; 1 &amp; \Delta{y} \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} v_x \\ v_y \\ 0 \end{bmatrix} = \begin{bmatrix} v_x \\ v_y \\ 0 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;It&amp;rsquo;s important to note that this matrix multiplication is still a &lt;em&gt;linear transformation&lt;/em&gt; and that this trick of translating 2D points is actually a shearing of the 3D projective plane.&lt;/p&gt;&#xA;&lt;h2 id=&#34;3d-translation&#34;&gt;3D Translation&lt;/h2&gt;&#xA;&lt;p&gt;Similarly to 2D, a 3D translation can be represented as a shearing of the 4D projective hyperplane, which has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{T} = \mathbf{H_{xyz}}(\Delta{x},\Delta{y},\Delta{z}) = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; \Delta{x} \\&#xA;0 &amp; 1 &amp; 0 &amp; \Delta{y} \\&#xA;0 &amp; 0 &amp; 1 &amp; \Delta{z} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When a 4D vector existing on the hyperplane $w = 1$ is transformed with this matrix, the result is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{H_{xyz}}(\Delta{x},\Delta{y},\Delta{z})\mathbf{v} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; \Delta{x} \\&#xA;0 &amp; 1 &amp; 0 &amp; \Delta{y} \\&#xA;0 &amp; 0 &amp; 1 &amp; \Delta{z} \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} v_x \\ v_y \\ v_z \\ 1 \end{bmatrix}  = \begin{bmatrix} v_x + \Delta{x} \\ v_y + \Delta{y} \\ v_z + \Delta{z} \\ 1 \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The general 3D translation matrix is then denoted as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{general-translation-matrix}&#xA;\mathbf{T} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 &amp; T_x \\&#xA;0 &amp; 1 &amp; 0 &amp; T_y \\&#xA;0 &amp; 0 &amp; 1 &amp; T_z \\&#xA;0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix} = \begin{bmatrix}&#xA;I_{3 \times 3} &amp; T_{3 \times 1} \\&#xA;0_{1 \times 3} &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Euler Angles</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/rotation/euler-angles/</link>
      <pubDate>Fri, 05 Feb 2016 13:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/rotation/euler-angles/</guid>
      <description>&lt;!-- &lt;style&gt; --&gt;&#xA;&lt;!-- #conversions table img {&#xA;  max-width: 100px;&#xA;} --&gt;&#xA;&lt;!-- &lt;/style&gt; --&gt;&#xA;&lt;!----&gt;&#xA;&lt;p&gt;Euler angles are three angles used to describe the orientation of a rigid body. They are typically denoted $\alpha, \beta, \gamma$. These angles represent a &lt;strong&gt;sequence of three elemental rotations&lt;/strong&gt; about the axes of some coordinate system.&lt;/p&gt;&#xA;&lt;h2 id=&#34;intrinsic-and-extrinsic-rotations&#34;&gt;Intrinsic and Extrinsic Rotations&lt;/h2&gt;&#xA;&lt;h3 id=&#34;intrinsic-rotations&#34;&gt;Intrinsic Rotations&lt;/h3&gt;&#xA;&lt;p&gt;A set of &lt;strong&gt;intrinsic rotations&lt;/strong&gt; represents rotations relative to the &lt;em&gt;object space&lt;/em&gt;, which changes after each rotation.&lt;/p&gt;&#xA;&lt;p&gt;If the axes of some coordinate system are $X,Y,Z$ (note that initially, the axes are aligned with the axes of a fixed coordinate system $x,y,z$), one of the most conventional sets of &lt;em&gt;intrinsic rotations&lt;/em&gt; is $z-x&amp;rsquo;-z&amp;rsquo;&amp;rsquo;$. It&amp;rsquo;s computed as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Perform a rotation of $\alpha$ around the $z$-axis. The resulting set of axes is $x&amp;rsquo;, y&amp;rsquo;, z&amp;rsquo;$ (note that $z&amp;rsquo; = z$).&lt;/li&gt;&#xA;&lt;li&gt;Perform a rotation of $\beta$ around the $x&amp;rsquo;$-axis. The resulting set of axes is $x&amp;rsquo;&amp;rsquo;, y&amp;rsquo;&amp;rsquo;, z&amp;rsquo;&amp;rsquo;$ (note that $x&amp;rsquo;&amp;rsquo; = x&amp;rsquo;$).&lt;/li&gt;&#xA;&lt;li&gt;Perform a rotation of $\gamma$ around the $z&amp;rsquo;&amp;rsquo;$-axis. The resulting set of axes is $x&amp;rsquo;&amp;rsquo;&amp;rsquo;, y&amp;rsquo;&amp;rsquo;&amp;rsquo;, z&amp;rsquo;&amp;rsquo;&amp;rsquo;$ (note that $z&amp;rsquo;&amp;rsquo;&amp;rsquo; = z&amp;rsquo;&amp;rsquo;$ and that the object space $z$-axis is used twice in the overall rotation).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;figure-images&#34;&gt;&#xA;    &lt;img class=&#34;lazy-load&#34; data-src=&#34;https://upload.wikimedia.org/wikipedia/commons/8/85/Euler2a.gif?1461803605967&#34; height=&#34;240&#34; alt=&#34;&#34;&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;&#xA;    &lt;span&gt;&lt;/span&gt;&#xA;    Intrinsic rotation \(z-x&#39;-z&#39;&#39;\). Note that the \(+z\)-axis points upward, the \(+x\)-axis points left, and the \(+y\)-axis points right (all shown in blue). The rotated system \(X,Y,Z\) is shown in red.&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;A rotation matrix (used to pre-multiply column vectors) can be used to represent a sequence of &lt;em&gt;intrinsic rotations&lt;/em&gt;. For example, the extrinsic rotations $x-y&amp;rsquo;-z&amp;rsquo;&amp;rsquo;$ with angles $\alpha, \beta, \gamma$ are represented as a multiplication of the following rotation matrices:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R} = \mathbf{X}(\alpha)\mathbf{Y}(\beta)\mathbf{Z}(\gamma)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\mathbf{X}(\alpha)$, $\mathbf{Y}(\beta)$, and $\mathbf{Z}(\gamma)$ are rotation matrices that represent a rotation around the $x$-axis by $\alpha$, around the $y$-axis by $\beta$, and around the $z$-axis by $\gamma$, respectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;extrinsic-rotations&#34;&gt;Extrinsic Rotations&lt;/h3&gt;&#xA;&lt;p&gt;A set of &lt;strong&gt;extrinsic rotations&lt;/strong&gt; represents rotations relative to a fixed coordinate system (typically the world coordinate system). For example, the set of &lt;em&gt;extrinsic rotations&lt;/em&gt; $z-x-z$ works as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Perform a rotation of $\alpha$ around the $z$-axis. The resulting set of axes is $x&amp;rsquo;, y&amp;rsquo;, z&amp;rsquo;$ (note that $z&amp;rsquo; = z$).&lt;/li&gt;&#xA;&lt;li&gt;Perform a rotation of $\beta$ around the $x$-axis. The resulting set of axes is $x&amp;rsquo;&amp;rsquo;, y&amp;rsquo;&amp;rsquo;, z&amp;rsquo;&amp;rsquo;$.&lt;/li&gt;&#xA;&lt;li&gt;Perform a rotation of $\gamma$ around the $z$-axis. The resulting set of axes is $x&amp;rsquo;&amp;rsquo;&amp;rsquo;, y&amp;rsquo;&amp;rsquo;&amp;rsquo;, z&amp;rsquo;&amp;rsquo;&amp;rsquo;$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;A rotation matrix (used to pre-multiply column vectors) can be used to represent a sequence of &lt;em&gt;intrinsic rotations&lt;/em&gt;. For example, the extrinsic rotations $x-y-z$ with angles $\alpha, \beta, \gamma$ are represented as a multiplication of the following rotation matrices:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R} = \mathbf{Z}(\gamma)\mathbf{Y}(\beta)\mathbf{X}(\alpha)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\mathbf{X}(\alpha)$, $\mathbf{Y}(\beta)$, and $\mathbf{Z}(\gamma)$ are rotation matrices that represent a rotation around the $x$-axis by $\alpha$, around the $y$-axis by $\beta$, and around the $z$-axis by $\gamma$, respectively.&lt;/p&gt;&#xA;&lt;h3 id=&#34;conversion-between-intrinsic-and-extrinsic-rotations&#34;&gt;Conversion Between Intrinsic and Extrinsic Rotations&lt;/h3&gt;&#xA;&lt;p&gt;Any intrinsic rotation is equivalent to an extrinsic rotation by the same angles but with an inverted order of rotations.&lt;/p&gt;&#xA;&lt;p&gt;For example, the intrinsic rotations $x-y&amp;rsquo;-z&amp;rsquo;&amp;rsquo;$ by the angles $\alpha,\beta,\gamma$ are equivalent to the extrinsic rotations $z-y-x$ by the angles $\gamma,\beta,\alpha$, both represented by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R} = \mathbf{X}(\alpha)\mathbf{Y}(\beta)\mathbf{Z}(\gamma)&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;proper-euler-angles&#34;&gt;Proper Euler Angles&lt;/h2&gt;&#xA;&lt;p&gt;A sequence of three elemental rotations is called &lt;strong&gt;proper Euler angles&lt;/strong&gt; when the first and third rotation axes are the same.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;figure-images&#34;&gt;&#xA;    &lt;img class=&#34;lazy-load&#34; data-src=&#34;https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Eulerangles.svg/213px-Eulerangles.svg.png&#34; alt=&#34;&#34;&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;&#xA;    &lt;p&gt;&#xA;      Proper Euler angles representing rotations about \(z-x&#39;-z&#39;&#39;\) by the angles $\alpha, \beta, \gamma$. The rotated system \(X,Y,Z\) is shown in red.&#xA;    &lt;/p&gt;&#xA;  &lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;There are six possibilities for choosing the rotation axes for proper Euler angles, which are &lt;em&gt;intrinsic rotations&lt;/em&gt;. In a similar way, there are six other possibilities for choosing the rotation axes, which are &lt;em&gt;extrinsic rotations&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;Intrinsic Rotations&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;Extrinsic Rotations&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-y&amp;rsquo;-x&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-y-x$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-z&amp;rsquo;-x&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-z-x$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-x&amp;rsquo;-y&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-x-y$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-z&amp;rsquo;-y&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-z-y$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-x&amp;rsquo;-z&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-x-z$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-y&amp;rsquo;-z&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-y-z$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;tait-bryan-angles&#34;&gt;Tait-Bryan Angles&lt;/h2&gt;&#xA;&lt;p&gt;A sequence of three elemental rotations is called &lt;strong&gt;Tait-Bryan angles&lt;/strong&gt; when the angles represent rotations about three distinct axes.&lt;/p&gt;&#xA;&lt;p&gt;Just like proper Euler angles, there are six possible &lt;em&gt;intrinsic rotations&lt;/em&gt; and six possible &lt;em&gt;extrinsic rotations&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;Intrinsic Rotations&lt;/th&gt;&#xA;          &lt;th style=&#34;text-align: left&#34;&gt;Extrinsic Rotations&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-y&amp;rsquo;-z&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-y-x$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-z&amp;rsquo;-y&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-z-x$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-x&amp;rsquo;-z&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-x-y$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-z&amp;rsquo;-x&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-z-y$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-x&amp;rsquo;-y&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$y-x-z$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$z-y&amp;rsquo;-x&amp;rsquo;&#39;$&lt;/td&gt;&#xA;          &lt;td style=&#34;text-align: left&#34;&gt;$x-y-z$&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;The set of &lt;em&gt;intrinsic rotations&lt;/em&gt; $z-y&amp;rsquo;-x&amp;rsquo;&amp;rsquo;$ is known as &lt;em&gt;yaw&lt;/em&gt;, &lt;em&gt;pitch&lt;/em&gt;, and &lt;em&gt;roll&lt;/em&gt;. These angles are also known as &lt;em&gt;nautical angles&lt;/em&gt; because they can describe the orientation of a ship or aircraft.&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;figure-images&#34;&gt;&#xA;    &lt;img class=&#34;lazy-load&#34; data-src=&#34;https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Taitbrianzyx.svg/245px-Taitbrianzyx.svg.png&#34; alt=&#34;&#34;&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;Tait–Bryan angles representing the sequence \(z-y&#39;-x&#39;&#39;\)&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;The rotation matrix for the sequence $z-y&amp;rsquo;-x&amp;rsquo;&amp;rsquo;$ (or $x-y-z$), which is known as &lt;em&gt;yaw&lt;/em&gt;, &lt;em&gt;pitch&lt;/em&gt;, and &lt;em&gt;roll&lt;/em&gt;, is given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{R} = \mathbf{Z}(\alpha)\mathbf{Y}(\beta)\mathbf{X}(\gamma)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;extrinsic-rotations-expressed-in-upright-space&#34;&gt;Extrinsic Rotations Expressed in Upright Space&lt;/h2&gt;&#xA;&lt;p&gt;An important thing to note is that the standard rotation matrices work in &lt;em&gt;upright space&lt;/em&gt;. If the &lt;em&gt;object space&lt;/em&gt; axes are not aligned with the &lt;em&gt;upright space&lt;/em&gt; axes (different direction), then the sequence of extrinsic rotations must be done on the axes expressed in &lt;em&gt;upright space&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;For example, given that world space is:&lt;/p&gt;&#xA;&lt;figure&gt;&#xA;  &lt;div class=&#34;figure-images&#34;&gt;&#xA;    &lt;img class=&#34;lazy-load&#34; data-src=&#34;https://www.mauriciopoppe.com/images/xyz.jpg&#34; alt=&#34;&#34;&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;Chosen world space: \(+x\) (right), \(+y\) (up), and \(+z\) (backward). Note that the choice is just personal preference.&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;If there&amp;rsquo;s an object whose &lt;em&gt;object space&lt;/em&gt; axes are $+x$ (backward), $+y$ (right), and $+z$ (up), then a sequence of intrinsic rotations $z-y&amp;rsquo;-x&amp;rsquo;&amp;rsquo;$ by the angles $\alpha, \beta, \gamma$ (equivalent to the extrinsic rotation $x-y-z$ by the angles $\gamma, \beta, \alpha$, which is also known as &lt;em&gt;yaw&lt;/em&gt;, &lt;em&gt;pitch&lt;/em&gt;, and &lt;em&gt;roll&lt;/em&gt;) is equivalent to the multiplication of the following rotation matrices:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R} = \mathbf{R}(\mathbf{w}, \alpha)\mathbf{R}(\mathbf{v}, \beta)\mathbf{R}(\mathbf{u}, \gamma)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\mathbf{R}(\mathbf{s}, t)$ is the general rotation matrix used to rotate around the axis $\mathbf{s}$ by the angle $t$.&lt;/li&gt;&#xA;&lt;li&gt;$\mathbf{u, v, w}$ are the columns of the transformation matrix used to transform any point $\mathbf{p}$ expressed in &lt;em&gt;object space&lt;/em&gt; to &lt;em&gt;upright space&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{p}_{upright} &amp;= \mathbf{M}_{upright \leftarrow object} \mathbf{p}_{object} \\&#xA;&amp;= \begin{bmatrix} \mathbf{u}_{3 \times 1} \mathbf{v}_{3 \times 1} \mathbf{w}_{3 \times 1}\end{bmatrix} \mathbf{p}_{object}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The problem can be simplified when the frame is somewhat aligned with the &lt;em&gt;upright space&lt;/em&gt; (the order might be different, and the axis directions might be reversed, but it&amp;rsquo;s still aligned). The following diagram shows some of these simplifications:&lt;/p&gt;&#xA;&lt;figure id=&#34;conversions&#34;&gt;&#xA;  &lt;div class=&#34;figure-table&#34; style=&#34;overflow: auto&#34;&gt;&#xA;    &lt;table&gt;&#xA;      &lt;tr&gt;&#xA;        &lt;th&gt;To/from&lt;/th&gt;&#xA;        &lt;th&gt;Description&lt;/th&gt;&#xA;        &lt;th&gt;Intrinsic/Extrinsic &lt;br/&gt; rotations&lt;/th&gt;&#xA;        &lt;th&gt;Equivalence in world space&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;        &lt;td&gt;&lt;img class=&#34;lazy-load&#34; data-src=&#34;https://www.mauriciopoppe.com/images/xyz.jpg&#34; alt=&#34;&#34;&gt;&lt;/td&gt;&#xA;        &lt;td&gt;yaw, pitch, roll&lt;/td&gt;&#xA;        &lt;td&gt;&#xA;        $$&#xA;        \begin{align*}&#xA;          y-x&#39;-z&#39;&#39; \\&#xA;          z-x-y&#xA;        \end{align*}&#xA;        $$&#xA;        &lt;/td&gt;&#xA;        &lt;td&gt;&#xA;        $$&#xA;        \begin{align*}&#xA;          \mathbf{Y}(\alpha) \\&#xA;          \mathbf{X}(\beta) \\&#xA;          \mathbf{Z}(\gamma)&#xA;        \end{align*}&#xA;        $$&#xA;        &lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;        &lt;td&gt;&lt;img class=&#34;lazy-load&#34; data-src=&#34;https://www.mauriciopoppe.com/images/xyz-z-up.jpg&#34; alt=&#34;&#34;&gt;&lt;/td&gt;&#xA;        &lt;td&gt;yaw, pitch, roll&lt;/td&gt;&#xA;        &lt;td&gt;&#xA;        $$&#xA;        \begin{align*}&#xA;          z-y&#39;-x&#39;&#39; \\&#xA;          x-y-z&#xA;        \end{align*}&#xA;        $$&#xA;        &lt;/td&gt;&#xA;        &lt;td&gt;&#xA;        $$&#xA;        \begin{align*}&#xA;          \mathbf{Z}(\alpha) \equiv \mathbf{Y_{wld}}(\alpha) \\&#xA;          \mathbf{Y}(\beta) \equiv \mathbf{X_{wld}}(\beta) \\&#xA;          \mathbf{X}(\gamma) \equiv \mathbf{Z_{wld}}(\gamma)&#xA;        \end{align*}&#xA;        $$&#xA;        &lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;        &lt;td&gt;&lt;img class=&#34;lazy-load&#34; data-src=&#34;https://www.mauriciopoppe.com/images/xyz-y-down.jpg&#34; alt=&#34;&#34;&gt;&lt;/td&gt;&#xA;        &lt;td&gt;yaw, pitch, roll&lt;/td&gt;&#xA;        &lt;td&gt;&#xA;        $$&#xA;        \begin{align*}&#xA;          y-x&#39;-z&#39;&#39; \\&#xA;          z-x-y&#xA;        \end{align*}&#xA;        $$&#xA;        &lt;/td&gt;&#xA;        &lt;td&gt;&#xA;        $$&#xA;        \begin{align*}&#xA;          \mathbf{Y}(\alpha) \equiv \mathbf{Y_{wld}}(-\alpha) \\&#xA;          \mathbf{X}(\beta) \equiv \mathbf{X_{wld}}(-\beta) \\&#xA;          \mathbf{Z}(\gamma) \equiv \mathbf{Z_{wld}}(\gamma)&#xA;        \end{align*}&#xA;        $$&#xA;        &lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;    &lt;/table&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;figcaption&gt;Equivalence of common extrinsic rotations in world space&lt;/figcaption&gt;&#xA;&lt;/figure&gt;&#xA;</description>
    </item>
    <item>
      <title>Shearing Objects with a Transformation Matrix</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/shearing/</link>
      <pubDate>Fri, 05 Feb 2016 10:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/shearing/</guid>
      <description>&lt;p&gt;This article is part 3 in the series about transformation matrices:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../coordinate-systems/&#34;target=&#34;_blank&#34;&gt;Part 1: Coordinate systems and transformations between them&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../scale/&#34;target=&#34;_blank&#34;&gt;Part 2: Scaling objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&#xA;&#xA;&lt;a href=&#34;../shearing/&#34;target=&#34;_blank&#34;&gt;Part 3: Shearing objects with a transformation matrix&lt;/a&gt;&#xA;&#xA; (this article)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../translation/&#34;target=&#34;_blank&#34;&gt;Part 4: Translating objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../combining-transformations/&#34;target=&#34;_blank&#34;&gt;Part 5: Combining Matrix Transformations&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;2d-shearing&#34;&gt;2D Shearing&lt;/h2&gt;&#xA;&lt;p&gt;In 2D, we can skew points towards the $x$-axis by making $x&amp;rsquo; = x + sy$. If $s &amp;gt; 0$, then points will skew towards the positive $x$-axis; if $s &amp;lt; 0$, points will move towards the negative $x$-axis.&lt;/p&gt;&#xA;&lt;p&gt;The transformation matrix that skews points towards the $x$-axis is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{2d-shear-x}&#xA;\mathbf{H_x}(s) = \begin{bmatrix}&#xA;1 &amp; s \\&#xA;0 &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Towards the $y$-axis is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{2d-shear-y}&#xA;\mathbf{H_y}(s) = \begin{bmatrix}&#xA;1 &amp; 0 \\&#xA;s &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For example, a vector $\mathbf{v}$ multiplied by \eqref{2d-shear-x} results in:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{H_x}(s)\mathbf{v} = \begin{bmatrix}&#xA;1 &amp; s \\&#xA;0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} v_x \\ v_y \end{bmatrix} = \begin{bmatrix} v_x + sv_y \\ v_y \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;3d-shearing&#34;&gt;3D Shearing&lt;/h2&gt;&#xA;&lt;p&gt;The notation $\mathbf{H_{xy}}$ indicates that the $x$ and $y$ coordinates are shifted by the other coordinate, $z$, i.e.:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x&#39; &amp;= x + sz \\&#xA;y&#39; &amp;= y + tz \\&#xA;z&#39; &amp;= z&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The shearing matrices in 3D are:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{shear-xy}&#xA;\mathbf{H_{xy}}(s,t) = \begin{bmatrix}&#xA;1 &amp; 0 &amp; s \\&#xA;0 &amp; 1 &amp; t \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{shear-xz}&#xA;\mathbf{H_{xz}}(s,t) = \begin{bmatrix}&#xA;1 &amp; s &amp; 0 \\&#xA;0 &amp; 1 &amp; 0 \\&#xA;0 &amp; t &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{shear-yz}&#xA;\mathbf{H_{yz}}(s,t) = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 \\&#xA;s &amp; 1 &amp; 0 \\&#xA;t &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For example, a vector $\mathbf{v}$ multiplied by \eqref{shear-xy} results in:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{H_{xy}}(s,t) \mathbf{v} = \begin{bmatrix}&#xA;1 &amp; 0 &amp; s \\&#xA;0 &amp; 1 &amp; t \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix} \begin{bmatrix} v_x \\ v_y \\ v_z \end{bmatrix}  = \begin{bmatrix} v_x + sv_z \\ v_y + tv_z \\ v_z \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Introduction to Rotation for Computer Graphics</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/rotation/introduction/</link>
      <pubDate>Tue, 15 Dec 2015 13:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/rotation/introduction/</guid>
      <description>&lt;h2 id=&#34;2d-rotation&#34;&gt;2D Rotation&lt;/h2&gt;&#xA;&lt;p&gt;A 2D rotation has only one parameter, $\theta$. When the basis vectors $\unit{i} = [1, 0]$ and $\unit{j} = [0, 1]$ are rotated by an angle $\theta$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p} = \cos{\theta} \unit{i} + \sin{\theta} \unit{j} \\&#xA;\mathbf{q} = -\sin{\theta} \unit{i} + \cos{\theta} \unit{j}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;two-dimensions&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Which builds the rotation matrix:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R}(\theta) = \begin{bmatrix}&#xA;\textbf{p} \\&#xA;\textbf{q}&#xA;\end{bmatrix} = \begin{bmatrix}&#xA;\cos{\theta} &amp; \sin{\theta} \\&#xA;-\sin{\theta} &amp; \cos{\theta}&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When a vector $\mathbf{v}$ is transformed by this matrix, we know that the vector will be a &lt;em&gt;linear combination of the basis&lt;/em&gt;, which are $\mathbf{p}$ and $\mathbf{q}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v&#39;} = \mathbf{vR}(\theta) &amp;= v_x \mathbf{p} + v_y \mathbf{q} \\&#xA;&amp;= v_x \begin{bmatrix}\cos{\theta} &amp; \sin{\theta}\end{bmatrix} + v_y \begin{bmatrix}-\sin{\theta} &amp; \cos{\theta}\end{bmatrix} \\&#xA;&amp;= \begin{bmatrix}&#xA;v_x \cos{\theta} - v_y \sin{\theta} \\&#xA;v_x \sin{\theta} + v_y \cos{\theta}&#xA;\end{bmatrix}^T&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Using a matrix to encode this operation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v&#39;} = \mathbf{vR}(\theta) &amp;= \begin{bmatrix}v_x &amp; v_y\end{bmatrix} \begin{bmatrix}&#xA;\cos{\theta} &amp; \sin{\theta} \\&#xA;-\sin{\theta} &amp; \cos{\theta}&#xA;\end{bmatrix} \\&#xA;&amp;= \begin{bmatrix}&#xA;v_x \cos{\theta} - v_y \sin{\theta} \\&#xA;v_x \sin{\theta} + v_y \cos{\theta}&#xA;\end{bmatrix}^T&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;See also &#xA;&#xA;&lt;a href=&#34;https://www.mauriciopoppe.com/notes/mathematics/numeral-systems/complex-numbers&#34;target=&#34;_blank&#34;&gt;complex numbers&lt;/a&gt;&#xA;&#xA;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;3d-rotation&#34;&gt;3D Rotation&lt;/h2&gt;&#xA;&lt;h3 id=&#34;about-cardinal-axes&#34;&gt;About Cardinal Axes&lt;/h3&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R_x}(\alpha) = \begin{bmatrix}&#xA;1 &amp; 0 &amp; 0 \\&#xA;0 &amp; \cos{\alpha} &amp; -\sin{\alpha} \\&#xA;0 &amp; \sin{\alpha} &amp; \cos{\alpha}&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R_y}(\beta) = \begin{bmatrix}&#xA;\cos{\beta} &amp; 0 &amp; \sin{\beta} \\&#xA;0 &amp; 1 &amp; 0 \\&#xA;-\sin{\beta} &amp; 0 &amp; \cos{\beta}&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R_z}(\gamma) = \begin{bmatrix}&#xA;\cos{\gamma} &amp; -\sin{\gamma} &amp; 0 \\&#xA;\sin{\gamma} &amp; \cos{\gamma} &amp; 0 \\&#xA;0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;See also:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;http://www.wikiwand.com/en/Rotation_matrix#In_three_dimensions&#34;target=&#34;_blank&#34;&gt;3D rotation on wikipedia.org&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;https://web.archive.org/web/20170725010216/https://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/3drota.htm&#34;target=&#34;_blank&#34;&gt;3D rotation - siggraph.org&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;about-an-arbitrary-axis&#34;&gt;About an Arbitrary Axis&lt;/h3&gt;&#xA;&lt;p&gt;Given an axis $\unit{n}$ and an amount of rotation around it $\theta$, our goal is to find a rotation matrix that rotates about $\unit{n}$ by the angle $\theta$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{R}(\unit{n}, \theta)\mathbf{v}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The basic idea is to solve this problem in a plane perpendicular to $\unit{n}$, which becomes a 2D problem.&lt;/p&gt;&#xA;&lt;p&gt;Separate $\mathbf{v}$ into two vectors: a vector parallel to $\unit{v}$ called $\mathbf{v_{\parallel}}$ and a vector perpendicular to $\unit{v}$ called $\mathbf{v_{\perp}}$ such that $\mathbf{v_{\parallel}} + \mathbf{v_{\perp}} = \mathbf{v}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v_{\parallel}} &amp;= (\mathbf{v} \cdot \unit{n}) \unit{n} \\&#xA;\mathbf{v_{\perp}} &amp;= \mathbf{v} - \mathbf{v_{\parallel}}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;After the rotation, it&amp;rsquo;s obvious that the $\mathbf{v_{\parallel}}$ component will be the same, and only the vector $\mathbf{v_{\perp}}$ will be rotated.&lt;/p&gt;&#xA;&lt;p&gt;A plane can be defined with two vectors that lie on it. Since we have $\mathbf{v_{\perp}}$ and we also know the normal of the plane (which is $\unit{n}$), any vector perpendicular to both vectors will also lie in the plane. We can use the cross product to find this vector:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mbold{w} = \unit{n} \times \mbold{v_{\perp}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The length of $\mbold{w}$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\left \| \mbold{w} \right \| &amp;= \left \| \unit{n} \right \| \left \| \mbold{v_{\perp}}\right \| \sin{\deg{90}} \\&#xA;&amp;= \left \| \mbold{v_{\perp}}\right \|&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which means that $\mbold{w}$ has the same length as $\mbold{v_{\perp}}$. Note that even though they have the same length, they don&amp;rsquo;t necessarily have unit length.&lt;/p&gt;&#xA;&lt;p&gt;$\mbold{w}$ and $\mbold{v_{\perp}}$ now form a 2D coordinate space where the $x$-axis is $\mbold{v_{\perp}}$ and the $y$-axis is $\mbold{w}$.&lt;/p&gt;&#xA;&lt;p&gt;Let $\mbold{v_{\perp}&amp;rsquo;}$ be a vector that is the result of rotating $\mbold{v_{\perp}}$ by an angle $\theta$. We can find the projection of it onto the $x$-axis and the $y$-axis as follows:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mbold{v_{\perp,x}&#39;} &amp;= (\magnitude{ \mbold{v_{\perp}} } \cos{\theta}) \unit{v_{\perp}} = \cos{\theta} \mbold{v_{\perp}}\\&#xA;\mbold{v_{\perp,y}&#39;} &amp;= (\magnitude{ \mbold{v_{\perp}} } \sin{\theta}) \unit{w} = \sin{\theta} \mbold{w}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Expressing $\mbold{v_{\perp}&amp;rsquo;}$ as a linear combination of the basis:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mbold{v_{\perp}&#39;} = \cos{\theta} \mbold{v_{\perp}} + \sin{\theta} \mbold{w}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Reconstructing the solution from the observations above:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mbold{v_{\parallel}} &amp;= (\mbold{v} \cdot \unit{n}) \unit{n} \\&#xA;\mbold{v_{\perp}} &amp;= \mbold{v} - \mbold{v_{\parallel}} \\&#xA;&amp;= \mbold{v} - (\mbold{v} \cdot \unit{n}) \unit{n} \\&#xA;\mbold{w} &amp;= \unit{n} \times \mbold{v_{\perp}} \\&#xA;&amp;= \unit{n} \times (\mbold{v} - \mbold{v_{\parallel}}) \\&#xA;&amp;= \unit{n} \times \mbold{v} - \unit{n} \times \mbold{v_{\parallel}} \\&#xA;&amp;= \unit{n} \times \mbold{v}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;\mbold{v&#39;} &amp;= \mbold{v_{\perp}&#39;} + \mbold{v_{\parallel}&#39;} \nonumber \\&#xA;&amp;= \cos{\theta} \mbold{v_{\perp}} + \sin{\theta} \mbold{w} + (\mbold{v} \cdot \unit{n}) \unit{n} \nonumber \\&#xA;&amp;= \cos{\theta} (\mbold{v - (\mbold{v} \cdot \unit{n}) \unit{n}}) + \sin{\theta} (\unit{n} \times \mbold{v}) + (\mbold{v} \cdot \unit{n}) \unit{n} \nonumber \\&#xA;&amp;= \cos{\theta} \mbold{v} - \cost (\mathbf{v} \cdot \unit{n}) \unit{n} + \sin{\theta} (\unit{n} \times \mbold{v}) + (\mbold{v} \cdot \unit{n}) \unit{n} \nonumber \\&#xA;&amp;= \cos{\theta} \mbold{v} + \sin{\theta} (\unit{n} \times \mbold{v}) + (1 - \cost)(\mathbf{v} \cdot \unit{n}) \unit{n} \label{3d-rotation}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now we can compute what the basis vectors are after the transformation above (by using each of the basis vectors as $\mbold{v}$ on \eqref{3d-rotation}) to construct a rotation matrix:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mbold{p} &amp;= \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} \quad \quad \quad \quad \mbold{p&#39;} = \begin{bmatrix}&#xA;n_x^2(1 - \cost) + \cost \\&#xA;n_xn_y(1 - \cost) + n_z \sint \\&#xA;n_xn_z(1 - \cost) - n_z \sint&#xA;\end{bmatrix}\\&#xA;\\&#xA;\mbold{q} &amp;= \begin{bmatrix}0 \\ 1 \\ 0\end{bmatrix} \quad \quad \quad \quad \mbold{q&#39;} = \begin{bmatrix}&#xA;n_yn_x(1 - \cost) - n_z \sint \\&#xA;n_y^2(1 - \cost) + \cost \\&#xA;n_yn_z(1 - \cost) + n_x \sint&#xA;\end{bmatrix}\\&#xA;\\&#xA;\mbold{r} &amp;= \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix} \quad \quad \quad \quad \mbold{r&#39;} = \begin{bmatrix}&#xA;n_zn_x(1 - \cost) + n_y \sint \\&#xA;n_zn_y(1 - \cost) - n_x \sint \\&#xA;n_z^2(1 - \cost) + \cost&#xA;\end{bmatrix}\\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Constructing the matrix from these vectors:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{R}(\unit{n}, \theta) =&#xA;\begin{bmatrix}&#xA;\mbold{p&#39;} &amp; \mbold{q&#39;} &amp; \mbold{r&#39;}&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;3d-rotations-using-quaternions&#34;&gt;3D Rotations Using Quaternions&lt;/h3&gt;&#xA;&lt;p&gt;A complex rotor is a unit norm complex number that rotates another complex number by the angle $\theta$ and has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;e^{i\theta} = \cos{\theta} + i \sin{\theta}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Hamilton had hoped that a unit-norm quaternion $q$ could be used to rotate a vector, which is stored as a pure quaternion $p$. The unit norm quaternion is given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;q &amp;= [s, \lambda \unit{n}] \quad s,\lambda \in \mathbb{R}, \unit{n} \in \mathbb{R}^3 \label{unit-norm-quaternion} \\&#xA;\left | \unit{n} \right | &amp;= 1 \nonumber \\&#xA;s^2 + \lambda^2 &amp;= 1 \nonumber&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;p = [0, \mbold{v}] \quad \mbold{v} \in \mathbb{R}^3&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s compute the product $p&amp;rsquo; = qp$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;p&#39; &amp;= qp \nonumber \\&#xA;&amp;= [s, \lambda \unit{n}][0, \mathbf{v}] \nonumber \\&#xA;&amp;= [-\lambda \unit{n} \cdot \mathbf{v}, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}] \label{p-prime}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;special-case&#34;&gt;Special Case&lt;/h4&gt;&#xA;&lt;p&gt;What if $\unit{n}$ is &lt;em&gt;perpendicular&lt;/em&gt; to $\mathbf{v}$? Then the scalar quantity of \eqref{p-prime} is zero, and we are left with the pure quaternion:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{p-prime-perpendicular}&#xA;p&#39; = [0, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}] \quad\quad \text{given that $\unit{n}$ is perpendicular to $\mathbf{v}$}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s analyze the vector part of $\eqref{p-prime-perpendicular}$ (which is now a 3D entity because it&amp;rsquo;s a pure quaternion). Since $\unit{n}$ is perpendicular to $\mathbf{v}$, then the vector $\unit{n} \times \mathbf{v}$ will have a norm equal to $\magnitude{ \unit{n} \times \mathbf{v} } = \magnitude{ \unit{n} } \magnitude { \mathbf{v} } \sin{\deg{90}}$. Also, since $\unit{n}$ is a unit vector, then $\magnitude{\unit{n} \times \mathbf{v}} = \magnitude{\mathbf{v}}$, which means that we have two orthogonal vectors with the same length.&lt;/p&gt;&#xA;&lt;p&gt;To rotate the vector $\mathbf{v}$ about $\unit{n}$, let&amp;rsquo;s transform $\mathbf{v}$ to the 2D space whose basis vectors are $\mathbf{v}$ and $\unit{n} \times \mathbf{v}$ and perform the rotation there, which is trivially $[\cos{\theta}, \sin{\theta}]$. Therefore, all we have to do in \eqref{p-prime-perpendicular} is make the scalar quantities multiplying each vector equal to the projection of the rotated vector over the basis:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;p&#39; = [0, \cos{\theta} \mathbf{v} + \sin{\theta} \unit{n} \times \mathbf{v}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which makes the quaternion $\mathbf{q}$ have the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;q &amp;= [\cos{\theta}, \sin{\theta}\unit{n}] \label{perp-rotor}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;And it acts as a rotor &lt;strong&gt;only when $\unit{n}$ is perpendicular to $\mathbf{v}$&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Important notes/facts about orthogonal quaternions:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $q$ is a rotor about the unit vector $\unit{n}$ by an angle $\theta$ whose vector term is perpendicular to the pure quaternion $p$:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$qp$ and $pq^{-1}$ rotate $p$ by an angle $\theta$ about $\unit{n}$.&lt;/li&gt;&#xA;&lt;li&gt;$pq$ and $q^{-1}p$ rotate $p$ by an angle $-\theta$ about $\unit{n}$.&lt;/li&gt;&#xA;&lt;li&gt;Each of these products leaves $p&amp;rsquo;$ unscaled (because $q$ is a unit norm quaternion).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;general-case&#34;&gt;General Case&lt;/h4&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s use \eqref{unit-norm-quaternion} as the starting point. Note that this time its vector part is not necessarily perpendicular to the pure quaternion $p$. The product $qp$ yields:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;qp &amp;= [s, \lambda \unit{n}][0, \mathbf{v}] \\&#xA;&amp;= [-\lambda \unit{n} \cdot \mathbf{v}, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the term $-\lambda \unit{n} \cdot \mathbf{v}$ does not vanish since for the general case, $\unit{n}$ and $\mathbf{v}$ are no longer perpendicular. What&amp;rsquo;s more important is that the product $qp$ is no longer a pure quaternion. Multiplying a vector by a non-orthogonal quaternion has converted some of the vector information into the quaternion&amp;rsquo;s scalar component.&lt;/p&gt;&#xA;&lt;p&gt;What happens if we post-multiply $qp$ by $q^{-1}$? Could it reverse the operation? (Note that since $q$ is a norm quaternion, $q^{-1} = q^*$.)&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;qpq^{-1} = [-\lambda \unit{n} \cdot \mathbf{v}, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}][s, -\lambda \unit{n}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s first check if doing this multiplication makes the scalar component vanish:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;qpq^{-1} &amp;= [-\lambda s \unit{n} \cdot \mathbf{v} - (s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}) \cdot (-\lambda \unit{n}), \ldots] \\&#xA;&amp;= [-\lambda s \unit{n} \cdot \mathbf{v} + (s \mathbf{v}) \cdot (\lambda \unit{n}) + (\lambda \unit{n} \times \mathbf{v}) \cdot (\lambda \unit{n}), \ldots] \\&#xA;&amp;= [-\lambda s \unit{n} \cdot \mathbf{v} + (s \mathbf{v}) \cdot (\lambda \unit{n}) + 0, \ldots] \quad \text {since $\unit{n}$ is perpendicular to $\unit{n} \times \mathbf{v}$ } \\&#xA;&amp;= [-\lambda s \unit{n} \cdot \mathbf{v} + \lambda s \mathbf{v} \cdot \unit{n}), \ldots] \\&#xA;&amp;= [0, \ldots]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Indeed, it magically made the scalar component vanish! Now let&amp;rsquo;s look at the vector component of $qpq^{-1}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;qpq^{-1} &amp;= [0, s (s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}) + (-\lambda \unit{n} \cdot \mathbf{v})(-\lambda \unit{n}) + (s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}) \times (-\lambda \unit{n})] \\&#xA;&amp;= [0, s^2 \mathbf{v} + s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - s \lambda (\mathbf{v} \times \unit{n}) - \lambda^2 (\unit{n} \times \mathbf{v} \times \unit{n})]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Triple_product#/section_Vector_triple_product&#34;target=&#34;_blank&#34;&gt;expand the cross product&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(\unit{n} \times \mathbf{v}) \times \unit{n} = (\unit{n} \cdot \unit{n}) \mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n} = \mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;qpq^{-1} &amp;= [0, s^2 \mathbf{v} + s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - s \lambda (\mathbf{v} \times \unit{n}) - \lambda^2 (\mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n})] \\&#xA;&amp;= [0, s^2 \mathbf{v} + s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - s \lambda (\mathbf{v} \times \unit{n}) - \lambda^2 \mathbf{v} + \lambda^2 (\mathbf{v} \cdot \unit{n}) \unit{n})] \\&#xA;&amp;= [0, s^2 \mathbf{v} + 2 s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - \lambda^2 \mathbf{v} + \lambda^2 (\mathbf{v} \cdot \unit{n}) \unit{n})] \\&#xA;&amp;= [0, (s^2 - \lambda^2) \mathbf{v} + 2 s \lambda (\unit{n} \times \mathbf{v}) + 2 \lambda^2 (\mathbf{v} \cdot \unit{n}) \unit{n}] \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s make $s = \cos{\theta}$ and $\lambda = \sin{\theta}$, just like in \eqref{perp-rotor} (it worked as a rotor when it was orthogonal to $p$; it might work with the general case too):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;qpq^{-1} = [0, (\cos^2{\theta} - \sin^2{\theta}) \mathbf{v} + 2 \cos{\theta} \sin{\theta} (\unit{n} \times \mathbf{v}) + 2 \sin^2{\theta} (\mathbf{v} \cdot \unit{n}) \unit{n}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which involves double-angle terms. Replacing these terms with &#xA;&#xA;&lt;a href=&#34;http://mathworld.wolfram.com/Double-AngleFormulas.html&#34;target=&#34;_blank&#34;&gt;double-angle identities&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;qpq^{-1} = [0, \cos{2\theta} \mathbf{v} + \sin{2\theta} (\unit{n} \times \mathbf{v}) + (1 - \cos{2\theta}) (\mathbf{v} \cdot \unit{n}) \unit{n}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The product created a pure quaternion equal to $\mathbf{v}$ rotated by an angle of $2\theta$. If we want to rotate $\mathbf{v}$ by an angle of $\theta$, we must build a half-angle $\theta$ quaternion $q$ (note above that $q$ was equal to \eqref{perp-rotor}):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{rotor}&#xA;q = [\cos{\frac{1}{2}\theta}, \sin{\frac{1}{2}\theta}\unit{n}]&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Using \eqref{rotor}, the product is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;qpq^{-1} = [0, \cos{\theta} \mathbf{v} + \sin{\theta} (\unit{n} \times \mathbf{v}) + (1 - \cos{\theta}) (\mathbf{v} \cdot \unit{n}) \unit{n}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the vector part of $qpq^{-1}$ is identical to \eqref{3d-rotation}.&lt;/p&gt;&#xA;&lt;h4 id=&#34;quaternion-difference-and-dot-product&#34;&gt;Quaternion Difference and Dot Product&lt;/h4&gt;&#xA;&lt;p&gt;Let $a$ and $b$ be two &lt;em&gt;unit norm&lt;/em&gt; quaternions (rotors that have the same form as \eqref{rotor}). The quaternion to rotate from $a$ to $b$ is given by $da = b$ and is known as &lt;em&gt;quaternion difference&lt;/em&gt;. Finding the value of $d$ given that we know $a$ and $b$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;da &amp;= b \\&#xA;d(aa^*) &amp;= ba^* \quad \quad \text{since $a$ is a unit norm quaternion, its inverse is equal to its conjugate} \\&#xA;d &amp;= ba^*&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Expanding the product:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;d &amp;= [s_b, \mathbf{b}][s_a, -\mathbf{a}] \\&#xA;&amp;= [s_bs_a + \mathbf{b} \cdot \mathbf{a}, -s_b\mathbf{a} + s_a\mathbf{b} - \mathbf{b} \times \mathbf{a}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the scalar part of this quaternion is equal to the &lt;em&gt;inner product&lt;/em&gt; (a generalization of the dot product to abstract vector spaces) between two quaternions:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;d = [\left \langle a, b \right \rangle, -s_b\mathbf{a} + s_a\mathbf{b} - \mathbf{b} \times \mathbf{a}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Remembering that a rotor is given by \eqref{rotor}, we can relate the &lt;em&gt;inner product&lt;/em&gt; between &lt;strong&gt;rotor quaternions&lt;/strong&gt; with the scalar quantity of \eqref{rotor} and interpret it geometrically, just like the dot product between two vectors in 3D/2D space, but this time noticing that the dot product gives the cosine of half the angle between the quaternions:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a \cdot b = \cos{\frac{\theta}{2}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This means that the angle between $a$ and $b$ is equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\theta = 2 \arccos{(a \cdot b)}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Or using the &#xA;&#xA;&lt;a href=&#34;http://tutorial.math.lamar.edu/pdf/Trig_Cheat_Sheet.pdf&#34;target=&#34;_blank&#34;&gt;half-angle formulas&lt;/a&gt;&#xA;&#xA;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\cos^2{\frac{\theta}{2}} &amp;= \frac{1}{2}(1 + \cos{\theta}) \\&#xA;(a \cdot b)^2 &amp;= \frac{1}{2}(1 + \cos{\theta}) \\&#xA;\cos{\theta} &amp;= 2 (a \cdot b)^2 - 1 \\&#xA;\theta &amp;= \arccos(2(a \cdot b)^2 - 1)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The second formula works for all cases, as noted &#xA;&#xA;&lt;a href=&#34;http://math.stackexchange.com/questions/90081/quaternion-distance&#34;target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;&#xA; (the first one doesn&amp;rsquo;t work when $a \cdot b &amp;lt; 0$).&lt;/p&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function () {&#xA;  function unitCircle() {&#xA;    return {&#xA;      x: &#39;cos(t)&#39;,&#xA;      y: &#39;sin(t)&#39;,&#xA;      color: &#39;lightgrey&#39;,&#xA;      fnType: &#39;parametric&#39;,&#xA;      graphType: &#39;polyline&#39;&#xA;    }&#xA;  }&#xA;&#xA;  functionPlot({&#xA;    target: &#39;#two-dimensions&#39;,&#xA;    grid: true,&#xA;    xAxis: { domain: [-6, 6] },&#xA;    data: [&#xA;      { vector: [1, 0], color: &#39;#FFCCCB&#39;, fnType: &#39;vector&#39;, graphType: &#39;polyline&#39; },&#xA;      { vector: [0, 1], color: &#39;#add8e6&#39;, fnType: &#39;vector&#39;, graphType: &#39;polyline&#39; },&#xA;      { vector: [0.86602540378, 0.5], color: &#39;red&#39;, fnType: &#39;vector&#39;, graphType: &#39;polyline&#39;},&#xA;      { vector: [-0.5, 0.86602540378], color: &#39;blue&#39;, fnType: &#39;vector&#39;, graphType: &#39;polyline&#39; },&#xA;      unitCircle()&#xA;    ]&#xA;  })&#xA;})&#xA; &lt;/script&gt;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Scaling Objects with a Transformation Matrix</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/scale/</link>
      <pubDate>Tue, 20 Oct 2015 13:30:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/scale/</guid>
      <description>&lt;p&gt;This article is part 2 in the series about transformation matrices:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../coordinate-systems/&#34;target=&#34;_blank&#34;&gt;Part 1: Coordinate systems and transformations between them&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&#xA;&#xA;&lt;a href=&#34;../scale/&#34;target=&#34;_blank&#34;&gt;Part 2: Scaling objects with a transformation matrix&lt;/a&gt;&#xA;&#xA; (this article)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../shearing/&#34;target=&#34;_blank&#34;&gt;Part 3: Shearing objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../translation/&#34;target=&#34;_blank&#34;&gt;Part 4: Translating objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../combining-transformations/&#34;target=&#34;_blank&#34;&gt;Part 5: Combining Matrix Transformations&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;scaling-along-the-cardinal-axes&#34;&gt;Scaling Along the Cardinal Axes&lt;/h2&gt;&#xA;&lt;p&gt;Intuitively, the basis vectors should be multiplied by a scalar. Also, they are independently affected by the scale factors.&lt;/p&gt;&#xA;&lt;p&gt;In 2D, the basis vectors become:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{p&#39;} = k_x \mathbf{p} = k_x \begin{bmatrix} 1 \\ 0 \end{bmatrix} = \begin{bmatrix} k_x \\ 0 \end{bmatrix} \\&#xA;\mathbf{q&#39;} = k_y \mathbf{q} = k_y \begin{bmatrix} 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ k_y \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Constructing the 2D scale matrix $\mathbf{S}(k_x, k_y)$ from these basis vectors:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{S}(k_x, k_y) = \begin{bmatrix} k_x &amp; 0 \\ 0 &amp; k_y \end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Similarly, the 3D scale matrix is given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{S}(k_x, k_y, k_z) = \begin{bmatrix}&#xA;k_x &amp; 0 &amp; 0 \\&#xA;0 &amp; k_y &amp; 0 \\&#xA;0 &amp; 0 &amp; k_z&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;scaling-along-an-arbitrary-axis&#34;&gt;Scaling Along an Arbitrary Axis&lt;/h2&gt;&#xA;&lt;p&gt;Let $\unit{n}$ be the unit vector parallel to the direction of scale and $k$ to be the scale factor. A vector transformed by this scale operation can be represented as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{S}(\unit{n}, k) \mathbf{v}&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://www.mauriciopoppe.com/images/scale%21arbitrary-axis.png&#34; alt=&#34;Scale Arbitrary Axis&#34; /&gt;&#xA;    &#xA;    &#xA;    &lt;figcaption&gt;&#xA;        &lt;p class=&#34;tw-text-base&#34;&gt;Scale Arbitrary Axis&lt;/p&gt;&#xA;        &#xA;    &lt;/figcaption&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&lt;p&gt;Separate $\mathbf{v}$ into two vectors: a vector parallel to $\unit{v}$ called $\mathbf{v_{\parallel}}$ and a vector perpendicular to $\unit{v}$ called $\mathbf{v_{\perp}}$ such that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = \mathbf{v_{\parallel}} + \mathbf{v_{\perp}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v_{\parallel}} &amp;= (\mathbf{v} \cdot \unit{n}) \unit{n} \\&#xA;\mathbf{v_{\perp}} &amp;= \mathbf{v} - \mathbf{v_{\parallel}}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can also represent $\mathbf{v&amp;rsquo;}$ as a sum of two vectors parallel and perpendicular to $\unit{n}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{v_{\parallel}&#39;} + \mathbf{v_{\perp}&#39;}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that any vector that lies in the 2D line or 3D plane perpendicular to $\unit{n}$ will not be affected by the scale operation, so $\mathbf{v&amp;rsquo;} = \mathbf{v_{\parallel}&amp;rsquo;} + \mathbf{v_{\perp}}$.&lt;/p&gt;&#xA;&lt;p&gt;Since $\mathbf{v_{\parallel}}$ is parallel to the direction of scale, then $\mathbf{v_{\parallel}&amp;rsquo;} = k\mathbf{v_{\parallel}}$.&lt;/p&gt;&#xA;&lt;p&gt;Reconstructing the solution from the observations above:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v_{\parallel}} &amp;= (\mathbf{v} \cdot \unit{n}) \unit{n} \\&#xA;\mathbf{v_{\perp}&#39;} &amp;= \mathbf{v_{\perp}} \\&#xA;&amp;= \mathbf{v} - \mathbf{v_{\parallel}} \\&#xA;&amp;= \mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n} \\&#xA;\mathbf{v_{\parallel}&#39;} &amp;= k\mathbf{v_{\parallel}} \\&#xA;&amp;= k(\mathbf{v} \cdot \unit{n}) \unit{n}  \\&#xA;\mathbf{v&#39;} &amp;= \mathbf{v_{\perp}&#39;} + \mathbf{v_{\parallel}&#39;} \\&#xA;&amp;= \mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n} + k(\mathbf{v} \cdot \unit{n}) \unit{n} \\&#xA;&amp;= \mathbf{v} + (k - 1) (\mathbf{v} \cdot \unit{n}) \unit{n}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can construct a general scale matrix by computing the vectors resulting after transforming the basis vectors $\mathbf{p}$, $\mathbf{q}$, and $\mathbf{r}$. For example, let&amp;rsquo;s transform $\mathbf{p} = \begin{bmatrix} 1 &amp;amp; 0 &amp;amp; 0 \end{bmatrix}^T$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{p&#39;} &amp;= \mathbf{p} + (k - 1) (\mathbf{p} \cdot \unit{n}) \unit{n} \\&#xA;&amp;= \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} + (k - 1) \left ( \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} \begin{bmatrix} n_x \\ n_y \\ n_z \end{bmatrix}^T \right ) \begin{bmatrix} n_x \\ n_y \\ n_z \end{bmatrix} \\&#xA;&amp;= \begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} + (k - 1) n_x \begin{bmatrix} n_x \\ n_y \\ n_z \end{bmatrix} \\&#xA;&amp;= \begin{bmatrix}&#xA;1 + (k - 1) {n_x}^2 \\&#xA;(k - 1)n_xn_y \\&#xA;(k - 1)n_xn_z&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Similarly, the values of $\mathbf{q&amp;rsquo;}$ and $\mathbf{r&amp;rsquo;}$ can be found, which make the general rotation matrix equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{S}(\unit{n}, k) &amp;= \begin{bmatrix} \mathbf{p&#39;} &amp; \mathbf{q&#39;} &amp; \mathbf{r&#39;} \end{bmatrix} \nonumber \\&#xA;&amp; = \begin{bmatrix}&#xA;1 + (k - 1) {n_x}^2 &amp; (k - 1)n_yn_x &amp; (k - 1)n_zn_x \\&#xA;(k - 1)n_xn_y &amp; 1 + (k - 1) {n_y}^2 &amp; (k - 1)n_zn_y \\&#xA;(k - 1)n_xn_z &amp; (k - 1)n_yn_z &amp; 1 + (k - 1) {n_z}^2&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Transformation Matrix</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/transformation-matrix/</link>
      <pubDate>Thu, 15 Oct 2015 13:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/transformation-matrix/</guid>
      <description>&lt;p&gt;Let&amp;rsquo;s say that we&amp;rsquo;re given the standard basis vectors $\mathbf{i} = [1, 0, 0], ; \mathbf{j} = [0, 1, 0], ; \mathbf{k} = [0, 0, 1]$, and we multiply each of these vectors by an &lt;em&gt;arbitrary&lt;/em&gt; matrix $\mathbf{M}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\&#xA;\mathbf{iM} &amp;= \begin{bmatrix}1 &amp; 0 &amp; 0\end{bmatrix}&#xA;\begin{bmatrix}&#xA;m_{11} &amp; m_{12} &amp; m_{13} \\&#xA;m_{21} &amp; m_{22} &amp; m_{23} \\&#xA;m_{31} &amp; m_{32} &amp; m_{33} \\&#xA;\end{bmatrix} = \begin{bmatrix} m_{11} &amp; m_{12} &amp; m_{13} \end{bmatrix} \\&#xA;\&#xA;\\&#xA;\&#xA;\mathbf{jM} &amp;= \begin{bmatrix}0 &amp; 1 &amp; 0\end{bmatrix}&#xA;\begin{bmatrix}&#xA;m_{11} &amp; m_{12} &amp; m_{13} \\&#xA;m_{21} &amp; m_{22} &amp; m_{23} \\&#xA;m_{31} &amp; m_{32} &amp; m_{33} \\&#xA;\end{bmatrix} = \begin{bmatrix} m_{21} &amp; m_{22} &amp; m_{23} \end{bmatrix} \\&#xA;\&#xA;\\&#xA;\&#xA;\mathbf{kM} &amp;= \begin{bmatrix}0 &amp; 0 &amp; 1\end{bmatrix}&#xA;\begin{bmatrix}&#xA;m_{11} &amp; m_{12} &amp; m_{13} \\&#xA;m_{21} &amp; m_{22} &amp; m_{23} \\&#xA;m_{31} &amp; m_{32} &amp; m_{33} \\&#xA;\end{bmatrix} = \begin{bmatrix} m_{31} &amp; m_{32} &amp; m_{33} \end{bmatrix} \\&#xA;\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The first row of $\mathbf{M}$ contains the result of &lt;em&gt;performing a transformation on the vector $\mathbf{i}$&lt;/em&gt;, the second row is the result of transforming $\mathbf{j}$, and the third row to $\mathbf{k}$.&lt;/p&gt;&#xA;&lt;p&gt;Let $\mathbf{v}$ be some vector expressed under this coordinate space, which means that it can be represented as a linear combination of the basis:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = v_x \mathbf{i} + v_y \mathbf{j} + v_z \mathbf{k}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we multiply this vector by the matrix $\mathbf{M}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;\mathbf{v&#39;} = \mathbf{vM} &amp;= (v_x \mathbf{i} + v_y \mathbf{j} + v_z \mathbf{k}) \mathbf{M}&#xA;\nonumber \\&#xA;&amp;= v_x (\mathbf{iM}) + v_y (\mathbf{jM}) + v_z (\mathbf{kM}) \nonumber \\&#xA;&amp;= v_x \begin{bmatrix} m_{11} &amp; m_{12} &amp; m_{13} \end{bmatrix} + v_y \begin{bmatrix} m_{21} &amp; m_{22} &amp; m_{23} \end{bmatrix} + v_z \begin{bmatrix} m_{31} &amp; m_{32} &amp; m_{33} \end{bmatrix} \label{vm} \\&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we let $\mathbf{M}$ have the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M} = \begin{bmatrix}&#xA;-\mathbf{p}- \\&#xA;-\mathbf{q}- \\&#xA;-\mathbf{r}-&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then \eqref{vm} can be rewritten as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{vM} = v_x \mathbf{p} + v_y \mathbf{q} + v_z \mathbf{r}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$\mathbf{vM}$ is a &lt;em&gt;linear combination&lt;/em&gt; of the rows of $\mathbf{M}$. If we interpret these row vectors as the &lt;em&gt;basis vectors&lt;/em&gt; of some coordinate system expressed/measured in terms of an &lt;strong&gt;outer coordinate system&lt;/strong&gt;, then we have successfully created a structure that encodes a space coordinate transformation (from &lt;em&gt;object space&lt;/em&gt; to &lt;em&gt;upright space&lt;/em&gt;) in the form of a matrix:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{vM} = \begin{bmatrix}v_x &amp; v_y &amp; v_z\end{bmatrix}&#xA;\begin{bmatrix}&#xA;-\textbf{p}- \\&#xA;-\textbf{q}- \\&#xA;-\textbf{r}-&#xA;\end{bmatrix} = v_x \mathbf{p} + v_y \mathbf{q} + v_z \mathbf{r}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Another way to see this is that $\mathbf{M}$ encodes in its rows a transformation made to the standard basis vectors $\mathbf{i}, \mathbf{j}, \mathbf{k}$.&lt;/p&gt;&#xA;&lt;p&gt;The following notation means the rotation matrix that transforms the frame $a$ to the frame $b$ and that is represented in the frame $c$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;^{c} \mathbf{M}_{a \to b}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If the frame $c$ is equal to the frame $b$, then it can be omitted since it&amp;rsquo;s assumed that the matrix is represented in terms of the frame $b$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{a \rightarrow b}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For example, the matrix that transforms from &lt;em&gt;object space&lt;/em&gt; to &lt;em&gt;upright space&lt;/em&gt; is represented as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{object \rightarrow upright}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Transforming the vector $\mathbf{v_{object}}$ expressed in &lt;em&gt;object space&lt;/em&gt; to &lt;em&gt;upright space&lt;/em&gt; is then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v}_{upright} = \mathbf{v}_{object} \mathbf{M}_{object \rightarrow upright}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;row-versus-column-vectors&#34;&gt;Row Versus Column Vectors&lt;/h2&gt;&#xA;&lt;p&gt;A space coordinate transform operation has the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{vM}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\mathbf{M}$ encodes in its &lt;strong&gt;rows&lt;/strong&gt; a transformation made to the standard basis vectors, and $\mathbf{v&amp;rsquo;}$ and $\mathbf{v}$ are &lt;strong&gt;row vectors&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say that we want to transform a &lt;strong&gt;row vector&lt;/strong&gt; by the matrices $\mathbf{A}$, $\mathbf{B}$, and $\mathbf{C}$ in that order. The operation is represented as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v&#39;} = \mathbf{vABC}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;However, it could be possible that $\mathbf{v}$ is instead a &lt;strong&gt;column vector&lt;/strong&gt;. In that case, $\mathbf{v&amp;rsquo;}$ must also be a column vector. For $\mathbf{v&amp;rsquo;}$ to have the correct result, we must &lt;strong&gt;pre-multiply $\mathbf{v}$ by the transpose of the transformation matrix&lt;/strong&gt;, which is equivalent to transposing both sides of the equation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v&#39;} &amp;= \mathbf{vABC} \\&#xA;\mathbf{v&#39;}^T &amp;= (\mathbf{vABC})^T &amp;&amp; \text{transposing both sides} \\&#xA;\mathbf{v&#39;}^T &amp;= \mathbf{C}^T \mathbf{B}^T \mathbf{A}^T \mathbf{v}^T &amp;&amp; \text{because of the }\href{https://www.wikiwand.com/en/Transpose#/Properties}{\text{matrix transpose properties}}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The transformation matrices $\mathbf{A}^T$, $\mathbf{B}^T$, and $\mathbf{C}^T$ encode in their &lt;strong&gt;columns&lt;/strong&gt; a transformation made to the standard basis vectors, i.e., they have the form:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M} = \begin{bmatrix}&#xA;\mathbf{p}_{3 \times 1} &amp; \mathbf{q}_{3 \times 1} &amp; \mathbf{r}_{3 \times 1} \end{bmatrix} \quad \text{where $\mathbf{p} = \begin{bmatrix} p_x \\ p_y \\ p_z \end{bmatrix}$, $\mathbf{q} = \begin{bmatrix} q_x \\ q_y \\ q_z \end{bmatrix}$ and $\mathbf{r} = \begin{bmatrix} r_x \\ r_y \\ r_z \end{bmatrix}$}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;In Dunn &amp;amp; Parberry&amp;rsquo;s book, a column vector inside a matrix is written as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M} = \begin{bmatrix}&#xA;\cuv{\mathbf{p}} &amp;&#xA;\cuv{\mathbf{q}} &amp;&#xA;\cuv{\mathbf{r}}&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Also, note that in this notation, the arrow that connects the frames involved in the transformation is reversed. For example, the transformation matrix that transforms from &lt;em&gt;object space&lt;/em&gt; to &lt;em&gt;upright space&lt;/em&gt; is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{M}_{upright \leftarrow object}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;In computer graphics, &#xA;&#xA;&lt;a href=&#34;https://web.archive.org/web/20150321091101/http://chrishecker.com/Column_vs_row_vectors&#34;target=&#34;_blank&#34;&gt;&lt;em&gt;column vectors&lt;/em&gt; should be used&lt;/a&gt;&#xA;&#xA; to represent points, differences between points, and the like.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Coordinate systems and transformations between them</title>
      <link>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/coordinate-systems/</link>
      <pubDate>Thu, 15 Oct 2015 12:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-graphics/transformation-matrices/coordinate-systems/</guid>
      <description>&lt;p&gt;This article is part 1 in the series about transformation matrices:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&#xA;&#xA;&lt;a href=&#34;../coordinate-systems/&#34;target=&#34;_blank&#34;&gt;Part 1: Coordinate systems and transformations between them&lt;/a&gt;&#xA;&#xA; (this article)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../scale/&#34;target=&#34;_blank&#34;&gt;Part 2: Scaling objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../shearing/&#34;target=&#34;_blank&#34;&gt;Part 3: Shearing objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../translation/&#34;target=&#34;_blank&#34;&gt;Part 4: Translating objects with a transformation matrix&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;../combining-transformations/&#34;target=&#34;_blank&#34;&gt;Part 5: Combining Matrix Transformations&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;world-space-upright-space-object-space&#34;&gt;World space&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, upright space, object space&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Why bother having multiple spaces?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Information is given only in the context of a particular reference frame.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;World space&lt;/strong&gt;: A global reference frame.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The position of other coordinate spaces can be expressed in terms of this space.&lt;/li&gt;&#xA;&lt;li&gt;This space cannot be expressed in terms of any larger/outer space.&lt;/li&gt;&#xA;&lt;li&gt;Note that there&amp;rsquo;s no &amp;ldquo;absolute&amp;rdquo; space; however, this space is the largest one we care about.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Object space&lt;/strong&gt;: The space associated with each object that belongs to the world space.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Camera space&lt;/strong&gt;: The object space associated with the viewport used for rendering.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Upright space&lt;/strong&gt;: A special space associated with each object. It&amp;rsquo;s halfway between world space and object space in the sense that &lt;em&gt;the axes of this space are &lt;strong&gt;parallel&lt;/strong&gt; to the ones of the world space&lt;/em&gt;, but the origin of this space is coincident with the origin of the object space.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Why do we have an upright space?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Thanks to this space, the problem of transforming a point between object space and world space (and vice-versa) can be divided into two subproblems:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Object space to upright space (a rotation)&lt;/li&gt;&#xA;&lt;li&gt;Upright space to world space (a change of location)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;coordinates-of-a-vector&#34;&gt;Coordinates of a vector&lt;/h2&gt;&#xA;&lt;p&gt;A coordinate system consists of:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;An origin (displacement from another coordinate system&amp;rsquo;s origin)&lt;/li&gt;&#xA;&lt;li&gt;A basis (a set of three vectors)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The numeric coordinates of a vector expressed with respect to some basis are the coefficients of the representation of the vector as a linear combination of the basis vectors.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = v_x \mathbf{i} + v_y \mathbf{j} + v_z \mathbf{k}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;In other words, the numeric coordinates are the quantities that multiply each basis vector, which are $v_x$, $v_y$, and $v_z$.&lt;/p&gt;&#xA;&lt;p&gt;When the basis vectors are $\mathbf{i} = [1, 0, 0]$, $\mathbf{j} = [0, 1, 0]$, and $\mathbf{k} = [0, 0, 1]$, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v} &amp;= v_x \begin{bmatrix} 1 &amp; 0 &amp; 0 \end{bmatrix} + v_y \begin{bmatrix} 0 &amp; 1 &amp; 0 \end{bmatrix} + v_z \begin{bmatrix} 0 &amp; 0 &amp; 1 \end{bmatrix} \\&#xA;&amp;= \begin{bmatrix} v_x &amp; v_y &amp; v_z \end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;transformations-between-space-coordinates&#34;&gt;Transformations between space coordinates&lt;/h2&gt;&#xA;&lt;h3 id=&#34;from-object-space-to-upright-space&#34;&gt;From object space to upright space&lt;/h3&gt;&#xA;&lt;p&gt;Let $\mathbf{v}$ be some vector expressed/measured relative to a space (object space) whose basis vectors are $\mathbf{p}, \mathbf{q}, \mathbf{r}$ (which are themselves expressed/measured relative to a wrapper space). The vector $\mathbf{v}$ expressed relative to the wrapper space is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;\mathbf{v}_{upright} &amp;= v_x \mathbf{p} + v_y \mathbf{q} + v_z \mathbf{r} \label{object-upright}&#xA;&amp;= v_x \begin{bmatrix} p_x &amp; p_y &amp; p_z \end{bmatrix} + v_y \begin{bmatrix} q_x &amp; q_y &amp; q_z \end{bmatrix} + v_z \begin{bmatrix} r_x &amp; r_y &amp; r_z \end{bmatrix} \nonumber \&#xA;&amp;= \begin{bmatrix}&#xA;v_x p_x + v_y q_x + v_z r_x &amp;&#xA;v_x p_y + v_y q_y + v_z r_y &amp;&#xA;v_x p_z + v_y q_z + v_z r_z&#xA;\end{bmatrix}  \nonumber&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that if $\mathbf{p}, \mathbf{q}, \mathbf{r}$ were not orthogonal, then $\mathbf{v}_{upright}$ couldn&amp;rsquo;t be &lt;em&gt;uniquely&lt;/em&gt; determined.&lt;/p&gt;&#xA;&lt;p&gt;The coordinates of $\mathbf{p}, \mathbf{q}, \mathbf{r}$ are always equal to $[1, 0, 0], [0, 1, 0]$, and $[0, 0, 1]$ respectively &lt;em&gt;when expressed using the coordinate system for which they are the basis&lt;/em&gt;; relative to other wrapper coordinate systems, they will have arbitrary coordinates.&lt;/p&gt;&#xA;&lt;h3 id=&#34;from-upright-space-to-world-space&#34;&gt;From upright space to world space&lt;/h3&gt;&#xA;&lt;p&gt;Since the axes of the upright space are parallel to the axes of the world space, the only difference between these spaces is the translation of these axes with respect to the origin of the axes of the world space. Let $\mathbf{o}$ be the translation of the upright basis axes, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v}_{world} = \mathbf{o} + \mathbf{v}_{upright}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;from-world-space-to-upright-space&#34;&gt;From world space to upright space&lt;/h3&gt;&#xA;&lt;p&gt;We just have to translate the whole space so that the origin lies exactly on the origin of the upright space. If $\mathbf{o}$ is the origin of the upright space expressed in world space, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v}_{upright} = \mathbf{v}_{world} - \mathbf{o}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;from-upright-space-to-object-space&#34;&gt;From upright space to object space&lt;/h3&gt;&#xA;&lt;p&gt;What if $\mathbf{v}_{upright}$ is known and we want to know $\mathbf{v}$? The dot product is the key, as it&amp;rsquo;s used to measure distance in a particular direction. Since we know that the basis vectors $\mathbf{p}, \mathbf{q}, \mathbf{r}$ are expressed in terms of the upright space perspective, we just have to calculate the projection of $\mathbf{v}_{upright}$ in the direction of each of $\mathbf{p}, \mathbf{q}, \mathbf{r}$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;v_x = \mathbf{v}_{upright} \cdot \mathbf{p} \\&#xA;v_y = \mathbf{v}_{upright} \cdot \mathbf{q} \\&#xA;v_z = \mathbf{v}_{upright} \cdot \mathbf{r}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we use \eqref{object-upright}, this works because the dot product with $\mathbf{p}$ will isolate the $v_x$ coordinate:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\mathbf{v}_{upright} \cdot \mathbf{p} &amp;= v_x (\mathbf{p} \cdot \mathbf{p}) + v_y (\mathbf{q} \cdot \mathbf{p}) + v_z (\mathbf{r} \cdot \mathbf{p}) \\&#xA;&amp;= v_x (1) + v_y (0) + v_z (0) \\&#xA;&amp;= v_x&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This only works when $\mathbf{p}, \mathbf{q}, \mathbf{r}$ are orthonormal. For the general case, we have to solve this using linear algebra.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;Words like &amp;ldquo;coordinate system&amp;rdquo;, &amp;ldquo;coordinate frame&amp;rdquo;, or &amp;ldquo;space&amp;rdquo; are used interchangeably.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Quaternions</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/numeral-systems/quaternions/</link>
      <pubDate>Tue, 08 Sep 2015 20:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/numeral-systems/quaternions/</guid>
      <description>&lt;h2 id=&#34;definition&#34;&gt;Definition&lt;/h2&gt;&#xA;&lt;p&gt;The existence of complex numbers presented a question for mathematicians: if a complex number exists in a 2D complex plane, could there be a 3D equivalent?&lt;/p&gt;&#xA;&lt;p&gt;&lt;i&gt;Sir William Rowan Hamilton&lt;/i&gt;, among many other mathematicians of the 18th and 19th centuries, had been searching for the answer. Hamilton conjectured that a 3D complex number could be represented by the triple $a + bi + cj$, where $i$ and $j$ are imaginary quantities and square to $-1$. When he was developing the algebra for this triplet, the product of them raised a problem when expanded:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z_1 &amp;= a_1 + b_1i + c_1j \\&#xA;z_2 &amp;= a_2 + b_2i + c_2j \\&#xA;z_1z_2 &amp;= (a_1 + b_1i + c_1j)(a_2 + b_2i + c_2j) \\&#xA;&amp;= (a_1a_2 - b_1b_2 - c_1c_2) + (a_1b_2 + b_1a_2)i + (a_1c_2 + c_1a_2)j \\&#xA;&amp; \quad + b_1c_2ij + c_1b_2ji&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The quantities $ij$ and $ji$ represented a problem for Hamilton. Even if $ij = -ji$, we are still left with $(b_1c_2 - c_1b_2)ij$.&lt;/p&gt;&#xA;&lt;p&gt;On October 16th, 1843, while he was walking with his wife along the Royal Canal in Ireland, he saw the solution as a &lt;i&gt;quadruple&lt;/i&gt; instead of a &lt;i&gt;triple&lt;/i&gt;. Instead of using two imaginary terms, three imaginary terms provided the necessary quantities to resolve products like $ij$.&lt;/p&gt;&#xA;&lt;p&gt;Hamilton defined a quaternion $q$ as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q = s + ai + bj + ck, \quad s,a,b,c \in \mathbb{R} \\&#xA;i^2 = j^2 = k^2 = ijk = -1 \\&#xA;ij = k, \quad jk = i, \quad ki = j \\&#xA;ji = -k, \quad kj = -i, \quad ik = -j&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If a complex number $i$ is capable of rotating points on the plane by $90^\circ$, then perhaps a triple rotates points in space by $90^\circ$. In the end, the triplet was replaced by a quaternion.&lt;/p&gt;&#xA;&lt;h2 id=&#34;notation&#34;&gt;Notation&lt;/h2&gt;&#xA;&lt;p&gt;There are three ways of annotating a quaternion $q$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;q &amp;= s + xi + yj + zk \\&#xA;q &amp;= s + \mathbf{v} \\&#xA;q &amp;= [s, \mathbf{v}] \\&#xA;&amp; \text{where } s,x,y,z \in \mathbb{R}, \mathbf{v} \in \mathbb{R}^3 \\&#xA;&amp; \text{and } i^2 = j^2 = k^2 = ijk = -1 \nonumber&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;real-quaternion&#34;&gt;Real Quaternion&lt;/h3&gt;&#xA;&lt;p&gt;A real quaternion has a zero vector term:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q = [s, \mathbf{0}]&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;pure-quaternion&#34;&gt;Pure Quaternion&lt;/h3&gt;&#xA;&lt;p&gt;A pure quaternion is a quaternion having a zero scalar term:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q = [0, \mathbf{v}]&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;quaternion-conjugate&#34;&gt;Quaternion Conjugate&lt;/h3&gt;&#xA;&lt;p&gt;Given:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q = [s, \mathbf{v}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The quaternion conjugate is defined as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q^* = [s, - \mathbf{v}]&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;quaternion-norm&#34;&gt;Quaternion Norm&lt;/h3&gt;&#xA;&lt;p&gt;The norm of a quaternion $q = [s, \mathbf{v}]$ is defined as the square root of the product of itself and its conjugate (the multiplication operation is defined later):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\norm{q} &amp;= \sqrt{qq^*} \\&#xA;&amp;= \sqrt{s^2 + x^2 + y^2 + z^2}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Also note that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\norm{q}^2 = qq^*&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Norm facts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$\norm{qq^*} = \norm{q}\norm{q^*}$&lt;/li&gt;&#xA;&lt;li&gt;$\norm{q^*} = \norm{q}$&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;unit-quaternion&#34;&gt;Unit Quaternion&lt;/h3&gt;&#xA;&lt;p&gt;A unit quaternion is a quaternion of norm one given by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;q &amp;= [s, \lambda \unit{n}] \quad s,\lambda \in \mathbb{R}, \unit{n} \in \mathbb{R}^3 \label{unit-norm-quaternion}\\&#xA;\left | \unit{n} \right | &amp;= 1 \nonumber \\&#xA;s^2 + \lambda^2 &amp;= 1 \nonumber&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note: dividing a non-zero quaternion by its norm produces a unit norm quaternion.&lt;/p&gt;&#xA;&lt;h2 id=&#34;operations&#34;&gt;Operations&lt;/h2&gt;&#xA;&lt;h3 id=&#34;quaternion-product&#34;&gt;Quaternion Product&lt;/h3&gt;&#xA;&lt;p&gt;Given two quaternions:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q_a = [s_a, \mathbf{a}], \quad \quad \mathbf{a} = x_a i + y_a j + z_a k \\&#xA;q_b = [s_b, \mathbf{b}], \quad \quad \mathbf{b} = x_b i + y_b j + z_b k&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The product $q_aq_b$ is computed as follows:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;q_aq_b &amp;= (s_a + x_a i + y_a j + z_a k)(s_b + x_b i + y_b j + z_b k) \nonumber \\&#xA;&amp;= (s_as_b - x_ax_b - y_ay_b - z_az_b) \nonumber \\&#xA;&amp; \quad + (s_ax_b + s_bx_a + y_az_b - y_bz_a)i \nonumber \\&#xA;&amp; \quad + (s_ay_b + s_by_a + z_ax_b - z_bx_a)j \nonumber \\&#xA;&amp; \quad + (s_az_b + s_bz_a + x_ay_b - x_by_a)k \label{quaternion-product}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Replacing the imaginaries by the ordered pairs (which are themselves &lt;i&gt;quaternion units&lt;/i&gt;):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;i = [0, \mathbf{i}], \quad j = [0, \mathbf{j}], \quad k = [0, \mathbf{k}], \quad 1 = [1, \mathbf{0}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;And substituting them in \eqref{quaternion-product}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q_aq_b &amp;= (s_as_b - x_ax_b - y_ay_b - z_az_b)[1, \mathbf{0}] \\&#xA;&amp; \quad + (s_ax_b + s_bx_a + y_az_b - y_bz_a)[0, \mathbf{i}] \\&#xA;&amp; \quad + (s_ay_b + s_by_a + z_ax_b - z_bx_a)[0, \mathbf{j}] \\&#xA;&amp; \quad + (s_az_b + s_bz_a + x_ay_b - x_by_a)[0, \mathbf{k}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;By doing some groupings:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q_aq_b &amp;= [s_as_b - x_ax_b - y_ay_b - z_az_b, \\&#xA;&amp; \quad s_a(x_b \mathbf{i} + y_b \mathbf{j} + z_b \mathbf{k}) + s_b(x_a \mathbf{i} + y_a \mathbf{j} + z_a \mathbf{k}) \\&#xA;&amp; \quad + (y_az_b - y_bz_a) \mathbf{i} + (z_ax_b - z_bx_a) \mathbf{j} + (x_ay_b - x_by_a) \mathbf{k}] \\&#xA;&amp;= [s_as_b - \mathbf{a} \cdot \mathbf{b}, s_a\mathbf{b} + s_b\mathbf{a} + \mathbf{a} \times \mathbf{b}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now let&amp;rsquo;s compute the product $q_bq_a$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q_bq_a = [s_bs_a - \mathbf{b} \cdot \mathbf{a}, s_b\mathbf{a} + s_a\mathbf{b} + \mathbf{b} \times \mathbf{a}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the scalar quantity of both products is the same; however, the vector quantity varies (the cross product sign is changed). Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q_aq_b \neq q_bq_a&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This is an important fact to note since for complex numbers the product commutes; however, for quaternions, it doesn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;h4 id=&#34;product-of-a-scalar-and-a-quaternion&#34;&gt;Product of a Scalar and a Quaternion&lt;/h4&gt;&#xA;&lt;p&gt;Let $k$ be a scalar represented as a quaternion as $q_k = [k, \mathbf{0}]$ and $q = [s, \mathbf{v}]$.&lt;/p&gt;&#xA;&lt;p&gt;Their product is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q_kq &amp;= [k, \mathbf{0}][s, \mathbf{v}] \\&#xA;&amp;= [ks, k\mathbf{v}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that this product is commutative.&lt;/p&gt;&#xA;&lt;h4 id=&#34;product-of-a-quaternion-with-itself-square-of-a-quaternion&#34;&gt;Product of a Quaternion with Itself (Square of a Quaternion)&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q &amp;= [s, \mathbf{v}] \\&#xA;q^2 &amp;= [s, \mathbf{v}] [s, \mathbf{v}] \\&#xA;&amp;= [s^2 - \mathbf{v} \cdot \mathbf{v}, 2s\mathbf{v} + \mathbf{v} \times \mathbf{v}] \\&#xA;&amp;= [s^2 - \|v\|^2, 2s\mathbf{v}] \\&#xA;&amp;= [s^2 - (x^2 + y^2 + z^2), 2s(x\mathbf{i} + y\mathbf{j} + z\mathbf{k})]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;product-of-a-quaternion-and-its-conjugate&#34;&gt;Product of a Quaternion and Its Conjugate&lt;/h4&gt;&#xA;&lt;p&gt;Let $q = [s, \mathbf{v}]$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;qq^* &amp;= [s, \mathbf{v}][s, -\mathbf{v}] \\&#xA;&amp;= [s^2 + \mathbf{v} \cdot \mathbf{v}, -s \mathbf{v} + s\mathbf{v} - \mathbf{v} \times \mathbf{v}] \\&#xA;&amp;= [s^2 + \mathbf{v} \cdot \mathbf{v}, \mathbf{0}] \\&#xA;&amp;= s^2 + x^2 + y^2 + z^2&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that this product commutes, i.e., $qq^* = q^*q$.&lt;/p&gt;&#xA;&lt;h4 id=&#34;product-of-unit-quaternions&#34;&gt;Product of Unit Quaternions&lt;/h4&gt;&#xA;&lt;p&gt;Given:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q_a = [s_a, \mathbf{a}] \\&#xA;q_b = [s_b, \mathbf{b}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\norm{q_a} = \norm{q_b} = 1$, the product is another unit-norm quaternion:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q_c = [s_c, \mathbf{c}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\norm{q_c} = 1$.&lt;/p&gt;&#xA;&lt;h4 id=&#34;product-of-pure-quaternions&#34;&gt;Product of Pure Quaternions&lt;/h4&gt;&#xA;&lt;p&gt;Let:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q_a = [0, \mathbf{a}] \\&#xA;q_b = [0, \mathbf{b}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The product $q_aq_b$ is defined as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q_aq_b &amp;= [-\mathbf{a} \cdot \mathbf{b}, \mathbf{a} \times \mathbf{b}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the resulting quaternion is no longer a &lt;em&gt;pure quaternion&lt;/em&gt; as some information has propagated into the real part via the dot product.&lt;/p&gt;&#xA;&lt;h4 id=&#34;product-of-a-pure-quaternion-with-itself-square-of-a-pure-quaternion&#34;&gt;Product of a Pure Quaternion with Itself (Square of a Pure Quaternion)&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q &amp;= [0, \mathbf{v}] \\&#xA;q^2 &amp;= [0, \mathbf{v}] [0, \mathbf{v}] \\&#xA;&amp;= [-\mathbf{v} \cdot \mathbf{v}, \mathbf{v} \times \mathbf{v}] \\&#xA;&amp;= [-(x^2 + y^2 + z^2), \mathbf{0}] \\&#xA;&amp;= -\norm{v}^2&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If $q$ is a unit norm pure quaternion, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;q^2 = -1&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;product-of-a-pure-quaternion-with-its-conjugate&#34;&gt;Product of a Pure Quaternion with Its Conjugate&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q^*q = qq^* &amp;= [0, \mathbf{v}][0, -\mathbf{v}] \\&#xA;&amp;= [\mathbf{v} \cdot \mathbf{v}, -\mathbf{v \times v}] \\&#xA;&amp;= [\mathbf{v} \cdot \mathbf{v}, \mathbf{0}] \\&#xA;&amp;= \norm{v}^2&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;inverse-of-a-quaternion&#34;&gt;Inverse of a Quaternion&lt;/h3&gt;&#xA;&lt;p&gt;By definition, the inverse $q^{-1}$ of $q$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;qq^{-1} = [1, \mathbf{0}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To isolate $q^{-1}$, let&amp;rsquo;s pre-multiply both sides by $q^**:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q^*qq^{-1} &amp;= q^* \\&#xA;\norm{q}^2q^{-1} &amp;= q^* \\&#xA;q^{-1} &amp;= \frac{q^*}{\norm{q}^2}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;quaternion-units&#34;&gt;Quaternion Units&lt;/h3&gt;&#xA;&lt;p&gt;Given the vector $\mathbf{v}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\mathbf{v} = v \hat{\mathbf{v}}, \quad \text{where } v = |\mathbf{v}|, \text{ and } |\hat{\mathbf{v}}| = 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Combining this with the definition of a &lt;em&gt;pure quaternion&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;q &amp;= [0, \mathbf{v}] \\&#xA;&amp;= [0, v \hat{\mathbf{v}}] \\&#xA;&amp;= v[0, \hat{\mathbf{v}}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;It&amp;rsquo;s convenient to identify the unit quaternion as $\hat{q}$ (where $v = 1$):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\hat{q} = [0, \hat{\mathbf{v}}]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s check if the quaternion unit $\mathbf{i}$ squares to the ordered pair $[-1, \mathbf{0}]$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;i^2 &amp;= [0, \mathbf{i}][0, \mathbf{i}] \\&#xA;&amp;= [0 \cdot 0 - \mathbf{i} \cdot \mathbf{i}, 0 \cdot \mathbf{i} + 0 \cdot \mathbf{i} - \mathbf{i} \times \mathbf{i}] \\&#xA;&amp;= [-|\mathbf{i}|^2, \mathbf{0}] \quad \text{since } \mathbf{i} \times \mathbf{i} = 0 \\&#xA;&amp; = [-1, \mathbf{0}]&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;misc-operations&#34;&gt;Misc Operations&lt;/h3&gt;&#xA;&lt;h4 id=&#34;taking-the-scalar-part-of-a-quaternion&#34;&gt;Taking the Scalar Part of a Quaternion&lt;/h4&gt;&#xA;&lt;p&gt;To isolate the scalar part of $q$, we could add $q^*$ to it:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;2 S(q) = q + q^*&#xA;$$&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Complex Numbers</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/numeral-systems/complex-numbers/</link>
      <pubDate>Tue, 08 Sep 2015 13:30:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/numeral-systems/complex-numbers/</guid>
      <description>&lt;h2 id=&#34;imaginary-numbers&#34;&gt;Imaginary Numbers&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Invented to solve problems where an equation has no real roots, e.g., $x^2 + 16 = 0$. The idea of declaring the existence of a quantity $i$ such that $i^2 = -1$ allows us to express the solution as:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA;x = \sqrt{-16} = \sqrt{16i^2} = \pm4i&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The set represented by $\mathbb{I}$ defines an imaginary number as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;i^2 = -1&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;powers-of-i&#34;&gt;Powers of i&lt;/h3&gt;&#xA;&lt;p&gt;If $i^2 = -1$, then $i^4 = i^2i^2 = -1 \cdot -1 = 1$.&lt;/p&gt;&#xA;&lt;p&gt;Therefore, we have the sequence:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{array}{ccccc}&#xA;\hline&#xA;i &amp; i^2 &amp; i^3 &amp; i^4 &amp; i^5 &amp; \ldots \\&#xA;\hline&#xA;i &amp; -1 &amp; -i &amp; 1 &amp; i &amp; \ldots \\&#xA;\hline&#xA;\end{array}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;complex-numbers&#34;&gt;Complex Numbers&lt;/h2&gt;&#xA;&lt;p&gt;A complex number is just the sum of a real and an imaginary number:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z = a + bi, \quad a,b \in \mathbb{R}, \quad i^2 = -1&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;operations-on-complex-numbers&#34;&gt;Operations on Complex Numbers&lt;/h3&gt;&#xA;&lt;p&gt;Given two complex numbers:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z_1 = a_1 + b_1i \\&#xA;z_2 = a_2 + b_2i&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;addition-and-subtraction&#34;&gt;Addition and Subtraction&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;z_1 \pm z_2 = a_1 \pm a_2 + (b_1 \pm b_2)i&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;product&#34;&gt;Product&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z_1z_2 &amp;= a_1a_2 + a_1b_2i + a_2b_1i + b_1b_2i^2 \quad \text{given that i^2 = -1} \\&#xA;&amp;= (a_1a_2 - b_1b_2) + (a_1b_2 + b_1a_2)i&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Given the complex number:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z = a + bi&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;norm-modulus-or-absolute-value&#34;&gt;Norm (Modulus or Absolute Value)&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;|z| = \sqrt{a^2 + b^2}&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;complex-conjugate&#34;&gt;Complex Conjugate&lt;/h4&gt;&#xA;&lt;p&gt;The product of two complex numbers where the only difference between them is the &lt;strong&gt;sign&lt;/strong&gt; of the imaginary part is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(a + bi)(a - bi) = a^2 - abi + abi - b^2i^2 = a^2 + b^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This quantity $a - bi$ is called the &lt;em&gt;complex conjugate&lt;/em&gt; of $z$ (denoted as $z^*$). It implies that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;zz^* = |z|^2&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;inverse&#34;&gt;Inverse&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;z^{-1} = \frac{1}{z}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Multiplying the numerator and denominator with the conjugate of $z$ (so that we have a real part on the denominator):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z^{-1} = \frac{1}{z} \frac{z^*}{z^*} = \frac{z^*}{zz^*} = \frac{z^*}{|z|^2}&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;square-root-of-i&#34;&gt;Square Root of $i$&lt;/h4&gt;&#xA;&lt;p&gt;We&amp;rsquo;re trying to find a complex number $z$ such that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sqrt{i} = z \\&#xA;i = z^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Assuming that $z$ is the complex number $z = a + bi$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;i &amp;= (a + bi)^2 \nonumber \\&#xA;&amp;= (a + bi)(a + bi) \nonumber \\&#xA;&amp;= a^2 - b^2 + 2abi \label{square-imaginary}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(a^2 - b^2) + (2ab)i = 0 + 1i&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Equating real and imaginary parts:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;a^2 - b^2 &amp;= 0 \\&#xA;2ab = 1&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore, $a = \pm b$. Replacing $a = -b$ in the second equation, we obtain $-2b^2 = 1$, which is not satisfied by any real number $b$. Therefore, the case $a = -b$ is impossible. Replacing $a = b$ in the second equation, we obtain $2a^2 = 1$, so:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;2a^2 = 1 \\&#xA;a^2 = \frac{1}{2} \\&#xA;a = b = \pm \sqrt{\frac{1}{2}} = \pm \frac{1}{\sqrt{2}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally, the value of $\sqrt{i}$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sqrt{i} = (a + bi) = \pm{\frac{1}{\sqrt{2}}} (1 + i)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The value of $\sqrt{-i}$ is found in the same way (by replacing $b = -a$ in the equation $-2ab = 1$ found from multiplying \eqref{square-imaginary} by $-1$):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sqrt{-i} = (a + bi) = \pm{\frac{1}{\sqrt{2}}} (1 - i)&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;matrix-representation-of-a-complex-number&#34;&gt;Matrix Representation of a Complex Number&lt;/h3&gt;&#xA;&lt;p&gt;The matrix $C$ for a complex number is the sum of two other matrices representing the real $R$ and imaginary $I$ parts:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;C = R + I&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;which can be written as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;C = a \hat{R} + b \hat{I}, \quad\quad a, b \in \mathbb{R}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $R = 1$ and $I = i$.&lt;/p&gt;&#xA;&lt;p&gt;The matrix representation of $R = 1$ in 2D is the identity matrix:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix}&#xA;1 &amp; 0 \\&#xA;0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To find the matrix representation of $i$, we have to analyze the definition of $i$, which is &lt;em&gt;a quantity&lt;/em&gt; which squares to $-1$. Given that we already know the value of $1$ in matrix form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;i^2 &amp;= -1 \cdot \begin{bmatrix}&#xA;1 &amp; 0 \\&#xA;0 &amp; 1&#xA;\end{bmatrix} \\&#xA;&amp;= \begin{bmatrix}&#xA;-1 &amp; 0 \\&#xA;0 &amp; -1&#xA;\end{bmatrix}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Squaring the following matrix gives the matrix above. Then the value of $i$ expressed in matrix form is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;I = \begin{bmatrix}&#xA;0 &amp; -1 \\&#xA;1 &amp; 0&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally, the value of $C$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;C = a \begin{bmatrix}&#xA;1 &amp; 0 \\&#xA;0 &amp; 1&#xA;\end{bmatrix} + b \begin{bmatrix}&#xA;0 &amp; -1 \\&#xA;1 &amp; 0&#xA;\end{bmatrix} =&#xA;\begin{bmatrix}&#xA;a &amp; -b \\&#xA;b &amp; a&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;the-complex-plane&#34;&gt;The Complex Plane&lt;/h3&gt;&#xA;&lt;p&gt;The powers of $i$ give rise to the sequence $(1, i, -1, -i, 1, \ldots)$, which is quite similar to the pattern&#xA;$(x, y, -x, -y, x, \ldots)$. The resemblance is no coincidence, as complex numbers belong to a 2-dimensional plane. This complex plane allows us to visualize complex numbers using the horizontal axis for the real part and the vertical axis for the imaginary part.&lt;/p&gt;&#xA;&lt;div id=&#34;complex-plane&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;tw-text-center&#34;&gt;$1, i, -1, -i$&lt;/div&gt;&#xA;&lt;p&gt;We can see that the positions of $i^0 = 1, i^1 = i, i^2 = -1, i^3 = -i, \ldots$ suggest that the multiplication of a complex number by $i$ is equivalent to rotating through 90 degrees.&lt;/p&gt;&#xA;&lt;p&gt;e.g.,&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z_1 &amp;= 2 + i \\&#xA;z_2 &amp;= (2 + i)(i) = -1 + 2i \\&#xA;z_3 &amp;= (-1 + 2i)(i) = -2 - i \\&#xA;z_4 &amp;= (-2 - i)(i) = 1 - 2i \\&#xA;z_5 &amp;= (1 - 2i)(i) = 2 + i = z_1&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;complex-2-i&#34;&gt;&lt;/div&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A complex number is rotated $\pm 90^{\circ}$ by multiplying it by $\pm i$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s graph the roots of $\sqrt{i} = \pm \frac{1}{\sqrt{2}} (1 + i)$:&lt;/p&gt;&#xA;&lt;div id=&#34;complex-square-root&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;We can see that $\tfrac{1}{\sqrt{2}} (1 + i)$ is exactly at $45^{\circ}$ and $- \tfrac{1}{\sqrt{2}} (1 + i)$ is exactly at $225^{\circ}$.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s multiply the complex number $2 + i$ by $\sqrt{i}$ (it should rotate it by $45^{\circ}$):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z_1 &amp;= 2 + i \\&#xA;z_2 &amp;= (2 + i)(\sqrti + \sqrti i) = \sqrti + 3 \sqrti i&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;complex-45&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Multiplying $z_2$ by $\sqrt{i}$ again should be equal to multiplying $z_1$ by $i$ (because $z_2$ is already rotated by $45^{\circ}$):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z_2 &amp;= \sqrti + 3 \sqrti i \\&#xA;z_3 &amp;= (\sqrti + 3 \sqrti i)(\sqrti + \sqrti i) \\&#xA;&amp;= (\frac{1}{2} - \frac{3}{2}) + (\frac{1}{2} + \frac{3}{2})i \\&#xA;&amp;= -1 + 2i&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which is exactly what we find if we multiply $z_1$ by $i$. These observations suggest that we can build a complex number which can rotate another complex number by any angle.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A complex number is rotated $45^{\circ}$ by multiplying it by $\tfrac{1}{\sqrt{2}} + \tfrac{1}{\sqrt{2}}i$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A complex number is rotated $225^{\circ}$ by multiplying it by $-\tfrac{1}{\sqrt{2}} - \tfrac{1}{\sqrt{2}}i$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;polar-representation&#34;&gt;Polar Representation&lt;/h3&gt;&#xA;&lt;p&gt;Instead of using coordinates in the complex plane, we can represent a polar number with the length of the vector from the origin to the complex coordinate and the angle between the complex vector and the positive real axis:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;r = |z| = \sqrt{a^2 + b^2} \\&#xA;\theta = \arctan(\frac{b}{a})&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The horizontal component of $z$ is then $r \cos(\theta)$, and the vertical component is $r \sin(\theta)$. Expressing the complex number using these quantities:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;z &amp;= a + bi \\&#xA;&amp;= r \cos \theta + ri\; \sin \theta \\&#xA;&amp;= r (\cos \theta + i \sin \theta)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Euler provided the identity:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{rotor}&#xA;e^{i\theta} = \cos \theta + i \sin \theta&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which allows us to represent any complex number as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z = r\,e^{i\theta}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Given two polar numbers:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;z = r\,e^{i\theta} \\&#xA;w = s\,e^{i\phi} \\&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Their product is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;zw = rs\, e^{i(\theta + \phi)} = rs [ \cos (\theta + \phi) + i \sin (\theta + \phi)]&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which effectively rotated the complex number $z$ by $\phi$ angles! However, the quantity $zw$ was scaled by $s$ units. To avoid scaling, we can normalize $w$ (i.e., making $r = 1$, which is equal to \eqref{rotor}).&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A &lt;em&gt;rotor&lt;/em&gt; is a complex number that rotates another complex number by an angle $\theta$ (through multiplication) and has the form:&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div&gt;$$&#xA;e^{i\theta} = \cos \theta + i \sin \theta&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Rotating a complex number $x + yi$ by an angle $\theta$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x&#39; + y&#39;i &amp;= (x + yi)(\cos \theta + i \sin \theta) \\&#xA;&amp;= (x \cos \theta - y \sin \theta) + (x \sin \theta + y \cos \theta)i&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which in matrix form is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{bmatrix}&#xA;x&#39; &amp; -y&#39; \\&#xA;y&#39; &amp; x&#39;&#xA;\end{bmatrix} = \begin{bmatrix}&#xA;x &amp; -y \\&#xA;y &amp; x&#xA;\end{bmatrix} \begin{bmatrix}&#xA;\cos \theta &amp; -\sin \theta \\&#xA;\sin \theta &amp; \cos \theta&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that because of the way the complex product is defined, the multiplication between two complex numbers commutes:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x&#39; + y&#39;i &amp;= (\cos \theta + i \sin \theta)(x + yi) \\&#xA;&amp;= (x \cos \theta - y \sin \theta) + (x \sin \theta + y \cos \theta)i&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/math/numeral-systems/complex-numbers.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Hamiltonian Graphs</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/special/hamiltonian_graphs/</link>
      <pubDate>Tue, 07 Jul 2015 19:30:51 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/special/hamiltonian_graphs/</guid>
      <description>&lt;p&gt;A cycle that contains every vertex of a graph $G$ is called a &lt;strong&gt;Hamiltonian cycle&lt;/strong&gt;. A Hamiltonian cycle is a spanning cycle of $G$. A &lt;strong&gt;Hamiltonian graph&lt;/strong&gt; is a graph that contains a Hamiltonian cycle.&lt;/p&gt;&#xA;&lt;p&gt;A path in a graph that contains every vertex of $G$ is called a &lt;strong&gt;Hamiltonian path&lt;/strong&gt; in $G$. If a graph contains a Hamiltonian cycle, then it also contains a Hamiltonian path. Obviously, removing any edge from a Hamiltonian cycle produces a Hamiltonian path.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-hamiltonian-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$&#xA;C = {v_0, v_1, v_3, v_8, v_{12}, v_{13}, v_9, v_4, v_5, v_6, v_{10}, v_{14}, v_{11}, v_7, v_2, v_0}&#xA;$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Every complete graph $K_n$ is a Hamiltonian graph.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/graph/hamiltonian-graph.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Eulerian Graph and Eulerian Trails</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/special/eulerian-graphs/</link>
      <pubDate>Sun, 05 Jul 2015 15:22:15 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/special/eulerian-graphs/</guid>
      <description>&lt;p&gt;A circuit $C$ in a graph $G$ is called an &lt;strong&gt;Eulerian circuit&lt;/strong&gt; if $C$ contains every edge of $G$ (remember that a circuit is a closed trail, i.e., a walk in which no edge is traversed more than once and that begins and ends at the same vertex).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Every edge of $G$ appears only once in the circuit.&lt;/li&gt;&#xA;&lt;li&gt;Only graphs with one component can contain such a circuit.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;A connected graph $G$ that contains an Eulerian circuit $C$ is called an &lt;strong&gt;Eulerian Graph&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-eulerian-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;C = (v_0,v_1,v_2,v_3,v_1,v_6,v_3,v_4,v_5,v_6,v_7,v_5,v_8,v_7,v_{10},v_8,v_9,v_{10},v_0)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;An &lt;strong&gt;Eulerian trail&lt;/strong&gt; is an open trail $T$ that contains all the edges of $G$ (but doesn&amp;rsquo;t end in the same start vertex).&lt;/p&gt;&#xA;&lt;div id=&#34;figure-eulerian-trail&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;T = (v_0,v_1,v_2,v_4,v_3,v_1,v_4,v_5)&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;königsberg-bridge-problem&#34;&gt;Königsberg Bridge Problem&lt;/h2&gt;&#xA;&lt;p&gt;The city of Königsberg, located in Prussia, was separated by a river into four land areas. To travel between these areas, seven bridges were built. Some citizens wondered whether it was possible to go for a walk in Königsberg and pass over each bridge exactly once.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-konigsberg-bridges&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;tw-text-center&#34;&gt;&#xA;The land areas and the bridges built in the city of Königsberg modeled as a graph &lt;span class=&#34;math&#34;&gt;\(M\)&lt;/span&gt;&#xA;&lt;/div&gt;&#xA;&lt;br /&gt;&#xA;&lt;p&gt;In graph theory terms, the problem can be stated as follows:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Does the multigraph $M$ of order $n = 4$ and size $m = 7$ contain an Eulerian circuit or an Eulerian trail?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Suppose that such a journey is possible. Then it must begin at some land area and end at some land area (possibly the same one). Certainly, each land area must appear in the trail. Note that at least two vertices of $M$ are neither the initial nor the terminal vertex of the trail. Let&amp;rsquo;s say that we start at land $A$ and end at land $A$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;T = (A, L_1, L_2, L_3, L_4, L_5, L_6, A)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Each of the land areas, except for the first and the last, is entered and exited every time it appears in the trail. This implies that all such land areas must have an even degree for a trail to exist.&lt;/p&gt;&#xA;&lt;p&gt;Going back to the Königsberg bridge problem, we can see that it&amp;rsquo;s impossible to find a trail because all the vertices have an odd degree.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The length of the Eulerian circuit/trail of a graph $G$ is equal to $m + 1$, where $m$ is the size of $G$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For undirected graphs:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A graph $G$ is an &lt;strong&gt;Eulerian graph&lt;/strong&gt; if and only if every vertex of $G$ has an even degree.&lt;/li&gt;&#xA;&lt;li&gt;A graph $G$ contains an &lt;strong&gt;Eulerian trail&lt;/strong&gt; if and only if exactly &lt;strong&gt;two vertices&lt;/strong&gt; of $G$ have an odd degree. Also, each trail of $G$ begins at one of these vertices and ends at the other.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For directed graphs:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A graph $G$ is an &lt;strong&gt;Eulerian graph&lt;/strong&gt; if and only if every vertex of $G$ has the same incoming and outgoing degree and is strongly connected.&lt;/li&gt;&#xA;&lt;li&gt;A graph $G$ contains an &lt;strong&gt;Eulerian trail&lt;/strong&gt; if and only if for each vertex, the difference between its incoming and outgoing degrees is 0, except for two vertices, one with a difference of $-1$ (start) and one with a difference of $+1$ (end). If these two vertices are connected by an edge, then the graph is strongly connected.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;hierholzers-algorithm&#34;&gt;Hierholzer&amp;rsquo;s algorithm&lt;/h2&gt;&#xA;&lt;p&gt;Let $C$ be a cycle in an Eulerian graph. Removing $E(C)$ from $G$ will create a subgraph that has an Eulerian trail.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Identify a circuit $C$ in $G$ and mark the edges of $C$.&lt;/li&gt;&#xA;&lt;li&gt;If $C$ contains all the edges of $G$, then stop.&lt;/li&gt;&#xA;&lt;li&gt;Otherwise, let $v_i$ be a node on $C$ that is incident with an unmarked edge $e_i$.&lt;/li&gt;&#xA;&lt;li&gt;Build a circuit $D$ starting at node $v_i$ and using edge $e_1$, and mark the edges of $D$.&lt;/li&gt;&#xA;&lt;li&gt;Join the circuit $D$ to $C$ by inserting the edges of $D$ into $C$ at position $v_1$, and then move to step 2.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;implementation-notes&#34;&gt;Implementation notes&lt;/h3&gt;&#xA;&lt;p&gt;In the implementation, a source vertex $u$ is chosen to be arbitrary or to be one of the two odd-degree vertices. Then an edge $uv$ is marked as visited, and we move to vertex $v$. Next, an edge $vw$ is marked as visited. Eventually, we will get to a vertex $z$ that doesn&amp;rsquo;t have any unvisited edges. This means that there&amp;rsquo;s a circuit starting and ending at vertex $z$. Next, there might be a vertex $y$ in the circuit $z-z$ that has unvisited edges. If one is found, we know that there&amp;rsquo;s another circuit $y-y$. Both circuits $z-z$ and $y-y$ might have nested circuits themselves. When the $y-y$ circuit doesn&amp;rsquo;t have a vertex with unvisited edges, then the result is appended to the main circuit $z-z$, i.e., $u-v-\ldots-z-y-y-z$.&lt;/p&gt;&#xA;&lt;!--&#xA;&#xA;&lt;style&gt;&#xA;#stack, #trail {&#xA;  height: 40px;&#xA;}&#xA;#figure-find-eulerian-trail span {&#xA;  width: 50px;&#xA;  border: 1px solid #999;&#xA;  padding: 5px 10px;&#xA;}&#xA;&lt;/style&gt;&#xA;&#xA;&lt;div id=&#34;figure-find-eulerian-trail&#34;&gt;&#xA;  &lt;div class=&#34;overlay&#34; style=&#34;position: absolute&#34;&gt;&lt;/div&gt;&#xA;  &lt;div id=&#34;stack&#34;&gt;&#xA;    stack:&#xA;  &lt;/div&gt;&#xA;  &lt;div id=&#34;trail&#34;&gt;&#xA;    trail:&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;--&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// each edge is saved by id, helper to avoid the traversal&#xA;// of an edge many times&#xA;vector&amp;lt;bool&amp;gt; edge_used;&#xA;// the number of edges used in the adjacency list of the vertex `i`&#xA;vector&amp;lt;int&amp;gt; edge_pointer;&#xA;// the eulerian trail&#xA;vector&amp;lt;int&amp;gt; trail;&#xA;// the adjacency list representation of `g`, each element `g_{i,j}` is&#xA;// a tuple (to, id) which denotes an edge `(i, to)` with id `id`&#xA;vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt; g;&#xA;&#xA;void dfs(int v) {&#xA;  for (; edge_pointer[v] &amp;lt; g[v].size(); edge_pointer[v] &amp;#43;= 1) {&#xA;    pair&amp;lt;int, int&amp;gt; &amp;amp;edge = g[v][edge_pointer[v]];&#xA;    if (edge_used[edge.second]) {&#xA;      // if the edge was already used analyze the next one&#xA;      continue;&#xA;    }&#xA;    // mark the edge&#xA;    edge_used[edge.second] = true;&#xA;    dfs(edge.first);&#xA;  }&#xA;  trail.push_back(v);&#xA;}&#xA;&#xA;/**&#xA; * Computes an euler trail if possible in an undirected graph `G`&#xA; * whose `edges` are given as an input&#xA; *&#xA; * NOTE: The trail if it exists is saved on the global `trail`&#xA; *&#xA; * @param {int} n The order of the graph&#xA; * @param {vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt;} A collection of tuples&#xA; * denoting the indexes of the vertices the edge `i` is incident to&#xA; * @return {bool} True if the graph has an euler trail&#xA; */&#xA;bool euler_trail_undirected(int n, vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;amp;edges) {&#xA;  int m = edges.size();&#xA;  g.assign(n, vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; ());&#xA;  edge_pointer.assign(n, 0);&#xA;  edge_used.assign(m, 0);&#xA;  vector&amp;lt;int&amp;gt; deg(n, 0);&#xA;&#xA;  // build the adjacency list of the graph&#xA;  for (int i = 0; i &amp;lt; m; i &amp;#43;= 1) {&#xA;    int u = edges[i].first;&#xA;    int v = edges[i].second;&#xA;    g[u].push_back({ v, i });&#xA;    g[v].push_back({ u, i });&#xA;    deg[u] &amp;#43;= 1;&#xA;    deg[v] &amp;#43;= 1;&#xA;  }&#xA;&#xA;  // find an odd vertex&#xA;  int start = 0;&#xA;  int odd_degree_count = 0;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (deg[i] % 2 != 0) {&#xA;      &amp;#43;&amp;#43;odd_degree_count;&#xA;      start = i;&#xA;    }&#xA;  }&#xA;&#xA;  if (odd_degree_count == 2 || odd_degree_count == 0) {&#xA;    dfs(start);&#xA;    return trail.size() == m &amp;#43; 1;&#xA;  }&#xA;  return false;&#xA;}&#xA;&#xA;&#xA;/**&#xA; * Computes an euler trail if possible in an directed graph `G`&#xA; * whose `edges` are given as an input&#xA; *&#xA; * NOTE: The trail if it exists is saved on the global `trail`&#xA; *&#xA; * @param {int} n The order of the graph&#xA; * @param {vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt;} A collection of tuples&#xA; * denoting the indexes of the vertices the edge `i` is incident to&#xA; * @return {bool} True if the graph has an euler trail&#xA; */&#xA;bool euler_trail_directed(int n, vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;amp;edges) {&#xA;  int m = edges.size();&#xA;  g.assign(n, vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; ());&#xA;  edge_pointer.assign(n, 0);&#xA;  edge_used.assign(m, 0);&#xA;  vector&amp;lt;int&amp;gt; in_deg(n, 0), out_deg(n, 0);&#xA;&#xA;  // build the adjacency list of the graph&#xA;  for (int i = 0; i &amp;lt; m; i &amp;#43;= 1) {&#xA;    int u = edges[i].first;&#xA;    int v = edges[i].second;&#xA;    g[u].push_back({ v, i });&#xA;    out_deg[u] &amp;#43;= 1;&#xA;    in_deg[v] &amp;#43;= 1;&#xA;  }&#xA;&#xA;  // find an odd vertex&#xA;  int start = 0;&#xA;  int odd_degree_count = 0;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (in_deg[i] - out_deg[i] != 0) {&#xA;      &amp;#43;&amp;#43;odd_degree_count;&#xA;      if (out_deg[i] &amp;gt; in_deg[i]) {&#xA;        start = i;&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  if (odd_degree_count == 2 || odd_degree_count == 0) {&#xA;    dfs(start);&#xA;    return trail.size() == m &amp;#43; 1;&#xA;  }&#xA;  return false;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/graph/eulerian-graphs.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Single Source Shortest Path (SSSP) in a graph</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/single-source-shortest-path/</link>
      <pubDate>Fri, 03 Jul 2015 13:21:32 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/single-source-shortest-path/</guid>
      <description>&lt;h2 id=&#34;unweighted-graph&#34;&gt;Unweighted graph&lt;/h2&gt;&#xA;&lt;p&gt;We call a shortest path from vertex $u$ to vertex $v$ a path of length $k$, where the path consists of vertices $p = (x_1, x_2, \ldots, x_k)$ such that $x_1 = u$, $x_k = v$, and $k$ is minimum.&lt;/p&gt;&#xA;&lt;p&gt;In an unweighted graph, a breadth-first search guarantees that when we analyze a vertex $v$, it will actually hold the shortest path to it. More searching will never find a path to $v$ with fewer edges.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Let $d(v)$ be the shortest distance from a vertex $v$ to $s$. Initially, $d(v) = \infty$ for $v \not= s$ and $d(s) = 0$.&lt;/li&gt;&#xA;&lt;li&gt;Whenever a vertex $v$ where $d(v) = \infty$ is reached by some other vertex $u$ whose $d(u)$ was already computed, then $d(v) = d(u) + 1$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Breadth first search algorithm applied on an unweighted graph `G`&#xA; * of order `n` and size `m` to find the shortest path from a source&#xA; * vertex `s`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt;} g The adjacency list representation&#xA; *  of `G`, each entry `g_{ij}` holds the end `v` of the edge `iv`&#xA; * @param {int} s The source vertex&#xA; * @return {vector&amp;lt;int&amp;gt;} The shortest path from `s` to all the other vertices&#xA; */&#xA;vector&amp;lt;int&amp;gt; bfs(vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; &amp;amp;g, int s) {&#xA;  int n = g.size();&#xA;&#xA;  // the vertex predecessor of `i` in the `s-i` path&#xA;  vector&amp;lt;int&amp;gt; parent(n, -1);&#xA;  // holds the shortest distance from `s` to vertex `i`&#xA;  vector&amp;lt;int&amp;gt; d(n, INF);&#xA;&#xA;  // the distance from the source vertex is zero&#xA;  d[s] = 0;&#xA;&#xA;  // accumulated weight, next vertex (weight, v)&#xA;  queue&amp;lt;int&amp;gt; q;&#xA;  q.push(s);&#xA;&#xA;  while (!q.empty()) {&#xA;    int v = q.front();&#xA;    q.pop();&#xA;&#xA;    for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;      int to = g[v][i];&#xA;      if (d[to] == INF) {&#xA;        d[to] = d[v] &amp;#43; 1;&#xA;        parent[to] = v;&#xA;        q.push(to);&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  return d;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;weighted-graph&#34;&gt;Weighted graph&lt;/h2&gt;&#xA;&lt;h3 id=&#34;dijkstras-algorithm&#34;&gt;Dijkstra&amp;rsquo;s algorithm&lt;/h3&gt;&#xA;&lt;p&gt;Dijkstra described an algorithm to solve the SSSP. There are some additional states that need to be stored per vertex:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Let $d(v)$ be an estimate of the shortest distance from a vertex $v$ to $s$. Initially, $d(v) = \infty$ for $v \not= s$ and $d(s) = 0$.&lt;/li&gt;&#xA;&lt;li&gt;Let $visited(v)$ be the visited state of a given vertex. Initially, $visited(v) = false$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The algorithm consists of a series of iterations. In each iteration, let $u$ be the vertex with the minimum distance to $s$ that hasn&amp;rsquo;t been visited yet. A process called &lt;strong&gt;relaxation&lt;/strong&gt; is then performed with $u$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The visited state is set to true, i.e., $visited(u) = true$.&lt;/li&gt;&#xA;&lt;li&gt;Let $uv$ be an edge to an unvisited node $v$ with weight $w(uv)$. We might improve the best estimate of the shortest path between $s$ and $v$ by including $uv$ in the path, so:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div&gt;$$&#xA; d(v) = min(d(v), d(u) + w(uv))&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;After $n$ iterations, all the vertices will be marked, and the $d(v)$ state will hold the shortest path from $s$ to all other vertices.&lt;/p&gt;&#xA;&lt;p&gt;We need a data structure that quickly supports the following three operations:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Remove a vertex with the minimum distance that hasn&amp;rsquo;t been discovered yet (up to once for each vertex in the graph).&lt;/li&gt;&#xA;&lt;li&gt;Add a new vertex (up to once for each vertex in the graph).&lt;/li&gt;&#xA;&lt;li&gt;Update the estimated distance of an existing vertex (once for each edge in the graph).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;implementation-with-an-array&#34;&gt;Implementation with an array&lt;/h4&gt;&#xA;&lt;p&gt;An array supports the operations above in $O(V)$, $O(1)$, and $O(1)$, respectively, leading to an overall time complexity of $O(V^2 + E)$, which is optimal for dense graphs (when $E \approx V^2$).&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * An implementation of Dijkstra&amp;#39;s algorithm which computes&#xA; * the shortest path from a source vertex `s` to all the other vertices&#xA; * in a graph `G` with `V` vertices and `E` edges.&#xA; *&#xA; * Time complexity: O(V^2 &amp;#43; E)&#xA; * Space complexity: O(V)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt;} g The adjacency list representation&#xA; *  of `G`, each entry `g_{ij}` holds the end `v` of the edge `iv` and the weight&#xA; *  `weight` of the edge i.e. (v, weight)&#xA; * @param {int} s The source vertex&#xA; * @return {vector&amp;lt;int&amp;gt;} The shortest path from `s` to all the other vertices&#xA; */&#xA;vector&amp;lt;int&amp;gt; dijkstra(vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt; &amp;amp;g, int s) {&#xA;  int V = g.size();&#xA;  int INF = 1e9;&#xA;&#xA;  vector&amp;lt;bool&amp;gt; visited(V);&#xA;  // the vertex predecessor of `i` in the `s-i` path&#xA;  vector&amp;lt;int&amp;gt; parent(V, -1);&#xA;  // holds the estimated distance&#xA;  vector&amp;lt;int&amp;gt; d(V, INF);&#xA;&#xA;  // the estimated distance from the source vertex is zero&#xA;  d[s] = 0;&#xA;&#xA;  for (int i = 0; i &amp;lt; V; i &amp;#43;= 1) {&#xA;    // the vertex with the minimum estimated distance&#xA;    int v = -1;&#xA;    for (int j = 0; j &amp;lt; V; j &amp;#43;= 1) {&#xA;      // find the vertices which haven&amp;#39;t been visited yet&#xA;      // among them find a vertex with the minimum estimated distance&#xA;      if (!visited[j] &amp;amp;&amp;amp; (v == -1 || d[j] &amp;lt; d[v])) {&#xA;        v = j;&#xA;      }&#xA;    }&#xA;&#xA;    if (d[v] == INF) {&#xA;      // the vertex selected is not reachable from `s`&#xA;      break;&#xA;    }&#xA;&#xA;    visited[v] = true;&#xA;&#xA;    // update the estimated distance from `v`&#xA;    // to all the other adjacent vertices&#xA;    for (int j = 0; j &amp;lt; g[v].size(); j &amp;#43;= 1) {&#xA;      pair&amp;lt;int, int&amp;gt; &amp;amp;edge = g[v][j];&#xA;      int next = edge.first;&#xA;      int weight = edge.second;&#xA;      int new_distance = d[v] &amp;#43; weight;&#xA;&#xA;      if (new_distance &amp;lt; d[next]) {&#xA;        d[next] = new_distance;&#xA;        parent[next] = v;&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  return d;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;implementation-with-a-bst&#34;&gt;Implementation with a BST&lt;/h4&gt;&#xA;&lt;p&gt;A balanced search tree supports the operations above in $O(\log V)$, $O(\log V)$, and $O(\log V)$, respectively, leading to an overall $O((E + V) \log V)$ time complexity, which is optimal for sparse graphs (when $E \approx V$).&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * C&amp;#43;&amp;#43;11&#xA; *&#xA; * An implementation of Dijkstra&amp;#39;s algorithm which computes&#xA; * the shortest path from a source vertex `s` to all the other vertices&#xA; * in a graph `G` of order `V` and size `E`&#xA; *&#xA; * Time complexity: O((E&amp;#43;V) log V)&#xA; * Space complexity: O(V)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt;&amp;gt;} g The adjacency list representation&#xA; *  of `G`, each entry `g_{ij}` holds a pair which represents an edge&#xA; * (vertex, weight) which tells that there&amp;#39;s an edge from `i` to `vertex`&#xA; * with weight `weight`&#xA; * @param {int} s The source vertex&#xA; * @return {vector&amp;lt;int&amp;gt;} The shortest path from `s` to all the other vertices&#xA; */&#xA;int dijkstra(vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt;&amp;gt; &amp;amp;g, int source) {&#xA;  int V = g.size();&#xA;  int INF = 1e9;&#xA;  int total = 0;&#xA;&#xA;  // the vertex predecessor of `i` in the `s-i` path&#xA;  vector&amp;lt;int&amp;gt; parent(V, -1);&#xA;  // holds the estimated distance&#xA;  vector&amp;lt;int&amp;gt; d(V, INF);&#xA;&#xA;  // the estimated distance from the source vertex is zero&#xA;  d[s] = 0;&#xA;&#xA;  // accumulated weight, next vertex (weight, v)&#xA;  set&amp;lt;pair&amp;lt;int, int&amp;gt;&amp;gt; q;&#xA;  q.insert({0, s});&#xA;&#xA;  while (!q.empty()) {&#xA;    pair&amp;lt;int, int&amp;gt; edge = *(q.begin());&#xA;    int from = edge.second;&#xA;    q.erase(q.begin());&#xA;&#xA;    for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;      int to, weight;&#xA;&#xA;      // note that in the graph the first element is the neighbor vertex&#xA;      // but in the set the first element is the edge weight&#xA;      tie(to, weight) = g[v][i];&#xA;&#xA;      if (d[from] &amp;#43; weight &amp;lt; d[to]) {&#xA;        q.erase({ d[to], to });&#xA;        d[to] = d[from] &amp;#43; weight;&#xA;        parent[to] = v;&#xA;        q.insert({ d[to], to });&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  return d;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;applications&#34;&gt;Applications&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Find the shortest path between two vertices $u$ and $v$.&lt;/li&gt;&#xA;&lt;li&gt;Find the shortest path from all vertices to a given vertex $v$ by reversing the direction of each edge in the graph.&lt;/li&gt;&#xA;&lt;li&gt;Find the shortest path for every pair of vertices $u$ and $v$ by running the algorithm once per vertex.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Introduction to Trees in Graph Theory</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/tree/introduction/</link>
      <pubDate>Tue, 30 Jun 2015 15:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/tree/introduction/</guid>
      <description>&lt;p&gt;A graph $G$ is called &lt;strong&gt;acyclic&lt;/strong&gt; if it has no cycles. A &lt;strong&gt;tree&lt;/strong&gt; is an acyclic connected graph.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-tree&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Every two vertices of a tree $T$ are connected by a unique path.&lt;/li&gt;&#xA;&lt;li&gt;Every nontrivial tree has at least two end-vertices.&lt;/li&gt;&#xA;&lt;li&gt;If $T$ is a tree of order $n$, then the size of the tree is $m = n - 1$.&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;http://www.wikiwand.com/en/Tree_%28graph_theory%29#/Definitions&#34;target=&#34;_blank&#34;&gt;Additional definitions&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/graph/trees/introduction.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Strongly Connected Components in Graph Theory</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/components/</link>
      <pubDate>Thu, 25 Jun 2015 15:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/components/</guid>
      <description>&lt;p&gt;A connected subgraph of $G$ that is not a proper subgraph of any other connected subgraph of $G$ is a &lt;strong&gt;component&lt;/strong&gt; of $G$; i.e., there&amp;rsquo;s a $u-v$ path in the mentioned subgraph.&lt;/p&gt;&#xA;&lt;p&gt;Strongly connected components are useful in a variety of graph algorithms, including finding the shortest path between two vertices, detecting cycles in a graph, and determining the structure of a graph.&#xA;They can be computed efficiently using algorithms such as Tarjan&amp;rsquo;s and Kosaraju&amp;rsquo;s algorithms.&lt;/p&gt;&#xA;&lt;h2 id=&#34;undirected-graphs&#34;&gt;Undirected graphs&lt;/h2&gt;&#xA;&lt;p&gt;The problem of finding components in an undirected graph requires a simple graph traversal starting from an arbitrary vertex, keeping track of the vertices that were already visited. It&amp;rsquo;s also necessary to run the algorithm above for every vertex of $G$ (given that it was not visited).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The number of components of an undirected graph $G$ is equal to the number of disconnected subgraphs.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;vector&amp;lt;bool&amp;gt; visited;&#xA;// adjacency list of G&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;&#xA;void dfs(int v) {&#xA;  visited[v] = true;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;    if (!visited[next]) {&#xA;      dfs(next);&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;/**&#xA; * Computes the number of connected components in an undirected graph `G`&#xA; * of order `n` and size `m`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @return {int} The number of components in `G`&#xA; */&#xA;int connected_components() {&#xA;  int n = g.size();&#xA;  visited.assign(n, false);&#xA;&#xA;  int components = 0;&#xA;  for (int i = 0; i &amp;lt; visited.size(); i &amp;#43;= 1) {&#xA;    if (!visited[i]) {&#xA;      dfs(i);&#xA;      &amp;#43;&amp;#43;components;&#xA;    }&#xA;  }&#xA;  return components;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;directed-graphs&#34;&gt;Directed graphs&lt;/h2&gt;&#xA;&lt;p&gt;Given a directed graph $G$, two nodes $u, v \in V(G)$ are called &lt;strong&gt;strongly connected&lt;/strong&gt; if $v$ is reachable from $u$ and $u$ is reachable from $v$.&lt;/p&gt;&#xA;&lt;p&gt;A &lt;strong&gt;strongly connected component&lt;/strong&gt; (SCC) of $G$ is a subgraph $C \subseteq V(G)$ such that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$C$ is not empty.&lt;/li&gt;&#xA;&lt;li&gt;For any $u,v \in V(G)$, $u$ and $v$ are strongly connected.&lt;/li&gt;&#xA;&lt;li&gt;For any $u \in V(G)$ and $v \in G - C$, $u$ and $v$ are not strongly connected.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;tarjans-algorithm&#34;&gt;Tarjan&amp;rsquo;s algorithm&lt;/h3&gt;&#xA;&lt;p&gt;The idea is to perform a DFS from an arbitrary vertex (conducting subsequent DFS from non-explored vertices). During the traversal, each vertex $v$ is assigned two numbers:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The &lt;strong&gt;time&lt;/strong&gt; it was explored, denoted as $v_{time}$.&lt;/li&gt;&#xA;&lt;li&gt;The smallest index of any node known to be reachable from $v$, denoted as $v_{low}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let $u$ be a node that belongs to an SCC. If $u$ is the arbitrary vertex chosen, then the only known vertex that is reachable from $u$ is $u$ itself. Let $v$ be a vertex discovered during the exploration of $u$. If there&amp;rsquo;s a $v \rightarrow u$ path, then it means that there&amp;rsquo;s a cycle, and all the vertices in the path $u-v$ belong to the same connected component. Such a node $u$ is called the &lt;strong&gt;root of the SCC&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Let $u$ be a node that belongs to an SCC. If it&amp;rsquo;s known that there&amp;rsquo;s a $u-v$ cycle and also that $u$ can reach a vertex $t$ with a lower index than $u$, then $v$ and $t$ belong to the same component.&lt;/p&gt;&#xA;&lt;p&gt;A stack is also needed to keep track of the nodes that were visited. The working of the stack follows the invariant: a node remains on the stack after exploration if and only if it has a path to some node earlier in the stack.&lt;/p&gt;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&#xA;        &#xA;        &#xA;&gt;&#xA;    &#xA;        &lt;img class=&#34;lazy-load&#34;  data-src=&#34;https://upload.wikimedia.org/wikipedia/commons/6/60/Tarjan%27s_Algorithm_Animation.gif?1435613160896&#34; /&gt;&#xA;    &#xA;    &#xA;&lt;/figure&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// adjacency list of G&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;&#xA;int time_spent;&#xA;// the number of scc&#xA;int total_scc;&#xA;&#xA;// the time a vertex was discovered&#xA;vector&amp;lt;int&amp;gt; time_in;&#xA;// the smallest index of any vertex known to be reachable from `i`&#xA;vector&amp;lt;int&amp;gt; back;&#xA;// the scc vertex `i` belongs to&#xA;vector&amp;lt;int&amp;gt; scc;&#xA;// invariant: a node remains in the stack after exploration if&#xA;// it has a path to some node explored earlier that is in the stack&#xA;vector&amp;lt;bool&amp;gt; in_stack;&#xA;stack&amp;lt;int&amp;gt; vertices;&#xA;&#xA;void dfs(int v) {&#xA;  int next;&#xA;&#xA;  // the lowest back edge discovery time of `v` is&#xA;  // set to the discovery time of `v` initally&#xA;  back[v] = time_in[v] = &amp;#43;&amp;#43;time_spent;&#xA;&#xA;  vertices.push(v);&#xA;  in_stack[v] = true;&#xA;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    next = g[v][i];&#xA;    if (time_in[next] == -1) {&#xA;      // unvisited edge&#xA;      dfs(next);&#xA;      // propagation of the lowest back edge discovery time&#xA;      back[v] = min(back[v], back[next]);&#xA;    } else if (in_stack[next]) {&#xA;      // (v, next) is a back edge only if it&amp;#39;s connected to a predecessor&#xA;      // of `v`, i.e. if `next` is in same branch in the dfs tree&#xA;      //&#xA;      // an alternative is to use the time a vertex finished exploring its&#xA;      // adjacent nodes, if the time is not set then it&amp;#39;s a back edge&#xA;      back[v] = min(back[v], time_in[next]);&#xA;    }&#xA;  }&#xA;&#xA;  // if the root node of a connected component has finished&#xA;  // exploring all its neighbors, assign the same component `id`&#xA;  // to all the elements in the scc&#xA;  if (back[v] == time_in[v]) {&#xA;    total_scc &amp;#43;= 1;&#xA;    do {&#xA;      next = vertices.top();&#xA;      vertices.pop();&#xA;      in_stack[next] = false;&#xA;      scc[next] = total_scc;&#xA;    } while (next != v);&#xA;  }&#xA;}&#xA;&#xA;/**&#xA; * Finds the strongly connected components in a digraph `G` of order `n`&#xA; * and size `m`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @returns {int} the number of strongly connected components&#xA; */&#xA;int tarjan() {&#xA;  int n = g.size();&#xA;&#xA;  scc.assign(n, -1);&#xA;  time_in.assign(n, -1);&#xA;  back.assign(n, -1);&#xA;  in_stack.assign(n, false);&#xA;  while (!vertices.empty()) {&#xA;    vertices.pop();&#xA;  }&#xA;&#xA;  time_spent = 0;&#xA;  total_scc = 0;&#xA;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (time_in[i] == -1) {&#xA;      dfs(i);&#xA;    }&#xA;  }&#xA;  return total_scc;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Minimum Spanning Tree</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/tree/spanning-tree/</link>
      <pubDate>Wed, 24 Jun 2015 18:31:59 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/tree/spanning-tree/</guid>
      <description>&lt;p&gt;If a connected graph $G$ of order $n$ has no cycles, then, of course, $G$ is a tree. Let&amp;rsquo;s suppose that $G$ contains cycles. Let $e_1$ be an edge lying on a cycle of $G$. We know that since $e_1$ is part of a cycle, it&amp;rsquo;s not a bridge, which means that $G - e_1$ is connected. If $G - e_1$ contains cycles, then let $e_2$ be an edge lying on a cycle of $G - e_1$. $e_2$ is not a bridge, and therefore $G - e_1 - e_2$ is still connected. Eventually, we arrive at the set $X = {e_1, e_2, \ldots, e_k}$ of edges such that $G - X$ doesn&amp;rsquo;t contain cycles (i.e., it&amp;rsquo;s a tree) and has the same vertex set as $G$ ($V(G) = V(G - X)$).&lt;/p&gt;&#xA;&lt;p&gt;Let $T = G - X$ be a tree with the same vertex set as $G$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$T$ is a spanning subgraph of $G$. Since $T$ is also a tree, it&amp;rsquo;s called a &lt;strong&gt;spanning tree&lt;/strong&gt; of $G$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div id=&#34;figure-spanning-tree&#34;&gt;&lt;/div&gt;&#xA;&lt;h2 id=&#34;minimum-spanning-tree&#34;&gt;Minimum spanning tree&lt;/h2&gt;&#xA;&lt;p&gt;The purpose of finding a minimum spanning tree (MST) is to identify the subset of edges of a given connected, undirected graph that forms a tree, connecting all the vertices and having the minimum possible total edge weight.&lt;/p&gt;&#xA;&lt;p&gt;Let $G$ be a &lt;em&gt;connected weighted graph&lt;/em&gt; where the weight of an edge $e \in E(G)$ is denoted by $w(e)$. For each subgraph $H$ of $G$, the weight of the subgraph $W$ is the sum of the weights of its edges.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;w(H) = \sum_{e \in E(H)} w(e)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We are looking for a spanning tree of $G$ whose weight is the minimum among all spanning trees of $G$. Such a spanning tree is called a &lt;strong&gt;minimum spanning tree&lt;/strong&gt; (shortened as MST)&lt;/p&gt;&#xA;&lt;div id=&#34;figure-minimum-spanning-tree&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA; \begin{align*}&#xA; G &amp;= (V, E) \\&#xA; V &amp;= \{0, 1, 2, 3, 4\} \\&#xA; E &amp;= \{\{0, 1\}, \{0, 2\}, \{0, 3\}, \{0, 4\}, \{1, 2\}, \{1, 3\}, \{1, 4\}, \{2, 3\}, \{3, 4\}\} \\&#xA; w(e) &amp;= \{1, 4, 4, 5, 3, 7, 5, 6, 2\}&#xA; \end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The MST is unique if the weights of all the edges are different.&lt;/li&gt;&#xA;&lt;li&gt;The maximum spanning tree is the tree whose weight is maximum among all spanning trees. It can be computed using the algorithm below by using the edges with the maximum weight instead of the ones with the minimum weight.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;kruskals-algorithm&#34;&gt;Kruskal&amp;rsquo;s algorithm&lt;/h3&gt;&#xA;&lt;p&gt;For a connected weighted graph $G$, a spanning tree is constructed as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For the first edge, $e_1$, we select any edge of $G$ with minimum weight.&lt;/li&gt;&#xA;&lt;li&gt;For the second edge, $e_2$, we select any remaining edge of $G$ with minimum weight.&lt;/li&gt;&#xA;&lt;li&gt;For the third edge, $e_3$, we select any remaining edge of $G$ with minimum weight &lt;em&gt;that does not produce a cycle with the previously selected edges&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;We continue in this manner until a spanning tree is produced.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s apply it to the weighted graph above. Sorting the edges in nondecreasing order, we have:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;w(e) = \{1, 2, 3, 4, 4, 5, 5, 6, 7\}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Some properties of the edges:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The edge with the minimum cost is $e_1 = v_0v_1$ with $w(e_1) = 1$. $e_1$ is part of the MST.&lt;/li&gt;&#xA;&lt;li&gt;The edge with the minimum cost is now $e_9 = v_3v_4$ with $w(e_9) = 2$. $e_9$ is part of the MST.&lt;/li&gt;&#xA;&lt;li&gt;The next edge is $e_5 = v_1v_2$ with $w(e_5) = 3$. Since it does not form a cycle with the previously selected edges, it&amp;rsquo;s part of the MST.&lt;/li&gt;&#xA;&lt;li&gt;The next edge is $e_2 = v_0v_2$ with $w(e_2) = 4$. This one forms a cycle with the path $v_0,v_1,v_2$, so it&amp;rsquo;s not part of the MST.&lt;/li&gt;&#xA;&lt;li&gt;The next edge is $e_3 = v_0v_3$ with $w(e_3) = 4$. Since it does not form a cycle with the previously selected edges, it&amp;rsquo;s part of the MST.&lt;/li&gt;&#xA;&lt;li&gt;There&amp;rsquo;s no need to do more iterations since the set is already a spanning tree.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;struct edge {&#xA;  int u, v, weight;&#xA;  edge(int _u, int _v, int _w) {&#xA;    u = _u; v = _v; weight = _w;&#xA;  }&#xA;  // custom sort&#xA;  bool operator&amp;lt;(const edge &amp;amp;other) const {&#xA;    return weight &amp;lt; other.weight;&#xA;  }&#xA;};&#xA;&#xA;vector&amp;lt;int&amp;gt; tree, size;&#xA;&#xA;void initialize_sets(int n) {&#xA;  tree.resize(n);&#xA;  size.resize(n);&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    tree[i] = i;&#xA;    size[i] = 1;&#xA;  }&#xA;}&#xA;&#xA;int find_set(int element) {&#xA;  if (element != tree[element]) {&#xA;    tree[element] = find_set(tree[element]);&#xA;  }&#xA;  return tree[element];&#xA;}&#xA;&#xA;void set_union(int x, int y) {&#xA;  int rx, ry;&#xA;  rx = find_set(x);&#xA;  ry = find_set(y);&#xA;  if (rx == ry) {&#xA;    return;&#xA;  }&#xA;  if (rx &amp;gt; ry) {&#xA;    size[rx] &amp;#43;= size[ry];&#xA;    tree[ry] = rx;&#xA;  } else {&#xA;    size[ry] &amp;#43;= size[rx];&#xA;    tree[rx] = ry;&#xA;  }&#xA;}&#xA;&#xA;/**&#xA; * An implementation of Kruskal&amp;#39;s algorithm which computes&#xA; * the minimum spanning tree of a graph `G`&#xA; *&#xA; * Time complexity: O(m log m)&#xA; * Space complexity: O(m)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt;} g The adjacency list representation&#xA; * of a graph `G`, each entry `g_{ij}` holds a pair which represents an edge&#xA; * (vertex, weight) which tells that there&amp;#39;s an edge from `i` to `vertex`&#xA; * with weight `weight`&#xA; * @return {int} The weight of the MST&#xA; */&#xA;int kruskal(vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt; &amp;amp;g) {&#xA;  int n = g.size();&#xA;&#xA;  vector&amp;lt;edge&amp;gt; edges;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    for (int j = 0; j &amp;lt; g[i].size(); j &amp;#43;= 1) {&#xA;      int v = g[i][j].first;&#xA;      int weight = g[i][j].second;&#xA;      edges.push_back(edge(i, v, weight));&#xA;    }&#xA;  }&#xA;&#xA;  initialize_sets(n);&#xA;&#xA;  sort(edges.begin(), edges.end());&#xA;&#xA;  int total = 0;&#xA;  for (int i = 0; i &amp;lt; edges.size(); i &amp;#43;= 1) {&#xA;    int u = find_set(edges[i].u);&#xA;    int v = find_set(edges[i].v);&#xA;    if (u != v) {&#xA;      set_union(u, v);&#xA;      total &amp;#43;= edges[i].weight;&#xA;    }&#xA;  }&#xA;&#xA;  return total;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;prims-algorithm&#34;&gt;Prim&amp;rsquo;s algorithm&lt;/h3&gt;&#xA;&lt;p&gt;For a connected weighted graph $G$, a spanning tree is constructed as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For an arbitrary vertex $u$, an edge of minimum weight $e_1$ incident to $u$ is chosen as the first edge of the MST.&lt;/li&gt;&#xA;&lt;li&gt;For subsequent edges $e_2, e_3, \ldots, e_{n - 1}$, we select an edge of minimum weight among those edges having &lt;strong&gt;exactly one of its vertices incident with an edge already selected&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;prim-in-dense-graphs&#34;&gt;Prim in dense graphs&lt;/h4&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say we&amp;rsquo;re given the following problem:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Given $n$ points in a plane, find the skeleton of minimum weight that connects them all.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;This problem can be modeled as a graph of order $n$ where each vertex is connected to every other vertex by an edge with a weight equal to the Euclidean distance between the vertices; therefore, $m \approx n^2$.&lt;/p&gt;&#xA;&lt;p&gt;Implementation strategies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We need a data structure that keeps track of a single edge per vertex (space: $O(n)$) and is able to find the one with the minimum weight (doing $O(n)$ queries). Since $m \approx n^2$, we visit each vertex, finding an edge with minimum cost (each query will take $O(n)$ for an overall $O(n^2)$ time complexity).&lt;/li&gt;&#xA;&lt;li&gt;After an arbitrary vertex $u$ has been chosen, all the vertices incident to $u$ will update their minimum edge weight.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * An implementation of Prim&amp;#39;s algorithm which computes&#xA; * the minimum spanning tree of a dense graph `G`&#xA; *&#xA; * Time complexity: O(n^2)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt;} g The adjacency matrix of `G`, each entry `a_{ij}`&#xA; * holds the weight of the edge connecting vertex `i` and vertex `j`, if this number&#xA; * is &amp;lt;= 0 then `i` and `j` are not adjacent&#xA; * @return {int} The weight of the MST&#xA; */&#xA;int prim(vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; &amp;amp;g) {&#xA;  int n = g.size();&#xA;  int INF = 1e9;&#xA;  int total = 0;&#xA;&#xA;  vector&amp;lt;bool&amp;gt; visited(n, false);&#xA;  // holds the weight of the edge of minimum weight incident&#xA;  // to the vertex `i`&#xA;  vector&amp;lt;int&amp;gt; min_weight_edge(n, INF);&#xA;  // (optional) holds the index of a vertex adjacent to the&#xA;  // vertex `i` in the MST, note that the size of the MST is&#xA;  // n - 1 so the first vertex won&amp;#39;t store the mentioned index&#xA;  vector&amp;lt;int&amp;gt; neighbor_selected(n, -1);&#xA;&#xA;  // pick the first node as the &amp;#34;arbitrary&amp;#34; node&#xA;  min_weight_edge[0] = 0;&#xA;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    int v = -1;&#xA;    for (int j = 0; j &amp;lt; n; j &amp;#43;= 1) {&#xA;      // find the vertices which haven&amp;#39;t been visited yet&#xA;      // among them find a vertex with the minimum edge weight&#xA;      if (!visited[j] &amp;amp;&amp;amp; (v == -1 ||&#xA;          min_weight_edge[j] &amp;lt; min_weight_edge[v])) {&#xA;        v = j;&#xA;      }&#xA;    }&#xA;&#xA;    visited[v] = true;&#xA;    total &amp;#43;= min_weight_edge[v];&#xA;&#xA;    // update the minimum edge weight of all the vertices&#xA;    // adjacent to `v`&#xA;    for (int to = 0; to &amp;lt; n; to &amp;#43;= 1) {&#xA;      if (g[v][to] &amp;gt; 0 &amp;amp;&amp;amp;&#xA;          g[v][to] &amp;lt; min_weight_edge[to]) {&#xA;        min_weight_edge[to] = g[v][to];&#xA;        // update the candidate neighbor of the vertex `to` to&#xA;        // be `v` since it&amp;#39;s connected with an edge&#xA;        // of minimum weight among all the adjacent vertices to `to`&#xA;        neighbor_selected[to] = v;&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  return total;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h4 id=&#34;prim-in-sparse-graphs&#34;&gt;Prim in sparse graphs&lt;/h4&gt;&#xA;&lt;p&gt;Implementation strategies:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We need a data structure that keeps track of a single edge per vertex (space: $O(n)$) and is able to find the one with the minimum weight (doing $O(n)$ queries). Since $m \approx n$, we analyze each edge, finding the one with the minimum weight $O(n)$ times. We can use a red-black tree (each operation takes $O(\log n)$ for an overall $O(m;\log ;n)$ time complexity).&lt;/li&gt;&#xA;&lt;li&gt;After an arbitrary vertex $u$ has been chosen, all the vertices incident to $u$ will update their minimum edge weight.&lt;/li&gt;&#xA;&lt;li&gt;The red-black tree will hold at most $n - 1$ entries (one entry per vertex). In each iteration, a vertex will be removed from the red-black tree.&lt;/li&gt;&#xA;&lt;li&gt;There will be exactly $n$ iterations if the graph is connected.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * C&amp;#43;&amp;#43;11&#xA; *&#xA; * An implementation of Prim&amp;#39;s algorithm which computes&#xA; * the minimum spanning tree of a sparse graph `G` of order `n` and size `m`&#xA; *&#xA; * Time complexity: O(m log n)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt;} g The adjacency list representation&#xA; * of a graph `G`, each entry `g_{ij}` holds a pair which represents an edge&#xA; * (vertex, weight) which tells that there&amp;#39;s an edge from `i` to `vertex`&#xA; * with weight `weight`&#xA; * @return {int} The weight of the MST or a negative number if the graph&#xA; * wasn&amp;#39;t connected&#xA; */&#xA;int prim(vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt; &amp;amp;g) {&#xA;  int n = g.size();&#xA;  int total = 0;&#xA;&#xA;  vector&amp;lt;bool&amp;gt; visited(n, false);&#xA;  // holds the weight of the edge of minimum weight incident&#xA;  // to the vertex `i`&#xA;  vector&amp;lt;int&amp;gt; min_cost(n, INF);&#xA;  // (optional) holds the index of a vertex adjacent to the&#xA;  // vertex `i` in the MST, note that the size of the MST is&#xA;  // n - 1 so the first vertex won&amp;#39;t store the mentioned index&#xA;  vector&amp;lt;int&amp;gt; neighbor(n, -1);&#xA;&#xA;  // the first node is the &amp;#34;arbitrary&amp;#34; node for the sake of the implementation&#xA;  min_cost[0] = 0;&#xA;&#xA;  // (min weight, vertex)&#xA;  set&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; q;&#xA;  q.insert({0, 0});&#xA;&#xA;  while (!q.empty()) {&#xA;    int v = q.begin()-&amp;gt;second;&#xA;&#xA;    // the vertex `v` belongs to the MST and is adjacent&#xA;    // to the vertex `neighbor[v]` with and edge&#xA;    // of weight `weight`&#xA;    total &amp;#43;= q.begin()-&amp;gt;first;&#xA;&#xA;    q.erase(q.begin());&#xA;&#xA;    visited[v] = true;&#xA;&#xA;    for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;      pair&amp;lt;int, int&amp;gt; &amp;amp;next = g[v][i];&#xA;&#xA;      // note that in the graph the first element is the neighbor vertex&#xA;      // but in the set the first element is the edge weight&#xA;      int to = next.first;&#xA;      int weight = next.second;&#xA;&#xA;      if (!visited[to] &amp;amp;&amp;amp; weight &amp;lt; min_cost[to]) {&#xA;        q.erase({ min_cost[to], to });&#xA;        min_cost[to] = weight;&#xA;        neighbor[to] = v;&#xA;        q.insert({ min_cost[to], to });&#xA;      }&#xA;    }&#xA;  }&#xA;  // check that every vertex has a min cost edge associated&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (min_cost[i] == INF) {&#xA;      return -1;&#xA;    }&#xA;  }&#xA;  return total;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;number-of-spanning-trees-in-a-graph&#34;&gt;Number of spanning trees in a graph&lt;/h2&gt;&#xA;&lt;p&gt;Let $G$ be a graph with $V(G) = {v_1, v_2, \ldots, v_n}$. Let $A = [a_{ij}]$ be the adjacency matrix of $G$, and let $C = [c_{ij}]$ be an $n \times n$ matrix where:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c_{ij} = \begin{cases}&#xA;deg\;v_i &amp; \text{if $i = j$} \\&#xA;-a_{ij} &amp; \text{if $i \neq j$} \\&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then the number of spanning trees of $G$ is the value of any cofactor of $C$.&lt;/p&gt;&#xA;&lt;p&gt;The matrix of cofactors is an $n \times n$ matrix $C = [c_{ij}]$ where:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c_{ij} = (-1)^{i + j} \cdot det(M_{ij})&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$det(M_{ij})$ indicates the determinant of the $(n - 1) \times (n - 1)$ submatrix of $M$ obtained by removing the $i$-th row and the $j$-th column.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Given a square matrix M of size (n x n) this method&#xA; * computes the a matrix of size (n - 1) x (n - 1) by eliminating&#xA; * the elements belonging to the `row` row of M and the `col`&#xA; * column of M&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; } m The square matrix&#xA; * @param {int} row The row to be ignored&#xA; * @param {int} col The column to be ignored&#xA; * @return {vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt;} the value of the determinant&#xA; */&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; minor(vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; m, int row, int col) {&#xA;  int n = m.size();&#xA;  vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; t(n - 1, vector&amp;lt;int&amp;gt;(n - 1));&#xA;&#xA;  int trow = 0;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (i == row) {&#xA;      continue;&#xA;    }&#xA;    int tcol = 0;&#xA;    for (int j = 0; j &amp;lt; n; j &amp;#43;= 1) {&#xA;      if (j == col) {&#xA;        continue;&#xA;      }&#xA;      t[trow][tcol] = m[i][j];&#xA;      tcol &amp;#43;= 1;&#xA;    }&#xA;    trow &amp;#43;= 1;&#xA;  }&#xA;  return t;&#xA;}&#xA;&#xA;/**&#xA; * Computes the determinant of an square matrix&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; } m The square matrix&#xA; * @return {int} the value of the determinant&#xA; */&#xA;int determinant(vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; m) {&#xA;  int n = m.size();&#xA;&#xA;  if (n == 1) {&#xA;    return m[0][0];&#xA;  }&#xA;  if (n == 2) {&#xA;    return m[0][0] * m[1][1] - m[1][0] * m[0][1];&#xA;  }&#xA;&#xA;  int result = 0;&#xA;  for (int col = 0; col &amp;lt; n; col &amp;#43;= 1) {&#xA;    vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; t = minor(m, 0, col);&#xA;    result &amp;#43;= m[0][col] * pow(-1, col) * determinant(t);&#xA;  }&#xA;  return result;&#xA;}&#xA;&#xA;/**&#xA; * Computes the number of spanning trees in an undirected graph `G`&#xA; *&#xA; * @param &amp;lt;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; &amp;gt; g The adjacency matrix of `G`&#xA; * @return {int} The number of spanning trees&#xA; */&#xA;int number_of_spanning_trees(vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; &amp;amp;g) {&#xA;  int n = g.size();&#xA;  vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; t = g;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    // -a_{ij} for elements that are not in the main diagonal&#xA;    int degree = 0;&#xA;    for (int j = 0; j &amp;lt; n; j &amp;#43;= 1) {&#xA;      if (i != j) {&#xA;        t[i][j] *= -1;&#xA;        if (t[i][j]) {&#xA;          degree &amp;#43;= 1;&#xA;        }&#xA;      }&#xA;    }&#xA;&#xA;    // deg v_i for t[i][i]&#xA;    t[i][i] = degree;&#xA;  }&#xA;&#xA;  // compute the (0,0) cofactor&#xA;  // c_{0, 0} = (-1)^{0 &amp;#43; 0} * determinant((0, 0) minor)&#xA;  //          = determinant((0, 0) minor)&#xA;  return determinant(minor(t, 0, 0));&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;number-of-spanning-trees-in-a-complete-graph-k_n&#34;&gt;Number of spanning trees in a complete graph $K_n$&lt;/h3&gt;&#xA;&lt;p&gt;Computing the number of spanning trees of a graph $G = K_n$, where $V(G) = {v_1, v_2, \ldots, v_n}$, is the same as computing the number of distinct trees with the vertex set ${v_1, v_2, \ldots, v_n}$. The formula is called the &lt;strong&gt;Cayley Tree Formula&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The number of spanning trees of order $n$ with a specific vertex set is $n^{n - 2}$.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/graph/trees/spanning-tree.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Cut-vertices (articulation points) in Graph Theory</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/cut-vertices/</link>
      <pubDate>Wed, 24 Jun 2015 15:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/cut-vertices/</guid>
      <description>&lt;p&gt;All the facts/properties below are considered for an undirected, connected graph $G$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $v$ is a vertex incident with a bridge in a graph $G$, then $v$ is a cut-vertex if $deg(v) \geq 2$ (if $deg(v) = 1$, then $v$ is an end-vertex of $G$, so $G - v$ is still connected).&lt;/li&gt;&#xA;&lt;li&gt;Given that the order of $G$ is $\geq 3$, if it contains a bridge, then it also contains a cut-vertex.&lt;/li&gt;&#xA;&lt;li&gt;If $v$ is a cut-vertex of $G$, and $u$ and $w$ are vertices in different components formed by $G - v$, then $v$ is part of every $u-w$ path in $G$.&lt;/li&gt;&#xA;&lt;li&gt;Let $u \in V(G)$. If $v$ is a vertex that is farthest from $u$, then $v$ is not a cut-vertex.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div id=&#34;figure-cut-vertex&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\text{$v_0, v_2$ are cut vertices}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let $G$ be an undirected graph. By analyzing the properties of the DFS tree, we can determine if a vertex is an articulation point given the following facts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A leaf vertex is not a cut-vertex.&lt;/li&gt;&#xA;&lt;li&gt;Let $u$ and $v$ be two vertices of the DFS tree such that $u$ is an ancestor of $v$.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $u$ and $v$ are not adjacent and there&amp;rsquo;s a &lt;em&gt;back edge&lt;/em&gt; $vw$ to some vertex $w$ such that $w$ is a predecessor of $u$, then none of the vertices in the $u-v$ path are cut-vertices.&lt;/li&gt;&#xA;&lt;li&gt;If $u$ and $v$ are not adjacent and there&amp;rsquo;s a &lt;em&gt;back edge&lt;/em&gt; from $v$ to some vertex &lt;strong&gt;in the $u-v$ path&lt;/strong&gt;, then $u$ is a cut-vertex.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Let $u$ be the root node of the DFS tree. It&amp;rsquo;s a cut-vertex if, during the exploration of its successor vertices, it&amp;rsquo;s found that it has more than one child, i.e., the root has more than one branch in the DFS tree.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int time_spent;&#xA;&#xA;// the adjacency list representation of `G`&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;// the time a vertex `i` was discovered first&#xA;vector&amp;lt;int&amp;gt; time_in;&#xA;// stores the discovery time of the lowest predecessor that vertex `i`&amp;#39;s&#xA;// succesor vertices can reach **through a back edge**, initially&#xA;// the lowest predecessor is set to the vertex itself&#xA;vector&amp;lt;int&amp;gt; back;&#xA;// the articulation points found during the dfs&#xA;vector&amp;lt;int&amp;gt; cut_vertex;&#xA;&#xA;void dfs(int v, int parent) {&#xA;  // the lowest back edge discovery time of `v` is&#xA;  // set to the discovery time of `v` initally&#xA;  back[v] = time_in[v] = &amp;#43;&amp;#43;time_spent;&#xA;&#xA;  // count the number of children for the `root` vertex&#xA;  int children = 0;&#xA;  int is_cut_vertex = false;&#xA;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;&#xA;    if (next == parent) {&#xA;      continue;&#xA;    }&#xA;&#xA;    if (time_in[next] == -1) {&#xA;      dfs(next, v);&#xA;      /// if there&amp;#39;s a back edge between a descendant of `next` and&#xA;      // a predecessor of `v` then `next` will have a lower reachable&#xA;      // vertex than `v` through a back edge, in this case the vertex `v` is not&#xA;      // a cut-vertex (the special case of the root node is handled below)&#xA;      if (back[next] &amp;gt;= time_in[v] &amp;amp;&amp;amp; parent != -1) {&#xA;        is_cut_vertex = true;&#xA;      }&#xA;      // propagation of the back edge to a vertex with the lowest discovery time&#xA;      back[v] = min(back[v], back[next]);&#xA;      &amp;#43;&amp;#43;children;&#xA;    } else {&#xA;      // * back edge *&#xA;      // update index of the vertex incident with this back edge to&#xA;      // be the one with the lowest discovery time&#xA;      // it&amp;#39;s possible for this edge to be a *forward edge*, in that&#xA;      // case the time won&amp;#39;t be updated since time[v] &amp;lt; time[next]&#xA;      back[v] = min(back[v], time_in[next]);&#xA;    }&#xA;  }&#xA;&#xA;  // the root vertex of the dfs tree is a cut-vertex&#xA;  // if it has more than two children in the dfs tree&#xA;  if (parent == -1 &amp;amp;&amp;amp; children &amp;gt; 1) {&#xA;    is_cut_vertex = true;&#xA;  }&#xA;&#xA;  if (is_cut_vertex) {&#xA;    cut_vertex.push_back(v);&#xA;  }&#xA;}&#xA;&#xA;/**&#xA; * Finds the articulation points in an undirected graph `G`&#xA; * of order`n` and size `m`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @returns {int} the number of articulation points&#xA; */&#xA;int articulation_points() {&#xA;  int n = g.size();&#xA;  time_spent = 0;&#xA;  time_in.assign(n, -1);&#xA;  back.assign(n, -1);&#xA;  cut_vertex.clear();&#xA;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (time_in[i] == -1) {&#xA;      dfs(i, -1);&#xA;    }&#xA;  }&#xA;  return cut_vertex.size();&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;biconnected-components-in-an-undirected-graph&#34;&gt;Biconnected components in an undirected graph&lt;/h3&gt;&#xA;&lt;p&gt;A biconnected graph is a nonseparable graph, meaning that if any vertex is removed, the graph is still connected, and therefore it doesn&amp;rsquo;t have cut-vertices.&lt;/p&gt;&#xA;&lt;p&gt;Key observations:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Two different biconnected components can&amp;rsquo;t have a common edge (but they might share a common vertex).&lt;/li&gt;&#xA;&lt;li&gt;A common vertex linking multiple biconnected components must be a cut-vertex of $G$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let $uv$ be an edge of an undirected graph $G$. We can keep a stack telling the order of the edges analyzed, so we push it to the stack. If $u$ is a cut-vertex, then all the edges from the top of the stack up to $uv$ are the edges of one biconnected component.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int time_spent;&#xA;&#xA;// the adjacency list representation of `G`&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;// the time a vertex `i` was discovered first&#xA;vector&amp;lt;int&amp;gt; time_in;&#xA;// stores the discovery time of the lowest predecessor that vertex `i`&amp;#39;s&#xA;// succesor vertices can reach **through a back edge**, initially&#xA;// the lowest predecessor is set to the vertex itself&#xA;vector&amp;lt;int&amp;gt; back;&#xA;&#xA;// the biconnected components found during the dfs&#xA;vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt; bcc;&#xA;stack&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; edges_processed;&#xA;&#xA;void output_biconnected_component(int u, int v) {&#xA;  pair&amp;lt;int, int&amp;gt; top;&#xA;  vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; component;&#xA;  do {&#xA;    top = edges_processed.top();&#xA;    edges_processed.pop();&#xA;    component.push_back(top);&#xA;  } while (u != top.first || v != top.second);&#xA;  bcc.push_back(component);&#xA;}&#xA;&#xA;void dfs(int v, int parent) {&#xA;  // the lowest back edge discovery time of `v` is&#xA;  // set to the discovery time of `v` initally&#xA;  back[v] = time_in[v] = &amp;#43;&amp;#43;time_spent;&#xA;&#xA;  // count the number of children for the `root` vertex&#xA;  int is_cut_vertex = false;&#xA;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;&#xA;    if (parent == next) {&#xA;      continue;&#xA;    }&#xA;&#xA;    // mark the edge (v, next) as processed&#xA;    if (time_in[next] == -1) {&#xA;      // this edge is being processed right now&#xA;      edges_processed.push(pair&amp;lt;int, int&amp;gt; (v, next));&#xA;&#xA;      dfs(next, v);&#xA;      // if there&amp;#39;s a back edge between a descendant of `next` and&#xA;      // a predecessor of `v` then `next` will have a lower reachable&#xA;      // vertex than `v` through a back edge, in this case the vertex `v` is not&#xA;      // a cut-vertex&#xA;      if (back[next] &amp;gt;= time_in[v]) {&#xA;        output_biconnected_component(v, next);&#xA;      }&#xA;      // propagation of the back edge to a vertex with the lowest discovery time&#xA;      back[v] = min(back[v], back[next]);&#xA;    } else if (time_in[next] &amp;lt; time_in[v]) {&#xA;      // * back edge *&#xA;      // update index of the vertex incident with this back edge to&#xA;      // be the one with the lowest discovery time&#xA;      back[v] = min(back[v], time_in[next]);&#xA;&#xA;      // push this edge to the stack only once&#xA;      edges_processed.push(pair&amp;lt;int, int&amp;gt; (v, next));&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;/**&#xA; * Finds the biconnected components in an undirected graph `G`&#xA; * of order`n` and size `m`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(m)&#xA; *&#xA; * @returns {int} the number of biconnected components&#xA; */&#xA;int biconnected_components() {&#xA;  int n = g.size();&#xA;  time_spent = 0;&#xA;  time_in.assign(n, -1);&#xA;  back.assign(n, -1);&#xA;&#xA;  while (!edges_processed.empty()) {&#xA;    edges_processed.pop();&#xA;  }&#xA;  bcc.clear();&#xA;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (time_in[i] == -1) {&#xA;      dfs(i, -1);&#xA;    }&#xA;  }&#xA;&#xA;  return bcc.size();&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;connectivity&#34;&gt;Connectivity&lt;/h2&gt;&#xA;&lt;p&gt;Let $G$ be a non-complete graph without cut-vertices. Let $U$ be a set of vertices of $G$ such that $G - U$ is disconnected. $U$ is called a &lt;strong&gt;vertex-cut set&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;The graph below doesn&amp;rsquo;t have a cut-vertex, but it has many vertex-cut sets: $U_1 = {v_1, v_2}$, $U_2 = {v_2, v_4}$, $U_3 = {v_1, v_2, v_3}$, $U_4 = {v_1, v_2, v_4}$, $U_5 = {v_0, v_2, v_4}$.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-cut-vertex-2&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The set with minimum cardinality is called a &lt;strong&gt;minimum vertex-cut set&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;A connected graph $G$ contains a &lt;strong&gt;cut-vertex set&lt;/strong&gt; only if $G$ is not complete.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;For a graph $G$ that is not complete, the &lt;strong&gt;vertex-connectivity&lt;/strong&gt;, denoted as $\kappa(G)$, is the cardinality of the minimum vertex-cut set of $G$. For the graph above, $\kappa(G) = 2$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $G$ is a graph of order $n$ and size $m \geq n - 1$, then $\kappa(G) = \left \lfloor \tfrac{2m}{n} \right \rfloor$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;There are other measures of how connected a graph is. Let $X$ be a set of edges of $G$ such that $G - X$ is disconnected or a trivial graph. $X$ is called an &lt;strong&gt;edge-cut set&lt;/strong&gt;. The &lt;strong&gt;edge-connectivity&lt;/strong&gt;, denoted as $\lambda(G)$, is the cardinality of the minimum edge-cut of $G$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;For a complete graph $G$ of order $n$, $\lambda(G) = n - 1$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function () {&#xA;  function getJson(file, callback) {&#xA;    fetch(file)&#xA;      .then((response) =&gt; response.json())&#xA;      .then((data) =&gt; callback(null, data))&#xA;      .catch((err) =&gt; callback(err))&#xA;  }&#xA;  getJson(&#39;/js/graph/data/cut-vertex.json&#39;, function (err, data) {&#xA;    if (err) { throw err }&#xA;    var options = {&#xA;      target: &#39;#figure-cut-vertex&#39;,&#xA;      data: data&#xA;    };&#xA;    greuler(options).update();&#xA;  });&#xA;  getJson(&#39;/js/graph/data/cut-vertex-2.json&#39;, function (err, data) {&#xA;    if (err) { throw err }&#xA;    greuler({&#xA;      target: &#39;#figure-cut-vertex-2&#39;,&#xA;      data: data&#xA;    }).update();&#xA;  });&#xA;})&#xA; &lt;/script&gt;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Cut-edges (bridges) in Graph Theory</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/cut-edges/</link>
      <pubDate>Wed, 24 Jun 2015 14:51:12 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/cut-edges/</guid>
      <description>&lt;h2 id=&#34;undirected-graph&#34;&gt;Undirected graph&lt;/h2&gt;&#xA;&lt;p&gt;In the following undirected graph $G$, the edges $v_2v_3$ and $v_3v_4$ are bridges.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-bridges&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;An edge $e$ of an undirected graph $G$ is a bridge if and only if $e$ lies on &lt;strong&gt;no cycle&lt;/strong&gt; of $G$.&lt;/li&gt;&#xA;&lt;li&gt;Every edge of an undirected tree is a bridge.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let $G$ be an undirected graph. By analyzing the properties of the DFS tree, we can determine if an edge is a bridge given the following facts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Let $u$ and $v$ be two vertices of the DFS tree such that $u$ is an ancestor of $v$. Also, $u$ and $v$ are not adjacent.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If there&amp;rsquo;s a &lt;em&gt;back edge&lt;/em&gt; $vu$, then none of the edges in the $u-v$ path are bridges. If we remove one of them, the graph is still connected because of this edge.&lt;/li&gt;&#xA;&lt;li&gt;Otherwise, the edge is a bridge.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;implementation-notes&#34;&gt;Implementation notes&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;To check if a successor of a vertex $u$ has a back edge to a predecessor of $u$, an additional state is stored in each vertex, which is the discovery time of the lowest back edge of a successor of $u$ (by lowest back edge, we mean the back edge to a vertex with the lowest discovery time), denoted as $u_{back}$. Initially, this state is set to the discovery time of the vertex $v$, i.e., $u_{back} = u_{in}$. This state is propagated when backtracking is performed.&lt;/li&gt;&#xA;&lt;li&gt;Let $uv$ be a back edge. When this edge is analyzed, the $v_{back}$ state needs to be updated to be the minimum of the existing $v_{back}$ and the discovery time of $u$, i.e., $v_{back} = min(v_{back}, u_{in})$.&lt;/li&gt;&#xA;&lt;li&gt;Let $v$ be an adjacent successor of $u$ in the DFS tree. When we&amp;rsquo;ve finished analyzing the branch of the tree because of the $uv$ edge, we have to check if the $v_{back}$ state contains a back edge to some predecessor of $u$ ($v_{back}$ is propagated), i.e., $u_{in} &amp;gt; v_{back}$. If so, then $uv$ is not a bridge.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int time_spent;&#xA;&#xA;// the adjacency list representation of `G`&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;// the time a vertex `i` was discovered first&#xA;vector&amp;lt;int&amp;gt; time_in;&#xA;// stores the discovery time of the lowest predecessor that vertex `i`&amp;#39;s&#xA;// succesor vertices can reach **through a back edge**, initially&#xA;// the lowest predecessor is set to the vertex itself&#xA;vector&amp;lt;int&amp;gt; back;&#xA;// the bridges found during the dfs&#xA;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; cut_edge;&#xA;&#xA;void dfs(int v, int parent) {&#xA;  // the lowest back edge discovery time of `v` is&#xA;  // set to the discovery time of `v` initally&#xA;  back[v] = time_in[v] = &amp;#43;&amp;#43;time_spent;&#xA;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;&#xA;    if (next == parent) {&#xA;      continue;&#xA;    }&#xA;&#xA;    if (time_in[next] == -1) {&#xA;      dfs(next, v);&#xA;      // if there&amp;#39;s a back edge between a descendant of `next` and&#xA;      // a predecessor of `v` then `next` will have a lower back edge discovery time&#xA;      // otherwise it&amp;#39;s a bridge&#xA;      if (back[next] &amp;gt; time_in[v]) {&#xA;        cut_edge.push_back(pair&amp;lt;int, int&amp;gt; (v, next));&#xA;      }&#xA;      // propagation of the lowest back edge discovery time&#xA;      back[v] = min(back[v], back[next]);&#xA;    } else {&#xA;      // *back edge*&#xA;      // update the lowest back edge discovery time of `v`&#xA;      back[v] = min(back[v], time_in[next]);&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;/**&#xA; * Finds the bridges in an undirected graph `G` of order `n` and size `m`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; */&#xA;void bridges() {&#xA;  int n = g.size();&#xA;  time_spent = 0;&#xA;  time_in.assign(n, -1);&#xA;  back.assign(n, -1);&#xA;  cut_edge.clear();&#xA;&#xA;  for (int i = 0; i &amp;lt; n; i &amp;#43;= 1) {&#xA;    if (time_in[i] == -1) {&#xA;      dfs(i, -1);&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;directed-graph-strong-bridges&#34;&gt;Directed graph (strong bridges)&lt;/h2&gt;&#xA;&lt;p&gt;Let $G$ be a directed graph. An edge $uv \in E(G)$ is a &lt;strong&gt;strong bridge&lt;/strong&gt; if its removal increases the number of strongly connected components of $G$.&lt;/p&gt;&#xA;&lt;p&gt;The following is a connected graph $G$. Every edge but $v_2v_0$ is a strong bridge because removing it from $G$ increases the number of strongly connected components. Removing $v_2v_0$ doesn&amp;rsquo;t increase the number of strongly connected components, so it&amp;rsquo;s not a bridge.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-bridges-directed&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;A trivial algorithm to find the strong bridges of a digraph $G$ of order $n$ and size $m$ is as follows:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Compute the number of strongly connected components of $G$, denoted as $k(G)$.&lt;/li&gt;&#xA;&lt;li&gt;For each edge $e \in E(G)$:&lt;/li&gt;&#xA;&lt;li&gt;remove $e$ from $G$&lt;/li&gt;&#xA;&lt;li&gt;compute the number of strongly connected components of $G$, denoted as $k(G - e)$&lt;/li&gt;&#xA;&lt;li&gt;if $k(G) &amp;lt; k(G - e)$, then $e$ is a bridge.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The time complexity of the algorithm above is clearly $O(m(n + m))$.&lt;/p&gt;&#xA;&lt;p&gt;Let $uv$ be an edge of a digraph $G$. We say that $uv$ is &lt;strong&gt;redundant&lt;/strong&gt; if there&amp;rsquo;s an alternative path from vertex $u$ to vertex $v$ avoiding $uv$. Otherwise, we say that $uv$ is not redundant. Computing the strong bridges is equivalent to computing the non-redundant edges of a graph.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;http://www.sofsem.cz/sofsem12/files/presentations/Thursday/GiuseppeItaliano.pdf&#34;target=&#34;_blank&#34;&gt;http://www.sofsem.cz/sofsem12/files/presentations/Thursday/GiuseppeItaliano.pdf&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function () {&#xA;  function getJson(file, callback) {&#xA;    fetch(file)&#xA;      .then((response) =&gt; response.json())&#xA;      .then((data) =&gt; callback(null, data))&#xA;      .catch((err) =&gt; callback(err))&#xA;  }&#xA;&#xA;  getJson(&#39;/js/graph/data/bridges.json&#39;, function (err, data) {&#xA;    if (err) { throw err }&#xA;    greuler({&#xA;      target: &#39;#figure-bridges&#39;,&#xA;      data: data&#xA;    }).update()&#xA;  });&#xA;  getJson(&#39;/js/graph/data/bridges-directed.json&#39;, function (err, data) {&#xA;    if (err) { throw err }&#xA;    greuler({&#xA;      directed: true,&#xA;      target: &#39;#figure-bridges-directed&#39;,&#xA;      data: data&#xA;    }).update()&#xA;  });&#xA;}, false)&#xA; &lt;/script&gt;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Topological sorting of a graph</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/topological-sorting/</link>
      <pubDate>Wed, 24 Jun 2015 11:30:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/topological-sorting/</guid>
      <description>&lt;p&gt;Let $G$ be a digraph. The &lt;strong&gt;topological sorting&lt;/strong&gt; algorithm is a linear ordering of the vertices of $G$ such that for every directed edge $u \rightarrow v$, where $u,v \in V(G)$, $u$ comes before $v$ in the ordering. The ordering is possible only if the graph &lt;em&gt;has no directed cycles&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Since the graph has no directed cycles, at least one of the vertices has no incoming edges.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div id=&#34;figure-topological-sorting&#34;&gt;&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;vector&amp;lt;bool&amp;gt; visited;&#xA;// adjacency list of G&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;vector&amp;lt;int&amp;gt; order;&#xA;&#xA;void dfs(int v) {&#xA;  visited[v] = true;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;    if (!visited[next]) {&#xA;      dfs(next);&#xA;    }&#xA;  }&#xA;  order.push_back(v);&#xA;}&#xA;&#xA;/**&#xA; * Given a graph `G` of order `n` and size `m` computes a linear ordering&#xA; * of the vertices such that for every edge u -&amp;gt; v, `u` comes earlier than `v`&#xA; * in the ordering&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; */&#xA;void topological_sort() {&#xA;  int n = g.size();&#xA;  visited.assign(n, false);&#xA;&#xA;  for (int i = 0; i &amp;lt; visited.size(); i &amp;#43;= 1) {&#xA;    if (!visited[i]) {&#xA;      dfs(i);&#xA;    }&#xA;  }&#xA;&#xA;  reverse(order.begin(), order.end());&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;applications&#34;&gt;Applications&lt;/h2&gt;&#xA;&lt;h3 id=&#34;shortest-path-in-a-directed-acyclic-graph&#34;&gt;Shortest path in a Directed Acyclic Graph&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// adjacency list of G&#xA;// (to, weight)&#xA;vector&amp;lt;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; &amp;gt; g;&#xA;&#xA;// topological sort states&#xA;vector&amp;lt;bool&amp;gt; visited;&#xA;vector&amp;lt;int&amp;gt; order;&#xA;&#xA;// shortest path state&#xA;vector&amp;lt;int&amp;gt; dist;&#xA;&#xA;void dfs(int v) {&#xA;  visited[v] = true;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;    if (!visited[next]) {&#xA;      dfs(next);&#xA;    }&#xA;  }&#xA;  order.push_back(v);&#xA;}&#xA;&#xA;void topological_sort() {&#xA;  int n = g.size();&#xA;  visited.assign(n, false);&#xA;&#xA;  for (int i = 0; i &amp;lt; visited.size(); i &amp;#43;= 1) {&#xA;    if (!visited[i]) {&#xA;      dfs(i);&#xA;    }&#xA;  }&#xA;&#xA;  reverse(order.begin(), order.end());&#xA;}&#xA;&#xA;/**&#xA; * Given a weighted graph `G` of order `n` and size `m` and a source vertex `source`&#xA; * it computes the shortest distance between `source` and every other reachable&#xA; * vertex from `source`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; */&#xA;void shortest_path_dag(int source) {&#xA;  int n = g.size();&#xA;  dist.assign(n, -1);&#xA;&#xA;  topological_sort();&#xA;  dist[source] = 0;&#xA;&#xA;  for(int i = 0; i &amp;lt; order.size(); i &amp;#43;= 1) {&#xA;    int v = order[i];&#xA;    if (dist[v] &amp;gt;= 0) {&#xA;      for (int j = 0; j &amp;lt; g[v].size(); j &amp;#43;= 1) {&#xA;        int to = g[v][j].first;&#xA;        int weight = g[v][j].second;&#xA;        int path_distance = dist[v] &amp;#43; weight;&#xA;        if (dist[to] &amp;lt; 0 || dist[to] &amp;gt; path_distance) {&#xA;          dist[to] = path_distance;&#xA;        }&#xA;      }&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;script type=&#34;text/javascript&#34;&gt; &#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function () {&#xA;  d3.json(&#39;/js/graph/data/topological-sorting.json&#39;, function (err, data) {&#xA;    var width = document.querySelector(&#39;article.content&#39;).clientWidth&#xA;    if (err) { throw err }&#xA;    greuler({&#xA;      directed: true,&#xA;      target: &#39;#figure-topological-sorting&#39;,&#xA;      data: data,&#xA;      width: width&#xA;    }).update({ iterations: [30, 30, 30] })&#xA;  })&#xA;})&#xA; &lt;/script&gt;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Traversal of graphs</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/traversal/</link>
      <pubDate>Wed, 24 Jun 2015 11:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/traversal/</guid>
      <description>&lt;h2 id=&#34;breadth-first-search-bfs&#34;&gt;Breadth First Search (BFS)&lt;/h2&gt;&#xA;&lt;p&gt;Given a graph $G$ and a distinguished source vertex $s$, BFS explores the edges of $G$ to discover the vertices adjacent to $s$. As a consequence, it also computes the distance of the path from $s$ to each reachable vertex.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;vector&amp;lt;int&amp;gt; dist;&#xA;vector&amp;lt;int&amp;gt; parent;&#xA;&#xA;/**&#xA; * Traverses a graph `G` of order `n` and size `m` by breadth&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @param {vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt;} g The adjacency list representation&#xA; * of a graph&#xA; * @param {int} source The source vertex&#xA; */&#xA;void bfs(vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; &amp;amp;g, int source) {&#xA;  int n = g.size();&#xA;  dist.assign(n, -1);&#xA;  parent.assign(n, -1);&#xA;&#xA;  queue&amp;lt;int&amp;gt; remaining;&#xA;  dist[source] = 0;&#xA;  remaining.push(source);&#xA;&#xA;  while (!remaining.empty()) {&#xA;    int current = remaining.front();&#xA;    remaining.pop();&#xA;&#xA;    for (int i = 0; i &amp;lt; g[current].size(); i &amp;#43;= 1) {&#xA;      int next = g[current][i];&#xA;      if (dist[next] == -1) {&#xA;        dist[next] = dist[current] &amp;#43; 1;&#xA;        parent[next] = current;&#xA;        remaining.push(next);&#xA;      }&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;depth-first-search-dfs&#34;&gt;Depth First Search (DFS)&lt;/h2&gt;&#xA;&lt;p&gt;Given a graph $G$ and a distinguished source vertex $s$, DFS explores the edges incident to $s$ and explores as far as possible along each branch before backtracking. To prevent infinite loops caused by visiting a vertex multiple times, an additional state is used in each vertex, which denotes if the vertex was visited before.&lt;/p&gt;&#xA;&lt;p&gt;Whenever a vertex $v$ is discovered by some vertex $u$, we say that $u$ is a &lt;strong&gt;predecessor&lt;/strong&gt; of $v$. Also, since every vertex can only have one predecessor (a vertex can only be visited once) during the traversal, the algorithm forms a tree called the &lt;strong&gt;DFS tree&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;During the process of creating the DFS tree, the algorithm can also define &lt;strong&gt;timestamps&lt;/strong&gt; on each vertex (an integer denoting the time an action happened).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$v_{in}$ recorded when $v$ is first discovered.&lt;/li&gt;&#xA;&lt;li&gt;$v_{out}$ recorded when the search finishes exploring $v&#xA;s adjacent vertices.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;properties&#34;&gt;Properties&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The number of descendants of any vertex $v$ is equal to $\tfrac{v_{f} - v_{d} - 1}{2}$.&lt;/li&gt;&#xA;&lt;li&gt;For any two vertices $u$ and $v$, exactly one of the following holds:&lt;/li&gt;&#xA;&lt;li&gt;If the intervals $[u_{in}, u_{out}]$ and $[v_{in}, v_{out}]$ are disjoint, then neither $u$ is a descendant of $v$ nor is $v$ a descendant of $u$ in the DFS tree.&lt;/li&gt;&#xA;&lt;li&gt;If the interval $[u_{in}, u_{out}]$ is contained in $[v_{in}, v_{out}]$, then $u$ is a descendant of $v$.&lt;/li&gt;&#xA;&lt;li&gt;If the interval $[v_{in}, v_{out}]$ is contained in $[u_{in}, u_{out}]$, then $v$ is a descendant of $u$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;classification-of-edges&#34;&gt;Classification of edges&lt;/h3&gt;&#xA;&lt;p&gt;We can define four edge types produced by a DFS on $G$:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Tree edges&lt;/strong&gt;: An edge $uv$ is a tree edge if $v$ was first discovered by $u$.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Back edges&lt;/strong&gt;: An edge $uv$ is a back edge if it connects $u$ with an ancestor of $v$.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Forward edges&lt;/strong&gt;: An edge $uv$ is a forward edge if it connects $u$ with a descendant of $v$ (a non-tree edge).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Cross edges&lt;/strong&gt;: All other edges, e.g., an edge between branches in the DFS tree.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;We can identify these edges with an additional state stored in the vertices of the graph during the DFS tree process. The additional state will be $v_{color}$ and can have three possible values:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$v_{color} = WHITE$ if a vertex hasn&amp;rsquo;t been explored yet.&lt;/li&gt;&#xA;&lt;li&gt;$v_{color} = GRAY$ when a vertex is first discovered.&lt;/li&gt;&#xA;&lt;li&gt;$v_{color} = BLACK$ when a vertex has finished exploring its adjacent vertices.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;During the analysis of an edge, we can look at the color of the adjacent vertex to determine the type of edge. Given the edge $uv$, there are three possible outcomes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $v_{color} = WHITE$, then $uv$ is a &lt;em&gt;tree edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If $v_{color} = GRAY$, then $uv$ is a &lt;em&gt;back edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If $v_{color} = BLACK$, then $uv$ is a &lt;em&gt;forward/cross edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Another way to determine the type of edge is by analyzing the states $u_{in}$ ($u_{out}$ is undefined when all the edges $uv$ are being analyzed) and $v_{in}, v_{out}$ of the incident vertices to the edge. Given an edge $uv$:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $v_{in}$ is not defined, then $uv$ is a &lt;em&gt;tree edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If $v_{in}$ is defined and $v_{out}$ is not defined, then $uv$ is a &lt;em&gt;back edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If $v_{in}$ is defined, $v_{out}$ is defined, and $u_{in} &amp;lt; v_{in}$, then $uv$ is a &lt;em&gt;forward edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If $v_{in}$ is defined, $v_{out}$ is defined, and $u_{in} &amp;gt; v_{in}$, then $uv$ is a &lt;em&gt;cross edge&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;additional-properties-of-the-edges&#34;&gt;Additional properties of the edges&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $G$ is an undirected graph, then every edge of $G$ is either a tree edge or a back edge during the exploration of the DFS tree.&lt;/li&gt;&#xA;&lt;li&gt;A directed graph $G$ is acyclic if it contains no back edges.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int time_spent = 0;&#xA;&#xA;// the adjacency list of `G`&#xA;vector&amp;lt;vector&amp;lt;int&amp;gt; &amp;gt; g;&#xA;// the explored state of a vertex `i`&#xA;vector&amp;lt;bool&amp;gt; visited;&#xA;// the predecesor of a vertex `i` in the dfs tree&#xA;vector&amp;lt;bool&amp;gt; predecessor;&#xA;// the time a vertex `i` was discovered first&#xA;vector&amp;lt;int&amp;gt; time_in;&#xA;// the time a vertex `i` spent exploring each reachable non-visited vertices&#xA;vector&amp;lt;int&amp;gt; time_out;&#xA;&#xA;/**&#xA; * Traverses a graph `G` of order `n` and size `m` by depth,&#xA; * it&amp;#39;s assumed that `time_in`, `time_out`, `visited`, `predecessor`&#xA; * are initialized correctly with a size equal to `n`&#xA; *&#xA; * Time complexity: O(n &amp;#43; m)&#xA; * Space complexity: O(n)&#xA; *&#xA; * @param {int} v The current vertex being analyzed&#xA; */&#xA;void dfs(int v) {&#xA;  visited[v] = true;&#xA;  time_in[v] = &amp;#43;&amp;#43;time_spent;&#xA;&#xA;  for (int i = 0; i &amp;lt; g[v].size(); i &amp;#43;= 1) {&#xA;    int next = g[v][i];&#xA;&#xA;    // edge analysis&#xA;    if (!time_in[next]) {&#xA;      // edge (v, next) is a tree edge&#xA;    } else if (!time_out[next]) {&#xA;      // edge (v, next) is a back edge&#xA;    } else if (time_in[v] &amp;lt; time_in[next]) {&#xA;      // edge (v, next) is a forward edge&#xA;    } else {&#xA;      // edge (v, next) is a forward edge&#xA;    }&#xA;&#xA;    // traversal to adjacent vertices&#xA;    if (!visited[next]) {&#xA;      predecessor[next] = v;&#xA;      dfs(next);&#xA;    }&#xA;  }&#xA;&#xA;  time_out[v] = &amp;#43;&amp;#43;time_spent;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Introduction to Graph Theory</title>
      <link>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/introduction/</link>
      <pubDate>Mon, 22 Jun 2015 17:03:41 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/computer-science/data-structures/graphs/introduction/</guid>
      <description>&lt;p&gt;A graph is a pair $G = (V, E)$. It consists of a finite set $V$ of objects called &lt;em&gt;vertices&lt;/em&gt; (or nodes or points) and a set $E$ of 2-element subsets of $V$ called &lt;em&gt;edges&lt;/em&gt;. Another way to denote the vertex set/edges of a graph $G$ is by using $V(G)$ (the vertex set of $G$) and $E(G)$ (the edge set of $G$).&lt;/p&gt;&#xA;&lt;div id=&#34;figure-introduction&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;G &amp;= (V, E) \\ V &amp;= \{1, 2, 3, 4, 5, 6, 7\} \\ E &amp;= \{ \{1, 5\}, \{5, 7\}, \{2, 3\}, \{2, 4\}, \{3, 4\} \}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Properties:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The &lt;strong&gt;order&lt;/strong&gt; of a graph is the number of vertices (written as $\mid G \mid$).&lt;/li&gt;&#xA;&lt;li&gt;The &lt;strong&gt;size&lt;/strong&gt; of a graph is the number of edges (written as $\Vert G \Vert$).&lt;/li&gt;&#xA;&lt;li&gt;An edge ${u, v}$ is usually written as $uv$ (or $vu$). If $uv$ is an edge of $G$, then $u$ and $v$ are said to be &lt;strong&gt;adjacent&lt;/strong&gt; in $G$.&lt;/li&gt;&#xA;&lt;li&gt;A vertex $v$ is &lt;strong&gt;incident&lt;/strong&gt; with an edge &lt;em&gt;e&lt;/em&gt; if $v \in e$.&lt;/li&gt;&#xA;&lt;li&gt;The set of neighbors of a vertex $v$ is denoted by $N(v)$.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;strong&gt;degree of a vertex&lt;/strong&gt; $v$ is the number of edges incident to $v$ (loops are counted twice).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let $G = (V, E)$ and $G&amp;rsquo; = (V&amp;rsquo;, E&amp;rsquo;)$ be two graphs. We set $G \cup G&amp;rsquo; = (V \cup V&amp;rsquo;, E \cup E&amp;rsquo;)$ and $G \cap G&amp;rsquo; = (V \cap V&amp;rsquo;, E \cap E&amp;rsquo;)$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $G \cap G&amp;rsquo; = \varnothing$, then $G$ and $G&amp;rsquo;$ are &lt;strong&gt;disjoint&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If $V&amp;rsquo; \subseteq V$ and $E&amp;rsquo; \subseteq E$, then $G&amp;rsquo;$ is a &lt;strong&gt;subgraph&lt;/strong&gt; of $G$, written as $G&amp;rsquo; \subseteq G$.&lt;/li&gt;&#xA;&lt;li&gt;If $G&amp;rsquo;$ is a subgraph of $G$ and either $V&amp;rsquo; \subset V$ or $E&amp;rsquo; \subset E$, then $G&amp;rsquo;$ is a &lt;strong&gt;proper subgraph&lt;/strong&gt; of $G$.&lt;/li&gt;&#xA;&lt;li&gt;If $G&amp;rsquo;$ is a subgraph of $G$ and $V&amp;rsquo; = V$, then $G&amp;rsquo;$ is a &lt;strong&gt;spanning subgraph&lt;/strong&gt; of $G$.&lt;/li&gt;&#xA;&lt;li&gt;If $V&amp;rsquo; \subseteq V$ and all the edges $e = uv \in E$ such that $u \in V&amp;rsquo;$ and $v \in V&amp;rsquo;$ are also in $E&amp;rsquo;$, then $G&amp;rsquo;$ is an &lt;strong&gt;induced subgraph&lt;/strong&gt; of $G$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;movement&#34;&gt;Movement&lt;/h2&gt;&#xA;&lt;p&gt;A &lt;strong&gt;walk&lt;/strong&gt; in a graph is a sequence of movements beginning at $u$, moving to a neighbor of $u$, and then to a neighbor of that vertex, and so on, until we stop at a vertex $v$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;W = (u = v_0, v_1, \ldots, v = v_k)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;where $k \geq 0$. Note that there are no restrictions on the vertices visited, so a vertex can be visited more than once. Also, there are no restrictions on the edges traversed, so an edge can be traversed more than once. Every two consecutive vertices in $W$ are distinct since they are adjacent. If $u = v$, then we say that the walk is &lt;em&gt;closed&lt;/em&gt;; otherwise, it&amp;rsquo;s &lt;em&gt;open&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A &lt;strong&gt;trail&lt;/strong&gt; is a walk in which no edge is traversed more than once.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;strong&gt;path&lt;/strong&gt; is a walk in which no vertex is visited more than once (note that every path is also a trail).&lt;/li&gt;&#xA;&lt;li&gt;A &lt;strong&gt;circuit&lt;/strong&gt; is a &lt;em&gt;closed trail&lt;/em&gt; of length 3 or more (it begins and ends at the same vertex but repeats no edges).&lt;/li&gt;&#xA;&lt;li&gt;A &lt;strong&gt;cycle&lt;/strong&gt; is a circuit that repeats no vertices (think of it as a &lt;em&gt;closed path&lt;/em&gt;). A $k$-cycle is a cycle of length $k$ (e.g., a $3$-cycle is a triangle).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Properties related to path lengths:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The &lt;strong&gt;distance&lt;/strong&gt; between two vertices $u$ and $v$ is the smallest length of any $u - v$ path in $G$, denoted by $d(u, v)$.&lt;/li&gt;&#xA;&lt;li&gt;The &lt;strong&gt;diameter&lt;/strong&gt; is the greatest distance between any two vertices of a connected graph.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Some additional properties related to connectivity in a graph:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If a graph $G$ contains a $u-v$ path, then $u$ and $v$ are said to be &lt;strong&gt;connected&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;A graph $G$ is &lt;strong&gt;connected&lt;/strong&gt; if every two vertices of $G$ are connected.&lt;/li&gt;&#xA;&lt;li&gt;A connected subgraph of $G$ that is not a proper subgraph of any other connected subgraph of $G$ is a &lt;strong&gt;component&lt;/strong&gt; of $G$.&lt;/li&gt;&#xA;&lt;li&gt;The number of components of a graph is denoted by $k(G)$. A graph is connected if $k(G) = 1$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;common-classes-of-graphs&#34;&gt;Common classes of graphs&lt;/h2&gt;&#xA;&lt;h3 id=&#34;complete-graph&#34;&gt;Complete graph&lt;/h3&gt;&#xA;&lt;p&gt;A graph $G$ is &lt;strong&gt;complete&lt;/strong&gt; if every two distinct vertices of $G$ are adjacent.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-complete-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A complete graph of order $n$ is denoted by $K_n$. For complete graphs, $K_n$ has the maximum possible size for a graph of $n$ vertices.&lt;/li&gt;&#xA;&lt;li&gt;The number of pairs of vertices in $K_n$ is $\binom{n}{2} = \tfrac{n(n - 1)}{2}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;sparse-graph&#34;&gt;Sparse graph&lt;/h3&gt;&#xA;&lt;p&gt;A graph $G$ of order $n$ and size $m$ is a &lt;strong&gt;sparse graph&lt;/strong&gt; if $m$ is close to the minimal number of edges, i.e., when $m \approx n$. In this case, &lt;strong&gt;adjacency lists&lt;/strong&gt; are preferred since they require constant space for every edge. A tree is a good example of a sparse graph.&lt;/p&gt;&#xA;&lt;h3 id=&#34;dense-graph&#34;&gt;Dense graph&lt;/h3&gt;&#xA;&lt;p&gt;A graph $G$ of order $n$ and size $m$ is a &lt;strong&gt;dense graph&lt;/strong&gt; if $m$ is close to the maximal number of edges, i.e., when $m \approx n^2$. In this case, an &lt;strong&gt;adjacency matrix&lt;/strong&gt; is preferred. A complete graph is a dense graph.&lt;/p&gt;&#xA;&lt;h3 id=&#34;complement-graph&#34;&gt;Complement graph&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;strong&gt;complement&lt;/strong&gt; $\bar{G}$ of a graph $G$ is a graph whose vertex set is $V(G)$ and such that for each pair of distinct vertices $u, v$, $uv \in E(\bar{G})$ if and only if $uv \not\in E(G)$. This means that the complement of a complete graph is a graph of order $n$ and size $0$.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-complement-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $G$ is disconnected, $\bar{G}$ is connected.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;bipartite-graph&#34;&gt;Bipartite graph&lt;/h3&gt;&#xA;&lt;p&gt;A graph $G$ is bipartite when the set $V(G)$ can be partitioned into two subsets $U$ and $W$, called &lt;strong&gt;partite sets&lt;/strong&gt;, such that every edge of $G$ joins a vertex of $U$ and a vertex of $W$.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-bipartite-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A nontrivial graph $G$ is bipartite if it doesn&amp;rsquo;t contain &lt;em&gt;odd-length cycles&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;strong&gt;complete bipartite graph&lt;/strong&gt; is a bipartite graph where each vertex of $U$ is adjacent to every vertex of $W$. It&amp;rsquo;s denoted as $K_{\mid U \mid, \mid W \mid}$.&lt;/li&gt;&#xA;&lt;li&gt;A &lt;strong&gt;star&lt;/strong&gt; is a complete bipartite graph of the form $K_{1, \mid W \mid}$ or $K_{\mid U \mid, 1}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;k-partite-graph&#34;&gt;$k$-partite graph&lt;/h3&gt;&#xA;&lt;p&gt;A graph $G$ is $k$-partite when the set $V(G)$ can be partitioned into $k$ subsets $V_1, V_2, \ldots, V_k$ such that every edge of $G$ joins a vertex of $V_i$ and a vertex of $V_j$ for $i \neq j$.&lt;/p&gt;&#xA;&lt;h3 id=&#34;biconnected-graph&#34;&gt;Biconnected graph&lt;/h3&gt;&#xA;&lt;p&gt;A biconnected graph $G$ is a connected and &amp;ldquo;nonseparable&amp;rdquo; graph, meaning that if any vertex (and its incident edges) is removed, the graph will remain connected. Therefore, a biconnected graph doesn&amp;rsquo;t have cut-vertices.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-biconnected-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;multigraphs&#34;&gt;Multigraphs&lt;/h3&gt;&#xA;&lt;p&gt;A multigraph $M$ is a graph where any two vertices of $M$ may be joined by a finite number of edges. When two or more edges join the same pair of distinct vertices, those edges are called &lt;strong&gt;parallel edges&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-multigraph&#34;&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;pseudographs&#34;&gt;Pseudographs&lt;/h3&gt;&#xA;&lt;p&gt;A pseudograph $P$ is a graph in which an edge is allowed to join a vertex to itself. Such an edge is called a &lt;strong&gt;loop&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-pseudograph&#34;&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;weighted-graph&#34;&gt;Weighted graph&lt;/h3&gt;&#xA;&lt;p&gt;Let $G$ be a multigraph. Let&amp;rsquo;s replace all the parallel edges joining a particular pair of vertices with a single edge that is assigned a positive integer representing the number of parallel edges. This new representation is referred to as a &lt;strong&gt;weighted graph&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-weighted-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;digraphs&#34;&gt;Digraphs&lt;/h3&gt;&#xA;&lt;p&gt;A &lt;strong&gt;directed graph&lt;/strong&gt; $D$ is a finite, nonempty set $V$ of vertices and a set $E$ of ordered pairs of distinct vertices. The elements of the set $E$ are called &lt;strong&gt;directed edges&lt;/strong&gt; or &lt;strong&gt;arcs&lt;/strong&gt;. Arcs are represented with arrows instead of plain line segments.&lt;/p&gt;&#xA;&lt;div id=&#34;figure-directed-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If $uv$ is a directed edge, then $u$ is &lt;strong&gt;adjacent to&lt;/strong&gt; $v$, and $v$ is &lt;strong&gt;adjacent from&lt;/strong&gt; $u$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;degrees&#34;&gt;Degrees&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;strong&gt;degree&lt;/strong&gt; of a vertex $v$ is the number of edges incident with $v$, denoted by $deg(v)$ (with loops counted twice).&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The minimum degree of a graph $G$ is the minimum degree among all the vertices of $G$, denoted as $\delta(G)$.&lt;/li&gt;&#xA;&lt;li&gt;The maximum degree of a graph $G$ is the maximum degree among all the vertices of $G$, denoted as $\Delta(G)$.&lt;/li&gt;&#xA;&lt;li&gt;A vertex of degree $0$ is called an &lt;strong&gt;isolated vertex&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;A vertex of degree $1$ is called an &lt;strong&gt;end vertex&lt;/strong&gt; (or &lt;strong&gt;leaf&lt;/strong&gt;).&lt;/li&gt;&#xA;&lt;li&gt;A vertex of even degree is called an &lt;strong&gt;even vertex&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;A vertex of odd degree is called an &lt;strong&gt;odd vertex&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Two vertices of $G$ that have the same degree are called &lt;strong&gt;regular vertices&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;If a graph $G$ has the same degree $r$ for all its vertices, it&amp;rsquo;s called an &lt;strong&gt;r-regular graph&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;In a graph $G$ of $n$ vertices, the following equality relation holds:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;0 \leq \delta(G) \leq deg(v) \leq \Delta(G) \leq n - 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;First theorem of graph theory&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If $G$ is a graph of size $m$, then&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div&gt;$$&#xA;\sum_{v \in V(G)} deg(v) = 2m&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When summing the degrees of $G$, each edge is counted twice.&lt;/p&gt;&#xA;&lt;h3 id=&#34;degrees-in-a-bipartite-graph&#34;&gt;Degrees in a bipartite graph&lt;/h3&gt;&#xA;&lt;p&gt;Suppose that $G$ is a bipartite graph with two partite sets, $U$ and $W$. Then&lt;/p&gt;&#xA;&lt;div&gt;$ \sum_{u \in V(U)}deg(u) = \sum_{w \in V(W)} deg(w) = m $&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Corollary: every graph has an even number of odd vertices&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Proof:&lt;/em&gt; Let $G$ be a graph of size $m$. Dividing $V(G)$ into two subsets, $V_{even}$, which consists of even vertices, and $V_{odd}$, which consists of odd vertices, then by the first theorem of graph theory:&lt;/p&gt;&#xA;&lt;div&gt;$ \sum_{v \in V_{even}(G)} deg(v) + \sum_{v \in V_{odd}(G)} deg(v) = 2m $&lt;/div&gt;&#xA;&lt;p&gt;The number $\sum_{v \in V_{even}(G)} deg(v)$ is even since it&amp;rsquo;s a sum of even numbers. Thus, $\sum_{v \in V_{odd}(G)} deg(v)$ is also even, and it can be even only if the number of odd vertices is even (a sum of two odd numbers gives an even number).&lt;/p&gt;&#xA;&lt;h3 id=&#34;degree-sequences&#34;&gt;Degree sequences&lt;/h3&gt;&#xA;&lt;p&gt;If the degrees of a graph $G$ are listed in a sequence $s$, then $s$ is called a &lt;em&gt;degree sequence&lt;/em&gt;, e.g.,&lt;/p&gt;&#xA;&lt;div&gt;$ s: 4, 3, 2, 2, 2, 1, 1, 1, 0 $&lt;/div&gt;&#xA;&lt;div id=&#34;figure-degree-sequence&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Suppose we&amp;rsquo;re given a finite sequence $s$ of nonnegative integers. A well-known problem is whether we can build a graph out of this sequence. To solve this problem, let&amp;rsquo;s talk about some facts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The degree of any vertex can never be greater than $n - 1$, where $n$ is the order of the graph.&lt;/li&gt;&#xA;&lt;li&gt;A graph has an even number of odd vertices.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a theorem called the Havel-Hakimi theorem, which solves the problem above in polynomial time.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A non-increasing sequence $s: d_1, d_2, \ldots, d_n$, where $d_1 \geq 1$, can form a graph only if the sequence&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div&gt;$ s_1: d_2 - 1, d_3 - 1, \ldots, d_{d_1 + 1} - 1, d_{d_1 + 2}, \ldots, d_n $&lt;/div&gt;&#xA;forms a graph.&#xA;&lt;p&gt;According to this theorem, we can create a new sequence based on the one above that is also a graph. We can apply the theorem recursively to test if the original sequence forms a graph.&lt;/p&gt;&#xA;&lt;div&gt;$ \begin{align*} s_1 &amp;: 4, 3, 2, 2, 2, 1, 1, 1, 0 \ s_2 &amp;: 2, 1, 1, 1, 1, 1, 1, 0 \ \text{removing $d_1 = 4$ and subtracting $1$ from the following $4$ elements} \ s_3 &amp;: 1, 1, 1, 1, 0 \ \text{removing $d_1 = 2$ and subtracting $1$ from the following $2$ elements} \ s_4 &amp;: 1, 1, 0 \ \text{removing $d_1 = 1$ and subtracting $1$ from the following element} \ s_5 &amp;: 0 \ \text{removing $d_1 = 1$ and subtracting $1$ from the following element} \ \end{align*} $&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;bool graph_from_sequence(vector&amp;lt;int&amp;gt; &amp;amp;degrees) {&#xA;  int sum = 0;&#xA;  int size = degrees.size();&#xA;  for (int i = 0; i &amp;lt; size; i &amp;#43;= 1) {&#xA;    sum &amp;#43;= degrees[i];&#xA;    if (degrees[i] &amp;gt;= size || degrees[i] &amp;lt; 0) {&#xA;      // a vertice can have a maximum degree of n - 1&#xA;      // also none of the degrees can be negative&#xA;      return false;&#xA;    }&#xA;  }&#xA;&#xA;  if (sum == 0) {&#xA;    // trivial case&#xA;    return true;&#xA;  }&#xA;&#xA;  sort(degrees.begin(), degrees.end());&#xA;&#xA;  // removing d_1&#xA;  int max_degree = degrees.back();&#xA;  degrees.pop_back();&#xA;  size -= 1;&#xA;&#xA;  // subtracting 1 from the next d_1 elements&#xA;  for (int i = 0; i &amp;lt; max_degree; i &amp;#43;= 1) {&#xA;    degrees[size - 1 - i] -= 1;&#xA;  }&#xA;  return graph_from_sequence(degrees);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;graphs-and-matrices&#34;&gt;Graphs and matrices&lt;/h2&gt;&#xA;&lt;p&gt;A graph can also be described using a matrix. The &lt;strong&gt;adjacency matrix&lt;/strong&gt; of a graph $G$ of order $n$ and size $m$ is an $n \times n$ matrix $A = [a_{ij}]$ where&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a_{ij} =&#xA;\begin{cases}&#xA;1 &amp; \text{if $v_iv_j \in G$} \\&#xA;0 &amp; \text{otherwise}&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The &lt;strong&gt;incidence matrix&lt;/strong&gt; of a graph $G$ of order $n$ and size $m$ is an $n \times m$ matrix $B = [b_{ij}]$ where&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;b_{ij} =&#xA;\begin{cases}&#xA;1 &amp; \text{if $v_i$ is incident with $e_j$} \\&#xA;0 &amp; \text{otherwise}&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;figure-adjacency-incidence-matrix&#34;&gt;&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;G = (V, E) \\&#xA;V = \{0, 1, 2, 3, 4\} \\&#xA;E = \{\{0, 1\}, \{0, 2\}, \{0, 3\}, \{1, 3\}, \{2, 3\}, \{3, 4\}\}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;A = \begin{bmatrix}&#xA;0 &amp; 1 &amp; 1 &amp; 1 &amp; 0 \\&#xA;1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\&#xA;1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\&#xA;1 &amp; 1 &amp; 1 &amp; 0 &amp; 1 \\&#xA;0 &amp; 0 &amp; 0 &amp; 1 &amp; 0&#xA;\end{bmatrix} \quad&#xA;B = \begin{bmatrix}&#xA;1 &amp; 1 &amp; 1 &amp; 0 &amp; 0 &amp; 0 \\&#xA;1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 &amp; 0 \\&#xA;0 &amp; 1 &amp; 0 &amp; 0 &amp; 1 &amp; 0 \\&#xA;0 &amp; 0 &amp; 1 &amp; 1 &amp; 1 &amp; 1 \\&#xA;0 &amp; 0 &amp; 0 &amp; 0 &amp; 0 &amp; 1&#xA;\end{bmatrix}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;useful-observations&#34;&gt;Useful observations&lt;/h3&gt;&#xA;&lt;p&gt;Let $A^k$ be the adjacency matrix of a graph $G$ raised to the $k$-th power. The entry $a_{ij}^{(k)}$ is the number of distinct $v_i - v_j$ walks of length $k$ in $G$.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;Proof:&lt;/em&gt; Assume for a positive integer $k$ that the number of $v_i - v_j$ walks of length $k$ is given by $a_{ij}^{(k)}$ in the matrix $A^k$. Then $A^{k + 1} = A^k \times A$. Now, a cell $a_{ij}^{(k + 1)}$ is the dot product of row $i$ of $A^k$ and column $j$ of $A$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a_{ij}^{(k + 1)} = \sum_{t=1}^n a_{it}^{(k)} \cdot a_{tj}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The first element of this sum is the number of walks of length $k$ from $v_i$ to $v_1$ (stored in $a_{i1}^{(k)}$) times the number of walks of length $1$ from $v_1$ to $v_j$ (stored in $a_{1j}$). The second element follows the same formula but uses $v_2$ as the vertex used to &amp;ldquo;join&amp;rdquo; the walks of length $k$ and $1$.&lt;/p&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/graph/introduction.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Integer Factorization</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/integer-factorization/</link>
      <pubDate>Sun, 14 Jun 2015 15:08:08 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/integer-factorization/</guid>
      <description>&lt;p&gt;The fundamental theorem of arithmetic states that every positive integer can be written uniquely as a product of primes&lt;/p&gt;&#xA;&lt;p&gt;example:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;65340 = 2^2 \cdot 3^3 \cdot 5 \cdot 11^2&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;trial-division&#34;&gt;Trial division&lt;/h2&gt;&#xA;&lt;p&gt;Trial division is the simplest algorithm for factoring an integer. We assume that $s$ and $t$ are factors of a number $n$ such that $n = st$ and $s \leq t$ (note that $s$ and $t$ do not need to be prime numbers). When a divisor $s$ is found then $n / s$ is also a factor&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;vector&amp;lt;int&amp;gt; trial_division(int n) {&#xA;  for (int i = 2; i * i &amp;lt;= n; i += 1) {&#xA;    if (n % i == 0) {&#xA;      // `n` is a composite number&#xA;      return vector&amp;lt;int&amp;gt; {i, n / i};&#xA;    }&#xA;  }&#xA;  // n is a prime number&#xA;  return vector&amp;lt;int&amp;gt; {n};&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;fermat-factorization&#34;&gt;Fermat factorization&lt;/h2&gt;&#xA;&lt;p&gt;Fermat observed how to write an integer as the difference of squares&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;n &amp;= x^2 - y^2 \label{fermat} \\&#xA;&amp;= (x + y)(x - y)&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Assuming that $s$ and $t$ are &lt;strong&gt;odd&lt;/strong&gt; factors of $n$ such that $n = st$ and $s \leq t$, we can find $x$ and $y$ such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;s &amp;= x - y \\&#xA;t &amp;= x + y&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Adding both equations&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s + t = 2x \\&#xA;x = \frac{s + t}{2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Also&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y = \frac{t - s}{2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since we assumed that $s$ and $t$ are odd numbers, their difference is an even number which is divisible by $2$; therefore, $x$ and $y$ are integers. Since $s &amp;gt; 1$ and $t \geq s$ we find that $x \geq 1$ and $y \geq 0$&lt;/p&gt;&#xA;&lt;p&gt;From \eqref{fermat} we also know that $x = \sqrt{n + y^2}$ and hence $x \geq \sqrt{n}$. Also $x = \tfrac{s + t}{2}$ and we know that the upper bound of $s$ happens when $s$ is as close as $t$ as possible. Given that $s \leq t$, $x \leq \tfrac{t + t}{2} \leq n$&lt;/p&gt;&#xA;&lt;p&gt;Implementation notes: Since $s$ and $t$ are odd numbers, their product $n$ is also an odd number; therefore, the implementation below works with odd values of $n$&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;/**&#xA; * Factorization of an odd number `n` based on Fermat&#39;s&#xA; * factorization algorithm&#xA; *&#xA; * @param  {int} n&#xA; * @return {vector&amp;lt;int&amp;gt;} a vector with two odd integers if `n` is not a&#xA; * prime number, a single integer if `n` is a prime number&#xA; */&#xA;vector&amp;lt;int&amp;gt; fermat_factorization(int n) {&#xA;  for (int x = (int) ceil(sqrt(n)); x &amp;lt;= n; x += 1) {&#xA;    int ySquared = x * x - n;&#xA;    // check if `y` is the square of some number&#xA;    int y = (int) sqrt(ySquared);&#xA;    if (y * y == ySquared) {&#xA;      int s = x - y;&#xA;      int t = x + y;&#xA;      // `s` must be &amp;gt; 1&#xA;      if (s != 1 &amp;amp;&amp;amp; t != n) {&#xA;        return vector&amp;lt;int&amp;gt; {s, t};&#xA;      }&#xA;    }&#xA;  }&#xA;  // n is a prime number&#xA;  return vector&amp;lt;int&amp;gt; {n};&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;pollards-rho-factorization&#34;&gt;Pollard&amp;rsquo;s Rho factorization&lt;/h3&gt;&#xA;&lt;p&gt;Pollard&amp;rsquo;s Rho factorization is a probabilistic factorization algorithm based on the assumption that a number $n$ is a composite number, and the following facts:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;since $n$ is a &lt;strong&gt;composite number&lt;/strong&gt;, there must be a factor $d$&lt;/li&gt;&#xA;&lt;li&gt;let $a$ and $b$ be two positive integers, if $a \equiv b \pmod{d}$ then the difference $a - b$ is a multiple of $d$. Since $n$ is also a multiple of $d$ some multiple of $d$ is a divisor of $n$ and $a - b$. Particularly, $gcd(a - b, n)$ is a divisor of $n$. Let $gcd(a - b, n) &amp;gt; 1$ then we have found two factors of $n$ ($gcd(a - b, n), \tfrac{n}{gcd(a - b, n)}$)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Now the problem is reduced to finding $a$ and $b$ such that $gcd(a - b, n) &amp;gt; 1$, we can use the following algorithm which picks random numbers in the range $[1, n - 1]$.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-text&#34;&gt;let `n` be the number to be factorized&#xA;let `x` be an array of integers&#xA;&#xA;x[0] = random integer in the range [1, n - 1]&#xA;while we haven&#39;t found two numbers such that `gcd(x_i, x_j, n) &amp;gt; 1`&#xA;  x[i] = random integer in the range [1, n - 1]&#xA;  for all `j &amp;lt; i` and `j &amp;gt;= 0`&#xA;    if `gcd(x[i] - x[j], n) &amp;gt; 1`&#xA;      return x[i], x[j]&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;A simulation can find $a$ and $b$ with a probability $~50%$ after $\sqrt{n}$ iterations. The algorithm above is not very helpful, though, since at the $k$ iteration we have to do $k - 1$ pairwise checks&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s another algorithm to pick random numbers. Let $x$ be an integer in the range $[1, n - 1]$. A function that will generate a number in the range $[1, n - 1]$ based on a previous number is&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f(x) = x^2 + c \pmod{n}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Because there are only $n - 1$ possible values our generator will eventually fall into a cycle, for example let $n = 55, c = 2, x = 2$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x_0 &amp;= 2 \\&#xA;x_1 &amp;= (2^2 + 2) \pmod{55} = 6 \\&#xA;x_2 &amp;= (6^2 + 2) \pmod{55} = 38 \\&#xA;x_3 &amp;= (38^2 + 2) \pmod{55} = 16 \\&#xA;x_4 &amp;= (16^2 + 2) \pmod{55} = 38 \text{ which is equal to $x_2$ }&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Pollard detected the cycle using &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Cycle_detection#/Tortoise_and_hare&#34;target=&#34;_blank&#34;&gt;Floyd&amp;rsquo;s cycle-finding algorithm&lt;/a&gt;&#xA;&#xA;, which is based on two pointers which move through a sequence at different speeds: one moves a unit and the other moves two units each time. If there&amp;rsquo;s a cycle, eventually the two pointers will encounter at some element belonging to the cycle. If we&amp;rsquo;ve analyzed all the elements of the sequence and saw not a single contiguous pair fulfills $gcd(x_i - x_{i + 1}, n) &amp;gt; 1$ we need to choose other values for $x_0, a$ and rerun the algorithm.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// C&amp;#43;&amp;#43;11&#xA;#include &amp;lt;random&amp;gt;&#xA;&#xA;/**&#xA; * Computes a factor of `n` which is greater than `1`&#xA; * @param {long long} n The number to be factorized&#xA; * @return {long long} A positive integer which is a factor of `n`&#xA; * when the algorithm successfully finds a factor of `n`, -1 otherwise&#xA; */&#xA;long long pollard_rho(long long n) {&#xA;  if (n % 2 == 0) {&#xA;    return 2;&#xA;  }&#xA;&#xA;  std::random_device rd;&#xA;  std::mt19937 engine(rd());&#xA;  std::uniform_int_distribution&amp;lt;long long&amp;gt; dis(1, n - 1);&#xA;&#xA;  long long x = dis(engine);&#xA;  long long c = dis(engine);&#xA;  long long y = x;   // y = x^2 &amp;#43; c (mod n)&#xA;  do {&#xA;    // tortoise goes x = f(x)&#xA;    x = ((x * x) % n &amp;#43; c) % n;&#xA;&#xA;    // hare goes y = f(f(y))&#xA;    y = ((y * y) % n &amp;#43; c) % n;&#xA;    y = ((y * y) % n &amp;#43; c) % n;&#xA;&#xA;    long long gcd = __gcd(abs(x - y), n);&#xA;    if (gcd &amp;gt; 1) {&#xA;      return gcd;&#xA;    }&#xA;  } while (x != y);&#xA;&#xA;  return -1;&#xA;}&#xA;&#xA;/**&#xA; * Pollard rho factorization runner, it makes multiple calls to&#xA; * `pollard_rho` until a factor is found&#xA; * @param {long long} n The number to be factorized&#xA; * @return {long long} A factor of `n` (it is `n` when `n` is a prime number)&#xA; */&#xA;long long pollard_rho_factorization(long long n) {&#xA;  long long factor;&#xA;  do {&#xA;    factor = pollard_rho(n);&#xA;  } while(factor &amp;lt; 0);&#xA;  return factor;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;eratosthenes-sieve-factorization-of-a-range&#34;&gt;Eratosthenes Sieve factorization of a range&lt;/h3&gt;&#xA;&lt;p&gt;We can also compute the factorization of a number by modifying the sieve of Eratosthenes. Remember that each state of the sieve holds a boolean indicating if the number is prime or not. This time each state of the sieve will hold a pair of numbers&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the lowest prime that is a divisor of index &lt;code&gt;i&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;the maximum power of the lowest prime computed above (optional)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s represent $n$ as $p_1^{a_1} \cdot p_2^{a_2} \ldots p_n^{a_n}$, since we hold for each position the lowest prime and its maximum power, the state stored at the position $n$ of the sieve will be $p_1^{a_1}$. If we divide $n$ by this number we will move to the state of $p_2^{a_2} \ldots p_n^{a_n}$. This recursive process is run until the current state reached in the sieve is $1$.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// let `p` be the smallest prime factor of the index `i`, each element&#xA;// contains a pair `(p, x)` such that `p^x` is a divisor of `i`&#xA;// e.g.&#xA;//&#xA;//    8 = (2, 3)&#xA;//    15 = (3, 1)&#xA;//    6 = (2, 1)&#xA;//&#xA;vector&amp;lt;pair&amp;lt;int, int&amp;gt; &amp;gt; lp;&#xA;&#xA;void eratosthenes_sieve_factorization(long long n) {&#xA;  pair&amp;lt;int, int&amp;gt; unvisited(-1, -1);&#xA;&#xA;  // (-1, -1) is an unvisited state&#xA;  lp.assign(n &amp;#43; 1, unvisited);&#xA;&#xA;  for (int i = 2; i * i &amp;lt;= n; i &amp;#43;= 1) {&#xA;    if (lp[i] == unvisited) {&#xA;      // if an index is in an unvisited state it&amp;#39;s a prime number&#xA;      pair&amp;lt;int, int&amp;gt; base(i, 1);&#xA;      lp[i] = base;&#xA;      for (int j = i * i; j &amp;lt;= n; j &amp;#43;= i) {&#xA;        if (lp[j] == unvisited) {&#xA;          // if a multiple of the prime number is in an unvisited&#xA;          // state that means that it&amp;#39;s lowest prime divisor is&#xA;          // the current index `i`&#xA;          lp[j] = base;&#xA;          if (lp[j / i] != unvisited) {&#xA;            // `j` is a multiple of `i`, in fact `j = i^x` because&#xA;            // only numbers which don&amp;#39;t have other factors but `i`&#xA;            // reach this point, to accumulate the powers it&amp;#39;s enough&#xA;            // find out the power of `j / i`&#xA;            lp[j].second &amp;#43;= lp[j / i].second;&#xA;          }&#xA;        }&#xA;      }&#xA;    }&#xA;  }&#xA;&#xA;  // all the prime numbers &amp;gt; sqrt(n) will have an unvisited state&#xA;  // changing the unvisited state to prime_number^1&#xA;  int sqrtN = sqrt(n);&#xA;  if (sqrtN % 2 == 0) {&#xA;    sqrtN &amp;#43;= 1;&#xA;  }&#xA;  for (int i = sqrtN; i &amp;lt;= n; i &amp;#43;= 2) {&#xA;    if (lp[i] == unvisited) {&#xA;      lp[i] = pair&amp;lt;int, int&amp;gt;(i, 1);&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Divisor Function</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/divisor-function/</link>
      <pubDate>Sat, 13 Jun 2015 14:29:59 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/divisor-function/</guid>
      <description>&lt;p&gt;The divisor function represented as $d(n)$ counts the number of divisors of an integer.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; $d(18)$&lt;/p&gt;&#xA;&lt;p&gt;The numbers that divide $18$ are $1, 2, 3, 6, 9, 18$; then $d(18) = 6$&lt;/p&gt;&#xA;&lt;h2 id=&#34;important-observations&#34;&gt;Important observations&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if $p$ is a prime number, then $d(p) = 2$; also, $d(p^k) = k + 1$ because every power of $p$ is a divisor of $p^k$, e.g., $p^0, p^1, p^2, \ldots, p^k$.&lt;/li&gt;&#xA;&lt;li&gt;if $n$ is a product of two distinct primes, say $n = pq$, then $d(pq) = d(p) \cdot d(q)$; also, $d(p^iq^j) = d(p^i) \cdot d(q^j)$&lt;/li&gt;&#xA;&lt;li&gt;in general, let $n = p_1^{a_1} \cdot p_2^{a_2} \cdot \ldots \cdot p_n^{a_n}$, then $d(n) = d(p_1^{a_1}) \cdot d(p_2^{a_2}) \cdot \ldots \cdot d(p_n^{a_n})$ where $p_i$ is a prime factor that divides $n$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;example: $d(18)$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;d(18) &amp;= d(3^2 \cdot 2) \\&#xA;&amp;= d(3^2) \cdot (2) \\&#xA;&amp;= 3 \cdot 2 \\&#xA;&amp;= 6&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int number_of_divisors(int n) {&#xA;  int total = 1;&#xA;  for (int i = 2; i * i &amp;lt;= n; i &amp;#43;= 1) {&#xA;    int power = 0;&#xA;    while (n % i == 0) {&#xA;      power &amp;#43;= 1;&#xA;      n /= i;&#xA;    }&#xA;    total *= (power &amp;#43; 1);&#xA;  }&#xA;  if (n &amp;gt; 1){&#xA;    total *= 2;&#xA;  }&#xA;  return total;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;sum-of-divisors&#34;&gt;Sum of divisors&lt;/h2&gt;&#xA;&lt;p&gt;The sum of divisors is another important quantity represented by $\sigma_k(n)$. It&amp;rsquo;s the sum of the $k$-th powers of the divisors of $n$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sigma_k(n) = \sum_{d|n} d^k&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\sigma_0(18) &amp;= 1^0 + 2^0 + 3^0 + 6^0 + 9^0 + 18^0 \\&#xA;&amp;= 1 + 1 + 1 + 1 + 1 \\&#xA;&amp;= 6&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;So when $k = 0$, the sum of divisors ($\sigma_0{n}$) function is equal to $d(n)$; i.e., $\sigma_0(n)$ gives the number of divisors of $n$.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Another example:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\sigma_1(18) &amp;= 1^1 + 2^1 + 3^1 + 6^1 + 9^1 + 18^1 \\&#xA;&amp;= 1 + 2 + 3 + 6 + 9 + 18 \\&#xA;&amp;= 39&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;when $k = 1$, we actually get the function we expect (a function that sums the divisors).&lt;/p&gt;&#xA;&lt;h3 id=&#34;important-observations-1&#34;&gt;Important observations&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if $p$ is a prime number, then $\sigma(p) = 1 + p$ since the only divisors of a prime number are $1$ and $p$.&lt;/li&gt;&#xA;&lt;li&gt;if $p$ is a prime number, then $\sigma(p^k) = 1 + p + p^2 + \ldots + p^k$ because every power of $p$ is a divisor of $p^k$, e.g., $p^0, p^1, p^2, \ldots, p^k$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Consider&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{sigma-p-k}&#xA;\sigma(p^k) = 1 + p + p^2 + \ldots + p^k&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Multiplying the expression by $p$, we have&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{sigma-p-k-times-p}&#xA;p \cdot \sigma(p^k) = p + p^2 + p^3 + \ldots + p^{k + 1}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Subtracting \eqref{sigma-p-k} from \eqref{sigma-p-k-times-p}&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;p \cdot \sigma(p^k) - \sigma(p^k) = p^{k + 1} - 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Factoring $\sigma(p^k)$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sigma(p^k) (p - 1) = p^{k + 1} - 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;hence&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\sigma(p^k) = \frac{p^{k + 1} - 1}{p - 1}&#xA;$$&lt;/div&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;if $p$ is a product of two distinct primes, say $n = pq$, then $\sigma(pq) = \sigma(p) \cdot \sigma(q)$; also, $\sigma(p^iq^j) = \sigma(p^i) \cdot \sigma(q^j)$&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;in general, let $n = p_1^{a_1} \cdot p_2^{a_2} \cdot \ldots \cdot p_n^{a_n}$, then $\sigma(n) = \sigma(p_1^{a_1}) \cdot \sigma(p_2^{a_2}) \cdot \ldots \cdot \sigma(p_n^{a_n})$ where $p_i$ is a prime factor that divides $n$.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;example: $\sigma(18)$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\sigma(18) &amp;= \sigma(3^2 \cdot 2) \\&#xA;&amp;= \sigma(3^2) \cdot \sigma(2) \\&#xA;&amp;= \frac{3^3 - 1}{3 - 1} \cdot \frac{2^2 - 1}{2 - 1} \\&#xA;&amp;= 13 \cdot 3 \\&#xA;&amp;= 39&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int sum_of_divisors(int n) {&#xA;  int total = 1;&#xA;  for (int i = 2; i * i &amp;lt;= n; i &amp;#43;= 1) {&#xA;    if (n % i == 0) {&#xA;      int primePower = i;&#xA;      while (n % i == 0) {&#xA;        primePower *= i;&#xA;        n /= i;&#xA;      }&#xA;      // sigma(n^k) = (n^{k &amp;#43; 1} - 1) / (k - 1)&#xA;      total *= (primePower - 1) / (i  - 1);&#xA;    }&#xA;  }&#xA;  if (n &amp;gt; 1) {&#xA;    // if `n` is still a prime number after factorization&#xA;    // sigma(n) = 1 &amp;#43; n&#xA;    total *= (1 &amp;#43; n);&#xA;  }&#xA;  return total;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Primality Test</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/primality-test/</link>
      <pubDate>Thu, 11 Jun 2015 13:16:59 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/primality-test/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;A prime number is a natural number greater than $1$ which has no positive divisors other than $1$ and itself&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;naive-test&#34;&gt;Naive test&lt;/h2&gt;&#xA;&lt;p&gt;Let $n$ be the number we want to check for primality. If we find a natural number greater than $1$ that is a divisor of $n$, then $n$ is not prime.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if a number $n$ is divisible by $k$ then $k \leq \sqrt{n}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Complexity: $O(\sqrt{n})$&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;bool is_prime(int n) {&#xA;  if (n == 2) {&#xA;    // 2 is a prime number&#xA;    return true;&#xA;  }&#xA;  if (n == 1 || (n % 2 == 0)) {&#xA;    // 1 or any multiple of 2 is not a prime number&#xA;    return false;&#xA;  }&#xA;  for (int i = 3; i * i &amp;lt;= n; i += 2) {&#xA;    // check for any odd number &amp;lt; sqrt(n) if they are multiples of `n`&#xA;    if (n % i == 0) {&#xA;      return false;&#xA;    }&#xA;  }&#xA;  return true;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;eratosthenes-sieve&#34;&gt;Eratosthenes Sieve&lt;/h2&gt;&#xA;&lt;p&gt;If we have to make constant queries to check for numbers that are prime, less than some number $n$, we can preprocess them using the &#xA;&#xA;&lt;a href=&#34;../erathostenes-sieve/&#34;target=&#34;_blank&#34;&gt;Eratosthenes Sieve&lt;/a&gt;&#xA;&#xA; and answer each query in $O(1)$&lt;/p&gt;&#xA;&lt;h2 id=&#34;fermat-primality-test&#34;&gt;Fermat primality test&lt;/h2&gt;&#xA;&lt;h3 id=&#34;fermats-little-theorem&#34;&gt;Fermat&amp;rsquo;s little theorem&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If $a$ is an integer and $p$ is a prime number where $0 &amp;lt; a &amp;lt; p$, then&#xA;$$&#xA;a^p \equiv a \pmod{p}&#xA;$$&lt;/p&gt;&#xA;&lt;p&gt;or alternatively&lt;/p&gt;&#xA;&lt;p&gt;$$&#xA;a^{p-1} \equiv 1 \pmod{p}&#xA;$$&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Proofs of this theorem can be found &#xA;&#xA;&lt;a href=&#34;http://artofproblemsolving.com/wiki/index.php/Fermat%27s_Little_Theorem&#34;target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Some examples&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;3^{5 - 1} \equiv 81 \equiv 1 \pmod{5} \\&#xA;3^{11 - 1} \equiv 59049 \equiv 1 \pmod{11}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The converse of this theorem is &lt;strong&gt;not always&lt;/strong&gt; true&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If $$ a^{n - 1} \equiv 1 \pmod{n} $$ for some value of $0 &amp;lt; a &amp;lt; n$, then $n$ is prime&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;an example:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;5^{561 - 1} \equiv 1 \pmod{561} \text{ but $561 = 3 \cdot 11 \cdot 17$ }&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;but:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;3^{561 - 1} \equiv 375 \pmod{561}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;we can&amp;rsquo;t use the theorem directly to test if a number is prime, since there&amp;rsquo;s a chance that the input is one of these special numbers (called, &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Carmichael_number&#34;target=&#34;_blank&#34;&gt;Carmichael numbers&lt;/a&gt;&#xA;&#xA;) and the algorithm will give false positives; e.g., $a = 5, p = 561$&lt;/p&gt;&#xA;&lt;p&gt;What we can do is run the algorithm multiple times, increasing the probability of finding a number $a$ such that $a^{p - 1}&#xA;ot\equiv 1 \pmod{p}$, thus proving that $p$ is composite.&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// C&amp;#43;&amp;#43;11&#xA;#include &amp;lt;random&amp;gt;&#xA;&#xA;bool is_probably_prime(unsigned long long p, int iterations) {&#xA;  if (p == 2) {&#xA;    return true;&#xA;  }&#xA;  if (p % 2 == 0 || p == 1) {&#xA;    return false;&#xA;  }&#xA;&#xA;  std::random_device rd;&#xA;  std::mt19937 engine(rd());&#xA;  std::uniform_int_distribution&amp;lt;long long&amp;gt; dis(2, p - 2);&#xA;  while (iterations--) {&#xA;    // choose an integer between 2 and n-2&#xA;    long long a = dis(engine);&#xA;    if (binary_exponentiation_modulo_m(a, p - 1, p) != 1) {&#xA;      return false;&#xA;    }&#xA;  }&#xA;  return true;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;p&gt;No matter how many iterations we use in the algorithm above, there&amp;rsquo;s a chance that for each $a_1, a_2, \ldots, a_i$ Fermat&amp;rsquo;s little theorem holds true, even though the input is composite. Therefore, this test is not used in practice&lt;/p&gt;&#xA;&lt;h2 id=&#34;euler-primality-test&#34;&gt;Euler primality test&lt;/h2&gt;&#xA;&lt;p&gt;Euler Primality Test is an improvement over the Fermat Primality Test because it adds another equality condition that a prime number must fulfill. Assuming that $p$ is a prime number and $a$ is an integer, where $0 &amp;lt; a &amp;lt; p$, then&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;If $a$ is an integer and $p$ is a prime number where $0 &amp;lt; a &amp;lt; p$ and $p &amp;gt; 2$, then $ a^{&#x9;frac{p - 1}{2}}&#xA;equiv&#xA;\pm 1&#xA;\pmod{p} $&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The motivation for this definition comes from the fact that any prime $&amp;gt; 2$ is an odd number. Then the prime number can be expressed as $2q + 1$ where $q$ is an integer; thus,&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^{(2q + 1) - 1} \equiv 1 \pmod{p}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;which means that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^{2q} - 1 \equiv 0 \pmod{p}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;this can be factored as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;(a^q - 1)(a^q + 1) \equiv 0 \pmod{p}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;therefore $a^q$ is congruent to two possible values $1$ and $-1$. Going back to the definition of $q$ ($2q + 1 = p$), we can find the value of $q$ as $q = \tfrac{(p - 1)}{2}$&lt;/p&gt;&#xA;&lt;p&gt;Expressing Euler&amp;rsquo;s Primality Test formally:&lt;/p&gt;&#xA;&lt;p&gt;If $a^{(n - 1) / 2}&#xA;ot\equiv \pm 1 \pmod n$, where $gcd(a, n) = 1$, then $n$ must be a composite number for one of the following reasons:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if $a^{n - 1} \not\equiv 1 \pmod{n}$ then $n$ must be composite by Fermat&amp;rsquo;s Little Theorem&lt;/li&gt;&#xA;&lt;li&gt;if $a^{n - 1} \equiv 1 \pmod{n}$ then $n$ must be composite because $a^{(n - 1) / 2}$, which is a square root of $a^{n - 1} \pmod{n}$, must fulfill the following equivalence $a^{(n - 1) / 2} \equiv \pm 1 \pmod n$, which is a contradiction to the statement above&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This test also has some false positives e.g.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;3^{(341 - 1)/2} \equiv 1 \pmod{341} \text{ but $341 = 11 * 31$ }&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;miller-rabin-primality-test&#34;&gt;Miller-Rabin primality test&lt;/h2&gt;&#xA;&lt;p&gt;The Miller-Rabin Primality Test is quite similar to Euler&amp;rsquo;s Primality Test, but instead of looking at the square root of $a^{n - 1}$ it looks at the sequence of square roots/powers of two, derived from $a^{n - 1}$$&lt;/p&gt;&#xA;&lt;p&gt;Let $2^s$ be the largest power of $2$ that divides $n - 1$. Then $n - 1 = 2^s \cdot q$ for some &lt;strong&gt;odd&lt;/strong&gt; integer $q$. The sequence of powers of two that divide $n - 1$ is&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;2^0, 2^1, \ldots, 2^i \quad \text{where $0 \leq i \leq s$}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We know from Euler&amp;rsquo;s Primality Test that if $a^{n - 1} \equiv 1 \pmod{n}$ then $a^{(n - 1) / 2} \equiv \pm 1 \pmod{n}$. Let&amp;rsquo;s say that $a^{(n - 1) / 2} \equiv 1 \pmod{n}$; then, also because of Euler&amp;rsquo;s Primality Test, $a^{(n - 1) / 2^2} \equiv \pm 1 \pmod{n}$. What this says is that as long as we can take the square root of some $a^{(n - 1) / 2^i} \equiv 1 \pmod{n}$, the result must be $\pm 1$; otherwise, it&amp;rsquo;s a composite number by Euler&amp;rsquo;s Primality Test.&lt;/p&gt;&#xA;&lt;p&gt;The base case occurs when we cannot take the square root of some $a^{\tfrac{n - 1}{2^i}} \pmod{n}$, i.e., when $\tfrac{n - 1}{2^i}$ is no longer divisible by $2$, which is exactly the number $q$. For this base case, we&amp;rsquo;re sure of something: if $a^qar{\equiv} \pm 1 \pmod{n}$ then it means that it&amp;rsquo;s the square root of $a^{2q} \equiv 1 \pmod{n}$ (obviously, $2q \leq n - 1$ because $n - 1$ is even and must be divisible by at least $2$).&lt;/p&gt;&#xA;&lt;p&gt;If $a^q&#xA;ot\equiv \pm 1 \pmod{n}$, we have to analyze $a^2q \pmod{n}$ and there are three possible outcomes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;$a^2q \equiv 1 \pmod{n}$, which by Euler&amp;rsquo;s Primality Test implies that $a^q \equiv \pm 1 \pmod{n}$, which contradicts the statement above; therefore, $n$ is composite&lt;/li&gt;&#xA;&lt;li&gt;$a^2q \equiv -1 \pmod{n}$, which by Euler&amp;rsquo;s Primality Test implies that it&amp;rsquo;s the square root of some $a^{2^iq}$ (where $0 &amp;lt; i &amp;lt; s-1$), and which will eventually become $a^{n - 1} \equiv 1 \pmod{n}$ by successive squaring; therefore, we can say that $n$ is a probable prime&lt;/li&gt;&#xA;&lt;li&gt;$a^2q \not\equiv \pm 1 \pmod{n}$, which is the same as the statement above (therefore, we have to keep analyzing the next element in the sequence).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;// C&amp;#43;&amp;#43;11&#xA;#include &amp;lt;random&amp;gt;&#xA;&#xA;bool miller_rabin_primality_test(long long a, long long n) {&#xA;  int s = 0;&#xA;  long long q = n - 1;&#xA;  while (q % 2 == 0) {&#xA;    q /= 2;&#xA;    s &amp;#43;= 1;&#xA;  }&#xA;  long long m = binary_exponentiation_modulo_m(a, q, n);&#xA;  if (m == 1 || m == n - 1) {&#xA;    // base case a^q ≡ 1 (mod n)&#xA;    return true;&#xA;  }&#xA;  for (int i = 0; i &amp;lt; s; i &amp;#43;= 1) {&#xA;    // a^{2^iq} (mod n)&#xA;    m = (m * m) % n;&#xA;    if (m == n - 1) {&#xA;      return true;&#xA;    }&#xA;  }&#xA;  return false;&#xA;}&#xA;&#xA;bool is_probably_prime(long long p, int iterations) {&#xA;  // NOTE: test of the primes 2 and 3 because of&#xA;  // the distribution limits (p, p - 2)&#xA;  if (p == 2 || p == 3) {&#xA;    return true;&#xA;  }&#xA;  if (p % 2 == 0 || p == 1) {&#xA;    return false;&#xA;  }&#xA;  std::random_device rd;&#xA;  std::mt19937 engine(rd());&#xA;  std::uniform_int_distribution&amp;lt;long long&amp;gt; dis(2, p - 2);&#xA;  while (iterations--) {&#xA;    // choose an integer between 2 and n-2&#xA;    long long a = dis(engine);&#xA;    if (!miller_rabin_primality_test(a, p)) {&#xA;      return false;&#xA;    }&#xA;  }&#xA;  return true;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Prime factors of a factorial</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/prime-factors-factorial/</link>
      <pubDate>Tue, 09 Jun 2015 14:00:03 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/prime-factors-factorial/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;Given two numbers $n$ and $k$ find the greatest power of $k$ that divides $n!$&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Writing the factorial expression explicitly&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n! = 1 \cdot 2 \cdot 3 \ldots (n - 1) \cdot n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can see that every $k$-th member of the factorial is divisible by $k$; therefore, one answer is $\left \lfloor \tfrac{n}{k} \right \rfloor$. However, we can also see that every $k^2$-th term is also divisible by $k$ two times, and it gives one more term to the answer; that is, $\left \lfloor \tfrac{n}{k^2} \right \rfloor$, which means that every $k^i$-th term adds one factor to the answer; thus, the answer is&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\left \lfloor \frac{n}{k} \right \rfloor + \left \lfloor \frac{n}{k^2} \right \rfloor + \ldots + \left \lfloor \frac{n}{k^i} \right \rfloor + \ldots&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The sum is actually finite, and the maximum value of $i$ can be found using logarithms. Let $k^i &amp;gt; n$. Applying logarithms, we have $i \cdot log(k) &amp;gt; log(n)$, which is equal to $i &amp;gt; \tfrac{log(n)}{log(k)}$, which is the same as $i &amp;gt; log_k n$.&lt;/p&gt;&#xA;&lt;p&gt;The sum discovered by &#xA;&#xA;&lt;a href=&#34;http://www.wikiwand.com/en/Adrien-Marie_Legendre&#34;target=&#34;_blank&#34;&gt;Adrien-Marie Legendre&lt;/a&gt;&#xA;&#xA; is called &#xA;&#xA;&lt;a href=&#34;http://www.wikiwand.com/en/Legendre%27s_formula&#34;target=&#34;_blank&#34;&gt;Legendre&amp;rsquo;s Formula&lt;/a&gt;&#xA;&#xA;. Let $d_a(b)$ be the number of times $a$ divides $b$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;d_k(n!) = \sum_{i=1}^{log_k{n}} \left \lfloor \frac{n}{k^i} \right \rfloor&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes the maximum power of `k` that is a divisor of `n!`&#xA; *&#xA; * @param {int} n&#xA; * @param {int} k&#xA; * @return {int}&#xA; */&#xA;int max_power_in_factorial(int n, int k) {&#xA;  int ans = 0;&#xA;  while (n) {&#xA;    n /= k;&#xA;    ans &amp;#43;= n;&#xA;  }&#xA;  return ans;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Special factorial modulo p</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/special-factorial-modulo-m/</link>
      <pubDate>Tue, 09 Jun 2015 14:00:03 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/special-factorial-modulo-m/</guid>
      <description>&lt;p&gt;Let $n!_{\%p}$ be a special factorial where $n!$ is divided by the maximum exponent of $p$ that divides $n!$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n!_{\%p} = \frac{n!}{d_p(n!)}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Here, $d_p(n!)$ is called &#xA;&#xA;&lt;a href=&#34;http://www.wikiwand.com/en/Legendre%27s_formula&#34;target=&#34;_blank&#34;&gt;Legendre&amp;rsquo;s Formula&lt;/a&gt;&#xA;&#xA;, which is explained in detail in &#xA;&#xA;&lt;a href=&#34;../prime-factors-factorial&#34;target=&#34;_blank&#34;&gt;this article&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Compute $n!_{\%p} \pmod{p}$ given that $p$ is a prime number&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;First, let&amp;rsquo;s write this special factorial explicitly&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{explicit}&#xA;n!_{\%p} = \tfrac{1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot p \cdot (p + 1) \cdot \ldots \cdot (2p - 1) \cdot 2p \cdot (2p + 1) \cdot \ldots \cdot (kp - 1) \cdot kp \cdot (kp + 1) \cdot \ldots \cdot (n - 1) \cdot n}{p^{ \tfrac{n}{p} + \tfrac{n}{p^2} + ... }}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The number $kp$ is a number that is divisible by $p$. We also see that $k$ might be a composite number that may be divisible by $p$ again.&lt;/p&gt;&#xA;&lt;p&gt;Now, let&amp;rsquo;s first divide the equation by $p^{ \tfrac{n}{p} }$ which is exactly the number of multiples of $p$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n!_{\%p} = \tfrac{1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot 1 \cdot (p + 1) \cdot \ldots \cdot (2p - 1) \cdot 2 \cdot (2p + 1) \cdot \ldots \cdot (kp - 1) \cdot k \cdot (kp + 1) \cdot \ldots \cdot (n - 1) \cdot n}{p^{ \tfrac{n}{p^2} + ... }}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we apply the modulo operation to each term except the multiples of $p$ we have:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n!_{\%p} = \tfrac{1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot 1 \cdot 1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot 2 \cdot 1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot p \cdot 1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot kp}{p^{ \tfrac{n}{p^2} + ... }} \cdot 1 \cdot 2 \cdot \ldots \cdot (n - 1) \cdot n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; we&amp;rsquo;re not applying the modulo operator to each multiple of $p$ because they don&amp;rsquo;t actually exist, since there are no $p$ factors in the equation; they are reduced with posterior divisions by $p^{\frac{n}{p^i} }$&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; the number $kp$ described in \eqref{explicit} just denotes a multiple of $p$&lt;/p&gt;&#xA;&lt;p&gt;We see that the expression $1 \cdot 2 \cdot \ldots \cdot (p - 1)$ is repeated many times in the equation above, plus a product of some additional terms which don&amp;rsquo;t form an entire sequence. Let $c = 1 \cdot 2 \cdot \ldots \cdot (p - 1)$, then&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n!_{\%p} = \tfrac{1c \cdot 2c \cdot \ldots \cdot (p - 1)c \cdot pc \cdot (p + 1)c \cdot \ldots \cdot (kp - 1)c \cdot kpc}{p^{ \tfrac{n}{p^2} + ... }} \cdot 1 \cdot 2 \cdot \ldots \cdot (n - 1) \cdot n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since each $c$ factor occurs in every contiguous sequence of length $p$, there are exactly $\left \lfloor \tfrac{n}{p} \right \rfloor$ $c$ factors. Factoring $c$, we have&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n!_{\%p} = c^{\left \lfloor \tfrac{n}{p} \right \rfloor} \cdot \tfrac{1 \cdot 2 \cdot \ldots \cdot (p - 1) \cdot p \cdot (p + 1) \cdot \ldots \cdot (2p - 1) \cdot 2p \cdot (2p + 1) \cdot \ldots \cdot (kp - 1) \cdot kp}{p^{ \tfrac{n}{p^2} + ... }} \cdot 1 \cdot 2 \cdot \ldots \cdot (n - 1) \cdot n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Note that the term multiplying $c^{\left \lfloor \tfrac{n}{p} \right \rfloor}$ is the same as \eqref{explicit}, we now have to divide it by $p^{ \tfrac{n}{p^2} }$ which is exactly the number of multiples of $p^2$ (NOTE: $kp$ is a multiple of $p$ but might/might not be a multiple of $p^2$)&lt;/p&gt;&#xA;&lt;p&gt;This observation leads to a recursive implementation&lt;/p&gt;&#xA;&lt;p&gt;Complexity: $O(p , log_p{n})$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;long long special_factorial_mod_p(long long n, long long p) {&#xA;  long long res = 1;&#xA;&#xA;  // computation of c&#xA;  long long c = p-1;&#xA;&#xA;  while (n &amp;gt; 1) {&#xA;    res = (res * binary_exponentiation_modulo_m(c, n / p, p)) % p;&#xA;    for (long long i = 2; i &amp;lt;= n % p; i &amp;#43;= 1) {&#xA;      res = (res * (long long)i) % p;&#xA;    }&#xA;    n /= p;&#xA;  }&#xA;  return res % p;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;applications&#34;&gt;Applications&lt;/h2&gt;&#xA;&lt;h3 id=&#34;finding-the-value-of-ncr--p&#34;&gt;Finding the value of $nCr % p$&lt;/h3&gt;&#xA;&lt;p&gt;We can quickly calculate the value of $nCr % p$, we can compute the maximum exponents of $p$ in $n!$, $(n - r)!$ and $r!$, let those numbers be $p^a$, $p^b$ and $p^c$ then $nCr$ can be expressed as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;nCr = \binom{p^a \cdot \ldots}{p^b \cdot p^c \ldots}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which means that $nCr$ will be a multiple of $p$ when $a - b - c &amp;gt; 0$, if $a - b - c = 0$ then the number is equal to&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;nCr = \frac{n!_{\%p}}{(n - r)!_{\%p} \cdot r!_{\%p}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;NOTE: $a - b - c$ can never be less than zero, that would imply that $nCr$ is not an integer&lt;/p&gt;&#xA;&lt;p&gt;The denominator can be found using the modular multiplicative inverse of $(n - r)!_{\%p}$ and $r!_{\%p}$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;long long nCr_mod_p(int n, int r, int p) {&#xA;  int a = max_power_in_factorial(n, p);&#xA;  int b = max_power_in_factorial(n - r, p);&#xA;  int c = max_power_in_factorial(r, p);&#xA;  if (a &amp;gt; b &amp;#43; c) {&#xA;    return 0;&#xA;  }&#xA;&#xA;  return (special_factorial_mod_p(n, p) *&#xA;    ((modular_multiplicative_inverse(special_factorial_mod_p(n - r, p), p) *&#xA;    modular_multiplicative_inverse(special_factorial_mod_p(r, p), p)) % p) % p);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;problems-to-solve&#34;&gt;Problems to solve&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&#xA;&lt;a href=&#34;http://www.codechef.com/problems/CB01/&#34;target=&#34;_blank&#34;&gt;Codechef - CB01&lt;/a&gt;&#xA;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Discrete Logarithm</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/discrete-logarithm/</link>
      <pubDate>Mon, 08 Jun 2015 12:11:38 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/discrete-logarithm/</guid>
      <description>&lt;p&gt;Let $a$, $b$, and $x$ be positive real numbers such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^x = b&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We want to find the value of $x$. Applying logarithms&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x \cdot log(a) = log(b)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x = \frac{log(b)}{log(a)}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The &lt;strong&gt;discrete logarithm&lt;/strong&gt; problem is an analogue of this problem, with the condition that all the numbers exist in the ring of integers modulo $n$&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Let $a$, $b$ and $n$ be &lt;strong&gt;integers&lt;/strong&gt;, where $a$ and $n$ are coprime, find the value of $x$ in&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div&gt;$$&#xA;a^x \equiv b \pmod{n}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;trial-multiplication&#34;&gt;Trial multiplication&lt;/h2&gt;&#xA;&lt;p&gt;The brute force algorithm consists of computing all possible $a^i \pmod{n}$, where $0 \leq i &amp;lt; n$ until one matches $b$.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Given $n = 11$, $a = 2$, $b = 9$, find the value of $x$ in $a^x \equiv b \pmod{n}$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;a^0 &amp;\equiv 1 \pmod{11} \\&#xA;a^1 &amp;\equiv 2 \pmod{11} \\&#xA;a^2 &amp;\equiv 4 \pmod{11} \\&#xA;a^3 &amp;\equiv 8 \pmod{11} \\&#xA;a^4 &amp;\equiv 16 \equiv 5 \pmod{11} \\&#xA;a^5 &amp;\equiv 32 \equiv 10 \pmod{11} \\&#xA;a^6 &amp;\equiv 64 \equiv 9 \pmod{11}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$x = 6$ is a solution to the problem.&lt;/p&gt;&#xA;&lt;h2 id=&#34;baby-step-giant-step&#34;&gt;Baby Step Giant Step&lt;/h2&gt;&#xA;&lt;p&gt;The idea of Shank&amp;rsquo;s Baby Step Giant Step algorithm is based on rewriting $x$ in the congruence above as $x = im + j$ where $m = \sqrt{n}$, $0 \leq i &amp;lt; m$ and $0 \leq j &amp;lt; m$, so&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^{im + j} \equiv b \pmod{n}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Multiplying both sides by $a^{-im}$ (note that this is possible because $a$ and $n$ are coprime)&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^j \equiv b(a^{-m})^i \pmod{n}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we find $i$ and $j$ so that this holds, then we have found an exponent $x$&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; $a^{-m}$ can be computed using the modular multiplicative inverse of $a$ and then computing the $m$-th power of the inverse $\pmod{n}$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Let `a`, `b` and `n` be **integers**, where `a` and `n` are coprime,&#xA; * the following is an implementation of Shank&amp;#39;s baby step giant step&#xA; * algorithm which attempts to find a solution for the congruence&#xA; *&#xA; *    a^x ≡ b (mod n)&#xA; *&#xA; * `x` can be represented as `im &amp;#43; j` then&#xA; *&#xA; *   a^j ≡ b(a^{-m})^i (mod n)&#xA; *&#xA; * NOTE: `binary_exponentiation_modulo_m` is a function which computes&#xA; *&#xA; *    a^x (mod n)&#xA; *&#xA; * @param {int} a&#xA; * @param {int} b&#xA; * @param {int} n&#xA; * @returns {int} An integer &amp;gt;= 0 which is the value of `x`, -1&#xA; * if no value was found&#xA; */&#xA;int baby_step_giant_step(int a, int b, int n) {&#xA;  int m = ceil(sqrt(n));&#xA;&#xA;  // values in the left side&#xA;  map&amp;lt;int, int&amp;gt; M;&#xA;&#xA;  // store all possible a^j&#xA;  int aj = 1;&#xA;  for (int j = 0; j &amp;lt; m; j &amp;#43;= 1) {&#xA;    if (!M.count(aj)) {&#xA;      M[aj] = j;&#xA;    }&#xA;    aj = (aj * a) % n;&#xA;  }&#xA;&#xA;  // compute b(a^{-m})^i&#xA;  // first compute the modular multiplicative inverse of a&#xA;  int inverse;&#xA;  if (!modular_multiplicative_inverse(a, n, inverse)) {&#xA;    return -1;&#xA;  }&#xA;  int coef = binary_exponentiation_modulo_m(inverse, m, n);&#xA;&#xA;  // NOTE: the modular multiplicative inverse can also be computed&#xA;  // using Euler&amp;#39;s theorem only if `n` is prime&#xA;  // - first compute a^-1 with the identity a^-1 ≡ a^{n - 2} (mod n)&#xA;  // - compute inverse^m % n&#xA;  //&#xA;  // int coef = binary_exponentiation_modulo_m(a, n - 2, n);&#xA;  // coef = binary_exponentiation_modulo_m(coef, m, n);&#xA;&#xA;  int gamma = b;&#xA;  for (int i = 0; i &amp;lt; m; i &amp;#43;= 1) {&#xA;    if (M.count(gamma)) {&#xA;      return i * m &amp;#43; M[gamma];&#xA;    }&#xA;    gamma = (gamma * coef) % n;&#xA;  }&#xA;  return -1;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Chinese Remainder Theorem</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/chinese-remainder-theorem/</link>
      <pubDate>Fri, 05 Jun 2015 12:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/chinese-remainder-theorem/</guid>
      <description>&lt;p&gt;Let $p_1, p_2, \ldots, p_n$ be distinct numbers relatively prime. For any integers $a_1, a_2, \ldots, a_n$ there is an integer $x$ such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x &amp;\equiv a_1 \pmod{p_1} \\&#xA;x &amp;\equiv a_2 \pmod{p_2} \\&#xA; &amp; \; \vdots \\&#xA;x &amp;\equiv a_n \pmod{p_n} \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;All solutions of this system are congruent modulo $p_1p_2 \ldots p_n$&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;http://nrich.maths.org/5466&#34;target=&#34;_blank&#34;&gt;nrich&amp;rsquo;s article on the Chinese Remainder&lt;/a&gt;&#xA;&#xA; illustrates the system of equations with a coordinate system in $n$-dimensions. Basically, a number can represent a point in the coordinate system defined by the equation system, and the point itself is a sum of unit vectors scaled by some amount&lt;/p&gt;&#xA;&lt;p&gt;Example: To represent the number $17$ in the coordinate system defined by the integers that belong to the set $\mathbb{Z}/5$, $\mathbb{Z}/7$ and $\mathbb{Z}/11$ ($\mathbb{Z}/n$ has $n$ elements which are all the numbers in the range $0, 1, \ldots, n - 1$)&lt;/p&gt;&#xA;&lt;p&gt;The statement above is equivalent to&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;17 &amp;\equiv x \equiv 2 \pmod{5} \\&#xA;17 &amp;\equiv x \equiv 3 \pmod{7} \\&#xA;17 &amp;\equiv x \equiv 6 \pmod{11}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can see that $17$ is represented by the point $(2, 3, 6)$&lt;/p&gt;&#xA;&lt;p&gt;What we want to do is the opposite; that is, find the number whose representation in the coordinate system defined by the integers that belong to the set $\mathbb{Z}/p_1, \mathbb{Z}/p_2, \ldots, \mathbb{Z}/p_n$ results in the point $(a_1, a_2 \ldots, a_n)$&lt;/p&gt;&#xA;&lt;p&gt;What we can do is express these conditions as a sum of scaled unit vectors that belong to each axis of the coordinate systems. This means that a point $(a_1, a_2 \ldots, a_n)$ can be represented as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a_1(1, 0, 0, \ldots, 0) + a_2(0, 1, 0, 0, \ldots, 0) + \ldots + a_n(0, 0, \ldots, 0, 1) = (a_1, a_2, \ldots, a_n)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we represent each point as $x_i$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{chinese-remainder-as-points}&#xA;a_1x_1 + a_2x_2 + \ldots + a_nx_n = (a_1, a_2, \ldots, a_n)&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s take the first term of the sum. $x_1$ is a number which must fulfill the following equivalences for each axis of the coordinate system&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x_1 &amp;\equiv 1 \pmod{p_1} \\&#xA;x_1 &amp;\equiv 0 \pmod{p_2} \\&#xA; &amp; \vdots \\&#xA;x_1 &amp;\equiv 0 \pmod{p_n} \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;From the system of equations above, we can see that $x_1 \mid p_2p_3 \ldots p_n$ which means that $x_1$ is some multiple of the multiplication; i.e., $x_1&amp;rsquo; = p_2p_3 \ldots p_n \cdot x_1$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;p_2p_3 \ldots p_n \cdot x_1 \equiv 1 \pmod{p_1}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Given the fact that $p_2p_3 \ldots p_n$ is relatively prime to $p_1$, the product has a modular multiplicative inverse which can be found using the extended euclidean algorithm. In fact we have to solve $n$ of this equations, each having the form&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{p_1p_2 \ldots p_n}{p_i} \cdot x_i \equiv 1 \pmod{p_i}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Finally we have to plug these values into the equation \eqref{chinese-remainder-as-points}&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes the value of `x` for the linear congruent system of equations&#xA; *&#xA; *    x ≡ a_1 (mod p_1)&#xA; *    x ≡ a_2 (mod p_2)&#xA; *      |&#xA; *    x ≡ a_n (mod p_n)&#xA; *&#xA; * All the solutions are given by the expression `x &amp;#43; k · p_1p_2...p_n`&#xA; * where `k` is an integer&#xA; *&#xA; * @param {vector&amp;lt;int&amp;gt;} a&#xA; * @param {vector&amp;lt;int&amp;gt;} p&#xA; * @return {int} A solution for the system if it exists&#xA; */&#xA;int chinese_remainder(vector&amp;lt;int&amp;gt; &amp;amp;a, vector&amp;lt;int&amp;gt; &amp;amp;p) {&#xA;  int x = 0;&#xA;  int product = 1;&#xA;  for (int i = 0; i &amp;lt; p.size(); i &amp;#43;= 1) {&#xA;    product *= p[i];&#xA;  }&#xA;  for (int i = 0; i &amp;lt; a.size(); i &amp;#43;= 1) {&#xA;    int k = product / p[i];&#xA;    x &amp;#43;= a[i] * modular_multiplicative_inverse(k, p[i]) * k;&#xA;    x %= product;&#xA;  }&#xA;  return x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Modular Arithmetic</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/modular-arithmetic/</link>
      <pubDate>Thu, 04 Jun 2015 16:29:18 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/modular-arithmetic/</guid>
      <description>&lt;h2 id=&#34;congruence-relation&#34;&gt;Congruence relation&lt;/h2&gt;&#xA;&lt;p&gt;For a positive integer $n$, two integers $a$ and $b$ are said to be &lt;strong&gt;congruent modulo&lt;/strong&gt; $n$ if the remainders of $a / n$ and $b / n$ are the same. This is written as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{congruent-modulo}&#xA;a \equiv b \pmod n&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;It can also be proven that $n \mid a - b$. Let $a = xn + s$ and $b = yn + t$ where $x, y, s, t$ are integers. If the remainders of $a/n$ and $b/n$ are the same, then $t = s$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;s &amp;= a - xn \\&#xA;s &amp;= b - yn&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Which means that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a - xn = b - yn&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Reordering the equation&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{congruent-relation-proof}&#xA;a - b = n(x - y)&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since $x$ and $y$ are integers, then $x - y$ is also an integer, which means that $a - b$ is a multiple of $n$; thus $n \mid a - b$&lt;/p&gt;&#xA;&lt;h3 id=&#34;properties&#34;&gt;Properties&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Reflexive: $a \equiv a \pmod n$ since $a - a = 0$ is a multiple of any integer $n$&lt;/li&gt;&#xA;&lt;li&gt;Symmetric: $a \equiv b \pmod n \Rightarrow b \equiv a \pmod n$ (the same as multiplying \eqref{congruent-relation-proof} by $-1$)&lt;/li&gt;&#xA;&lt;li&gt;Transitive: if $a \equiv b \pmod n$ and $b \equiv c \pmod n$ then $a \equiv c \pmod n$&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;rules&#34;&gt;Rules&lt;/h3&gt;&#xA;&lt;p&gt;Let $a, b, c, d$ are integers and $n$ is a positive integer such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;a &amp;\equiv b \pmod n \\&#xA;c &amp;\equiv d \pmod n&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The following rules apply&lt;/p&gt;&#xA;&lt;h4 id=&#34;additionsubtraction-rule&#34;&gt;Addition/subtraction rule&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;a \pm c \equiv b \pm d \pmod n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof:&lt;/strong&gt; let $a - c = nk$ and $b - d = nl$. Adding both equations $(a + b) - (c + d) = n(k + l)$, which is the same as $a + b \equiv c + d \pmod n$&lt;/p&gt;&#xA;&lt;h4 id=&#34;multiplication-rule&#34;&gt;Multiplication rule&lt;/h4&gt;&#xA;&lt;div&gt;$$&#xA;ac \equiv bd \pmod n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof:&lt;/strong&gt; let&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a = nk + b \\&#xA;c = nl + d&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;multiplying both equations&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;ac &amp;= (nk + b)(nl + d) \\&#xA;ac &amp;= n^2kl + nk \cdot d + nl \cdot b + bd \\&#xA;ac - bd &amp;= n(nkl + kd + bl) \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;exponentiation-rule&#34;&gt;Exponentiation rule&lt;/h4&gt;&#xA;&lt;p&gt;Since $a^k$ is just repeated multiplication then&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^k \equiv b^k \pmod n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;where $k$ is a positive integer.&lt;/p&gt;&#xA;&lt;p&gt;Implementation based on &#xA;&#xA;&lt;a href=&#34;../binary-exponentiation/&#34;target=&#34;_blank&#34;&gt;Binary Exponentiation&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; *&#xA; * Computes&#xA; *&#xA; *    a^k % m&#xA; *&#xA; * Given the fact that a^k can be computed in O(log k) using&#xA; * binary exponentiation&#xA; *&#xA; * @param {int} a&#xA; * @param {int} k&#xA; * @param {int} m&#xA; * @return {int}&#xA; */&#xA;int binary_exponentiation_modulo_m(int a, int k, int m) {&#xA;  if (k == 0) {&#xA;    // a^0 = 1&#xA;    return 1;&#xA;  }&#xA;&#xA;  if (k % 2 == 1) {&#xA;    return (binary_exponentiation_modulo_m(a, k - 1, m) * a) % m;&#xA;  } else {&#xA;    int t = binary_exponentiation_modulo_m(a, k / 2, m);&#xA;    return (t * t) % m;&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;modular-multiplicative-inverse&#34;&gt;Modular multiplicative inverse&lt;/h3&gt;&#xA;&lt;h4 id=&#34;extended-euclidean-algorithm&#34;&gt;Extended Euclidean Algorithm&lt;/h4&gt;&#xA;&lt;p&gt;The multiplicative inverse of a number $a$ is a number which multiplied by $a$ yields the multiplicative identity. For modular arithmetic, the modular multiplicative inverse is also defined. The modular multiplicative inverse of a number $a$ modulo $m$ is an integer $x$ such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{modular-multiplicative-inverse}&#xA;a \; x \equiv 1 \pmod m&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Such a number exists only if &lt;em&gt;$a$ and $m$ are coprime&lt;/em&gt; (e.g., $gcd(a, m) = 1$)&lt;/p&gt;&#xA;&lt;p&gt;The number $x$ can be found using the &#xA;&#xA;&lt;a href=&#34;../extended-euclidean-algorithm/&#34;target=&#34;_blank&#34;&gt;Extended Euclidean Algorithm&lt;/a&gt;&#xA;&#xA;, by the definition of the congruence relation $m \mid ax - 1$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax - 1 = mq&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Rearranging&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax - mq = 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This is the exact form of the equation that the Extended Euclidean Algorithm solves, where $gcd(a, m) = 1$ is already predetermined, instead of discovered using the algorithm&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes the modular mutiplicative inverse of the number `a` in the ring&#xA; * of integers modulo `m`&#xA; *&#xA; *    ax ≡ 1 (mod m)&#xA; *&#xA; * `x` only exists if `a` and `m` are coprimes&#xA; *&#xA; * @param {int} a&#xA; * @param {int} m&#xA; * @param {int} x&#xA; * @returns {bool} True if the number `a` has a modular multiplicative&#xA; * inverse, false otherwise&#xA; */&#xA;bool modular_multiplicative_inverse(int a, int m, int &amp;amp;x) {&#xA;  // the value multiplying `y` is never used&#xA;  int y;&#xA;  int gcd = extended_euclidean(a, m, x, y);&#xA;  if (gcd != 1) {&#xA;    // `a` and `m` are not coprime&#xA;    return false;&#xA;  }&#xA;  // ensure that the value of `x` is positive&#xA;  x = (x % m &amp;#43; m) % m;&#xA;  return true;&#xA;}&#xA;&#xA;/**&#xA; * Same as above but throws an error if the `a` and `m` are not coprimes&#xA; *&#xA; * @param {int} a&#xA; * @param {int} m&#xA; * @returns {int} The modular multiplicative inverse of a&#xA; */&#xA;int modular_multiplicative_inverse(int a, int m) {&#xA;  // the value multiplying `y` is never used&#xA;  int x, y;&#xA;  int gcd = extended_euclidean(a, m, x, y);&#xA;  if (gcd != 1) {&#xA;    // `a` and `m` are not coprime&#xA;    throw std::invalid_argument(&amp;#34;a and m are not relative primes&amp;#34;);&#xA;  }&#xA;  // ensure that the value of `x` is positive&#xA;  x = (x % m &amp;#43; m) % m;&#xA;  return x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;eulers-theorem&#34;&gt;Euler&amp;rsquo;s Theorem&lt;/h3&gt;&#xA;&lt;p&gt;The modular multiplicative inverse can be also found using Euler&amp;rsquo;s Theorem. If $a$ is relatively prime to $n$, then&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^{\phi(m)} \equiv 1 \pmod m&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\phi(n)$ is &#xA;&#xA;&lt;a href=&#34;../eulers-phi/&#34;target=&#34;_blank&#34;&gt;Euler&amp;rsquo;s Phi Function&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;In the special case where $m$ is a prime number&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^{-1} \equiv a^{m - 2} \pmod m&#xA;$$&lt;/div&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes the modular multiplicative inverse of `a` in the ring&#xA; * of integers modulo `m` using Euler&amp;#39;s theorem,&#xA; * it assumes that `m` is a prime number and that is relatively prime to `a`&#xA; *&#xA; *    a^{-1} ≡ a^{m - 2} (mod m)&#xA; *&#xA; * @param {int} a&#xA; * @param {int} m&#xA; * @returns {int} The modular multiplicative inverse of a&#xA; */&#xA;int modular_multiplicative_inverse(int a, int m) {&#xA;  return binary_exponentiation_modulo_m(a, m - 2, m);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Extended Euclidean Algorithm</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/extended-euclidean-algorithm/</link>
      <pubDate>Tue, 02 Jun 2015 12:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/extended-euclidean-algorithm/</guid>
      <description>&lt;h2 id=&#34;bezouts-identity&#34;&gt;Bezout&amp;rsquo;s identity&lt;/h2&gt;&#xA;&lt;p&gt;For &lt;strong&gt;non-zero integers&lt;/strong&gt; $a$ and $b$, let $d$ be the greatest common divisor $d = gcd(a, b)$. Then there exist integers $x$ and $y$ such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{bezout}&#xA;ax + by = d&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If $a$ and $b$ are relatively prime, then $gcd(a, b) = 1$ and by Bezout&amp;rsquo;s Identity, there are integers $x$ and $y$ such that&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax + by = 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; $3x + 8y = 1$, one solution is $x = 3$ and $y = -1$.&lt;/p&gt;&#xA;&lt;h2 id=&#34;extended-euclidean-algorithm&#34;&gt;Extended Euclidean Algorithm&lt;/h2&gt;&#xA;&lt;p&gt;See &#xA;&#xA;&lt;a href=&#34;../divisibility/&#34;target=&#34;_blank&#34;&gt;divisibility&lt;/a&gt;&#xA;&#xA; for more details.&lt;/p&gt;&#xA;&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes the values `x` and `y` for the equation&#xA; *&#xA; *    ax &amp;#43; by = gcd(a, b)&#xA; *&#xA; * Given that `a` and `b` are positive integers&#xA; *&#xA; * @param {int} a&#xA; * @param {int} b&#xA; * @param {int} x&#xA; * @param {int} y&#xA; * @returns {int} gcd(a, b)&#xA; */&#xA;int extended_euclidean(int a, int b, int &amp;amp;x, int &amp;amp;y) {&#xA;  if (b == 0) {&#xA;    x = 1;&#xA;    y = 0;&#xA;    return a;&#xA;  }&#xA;  int x1, y1;&#xA;  int gcd = extended_euclidean(b, a % b, x1, y1);&#xA;  x = y1;&#xA;  y = x1 - a / b * y1;&#xA;  return gcd;&#xA;}&#xA;&#xA;/**&#xA; * Alternative version using a vector of ints&#xA; * Computes the values x and y for the equation&#xA; *&#xA; *    ax &amp;#43; by = gcd(a, b)&#xA; *&#xA; * @returns {vector&amp;lt;int&amp;gt;} A triplet with the values (gcd(a, b), x, y)&#xA; */&#xA;vector&amp;lt;int&amp;gt; extended_euclidean(int a, int b) {&#xA;  if (b == 0) {&#xA;    // base case:&#xA;    // b divides a so a(1) &amp;#43; b(0) = a&#xA;    return vector&amp;lt;int&amp;gt; {a, 1, 0};&#xA;  }&#xA;  vector&amp;lt;int&amp;gt; t = extended_euclidean(b, a % b);&#xA;  int gcd = t[0];&#xA;  int x1 = t[1];&#xA;  int y1 = t[2];&#xA;  return vector&amp;lt;int&amp;gt; {gcd, y1, x1 - a / b * y1};&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 id=&#34;applications&#34;&gt;Applications&lt;/h2&gt;&#xA;&lt;h3 id=&#34;diophantine-equations&#34;&gt;Diophantine equations&lt;/h3&gt;&#xA;&lt;p&gt;Equations with integer variables and coefficients are called &lt;em&gt;Diophantine equations&lt;/em&gt;. The simplest non-trivial linear equation has the form&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{linear-diophantine-equation}&#xA;ax + by = c&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $a, b, c$ are given integers and $x, y$ are unknown integers&lt;/p&gt;&#xA;&lt;p&gt;Using the &lt;em&gt;Extended Euclidean Algorithm&lt;/em&gt; it&amp;rsquo;s possible to find $x$ and $y$ given that $c$ is divisible by $gcd(a, b)$. Otherwise the equation has no solutions. This follows the fact that a linear combination of two numbers continues to be divided by their common divisor. Starting with \eqref{bezout}&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax_g + by_g = gcd(a, b)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Multiplying it by $\tfrac{c}{gcd(a, b)}$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{diophantine-equation-gcd}&#xA;a \cdot x_g \cdot \Big( \frac{c}{gcd(a, b)} \Big) + b \cdot y_g \cdot \Big( \frac{c}{gcd(a, b)} \Big) = c&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;then one of the solutions is given by&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax_0 + by_0 = c&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;where&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{cases}&#xA;x_0 = x_g \cdot \big( \frac{c}{gcd(a, b)} \big) \\&#xA;y_0 = y_g \cdot \big( \frac{c}{gcd(a, b)} \big)&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;we can find all of the solutions by replacing $x_0$ by $x_0 + \tfrac{b}{gcd(a, b)}$ and $y_0$ by $y_0 - \tfrac{a}{gcd(a, b)}$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a \cdot \Big( x_0 + \tfrac{b}{gcd(a, b)} \Big) + b \cdot \Big( y_0 - \tfrac{a}{gcd(a, b)} \Big) = ax_0 + \tfrac{ab}{gcd(a, b)} + by_0 - \tfrac{ab}{gcd(a, b)} = ax_0 + by_0 = c&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This process can be repeated for any number in the form&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{cases}&#xA;x = x_0 + k \cdot \big( \frac{b}{gcd(a, b)} \big) \\&#xA;y = y_0 - k \cdot \big( \frac{a}{gcd(a, b)} \big)&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $k \in \mathbb{Z}$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes the integer values `x` and `y` for the equation&#xA; *&#xA; *    ax &amp;#43; by = c&#xA; *&#xA; * if `c` is not divisible by `gcd(a, b)` then there isn&amp;#39;t a valid solution,&#xA; * otherwise there&amp;#39;s an infinite number of solutions, (`x`, `y`) form one pair&#xA; * of the set of possible solutions&#xA; *&#xA; * @param {int} a&#xA; * @param {int} b&#xA; * @param {int} c&#xA; * @param {int} x&#xA; * @param {int} y&#xA; * @returns {bool} True if the equation has solutions, false otherwise&#xA; */&#xA;bool linear_diophantine_solution(int a, int b, int c, int &amp;amp;x, int &amp;amp;y) {&#xA;  int gcd = extended_euclidean(abs(a), abs(b), x, y);&#xA;  if (c % gcd != 0) {&#xA;    // no solutions since c is not divisible by gcd(a, b)&#xA;    return false;&#xA;  }&#xA;  x *= c / gcd;&#xA;  y *= c / gcd;&#xA;  if (a &amp;lt; 0) { x *= -1; }&#xA;  if (b &amp;lt; 0) { y *= -1; }&#xA;  return true;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;modular-multiplicative-inverse&#34;&gt;Modular multiplicative inverse&lt;/h3&gt;&#xA;&lt;p&gt;See &#xA;&#xA;&lt;a href=&#34;../modular-arithmetic/&#34;target=&#34;_blank&#34;&gt;Modular Arithmetic&lt;/a&gt;&#xA;&#xA; for more info.&lt;/p&gt;&#xA;&lt;h3 id=&#34;linear-congruence-equations&#34;&gt;Linear congruence equations&lt;/h3&gt;&#xA;&lt;p&gt;A linear congruence is a congruence $\pmod p$ of the form&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax \equiv b \pmod m&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;By the definition of the congruence relation $m \mid ax - b$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax - b = my&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Reordering the equation&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;ax - my = b&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This is a linear Diophantine equation discussed above. It&amp;rsquo;s solvable only if $b$ is divisible by $gcd(a, m)$. Additionally, $gcd(a, m)$ tells us the number of distinct solutions in the ring of integers modulo $m$&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;https://brilliant.org/wiki/bezouts-identity/?subtopic=integers&amp;amp;chapter=greatest-common-divisor-lowest-common-divisor#proof&#34;target=&#34;_blank&#34;&gt;https://brilliant.org/wiki/bezouts-identity/?subtopic=integers&amp;chapter=greatest-common-divisor-lowest-common-divisor#proof&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;http://www.ugrad.cs.ubc.ca/~cs490/Spring05/notes/nt1.pdf&#34;target=&#34;_blank&#34;&gt;http://www.ugrad.cs.ubc.ca/~cs490/Spring05/notes/nt1.pdf&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Binary Exponentiation</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/binary-exponentiation/</link>
      <pubDate>Mon, 01 Jun 2015 12:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/binary-exponentiation/</guid>
      <description>&lt;h3 id=&#34;algorithm-description&#34;&gt;Algorithm description&lt;/h3&gt;&#xA;&lt;p&gt;Finding $a^n$ involves performing $n$ multiplications of $a$. The same operation can be done in $O(log(n))$ multiplications&lt;/p&gt;&#xA;&lt;p&gt;For any number $a$ raised to an &lt;strong&gt;even&lt;/strong&gt; power:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^n = (a^{n/2})^2 = a^{n/2} \cdot a^{n/2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For any number $a$ raised to an &lt;strong&gt;odd&lt;/strong&gt; power:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a^n = a^{n - 1} \cdot a&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;&#xA;&lt;p&gt;Time complexity: $O(log(n))$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;/**&#xA; * Computes&#xA; *&#xA; *    a^k&#xA; *&#xA; * Given the following facts:&#xA; *&#xA; * - if `k` is even then a^(2k) = (a^k)^2&#xA; * - if `k` is odd then a^(2k &amp;#43; 1) = (a^k)^2 * a&#xA; */&#xA;int logarithmic_exponentiation(int a, int k) {&#xA;  if (k == 0) {&#xA;    // a^0 = 1&#xA;    return 1;&#xA;  }&#xA;  if (k % 2 == 1) {&#xA;    return binary_exponentiation(a, k - 1) * a;&#xA;  } else {&#xA;    int t = binary_exponentiation(a, k / 2);&#xA;    return t * t;&#xA;  }&#xA;}&#xA;&#xA;// iterative implementation&#xA;int binary_exponentiation(int a, int k) {&#xA;  int x = 1;&#xA;  while (k) {&#xA;    // analyze the i-th bit of the binary representation of k&#xA;    if (k &amp;amp; 1) {&#xA;      x *= a;&#xA;    }&#xA;    a *= a;&#xA;    k &amp;gt;&amp;gt;= 1;&#xA;  }&#xA;  return x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Eratosthenes Sieve</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/erathostenes-sieve/</link>
      <pubDate>Mon, 01 Jun 2015 12:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/erathostenes-sieve/</guid>
      <description>&lt;h3 id=&#34;definition&#34;&gt;Definition&lt;/h3&gt;&#xA;&lt;p&gt;This algorithm finds prime numbers up to a number $n$.&lt;/p&gt;&#xA;&lt;h3 id=&#34;algorithm-description&#34;&gt;Algorithm description&lt;/h3&gt;&#xA;&lt;p&gt;Using a boolean vector of size $n$, iteratively mark all the multiples of non-visited positions as non-primes.&lt;/p&gt;&#xA;&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;&#xA;&lt;p&gt;Time complexity: $O(tn)$, $t$ is the number of primes between $1$ and $t$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;vector&amp;lt;bool&amp;gt; sieve;&#xA;&#xA;void eratothenes_sieve(int n) {&#xA;  // initialize the list&#xA;  sieve.resize(n &amp;#43; 1, false);&#xA;&#xA;  // multiples of 2 are not primes&#xA;  for (int i = 4; i &amp;lt;= n; i &amp;#43;= 2) {&#xA;    sieve[j] = true;&#xA;  }&#xA;&#xA;  // multiples of odd numbers&#xA;  for (int i = 3; i * i &amp;lt;= n; i &amp;#43;= 2) {&#xA;    if (!sieve[i]) {&#xA;      for (int j = i * i; j &amp;lt;= n; j &amp;#43;= 2 * i) {&#xA;        sieve[j] = true;&#xA;      }&#xA;    }&#xA;  }&#xA;}&#xA;&#xA;void is_prime(int n) {&#xA;  assert(n &amp;lt; sieve.size());&#xA;  return sieve[n];&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;</description>
    </item>
    <item>
      <title>Euclidean Algorithm</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/euclidean-algorithm/</link>
      <pubDate>Mon, 01 Jun 2015 12:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/euclidean-algorithm/</guid>
      <description>&lt;p&gt;Euclid&amp;rsquo;s Algorithm for finding the &lt;strong&gt;Greatest Common Divisor&lt;/strong&gt; of two or more integers is based on the following observations:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;if $x = y$ then&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div&gt;$$&#xA;gcd(x, y) = gcd(x, x) = x&#xA;$$&lt;/div&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;if $x &amp;gt; y$ then&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div&gt;$$&#xA;gcd(x, y) = gcd(x - y, y)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof:&lt;/strong&gt; suppose that $d$ is a divisor of $x$ and $y$, then $x$ and $y$ can be expressed as&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x &amp;= q_1d \\&#xA;y &amp;= q_2d&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;But then&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x - y = q_1d - q_2d = d(q_1 - q_2)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore, $d$ is a divisor of $x - y$&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int gcd(int x, int y) {&#xA;  while (x != y) {&#xA;    if (x &amp;gt; y) {&#xA;      x -= y;&#xA;    } else {&#xA;      y -= x;&#xA;    }&#xA;  }&#xA;  return x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Using the remainder operator instead of multiple subtraction operations is an improvement in performance; however, eventually one of $x$ or $y$ will become zero&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;gcd(x, 0) = gcd(0, x) = x&#xA;$$&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int gcd(int x, int y) {&#xA;  while (x != 0 &amp;amp;&amp;amp; y != 0) {&#xA;    if (x &amp;gt; y) {&#xA;      x %= y;&#xA;    } else {&#xA;      y %= x;&#xA;    }&#xA;  }&#xA;  return max(x, y);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;By ensuring that $x \geq y$, we can get rid of the &lt;code&gt;if&lt;/code&gt; statement inside the &lt;code&gt;while&lt;/code&gt; loop&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int gcd(int x, int y) {&#xA;  if (x &amp;lt; y) {&#xA;    swap(x, y);&#xA;  }&#xA;  while (y != 0) {&#xA;    int remainder = x % y;&#xA;    x = y;&#xA;    y = remainder;&#xA;  }&#xA;  // at this point `gcd(x, y) = gcd(x, 0) = x`&#xA;  return x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;However, if $x &amp;lt; y$, the first iteration of the loop will actually swap the operands (e.g., when $x = 3, y = 5$, $remainder = 3 % 5 = 3$, $x_{new} = 5$, $y_{new} = 3$). Therefore, it&amp;rsquo;s not necessary to make the initial swap&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;int gcd(int x, int y) {&#xA;  while (y != 0) {&#xA;    int remainder = x % y;&#xA;    x = y;&#xA;    y = remainder;&#xA;  }&#xA;  // at this point `gcd(x, y) = gcd(x, 0) = x`&#xA;  return x;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Finding the GCD of $102$ and $38$&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;102 &amp;= 2 \cdot 38 + 26 \\&#xA;38 &amp;= 1 \cdot 26 + 12 \\&#xA;26 &amp;= 2 \cdot 12 + 2 \\&#xA;12 &amp;= 6 \cdot 2 + 0&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The last non-zero remainder is $2$; thus, the GCD is 2.&lt;/p&gt;&#xA;&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;&#xA;&lt;p&gt;Recursive version&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int gcd(int x, int y) {&#xA;  if (y == 0) {&#xA;    return x;&#xA;  }&#xA;  return gcd(y, x % y);&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;http://people.cis.ksu.edu/~schmidt/301s12/Exercises/euclid_alg.html&#34;target=&#34;_blank&#34;&gt;explanation&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Euler&#39;s phi function</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/number-theory/eulers-phi/</link>
      <pubDate>Mon, 01 Jun 2015 00:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/number-theory/eulers-phi/</guid>
      <description>&lt;h3 id=&#34;examples&#34;&gt;Examples&lt;/h3&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\phi(1) &amp;= 1 \quad (1) \\&#xA;\phi(2) &amp;= 1 \quad (1) \\&#xA;\phi(3) &amp;= 2 \quad (1, 2) \\&#xA;\phi(4) &amp;= 2 \quad (1, 3) \\&#xA;\phi(5) &amp;= 4 \quad (1, 2, 3, 4) \\&#xA;\phi(6) &amp;= 2 \quad (1, 5)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;properties&#34;&gt;Properties&lt;/h3&gt;&#xA;&lt;p&gt;The following three properties will allow us to calculate it for any number:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if $p$ is a prime, then $\phi(p) = p - 1$&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof:&lt;/strong&gt; Obviously, since $p$ is a prime, the only divisors that it has are $1$ and $p$, but $gcd(1, p) = 1$ so $1$ falls under the definition of the Euler function; therefore, the only divisor valid for the Euler function for the case above is $p$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if $p$ is a prime and $k \geq 1$ a positive integer, then $\phi(p^k) = p^k - p^{k-1}$.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Proof:&lt;/strong&gt; Since the multiples of $p$ that are less than or equal to $p^k$ are $p, 2p, 3p, &amp;hellip;, p^{k-1}p \leq p^k$, we can see that in total there are $p^{k-1}$ numbers; therefore, the other $p^k - p^{k-1}$ are relatively coprime to $p^k$.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;$\phi(2^4)$&lt;/p&gt;&#xA;&lt;p&gt;Multiples of $2$ less than $2^4$ are $1 \cdot 2, 2 \cdot 2, 3 \cdot 2, 4 \cdot 2, 5 \cdot 2, 6 \cdot 2, 7 \cdot 2, 8 \cdot 2$, which are in total $2^3$ elements. Therefore, the other $2^4 - 2^3$ are relatively prime to $2^4$.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;if $a$ and $b$ are relatively prime, then $\phi(ab) = \phi(a)\phi(b)$&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;computation&#34;&gt;Computation&lt;/h3&gt;&#xA;&lt;p&gt;Given a number $n$, let&amp;rsquo;s decompose it into prime factors (factorization):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;n = p_1^{a_1} \cdot p_2^{a_2} \cdot ... \cdot p_k^{a_k}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying the Euler function we get:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\phi(n) &amp;= \phi(p_1^{a_1}) \cdot \phi(p_2^{a_2}) \cdot ... \cdot \phi(p_k^{a_k}) \\&#xA;&amp;= (p_1^{a_1} - p_1^{a_1 - 1}) \cdot (p_2^{a_2} - p_2^{a_2 - 1}) \cdot ... \cdot (p_k^{a_k} - p_k^{a_k - 1}) \\&#xA;&amp;= (p_1^{a_1} - \frac{p_1^{a_1}}{p_1}) \cdot (p_2^{a_2} - \frac{p_2^{a_2}}{p_2}) \cdot ... \cdot (p_k^{a_k} - \frac{p_k^{a_k}}{p_k}) \\&#xA;&amp;= p_1^{a_1} (1 - \frac{1}{p_1}) \cdot p_2^{a_2} (1 - \frac{1}{p_2}) \cdot ... \cdot p_k^{a_k} (1 - \frac{1}{p_k}) \\&#xA;&amp;= p_1^{a_1} \cdot p_2^{a_2} \cdot ... \cdot p_k^{a_k} \cdot (1 - \frac{1}{p_1}) \cdot (1 - \frac{1}{p_2}) \cdot ... \cdot (1 - \frac{1}{p_k}) \\&#xA;&amp;= n \cdot (1 - \frac{1}{p_1}) \cdot (1 - \frac{1}{p_2}) \cdot ... \cdot (1 - \frac{1}{p_k}) \\&#xA;&amp;= n \prod_{p|n}(1 - \frac{1}{p})&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;implementation&#34;&gt;Implementation&lt;/h3&gt;&#xA;&lt;p&gt;Time complexity: $O(\sqrt{n})$&#xA;Space: $O(1)$&lt;/p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;  &#xA;&#xA;&#xA;&lt;pre &gt;&lt;code&#xA;class=&#39;language-cpp &#39; &gt;int phi(int n) {&#xA;  int result = n;&#xA;  for (int i = 2; i * i &amp;lt;= n; i &amp;#43;= 1) {&#xA;    // if `i` is a divisor of `n`&#xA;    if (n % i == 0) {&#xA;      // divide it by `i^k` so that it&amp;#39;s no longer divisible by `i`&#xA;      while (n % i == 0) {&#xA;        n /= i;&#xA;      }&#xA;      // all the multiples of `i` are coprime to n, the number of&#xA;      // multiples is equal to `i * k` &amp;lt;= n, therefore `k &amp;lt;= n / i`&#xA;      result -= result / i;&#xA;    }&#xA;  }&#xA;  if (n &amp;gt; 1) {&#xA;    result -= result / n;&#xA;  }&#xA;  return result;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h3 id=&#34;problems&#34;&gt;Problems&lt;/h3&gt;&#xA;&lt;p&gt;&#xA;&#xA;&lt;a href=&#34;http://uva.onlinejudge.org/index.php?option=onlinejudge&amp;amp;page=show_problem&amp;amp;problem=1120&#34;target=&#34;_blank&#34;&gt;10179 - Irreducable Basic Fractions&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;http://uva.onlinejudge.org/index.php?option=onlinejudge&amp;amp;page=show_problem&amp;amp;problem=1240&#34;target=&#34;_blank&#34;&gt;10299 - Relatives&lt;/a&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;a href=&#34;https://uva.onlinejudge.org/index.php?option=com_onlinejudge&amp;amp;Itemid=8&amp;amp;page=show_problem&amp;amp;problem=2302&#34;target=&#34;_blank&#34;&gt;11327 - Enumerating Rational Numbers&lt;/a&gt;&#xA;&#xA;&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Derivative</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/calculus/derivative/</link>
      <pubDate>Thu, 02 Apr 2015 10:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/calculus/derivative/</guid>
      <description>&lt;h2 id=&#34;physical-interpretation-of-the-derivative&#34;&gt;Physical Interpretation of the Derivative&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The primary concept of calculus deals with the rate of change of one variable with respect to another.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h3 id=&#34;instantaneous-speed&#34;&gt;Instantaneous Speed&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine a person who travels 90 km in 3 hours. Their &lt;em&gt;average speed&lt;/em&gt; (rate of change of distance with respect to time) is 30 km/h. Of course, they don&amp;rsquo;t need to travel at that fixed speed; they may slow down or speed up at different times during their travel. For &lt;em&gt;many&lt;/em&gt; purposes, it suffices to know the average speed.&lt;/p&gt;&#xA;&lt;p&gt;However, in many daily happenings, the average speed is not a significant quantity. If a person traveling in an automobile strikes a tree, the quantity that matters is the speed at the &lt;em&gt;instant of collision&lt;/em&gt; (this quantity might determine if they survive or not).&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Concept&lt;/th&gt;&#xA;          &lt;th&gt;Description&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Interval&lt;/td&gt;&#xA;          &lt;td&gt;Happens over a &lt;em&gt;period&lt;/em&gt; of time&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Instant&lt;/td&gt;&#xA;          &lt;td&gt;Happens so fast that no time elapses&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Calculating the &lt;em&gt;average speed&lt;/em&gt; is simple. By definition, it&amp;rsquo;s the rate of change of distance with respect to time.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\text{average speed} = \frac{\text{distance traveled}}{\text{interval of time}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The same computation process can&amp;rsquo;t be applied to get the &lt;em&gt;instantaneous speed&lt;/em&gt; at some point in time. Since &lt;em&gt;instantaneous&lt;/em&gt; means that the event happened in an infinitesimal or very short space of time, then distance and time might both be zero. Hence, using the &lt;em&gt;average speed&lt;/em&gt; definition won&amp;rsquo;t help because $\frac{0}{0}$ is meaningless. We know that this is a physical reality, but if we can&amp;rsquo;t calculate it, it&amp;rsquo;s impossible to work with it mathematically.&lt;/p&gt;&#xA;&lt;p&gt;We can&amp;rsquo;t compute it with the knowledge we have right now, but we can surely approximate it. Let&amp;rsquo;s say that a ball is dropped near the surface of the Earth, and we want to know its instantaneous speed after 4 seconds. To calculate the instantaneous speed at any point in time, we need to know the distance it travels after some period of time. This relation can be expressed as a formula that relates distance and time traveled. The formula that relates the distance (in feet) to the time elapsed is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f(t) = s = 16t^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can calculate the distance the ball traveled after 4 seconds by replacing $t$ with 4:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;s_4 &amp;= 16 \cdot 4^2 \\&#xA;&amp;= 256 \text{ feet}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s also compute the distance the ball traveled after 5 seconds:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;s_5 &amp;= 16 \cdot 5^2 \\&#xA;&amp;= 400 \text{ feet}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The &lt;em&gt;average speed&lt;/em&gt; for this interval of time is then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\text{average speed for the interval of time [4, 5]} = \frac{s_5 - s_4}{1} = \frac{400 - 256}{1} = 144 \;\text{feet/s}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;So the &lt;em&gt;average speed&lt;/em&gt; during the fifth second is $144;\text{feet/s}$. This quantity is no more than an approximation of the &lt;em&gt;instantaneous speed&lt;/em&gt;, but we may improve the approximation by calculating the average speed in the interval of time from 4 to 4.1 seconds, which is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\text{average speed for the interval of time [4, 4.1]} = \frac{268.96 - 256}{0.1} = 129.6\;\text{feet/s}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s register more computations of the above process with smaller and smaller intervals of time in a table:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;|time elapsed after 4 seconds|  1|  0.1|  0.01|  0.001|  0.0001|&#xA;|average speed (in feet/s)   |144|129.6|128.16|128.016|128.0016|&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Of course, no matter how small the interval is, the result is not the instantaneous speed at the instant $t=4$. However, we now see that the average speed for the intervals seems to be approaching the fixed number &lt;strong&gt;128 feet/s&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;method-of-increments&#34;&gt;Method of Increments&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s redo the process described above over an &lt;em&gt;arbitrary&lt;/em&gt; interval of time. To do so, let&amp;rsquo;s introduce a quantity $h$, which represents an interval of time beginning at $t=4$ and extending before or after $t=4$. ($h$ is called an &lt;em&gt;increment&lt;/em&gt; in $t$ because it&amp;rsquo;s some interval of time.)&lt;/p&gt;&#xA;&lt;p&gt;The formula for the example above is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop}&#xA;s = 16t^2&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When calculated once by the end of the fourth second, it is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop1}&#xA;s_4 = 16 \cdot 4^2 = 256&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When substituted with the interval $[4, 4 + h]$, it is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;s_4 + k &amp;= 16 (4 + h) ^2 \notag \\&#xA;  &amp;= 256 + 128h + 16h^2 \label{balldrop2}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $k$ is the additional distance the object falls $h$ seconds after the initial $4$ seconds. To obtain $k$, we have to subtract $\eqref{balldrop1}$ from $\eqref{balldrop2}$. The result is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;k = 128h + 16h^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The average speed in this interval of time is then $\frac{k}{h}$. Dividing both sides by $h$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{k}{h} = 128 + 16h&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To compute the instantaneous speed, the interval $h$ must become smaller and smaller until it reaches 0. If $h$ approaches 0, then $16h$ also approaches 0. We can conclude that the instantaneous speed when $t=4$ approaches &lt;strong&gt;128 feet/s&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h4 id=&#34;generalization&#34;&gt;Generalization&lt;/h4&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s generalize the process above for $\eqref{balldrop}$ for any value of $t$. To do so, let&amp;rsquo;s apply the method of increments when $t$ is substituted with the interval $t + h$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;s + k &amp;= 16(t + h)^2 \\&#xA;&amp;= 16t^2 + 32th + h^2&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Subtracting $\eqref{balldrop}$ from the equation above:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;k &amp;= 32th + h^2&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Dividing both sides by $h$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop-derivative}&#xA;\frac{k}{h} = 32t + h&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Just as stated above, to compute the instantaneous speed, the interval $h$ must become smaller and smaller until it reaches 0. If $h$ approaches 0, then the instantaneous speed approaches $32t$, which is a function that will tell us the &lt;em&gt;instantaneous speed&lt;/em&gt; of the falling object at any time $t$!&lt;/p&gt;&#xA;&lt;p&gt;It has been customary since the days of Euler to use $\Delta{t}$ (&lt;em&gt;delta&lt;/em&gt; t) for the increment of $t$. $\Delta{t}$ means a &amp;ldquo;change in the value of $t$&amp;rdquo;. Thus, $\Delta{t}$ has the same meaning as $h$; likewise, $\Delta{s}$ has the same meaning as $k$. We can rewrite $\eqref{balldrop-derivative}$ as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop3}&#xA;\frac{\Delta{s}}{\Delta{t}} = 32t + 16\Delta{t}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;It&amp;rsquo;s desirable to have some short notation for the statement that we have evaluated the &lt;em&gt;limit&lt;/em&gt; of as the values of $\Delta{t}$ approach 0, which can be expressed as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\lim_{\Delta{t} \to 0} \frac{\Delta{s}}{\Delta{t}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where &lt;em&gt;lim&lt;/em&gt; is an abbreviation for limit, replacing $\eqref{balldrop3}$ with this new notation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop-limit}&#xA;\lim_{\Delta{t} \to 0} \frac{\Delta{s}}{\Delta{t}} = 32t&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To some mathematicians, this notation is somewhat lengthy; hence, mathematicians replaced it with different variations:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\lim_{\Delta{t} \to 0} \frac{\Delta{s}}{\Delta{t}} = \frac{ds}{dt} = s&#39; = f&#39;(t)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The rate of change is not always related to time or distances. A generalization of the formulas above is needed. Instead of the symbols $s$ and $t$, let&amp;rsquo;s use $x$ and $y$ without specifying what $x$ and $y$ mean physically.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s calculate the instantaneous rate of change of $y$ with respect to $x$ (the word &lt;em&gt;instantaneous&lt;/em&gt; does not really apply because $x$ doesn&amp;rsquo;t represent time), using the &lt;em&gt;method of increments&lt;/em&gt; on a function which depends on $x$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align}&#xA;y &amp;= f(x) \label{x-a} \\&#xA;y + \Delta{y} &amp;= f(x + \Delta{x}) \label{x-b}&#xA;\end{align}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Subtracting $\eqref{x-a}$ from $\eqref{x-b}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\Delta{y} = f(x + \Delta{x}) - f(x)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Dividing both sides by $\Delta{x}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{\Delta{y}}{\Delta{x}} = \frac{f(x + \Delta{x}) - f(x)}{\Delta{x}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The instantaneous rate of change of $y$ with respect to $x$ is reached when $\Delta{x}$ approaches 0:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation} \label{limit}&#xA;\lim_{\Delta{x} \to 0} \frac{f(x + \Delta{x}) - f(x)}{\Delta{x}}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can also use the variations for the notation of the rate of change:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\lim_{\Delta{t} \to 0} \frac{\Delta{y}}{\Delta{x}} = \frac{dy}{dx} = y&#39; = f&#39;(x)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;What we did with the process above was to &lt;em&gt;find the instantaneous rate of change of $y$ with respect to $x$&lt;/em&gt;. We call this rate the &lt;strong&gt;derivative&lt;/strong&gt; of $y$ with respect to $x$. The process of applying the method of increments to obtain the derivative is called &lt;strong&gt;differentiation&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;geometric-interpretation-of-the-derivative&#34;&gt;Geometric Interpretation of the Derivative&lt;/h2&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s graph the following formula:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{yx2}&#xA;y = x^2&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;geometric-representation&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;A point belonging to this geometrical representation of $y$ has the form $(x_1, f(x_1))$; e.g., when $x = 1, y = 1$ and when $x = 2, y = 4$.&lt;/p&gt;&#xA;&lt;div id=&#34;geometric-representation-two-points&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say that $(x_1, f(x_1))$ is a fixed point on the curve (for the sake of this example, the point will be $x_1 = 1, y_1 = 1$). Any other point that belongs to the curve can make a line with the fixed point.&lt;/p&gt;&#xA;&lt;div id=&#34;geometric-representation-secant&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;The slope is a quantity that describes the direction and steepness of a line and is calculated by finding the ratio of the &lt;em&gt;vertical change&lt;/em&gt; to the &lt;em&gt;horizontal change&lt;/em&gt; between any two &lt;strong&gt;distinct&lt;/strong&gt; points on the line. The previous statement expressed as a formula is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;m = \frac{y_2 - y_1}{x_2 - x_1} = \frac{\Delta{y}}{\Delta{x}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;What if the movable point gets closer and closer to the fixed point such that $\Delta{x}$ reaches 0? That&amp;rsquo;s exactly the definition of the derivative, which means that the derivative of a function will tell us the &lt;em&gt;slope&lt;/em&gt; of the &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Tangent&#34;target=&#34;_blank&#34;&gt;&lt;em&gt;tangent&lt;/em&gt; line&lt;/a&gt;&#xA;&#xA; to the function (represented geometrically as a curve) at any derivable point!&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s find the instantaneous rate of change of this function evaluated at $x=1$, using $\eqref{limit}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;m_1 = f&#39;(1) &amp;= \lim_{\Delta{x} \to 0} \frac{f(1 + \Delta{x}) - f(1)}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} \frac{(1 + \Delta{x}) ^ 2 - 1^2}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} \frac{1^2 + 2\Delta{x} - \Delta{x}^2 - 1^2}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} 2 - \Delta{x} \\&#xA;&amp;= 2&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;This fixed number is the value of the &lt;em&gt;slope&lt;/em&gt; of the line tangent to the derivative function when it&amp;rsquo;s evaluated with $1$. Let&amp;rsquo;s find out the &lt;em&gt;Point–slope&lt;/em&gt; form of the &lt;em&gt;tangent&lt;/em&gt; line whose &lt;em&gt;slope&lt;/em&gt; is $m$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{line-equation}&#xA;y - y_1 = m(x - x_1)&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Substituting $y_1=1$, $m=2$, and $x_1=1$ computed above:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;y &amp;= 2(x - 1) + 1 \\&#xA;  &amp;= 2x - 2 + 1 \\&#xA;  &amp;= 2x - 1&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we graph this line next to the geometric representation of $y = x^2$, we see that it&amp;rsquo;s actually touching the curve at the point $(1, 1)$.&lt;/p&gt;&#xA;&lt;div id=&#34;slope-static-x-1&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Before finding the equation of the slope for any value of $x$, let&amp;rsquo;s imagine the graph produced by the slope function. If we take a look at the graph produced by $\eqref{yx2}$, we can see that for any point that belongs to the curve whose $x$ coordinate is negative, the slope will be negative, and for any point that belongs to the curve whose $x$ coordinate is positive, the slope will be positive, expressed mathematically:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;sign(m) = \begin{cases}&#xA;-1 &amp; \text{if } x &lt; 0, \\&#xA;0 &amp; \text{if } x = 0, \\&#xA;1 &amp; \text{if } x &gt; 0.&#xA;\end{cases}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now that we have an idea of the values of the &lt;em&gt;slope&lt;/em&gt;, let&amp;rsquo;s find the value of $m$ for any value of $x$ that is the derivative of $y$ with respect to $x$, using $\eqref{limit}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;f&#39;(x) &amp;= \lim_{\Delta{x} \to 0} \frac{f(x + \Delta{x}) - f(x)}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} \frac{(x + \Delta{x}) ^ 2 - x^2}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} \frac{x^2 + 2x\Delta{x} - \Delta{x}^2 - x^2}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} 2x - \Delta{x} \\&#xA;&amp;= 2x&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;slope-graph&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;By looking at the line, we confirm our expectation of the values. Any point which belongs to the line whose $x$ coordinate is negative has its $y$ coordinate (the value of the &lt;em&gt;slope&lt;/em&gt;) negative as well, and any $x$ coordinate belonging to the line whose $x$ coordinate is positive has its $y$ coordinate positive as well.&lt;/p&gt;&#xA;&lt;p&gt;There are infinite tangent lines to the curve that represents $\eqref{yx2}$. In the following graph, the equation of the line is computed dynamically based on the position of the mouse pointer (computed by doing substitutions on $\eqref{line-equation}$):&lt;/p&gt;&#xA;&lt;div id=&#34;slope-dynamic&#34;&gt;&lt;/div&gt;&#xA;&lt;h3 id=&#34;second-derivative&#34;&gt;Second Derivative&lt;/h3&gt;&#xA;&lt;p&gt;Going back to the falling object formula ($s$ is the distance the object moved after $t$ seconds have elapsed):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = 16t^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The instantaneous rate of change of the distance with respect to time is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop-first-derivative}&#xA;s&#39; = 32t&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$s&amp;rsquo;$ represents speed, and it is customary to use $v$ (the first letter of velocity) instead of $s&amp;rsquo;$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop-velocity}&#xA;v = 32t&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now $v$ is a function of $t$, and we can ask for the rate of change of $v$ with respect to $t$. This is called &lt;em&gt;instantaneous acceleration&lt;/em&gt;. &lt;em&gt;Acceleration&lt;/em&gt; is a change of speed that takes place during an interval of time. If there weren&amp;rsquo;t acceleration in a moving object, the moving object would be moving for the rest of its life with a constant speed. If the speed is given as a function of time, then we can calculate the &lt;em&gt;instantaneous&lt;/em&gt; rate of change of the velocity with respect to time:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}&#xA;\label{balldrop-second-derivative}&#xA;v&#39; = 32&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The &lt;em&gt;instantaneous acceleration&lt;/em&gt; obtained above is the derived function of the &lt;em&gt;instantaneous speed&lt;/em&gt;, which is the derived function of the &lt;em&gt;distance function&lt;/em&gt;. Then we can relate the &lt;em&gt;instantaneous acceleration&lt;/em&gt; and the &lt;em&gt;distance function&lt;/em&gt; with the following notation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s&#39;&#39; \quad \text{or} \quad \frac{d^2s}{dt^2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The function above is called the &lt;em&gt;second derived function&lt;/em&gt; of $\eqref{balldrop}$. This notation applied to the generalized version using the variables $x$ and $y$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{d^2y}{dx^2} \quad \text{or} \quad y&#39;&#39; \quad \text{or} \quad f&#39;&#39;(x)&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;the-chain-rule&#34;&gt;The Chain Rule&lt;/h3&gt;&#xA;&lt;p&gt;Physical problems lead to more complicated algebraic functions, for example, $y = \sqrt{x^2 + 1}$, which arises when one wants to work with the upper half of the parabola $y^2 = x^2 + 1$. We can express this function as a combination of two functions:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y = \sqrt{u}\, \quad u = x^2 + 1&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If $y$ is a function of $u$ and $u$ is a function of $x$, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dy}{dx} = \frac{dy}{du} \cdot \frac{du}{dx}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Expressed in the function notation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y = f(u) \quad \text{and} \quad u = g(x)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{chain-rule}&#xA;\frac{dy}{dx} = f&#39;(u) \cdot g&#39;(x)&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Returning to the original problem, let&amp;rsquo;s find the derivative of $y = \sqrt{x^2 + 1}$ with respect to $x$ using the &lt;em&gt;chain rule&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;p&gt;Let $f(u) = u^{1/2}$ and $g(x) = x^2 + 1$.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dy}{dx} = f&#39;(u) \cdot g&#39;(x) = \frac{u^{-1/2}}{2} \cdot 2x = \frac{x}{\sqrt{x^2 + 1}}&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;differentiation-of-implicit-functions&#34;&gt;Differentiation of Implicit Functions&lt;/h4&gt;&#xA;&lt;p&gt;Going back to the definition of a function, it&amp;rsquo;s a relation between two variables such that given a value of one in some domain, there&amp;rsquo;s a unique value determined for the second variable. However, functions often occur in forms where giving the independent variable some value will not result in a unique value. For example, the equation of a circle of radius equal to 5 is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{implicit}&#xA;x^2 + y^2 = 25&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Here, $y$ is not expressed in terms of $x$. Solving for $y$, we have two equations:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{explicit}&#xA;y = \sqrt{25 - x^2} \quad y = -\sqrt{25 - x^2}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$\eqref{implicit}$ represents the circle &lt;em&gt;implicitly&lt;/em&gt;, and $\eqref{explicit}$ represents the equation &lt;em&gt;explicitly&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;We know that $y$ in $\eqref{implicit}$ represents some function of $x$. If we recognize that the left side of $\eqref{implicit}$ is only a set of terms in $x$, then we can differentiate it. The problem is to find the derivative of $y^2$, which should remind us of the chain rule ($y$ plays the role of $u$ in the chain rule):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{d(y^2)}{dx} = 2y \frac{dy}{dx}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying a differentiation process to $\eqref{implicit}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;2x + 2y \frac{dy}{dx} = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Solving for $\frac{dy}{dx}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dy}{dx} = -\frac{x}{y}&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;theorems-on-differentiation&#34;&gt;Theorems on Differentiation&lt;/h3&gt;&#xA;&lt;p&gt;Read &amp;ldquo;Calculus: An Intuitive and Physical Approach&amp;rdquo;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;applications-of-the-derivative&#34;&gt;Applications of the Derivative&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Determination of the velocity and acceleration of a particle given its distance as a function of time.&lt;/li&gt;&#xA;&lt;li&gt;Concentrate light, sound, and radio waves in a particular direction (see the &#xA;&#xA;&lt;a href=&#34;http://www.wikiwand.com/en/Parabola_#section_Proof_of_the_reflective_property&#34;target=&#34;_blank&#34;&gt;reflective property of the parabola&lt;/a&gt;&#xA;&#xA;).&lt;/li&gt;&#xA;&lt;li&gt;Finding the maximum/minimum value of a function, i.e., find the largest/smallest value of $f(x)$ when $a \leq x \leq b$. A well-described solution to this problem can be found &#xA;&#xA;&lt;a href=&#34;https://www.whitman.edu/mathematics/calculus/calculus_06_Applications_of_the_Derivative.pdf&#34;target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;li&gt;Approximation of the roots of a polynomial with Newton&amp;rsquo;s method, described &#xA;&#xA;&lt;a href=&#34;https://www.whitman.edu/mathematics/calculus/calculus_06_Applications_of_the_Derivative.pdf&#34;target=&#34;_blank&#34;&gt;here&lt;/a&gt;&#xA;&#xA;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;maximaminima&#34;&gt;Maxima/Minima&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say that we throw an object into the air and we want to know the maximum height it acquires. As it rises, its velocity decreases, and when it reaches the highest point, its velocity is zero. We also know that the velocity is the instantaneous rate of change of height with respect to time; hence, the derivative is involved in this process, and therefore we expect it to be involved in other maxima/minima problems.&lt;/p&gt;&#xA;&lt;p&gt;More generally, if $y$ is a function of $x$, it seems that to find the maximum value of $y$, we must find $y&amp;rsquo;$ and set it to 0.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s see an example. The following function has a maximum value of $3.333$ near $x = 1$ and a minimum value of $2$ near $x = 3$.&#xA;If we analyze the slope of the function near those points, we will see that on the left of $x = 1$, the slope is positive, and on the&#xA;right of $x = 1$, the slope is negative. Since we know that the derivative represents the slope of a function, we can also expect that&#xA;the derivative of this function near $x = 1$ will go from a positive value to a negative value, intersecting the x-axis.&#xA;If we analyze the slope near $x = 3$, we will see the same behavior with the slope, but it&amp;rsquo;s going from a negative value to a positive one.&lt;/p&gt;&#xA;&lt;div class=&#34;tw-flex tw-flex-col md:tw-flex-row&#34;&gt;&#xA;    &lt;div class=&#34;md:tw-w-1/2 tw-relative&#34;&gt;&#xA;        $$&#xA;            y = x^3/3 - 2x^2 + 3x + 2&#xA;        $$&#xA;        &lt;div id=&#34;maxima-minima-f&#34;&gt;&lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;md:tw-w-1/2 tw-relative&#34;&gt;&#xA;        $$&#xA;            y&#39; = x^2 - 4x + 3&#xA;        $$&#xA;        &lt;div id=&#34;maxima-minima-f-derivative&#34;&gt;&lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;Now the problem reduces to finding the points where $y&amp;rsquo; = 0$ in the derivative function. Finding them will tell us exactly the maximum/minimum value of $y$. Finding the values of $x$ when $y&amp;rsquo; = 0$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;0 &amp;= x^2 - 4x + 3 \\&#xA;0 &amp;= (x - 1)(x - 3)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;And we see that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y&#39; = 0 \quad \text{when} \quad x = 1 \quad \text{and} \quad x = 3&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The process didn&amp;rsquo;t actually find the maximum/minimum values since for $x &amp;gt; 3$, the function increases indefinitely. The same goes for when $x &amp;lt; 1$, but in this case, the function decreases indefinitely. These values are called the &lt;em&gt;relative maxima/minima&lt;/em&gt; because &lt;strong&gt;near&lt;/strong&gt; $x = 3$ or $x = 1$, these points are the minimum/maximum that can be found.&lt;/p&gt;&#xA;&lt;h4 id=&#34;applications-of-maximaminima&#34;&gt;Applications of Maxima/Minima&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Refraction of light: we can build a function of time which relates the velocity/distance the light travels in different mediums. Finding the derivative and making it equal to $0$ will find the relative minimum time needed to go from one point in medium $a$ to a point in medium $b$.&lt;/li&gt;&#xA;&lt;li&gt;Finding the sides of the rectangle with the maximum perimeter.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;newton-raphson-method&#34;&gt;Newton-Raphson Method&lt;/h3&gt;&#xA;&lt;p&gt;The slope of the tangent line of a function $f(x)$ at any derivable point is given by $m = f&amp;rsquo;(x)$. Let $x_1$ be a derivable point; then the slope of the tangent line at $x_1$ is $m_1 = f&amp;rsquo;(x_1)$. The &lt;em&gt;Point–slope&lt;/em&gt; form of the &lt;em&gt;tangent&lt;/em&gt; line whose &lt;em&gt;slope&lt;/em&gt; is $f&amp;rsquo;(x_1)$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;y - y_1 &amp;= m_1(x - x_1) \\&#xA;y - f(x_1) &amp;= f&#39;(x_1) \cdot (x - x_1)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Newton found out that if we find the intercept of this tangent line with the $x$-axis at some initial guess $x_1$, the value found approaches one of the roots of $f(x)$, i.e., when $f(x) = 0$ (obviously, given that it has roots).&lt;/p&gt;&#xA;&lt;p&gt;If $y = f(x) = 0$, then the equation of the line is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;0 - f(x_1) = f&#39;(x_1) \cdot (x - x_1)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Solving for $x$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{newton-raphson}&#xA;x = x_1 - \frac{f(x_1)}{f&#39;(x_1)}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$x$ in the last equation is the abscissa of the next approximation of one of the roots of $f(x)$. If we run the algorithm above a few times with an acceptable initial guess, then we&amp;rsquo;ll obtain a better approximation of one of the roots of $f(x)$.&lt;/p&gt;&#xA;&lt;div id=&#34;newton-raphson&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;tw-text-center tw-mb-4&#34;&gt;&#xA;  &lt;button id=&#34;run-newton-raphson&#34; class=&#34;tw-inline-block tw-p-2 tw-rounded-md tw-border-2 tw-border-primary&#34;&gt;Approximate with Newton-Raphson&lt;/button&gt;&#xA;&lt;/div&gt;&#xA;&lt;h4 id=&#34;finding-the-square-root-of-a-number&#34;&gt;Finding the Square Root of a Number&lt;/h4&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say that we want to find the square root of a number $n$. This is equivalent to finding the solution to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x^2 = n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The function to use is then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f(x) = x^2 - n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;whose derivative is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f&#39;(x) = 2x&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Substituting in $\eqref{newton-raphson}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;x &amp;= x_1 - \frac{x_1^2 - n}{2x_1} \\&#xA;&amp;= x_1 - \frac{x_1}{2} + \frac{n}{2x_1} \\&#xA;&amp;= \frac{x_1}{2} + \frac{n}{2x_1} \\&#xA;&amp;= \frac{1}{2} \cdot \big ( x_1 + \frac{n}{x_1} \big )&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-cpp&#34;&gt;double square_root(double n) {&#xA;  // initial guess&#xA;  double EPS = 1e-15;&#xA;  double x0 = 1;&#xA;  while (true) {&#xA;    double xi = (x0 + n / x0) / 2.0;&#xA;    if (abs(x0 - xi) &amp;lt; EPS) {&#xA;      break;&#xA;    }&#xA;    x0 = xi;&#xA;  }&#xA;  return x0;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/calculus/derivative.js&#34;&gt;&lt;/script&gt;&#xA;</description>
    </item>
    <item>
      <title>Integral</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/calculus/integral/</link>
      <pubDate>Thu, 02 Apr 2015 10:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/calculus/integral/</guid>
      <description>&lt;style&gt;&#xA;.line-1 {&#xA;  opacity: 0.4!important;&#xA;}&#xA;&lt;/style&gt;&#xA;&lt;p&gt;We&amp;rsquo;re asked to find the derivative of the following function with respect to $x$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{definition-function}&#xA;y = 3x^2&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Performing the differentiation process:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;y&#39; &amp;= \lim_{\Delta{x} \to 0} \frac{f(x + \Delta{x}) - f(x)}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} \frac{3(x + \Delta{x}) ^ 2 - 3x^2}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} \frac{3x^2 + 6x\Delta{x} - \Delta{x}^2 - 3x^2}{\Delta{x}} \\&#xA;&amp;= \lim_{\Delta{x} \to 0} 6x - \Delta{x} \\&#xA;&amp;= 6x&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say that we&amp;rsquo;re given the same problem in a reversed version. We&amp;rsquo;re asked to find the &lt;em&gt;original function&lt;/em&gt; of the following derivative function:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{definition-function-derivate}&#xA;y&#39; = 6x&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Why? Because &amp;ldquo;when we formulate physical problems mathematically, the given physical information usually leads to derived functions, and the primary objective in solving the physical problems is to find the original functions&amp;rdquo; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&#xA;&lt;p&gt;We know that the original function corresponding to \eqref{definition-function-derivate} is \eqref{definition-function}, but is there an algorithm to find the derivative for the case above? A possible algorithm for the differentiation of the &lt;strong&gt;function above&lt;/strong&gt; might be:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;for each term in the function:&#xA;  - multiply the coefficient with the exponent of the independent variable&#xA;  - reduce the exponent of the independent variable by one&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Reversing the algorithm above means that we&amp;rsquo;re actually trying to find the &lt;em&gt;original function&lt;/em&gt;. A reversed version of the algorithm above might be:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;for each term in the function:&#xA;  - increment the exponent of the independent variable by one&#xA;  - divide the coefficient with the exponent of the independent variable&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If we apply it to \eqref{definition-function-derivate}, we get the &lt;em&gt;original function&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;6x \to 6x^2 \to 6/2x^2 \\&#xA;3x^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;However, we have overlooked one point. It&amp;rsquo;s also true that \eqref{definition-function-derivate} is the derived function of $y = 3x^2 + C$, where $C$ is some constant. This means that a constant term that was in the original function doesn&amp;rsquo;t show up in the derived function. In view of this possibility, we must say that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y = 3x^2 + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The process of going from the derived function to the original function is called &lt;em&gt;antidifferentiation&lt;/em&gt; or &lt;em&gt;integration&lt;/em&gt;. The original function is called the &lt;em&gt;primitive function&lt;/em&gt; or the &lt;em&gt;indefinite integral&lt;/em&gt; of the given function (which is shortened to &lt;em&gt;integral&lt;/em&gt;).&lt;/p&gt;&#xA;&lt;p&gt;Before proving the correctness of the previous algorithm, let&amp;rsquo;s try it on similar functions. The formula for instantaneous acceleration (the instantaneous rate of change of speed with respect to time) is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v&#39; = 32&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Here, the independent variable is actually $x^0$. Applying the 2-step algorithm to find the original function:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;32t^0 \to 32t \to 32/1\;t \\&#xA;32t&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Same as above, since the original function might have had a constant:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v = 32t + C&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;straight-line-motion-in-one-direction&#34;&gt;Straight Line Motion in One Direction&lt;/h2&gt;&#xA;&lt;p&gt;Galileo obtained a basic physical principle: if one neglects air resistance, &lt;strong&gt;all&lt;/strong&gt; objects near the Earth&amp;rsquo;s surface fall to Earth with the same acceleration, which is constant (a downward acceleration). The constant value is equal to:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;32 \text{ feet/s }&#xA;$$&lt;/div&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Find how long it takes for an object dropped from 400 feet above the Earth&amp;rsquo;s surface to reach the surface.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The instantaneous acceleration, as seen above, is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a = v&#39; = 32&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying the 2-step algorithm:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v = 32t + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If the object is dropped, it leaves with zero speed (when $t=0$, $v=0$). Substituting these values in the formula above to find the value of $C$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;0 = 32 \cdot 0 + C \\&#xA;C = 0&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Therefore, the correct formula for speed is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{speed-example}&#xA;v = s&#39; = 32t&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying a new process of &lt;em&gt;antidifferentiation&lt;/em&gt; to \eqref{speed-example}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = 16t^2 + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we agree to measure distance from the point the object is dropped, then the initial distance when $t = 0$ is also zero. $C$ will also have a value of zero. Hence, the correct formula for distance is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = 16t^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To answer the original equation, we must find out the value of $t$ given that $s=400$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;t = \pm\sqrt{\frac{s}{16}} = \pm\sqrt{\frac{400}{16}} = \pm\sqrt{25} = \pm 5&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For the physical problem, only the positive solution is valid. With the same knowledge, we can also tackle problems where the object is thrown instead of dropped.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Find how long it takes for an object thrown downward with a velocity of 100 ft/s from a height of 1000 feet to reach the Earth&amp;rsquo;s surface.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;Starting with the formula of instantaneous acceleration:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;a = 32&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying the 2-step algorithm:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v = 32t + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The object is thrown downwards instead of dropped, which means that when $t=0,;v=100$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;100 = 32 \cdot 0 + C \\&#xA;C = 100&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Hence, the correct formula for speed is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v = 32t + 100&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying a new process of &lt;em&gt;antidifferentiation&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = 16t^2 + 100t + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If we agree to measure the distance from the point where the object is thrown, then $C = 0$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = 16t^2 + 100t&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;It&amp;rsquo;s convenient to measure distance from the Earth&amp;rsquo;s surface and not from any arbitrary distance like the examples above. However, this means that the upward direction is positive. Then the acceleration of gravity must be negative, i.e., $-32;ft/sec^2$, so that the distance traveled by reason of this acceleration is recorded as downward.&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v&#39; = -32\;ft/sec^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then by &lt;em&gt;antidifferentiation&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{speed-raw}&#xA;v = -32t + C&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;If an object is thrown upward, it must have an initial upward velocity. Let&amp;rsquo;s say that an object located on the Earth&amp;rsquo;s surface is thrown upward with an initial velocity equal to $128;ft/s$. Substituting these values in \eqref{speed-raw} (when $t = 0,; v = 128$):&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;128 = -32 \cdot 0 + C \\&#xA;C = 128&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;so that:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{velocity-1}&#xA;v = -32t + 128&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying a new process of &lt;em&gt;antidifferentiation&lt;/em&gt; to find the distance traveled upward at any time $t$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = -16t^2 + 128t + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Because we have agreed to measure distance from the surface, the value of $C$ is zero because when $t = 0$, the object is still on the ground:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{distance-1}&#xA;s = -16t^2 + 128t&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;One question of interest is the &lt;em&gt;maximum height&lt;/em&gt; attained by an object whose motion is represented by \eqref{distance-1}. This problem could be answered if we knew at what $t$ the object attains maximum height. However, we can use \eqref{velocity-1} to obtain the time since we know that the instant the object attains maximum height, the velocity will be zero (the object will rise until its velocity is zero and then fall). Substituting zero as the speed in \eqref{velocity-1}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;0 = -32t + 128 \\&#xA;t = \frac{128}{32} = 4&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now that we know the time at which the object attains the &lt;em&gt;maximum height&lt;/em&gt;, let&amp;rsquo;s replace it in \eqref{distance-1}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;s &amp;= -16(4)^2 + 128 \cdot 4 \\&#xA;  &amp;= -256 + 512 \\&#xA;  &amp;= 256 \text{ feet }&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can generalize the solutions above for objects thrown on any planet. We can represent the acceleration with the symbol $g$, so the acceleration due to this gravity felt from the ground is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{acceleration}&#xA;a = -g&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;By &lt;em&gt;antidifferentiation&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;v = -gt + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since it&amp;rsquo;s a generalization, we don&amp;rsquo;t know the initial velocity (the value of $C$ is some constant). Let&amp;rsquo;s represent the initial velocity of the object with the symbol $v_0$. Hence, the formula for the velocity is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{speed}&#xA;v = v_0 - gt&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Applying a new process of &lt;em&gt;antidifferentiation&lt;/em&gt; to find the distance of the object from the ground:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = v_0t - \frac{gt^2}{2} + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;For this case, we also don&amp;rsquo;t know the initial distance from the ground the object is when $t = 0$. Let&amp;rsquo;s represent the initial distance from the ground with the symbol $s_0$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{distance}&#xA;s = s_0 + v_0t - \frac{gt^2}{2}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;definite-integral&#34;&gt;Definite Integral&lt;/h2&gt;&#xA;&lt;h3 id=&#34;area-as-the-limit-of-the-sum&#34;&gt;Area as the Limit of the Sum&lt;/h3&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say we want to compute the area of the graph below $f(x)$ and the $x$-axis bounded by the vertical lines $x = a = 1$ and $x = b = 2$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;f(x) = x^2&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;area-a-b&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;An approximation to the area can be found by taking the maximum y-value in $(a, b)$, called $m_1$, and multiplying it by $(b - a)$, which will be expressed as $\Delta(x)$. Then the first approximation is $m_1\Delta{x}$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;S_1 = m_1\Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;area-first-approximation&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;We can obtain a better approximation if we divide the interval $(a, b)$ into two equal parts, each denoted by $\Delta{x}$, multiplied by the maximum y-value in each part, and then form the sum:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;S_2 = m_1\Delta{x} + m_2\Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;area-second-approximation&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Dividing the interval $(a, b)$ into $n$ equal parts, each denoted as $\Delta{x}$, and choosing $n$ maximum y-values for each part, we form the sum:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;S_n = m_1\Delta{x} + m_2\Delta{x} + \ldots + m_n\Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;&#xA;  &lt;div id=&#34;sum-area&#34;&gt;&lt;/div&gt;&#xA;  &lt;input class=&#34;center&#34; style=&#34;width: 300px; margin: 0 auto; display: block&#34; type=&#34;range&#34; id=&#34;sum-area-slider&#34; value=&#34;30&#34; min=&#34;2&#34; max=&#34;100&#34;&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;The quantity $n$ can increase without a limit. To each $n$, there&amp;rsquo;s a corresponding sum. Now the quantity:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\lim_{n \to \infty} S_n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;seems to give the exact area under the curve bounded by $a$ and $b$. Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\lim_{n \to \infty} S_n = A&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;There is another notation for this limit which keeps the bounds that determine the area. If $y = f(x)$, then we write for the limit:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\int_{a}^{b} f(x) dx&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The elongated S denotes integration. The symbols $a$ and $b$ are the left and right ends of the domain whose area is being calculated, and $f(x)dx$ is a reminder that we took rectangles of height $y_i$ and width $\Delta{x_i}$.&lt;/p&gt;&#xA;&lt;h3 id=&#34;evaluation-of-definite-integrals&#34;&gt;Evaluation of Definite Integrals&lt;/h3&gt;&#xA;&lt;p&gt;Another way to find the area is as follows. Previously, we found an approximation of the area as ($\Delta{x} \cdot \max(f(x))$ for all $x \in [a, b]$). Similarly, we can take the lower bound instead ($\Delta{x} \cdot \min(f(x))$ for all $x \in [a, b]$). Let&amp;rsquo;s assume that somehow we have found the area below the curve bounded by $[a, x_0]$. Moving $x_0$ to the right will generate an increment in the area. This change in the area can be expressed as:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\Delta{A} = \bar{y} \cdot \Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\frac{\Delta{A}}{\Delta{x}} = \bar{y}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The value of $\bar{y}$ is some value between $f(x_0)$ and $f(x_0 + \Delta{x})$. To obtain the instantaneous rate of change in the area with respect to $x$, we must find the limit of $\Delta{A}/\Delta{x}$ as $\Delta{x}$ approaches zero. Also, as $\Delta{x}$ approaches zero, the value of $\bar{y}$ also approaches $f(x_0)$. Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dA}{dx} = y_0 = f(x_0)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Because this is true for any value of $x$ in the interval $[a, b]$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dA}{dx} = y = f(x)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To find the value of $A(x)$, we apply antidifferentiation:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;A = \int f(x) \; dx&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;As an example, let&amp;rsquo;s apply the above to the function $f(x) = x^2$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{integral-eval}&#xA;A = \int x^2 \; dx = \frac{x^3}{3} + C&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;When $x = a = 1$, we know that the area is zero. Then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;0 &amp;= \frac{1^3}{3} + C \\&#xA;C &amp;= -\frac{1}{3}&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;A = \frac{x^3}{3} - \frac{1}{3}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;is the function which expresses the area from $a$ to any position $x$. To find the area bounded by $[a, b]$, we substitute $x = b = 2$ and get:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;A = \frac{2^3}{3} - \frac{1}{3} = \frac{7}{3}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can obtain the same result if we take the expression \eqref{integral-eval}, substituting 2 for $x$, 1 for $x$, and then subtracting the second result from the first:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{2^3}{3} + C - (\frac{1}{3} + C) = \frac{7}{3}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The constant of integration is eliminated in the process. This process is actually called the &lt;em&gt;fundamental theorem of calculus&lt;/em&gt;:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\int_{a}^{b} f(x)\,dx = F(b) - F(a)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $F(x)$ is the antiderivative of $f(x)$.&lt;/p&gt;&#xA;&lt;h3 id=&#34;additional-properties-of-the-definite-integral&#34;&gt;Additional Properties of the Definite Integral&lt;/h3&gt;&#xA;&lt;div&gt;$$&#xA;\int_{a}^{b} f(x)\,dx = -\int_{b}^{a} f(x)\,dx&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\int_{a}^{b} f(x)\,dx = \int_{a}^{x_0} f(x)\,dx + \int_{x_0}^{b} f(x)\,dx&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\int_{a}^{b} u\,dx \pm \int_{a}^{b} v\,dx = \int_{a}^{b} (u \pm v)\,dx&#xA;$$&lt;/div&gt;&#xA;&lt;div&gt;$$&#xA;\frac{d}{dx} \int_{a}^{x} u\,du = f(x)&#xA;$$&lt;/div&gt;&#xA;&lt;h3 id=&#34;numerical-methods-for-evaluating-definite-integrals&#34;&gt;Numerical Methods for Evaluating Definite Integrals&lt;/h3&gt;&#xA;&lt;h4 id=&#34;trapezoid-rule&#34;&gt;Trapezoid Rule&lt;/h4&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s imagine that we have a curve for which it&amp;rsquo;s impossible to find the antiderivative, and thus the area below the curve. Instead of calculating it, we can approximate its value by using trapezoids instead of rectangles, as we&amp;rsquo;ve done before. We also know that approximating the area below the curve using the $\min(f(x))$ value found in the interval $[a, b]$ multiplied by $b - a$ (denoted as $\Delta{x}$) gives a lower bound of the area below the curve:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\underline{S_n} = y_0 \Delta{x} + y_1 \Delta{x} + \ldots y_{n-1} \Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Another approximation was using the $\max(f(x))$ value found in the interval $[a, b]$ multiplied by $b - a$ (denoted as $\Delta{x}$), which gives the upper bound of the area below the curve:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\overline{S_n} = y_1 \Delta{x} + y_2 \Delta{x} + \ldots y_{n} \Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Calculating the average of these sums will definitely give an approximate result:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;S_n = \tfrac{1}{2} (y_0 + y_1) \Delta{x} + \tfrac{1}{2} (y_1 + y_2) \Delta{x} + \ldots +&#xA;\tfrac{1}{2} (y_{n-1} + y_n) \Delta{x}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Each of these terms is the &#xA;&#xA;&lt;a href=&#34;https://www.wikiwand.com/en/Trapezoid#/Area&#34;target=&#34;_blank&#34;&gt;area of a trapezoid&lt;/a&gt;&#xA;&#xA; of height $\Delta{x}$ and bases $y_i$, $y_{i + 1}$.&lt;/p&gt;&#xA;&lt;div id=&#34;numerical-trapezoid&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;Rewriting the equation above:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\int_{a}^b f(x)\,dx \approx \Delta{x} \cdot (\tfrac{1}{2}y_0 + y_1 + y_2 + \ldots + y_{n-1} + \tfrac{1}{2} y_n)&#xA;$$&lt;/div&gt;&#xA;&lt;h4 id=&#34;simpsons-rulesimpson&#34;&gt;[Simpson&amp;rsquo;s Rule][simpson]&lt;/h4&gt;&#xA;&lt;p&gt;Simpson&amp;rsquo;s rule approximates the value of a definite integral by using quadratic polynomials of the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{quadratic}&#xA;y = ax^2 + bx + c&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;which pass through three points belonging to the curve, which are $(-h, y_0)$, $(0, y_1)$, and $(h, y_2)$.&lt;/p&gt;&#xA;&lt;div id=&#34;numerical-simpson&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;The area below the curve bounded by $[-h, h]$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;A &amp;= \int_{-h}^{h} (ax^2 + bx + c) \; dx \\&#xA;  &amp;= \frac{ax^3}{3} + \frac{bx^2}{2} + cx \; \Big|_{-h}^h \\&#xA;  &amp;= \frac{2ah^3}{3} + 2ch \\&#xA;  &amp;= \frac{h}{3} (2ah^2 + 6c)&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Since the points $(-h, y_0)$, $(0, y_1)$, and $(h, y_2)$ are on the curve, they satisfy \eqref{quadratic}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;y_0 &amp;= ah^2 - bh + c \\&#xA;y_1 &amp;= c \\&#xA;y_2 &amp;= ah^2 + bh + c&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The quantity:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y_0 + 4y_1 + y_2 = (ah^2 - bh + c) + 4c + (ah^2 + bh + c) = 2ah^2 + 6c&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;is equal to a part of the area under the quadratic polynomial found above. Therefore:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;A = \frac{h}{3} (y_0 + 4y_1 + y_2)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To find the area bounded by $[a, b]$, we have to take an even number $n$ of subintervals of equal length:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;h = \frac{b - a}{n}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$n$ subintervals are defined with $n + 1$ points, which are:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;x_0 = a, \quad x_1 = a + h, \quad x_2 = a + 2h, \quad \ldots, \quad x_n = a + nh = b&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can estimate the value of the integral by adding the areas computed for each unique contiguous pair of subintervals:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{align*}&#xA;\int_{a}^{b} f(x) \; dx &amp;\approx \tfrac{h}{3} (y_0 + 4y_1 + y_2) + \tfrac{h}{3} (y_2 + 4y_3 + y_4) + \cdots + \tfrac{h}{3} (y_{n-2} + 4y_{n-1} + y_n) \\&#xA;  &amp;\approx \tfrac{h}{3} (y_0 + 4y_1 + 2y_2 + 4y_3 + 2y_4 + \ldots + 4y_{n-1} + y_n) \\&#xA;\end{align*}&#xA;$$&lt;/div&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/calculus/integral.js&#34;&gt;&lt;/script&gt;&#xA;&lt;h3 id=&#34;physical-applications-of-the-definite-integral&#34;&gt;Physical Applications of the Definite Integral&lt;/h3&gt;&#xA;&lt;h4 id=&#34;the-calculation-of-work&#34;&gt;The Calculation of Work&lt;/h4&gt;&#xA;&lt;p&gt;When a force applied to an object causes a displacement, it&amp;rsquo;s said that &lt;strong&gt;work&lt;/strong&gt; was done upon the object. This quantity, expressed with the symbol $W$, is the product:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;W = Fs&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;As an example, let&amp;rsquo;s calculate the work done by the force of gravity. Choosing the direction from the center of the Earth upward as the positive direction, we can use Newton&amp;rsquo;s law for gravitation. This law states that any two objects attract each other, and this force is given quantitatively by:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;F = \frac{GmM}{r^2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;$G$ is a constant, $m$ and $M$ are the masses of the two objects, and $r$ is the distance between the objects (idealized as point particles).&lt;/p&gt;&#xA;&lt;p&gt;Since this force of gravity actually pulls objects towards the center of the Earth, and we chose the direction from the center of the Earth upward as positive, this quantity must be negative:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{gravity}&#xA;F = -\frac{GmM}{r^2}&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To calculate the work done by gravity, we cannot multiply the force of gravity by the displacement because the force actually varies from point to point along the path. Suppose the object is at some distance $r$ from the center of the Earth and gravity pulls the object downward a small distance $\Delta{r}$. Then the work done by gravity is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\Delta{W} = F\Delta{r}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;By division:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{\Delta{W}}{\Delta{r}} = F&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We now determine the limit of $\tfrac{\Delta{W}}{\Delta{r}}$ as $\Delta{r}$ approaches 0, which is the rate of change of work with respect to the displacement over the path:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dW}{dr} = \lim_{\Delta{r} \to 0} \frac{\Delta{W}}{\Delta{r}} = F&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Replacing \eqref{gravity}:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{dW}{dr} = -\frac{GmM}{r^2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To find $W$, we apply an antidifferentiation process:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;W = \int{-\frac{GmM}{r^2}} = \frac{GmM}{r} + C&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Assuming that initially, when the object was at $r = r_1$, there was no force being applied to it, therefore $W = 0$ and $C = -GmM/r_1$, and:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;W = \frac{GmM}{r} - \frac{GmM}{r_1}&#xA;$$&lt;/div&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;Excerpt From: Morris Kline. “Calculus: An Intuitive and Physical Approach (Second Edition).”&#xA;[simpson]: &#xA;&#xA;&lt;a href=&#34;http://pages.pacificcoast.net/~cazelais/187/simpson.pdf&#34;target=&#34;_blank&#34;&gt;http://pages.pacificcoast.net/~cazelais/187/simpson.pdf&lt;/a&gt;&#xA;&#xA;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
    </item>
    <item>
      <title>Taylor&#39;s Theorem and Infinite Series</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/calculus/taylor-theorem-infinite-series/</link>
      <pubDate>Thu, 02 Apr 2015 10:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/calculus/taylor-theorem-infinite-series/</guid>
      <description>&lt;p&gt;There are simple functions for which we cannot find antiderivatives in terms of the functions we know. Some examples are:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\frac{\sin(x)}{x} \quad\quad e^{-x^2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Another problem that arises in calculus is calculating the values of functions. For a given polynomial like $3x^2 + 7x + 1$, it&amp;rsquo;s simple to calculate the value of the function for various values of $x$, but it&amp;rsquo;s not so simple for a function like $\sin(x)$. To calculate the value of the function at some value of $x$, we would have to construct a right triangle containing the desired angle $x$ and then measure the opposite side and the hypotenuse. However, this process is not very accurate if $x$ is, for example, 30°50&#39;47&amp;quot;.&lt;/p&gt;&#xA;&lt;p&gt;The answer to the problems above is to approximate unmanageable functions with manageable ones, while also precisely determining the incurred error. If we are to approximate a given function $f(x)$ by $g(x)$, we should make $g(x)$ relatively simple so that we can calculate its values. The simplest functions to work with are &lt;em&gt;polynomials&lt;/em&gt;, and therefore we should approximate the function by polynomials.&lt;/p&gt;&#xA;&lt;p&gt;First, let&amp;rsquo;s look into the simpler problem of approximating a function around one value of $x$. Let&amp;rsquo;s say that we have the function $f(x)$ and we want to approximate its value near $x = 0$. Let&amp;rsquo;s consider the polynomial $g(x)$ as an approximation to $f(x)$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{gx}&#xA;g(x) = c_0 + c_1x + c_2x^2 + \cdots + c_nx^n&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can make $g(x)$ agree with $f(x)$ at $x = 0$ because, with $g(0) = c_0$, we can take $c_0$ to be $f(0)$. If we expect that $g(x)$ is an approximation of $f(x)$ at $x = 0$, we would also expect that the tangent line at $x = 0$ approximates the curve closely at the point of tangency. Hence, we should make the slope of $g(x)$ agree with the slope of $f(x)$ at $x = 0$. Applying a differentiation process to $g(x)$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;g&#39;(x) = c_1 + 2c_2x + 3c_3x^2 + 4c_4x^3 + \cdots + nc_nx^{n-1}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;At $x = 0$, $g&amp;rsquo;(0) = c_1$. If $g&amp;rsquo;(0)$ agrees with $f&amp;rsquo;(0)$, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c_1 = f&#39;(0)&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can apply the same idea by making $g&amp;rsquo;&amp;rsquo;(x)$ agree with $f&amp;rsquo;&amp;rsquo;(x)$ at $x = 0$. Applying a differentiation process to $g&amp;rsquo;(x)$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;g&#39;&#39;(x) = 2c_2 + 2 \cdot 3c_3x^1 + 3 \cdot 4c_4x^2 + \cdots + n(n - 1)c_nx^{n-2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then $g&amp;rsquo;&amp;rsquo;(0) = 2c_2$, and if $g&amp;rsquo;&amp;rsquo;(0)$ is the same as $f&amp;rsquo;&amp;rsquo;(0)$, then $f&amp;rsquo;&amp;rsquo;(0) = 2c_2$, or:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c_2 = \frac{f&#39;&#39;(0)}{2}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;To determine $c_3$, we would make the third derivatives of both functions agree at $x = 0$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;g&#39;&#39;&#39;(x) = 2 \cdot 3c_3 + 2 \cdot 3 \cdot 4c_4x + \cdots + n(n - 1)(n - 2)c_nx^{n-3}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then $g&amp;rsquo;&amp;rsquo;&amp;rsquo;(0) = 2 \cdot 3c_3$, which is the same as $f&amp;rsquo;&amp;rsquo;&amp;rsquo;(0)$, then:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c_3 = \frac{f&#39;&#39;&#39;(0)}{2 \cdot 3}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We can see that the $n$-th derivative of $g(x)$ is $g^{(n)}(x) = n(n - 1)(n - 2)\ldots$, and if $g^{(n)}(0)$ is equal to $f^{(n)}(0)$:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;c_n = \frac{f^{(n)}(0)}{n(n-1)(n-2) \ldots 2 \cdot 1} = \frac{f^{(n)}(0)}{n!}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Because we used the condition that each pair of successive derivatives agree at $x = 0$, $g(x)$ takes the form:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;g(x) = f(0) + f&#39;(0)x + \frac{f&#39;&#39;(0)}{2!}x^2 + \cdots + \frac{f^{(n)}(0)}{n!}x^n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;We could equally make the approximation near any other value of $x$, e.g., $x = a$. Thus, the proper form of $g(x)$ which generalizes on the form \eqref{gx} is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;g(x) = c_0 + c_1(x - a) + c_2(x - a)^2 + \cdots + c_n(x - a)^n&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Then the final formula for approximating any function $f(x)$ by a polynomial $g(x)$ near $x = a$ is:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;\begin{equation}\label{taylor}&#xA;g(x) = f(a) + f&#39;(a)(x - a) + \frac{f&#39;&#39;(a)}{2!}(x - a)^2 + \cdots + \frac{f^{(n)}(a)}{n!}(x - a)^n&#xA;\end{equation}&#xA;$$&lt;/div&gt;&#xA;&lt;h2 id=&#34;taylors-theorem&#34;&gt;Taylor&amp;rsquo;s Theorem&lt;/h2&gt;&#xA;&lt;p&gt;\eqref{taylor} approximates the value of a function $f(x)$ at the point $a$; however, we do not know how good the approximation is numerically. At $x = a, g(a) = f(a)$, which is exact. However, for any $x$ near $a$, like $a + h, g(a + h) \approx f(a + h)$. The difference $f(a + h) - g(a + h)$ is the error in approximating $f(x)$ by the polynomial $g(x)$. The formula that approximates $f(x)$, considering also the error, was first given by Brook Taylor.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;For any function $f(x)$ which has $(n + 1)$ derivatives in the interval from $a$ to $x$:&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;div&gt;$$&#xA;f(x) = f(a) + f&#39;(a)(x - a) + f&#39;&#39;(a)\frac{(x - a)^2}{2!} + \cdots + f^n(a) \frac{(x - a)^n}{n!} + f^{(n + 1)}(\mu) \frac{(x - a)^{n + 1}}{(n + 1)!}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Where $\mu$ is between $x$ and $a$.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Introduction to Calculus</title>
      <link>https://www.mauriciopoppe.com/notes/mathematics/calculus/introduction/</link>
      <pubDate>Tue, 31 Mar 2015 15:35:06 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/notes/mathematics/calculus/introduction/</guid>
      <description>&lt;h3 id=&#34;why&#34;&gt;Why?&lt;/h3&gt;&#xA;&lt;p&gt;Calculus was created to solve some problems that other branches of math were not adequate to treat:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Determination of tangents to various curves (e.g., to determine the course of a light ray after it strikes the surface of a lens).&lt;/li&gt;&#xA;&lt;li&gt;Finding the minima/maxima (e.g., determination of the maximum range of a projectile, maximum/minimum distance of a planet that is moving about the sun).&lt;/li&gt;&#xA;&lt;li&gt;Length of curves, areas, and volumes of figures bounded by curves.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To solve these problems, the following concepts are needed:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Limit (fundamental to formulate the derivative and the integral).&lt;/li&gt;&#xA;&lt;li&gt;Derivative.&lt;/li&gt;&#xA;&lt;li&gt;Integral.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;the-concept-of-a-function&#34;&gt;The Concept of a Function&lt;/h3&gt;&#xA;&lt;p&gt;A function is the relation between variables (whose value can be expressed numerically). The most effective mathematical representation of a function is through a &lt;em&gt;formula&lt;/em&gt; like the one below:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;s = 16 t^2&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;The above formula says that when $t=2$, then $s=16 \cdot 2^2 = 64$ and is represented as $s_2$. For each value of $t$, there&amp;rsquo;s a corresponding value of $s$. In the above form, $t$ is the &lt;em&gt;independent&lt;/em&gt; variable, and $s$ is the &lt;em&gt;dependent&lt;/em&gt; variable. If we solve the equation above for $t$, we have:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;t = \pm \sqrt{\frac{s}{16}}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;Now $s$ is the &lt;em&gt;independent&lt;/em&gt; variable, and $t$ is the dependent variable.&lt;/p&gt;&#xA;&lt;p&gt;The notation $f(x)$ can also represent functions without extensive verbiage, e.g., $f(x) = x^2 - 9$. This notation also has the advantage of telling us which is the &lt;em&gt;independent&lt;/em&gt; variable. If we want to calculate the value of the function, we can use something like $f(3)$, which is the value of $f(x)$ when $x = 3$.&lt;/p&gt;&#xA;&lt;p&gt;A formula can also be represented as a curve (this method of interpreting formulas geometrically is known as &lt;em&gt;analytic geometry&lt;/em&gt;). Let&amp;rsquo;s represent the following function below using a curve:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y = x^2&#xA;$$&lt;/div&gt;&#xA;&lt;div id=&#34;formula-as-a-curve&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;The function above is simple in that for each value of $x$, there&amp;rsquo;s a corresponding value of $y$. However, the concept of a function does not require this. For example, the function:&lt;/p&gt;&#xA;&lt;div&gt;$$&#xA;y = \frac{1}{x}&#xA;$$&lt;/div&gt;&#xA;&lt;p&gt;does not have a valid value when $x = 0$. This means that the function exists for each value of $x$ other than $0$.&lt;/p&gt;&#xA;&lt;div id=&#34;for-other-than-0&#34;&gt;&lt;/div&gt;&#xA;&lt;p&gt;The concept of a function, then, doesn&amp;rsquo;t require that there&amp;rsquo;s a $y$ for every $x$, but it does require a $y$-value for each value $x$ in some collection/set of $x$ values. The collection of $x$ values for which a $y$ value exists is called the &lt;em&gt;domain&lt;/em&gt;, and the collection of the corresponding $y$ values is called the &lt;em&gt;range&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;script src=&#34;https://www.mauriciopoppe.com/js/calculus/intro.js&#34;&gt;&lt;/script&gt;&#xA;&lt;p&gt;&lt;em&gt;Image taken from &#xA;&#xA;&lt;a href=&#34;https://wordsmithofbengal.wordpress.com/2021/08/02/dr-philos-the-creative-fantasy-of-differential-and-integral-calculus/&#34;target=&#34;_blank&#34;&gt;https://wordsmithofbengal.wordpress.com/2021/08/02/dr-philos-the-creative-fantasy-of-differential-and-integral-calculus/&lt;/a&gt;&#xA;&#xA;&lt;/em&gt;&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Chai</title>
      <link>https://www.mauriciopoppe.com/recipes/chai/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.mauriciopoppe.com/recipes/chai/</guid>
      <description></description>
    </item>
  </channel>
</rss>
