<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://systemhalted.in/feed.xml" rel="self" type="application/atom+xml" /><link href="https://systemhalted.in/" rel="alternate" type="text/html" /><updated>2026-02-06T03:56:36+00:00</updated><id>https://systemhalted.in/feed.xml</id><title type="html">The System Halted</title><subtitle>SystemHalted - I am just a DOS error</subtitle><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><entry><title type="html">Insight Agents and the End of Dashboard-Driven Analytics</title><link href="https://systemhalted.in/2026/02/06/insight-agents-end-of-dashboards/" rel="alternate" type="text/html" title="Insight Agents and the End of Dashboard-Driven Analytics" /><published>2026-02-06T00:00:00+00:00</published><updated>2026-02-06T00:00:00+00:00</updated><id>https://systemhalted.in/2026/02/06/insight-agents-end-of-dashboards</id><content type="html" xml:base="https://systemhalted.in/2026/02/06/insight-agents-end-of-dashboards/"><![CDATA[<p>I just finished reading the Amazon Research paper <em>“Insight Agents: An LLM-Based Multi-Agent System for Data Insights”</em><sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> and this is the first time I have seen a truly production-minded attempt to close the gap between dashboards that show data and systems that actually help make decisions..</p>

<p>This is not a chatbot over a database.<br />
This is not Text-to-SQL dressed up as AI.</p>

<p>This is a hierarchical multi-agent system that actually understands how business questions turn into data queries and then into insights.</p>

<p>What really stood out to me was the engineering discipline.</p>

<p>They did <strong>not</strong> use an LLM for everything.</p>

<ul>
  <li>
    <p>An auto-encoder handles intent detection in <strong>0.009 seconds</strong> instead of 1.6 seconds.</p>
  </li>
  <li>
    <p>A fine-tuned BERT model handles routing in <strong>0.3 seconds</strong> instead of ~2 seconds.</p>
  </li>
</ul>

<p>Only after this fast triage does the LLM come in for reasoning and narrative insight generation.</p>

<p>Small models for speed.<br />
LLM for thinking.</p>

<p>That pattern alone is worth studying.</p>

<p>They also avoid naive Text-to-SQL. Instead, they use augmented querying with business context, APIs, and plan-and-execute workflows. The system breaks a question into steps, fetches the right data, and produces explanations that humans can actually act on.</p>

<p>In their evaluation, 90th percentile latency is under ~13 seconds with ~89% relevance and correctness judged by humans.</p>

<p>That is interactive. That is usable. That is very close to real.</p>

<p>The most important idea here is this:</p>

<p>You don’t explore dashboards anymore.</p>

<p>You ask questions to a system that already understands your schema, your metrics, your seasonality, and your business vocabulary.</p>

<p>And it tells you what happened and why.</p>

<p>This does not replace BI teams or data engineers.</p>

<p>It amplifies them.</p>

<p>It turns data infrastructure into a thinking layer for the business.</p>

<p>If you are building analytics platforms, GenAI agents, or data products, this paper is worth your time.</p>

<p>The future of analytics is not more charts.</p>

<p>It is conversational understanding over structured data.</p>

<h2 id="references">References</h2>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Paper, https://arxiv.org/pdf/2601.20048 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Software Engineering" /><category term="Computer Science" /><category term="Data" /><category term="AI" /><category term="analytics" /><category term="agentic-ai" /><category term="genai" /><category term="llm" /><category term="multi-agent-systems" /><category term="data-insights" /><category term="business-intelligence" /><category term="amazon-research" /><summary type="html"><![CDATA[Why Insight Agents signal a shift from dashboard-driven analytics to conversational, agentic systems that prioritize speed, context, and real business understanding.]]></summary></entry><entry><title type="html">Part 8: Big Decimal Rounding Modes - Why HALF_UP Isn’t Always the Answer</title><link href="https://systemhalted.in/2026/02/05/rounding-modes-why-half-up-isnt-always-the-answer/" rel="alternate" type="text/html" title="Part 8: Big Decimal Rounding Modes - Why HALF_UP Isn’t Always the Answer" /><published>2026-02-05T00:00:00+00:00</published><updated>2026-02-05T00:00:00+00:00</updated><id>https://systemhalted.in/2026/02/05/rounding-modes-why-half-up-isnt-always-the-answer</id><content type="html" xml:base="https://systemhalted.in/2026/02/05/rounding-modes-why-half-up-isnt-always-the-answer/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>In <a href="https://systemhalted.in/2026/01/11/kahan-summation-java-streams/">Part 7</a>, we tackled summation error with Kahan compensation. Now we zoom in on a different precision trap: the moment you round a value to fewer digits.</p>

<p>Rounding is one of those “small” problems that quietly eats your lunch, your audit trail, and your sleep.</p>

<p>Most teams pick a rounding mode the way people pick a Netflix show: whatever was already playing.</p>

<p>In Java, that default story often becomes:</p>

<blockquote>
  <p>“We’ll use <code class="language-plaintext highlighter-rouge">HALF_UP</code>. That’s normal rounding. Done.”</p>
</blockquote>

<p>And then you ship a pricing engine, a statement generator, a ledger, a tax calculator, or an amortization schedule…</p>

<p>…and then you discover that <strong>rounding is policy</strong>, not maths. Fine. It’s maths. But it’s maths with consequences.</p>

<p>This post is about <strong>choosing rounding modes intentionally</strong>, and why <code class="language-plaintext highlighter-rouge">HALF_UP</code> is not the universal solvent people think it is.</p>

<h2 id="cheat-sheet">Quick Reference: Rounding Mode Cheat Sheet</h2>

<table>
  <thead>
    <tr>
      <th>Mode</th>
      <th>Behavior</th>
      <th>When</th>
      <th>Jump</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">HALF_EVEN</code></td>
      <td>Ties -&gt; nearest even digit</td>
      <td>Aggregates, reducing bias</td>
      <td><a href="#use-half-even">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">HALF_UP</code></td>
      <td>Ties -&gt; away from zero</td>
      <td>Schoolbook rounding, retail</td>
      <td><a href="#use-half-up">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">HALF_DOWN</code></td>
      <td>Ties -&gt; toward zero</td>
      <td>Policy requires ties toward zero (rare; document it)</td>
      <td><a href="#toolbox">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">UP</code></td>
      <td>Always away from zero</td>
      <td>Conservative bounds (never underestimate magnitude)</td>
      <td><a href="#toolbox">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DOWN</code></td>
      <td>Always toward zero</td>
      <td>Fee caps, conservative limits</td>
      <td><a href="#use-down">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">CEILING</code></td>
      <td>Toward +∞ (1.231 -&gt; 1.24, -1.231 -&gt; -1.23)</td>
      <td>“At least” constraints</td>
      <td><a href="#use-ceiling-floor">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">FLOOR</code></td>
      <td>Toward -∞ (1.231 -&gt; 1.23, -1.231 -&gt; -1.24)</td>
      <td>“At most” constraints</td>
      <td><a href="#use-ceiling-floor">↓</a></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">UNNECESSARY</code></td>
      <td>Throw if rounding needed</td>
      <td>Validation, catching assumptions</td>
      <td><a href="#use-unnecessary">↓</a></td>
    </tr>
  </tbody>
</table>

<p><strong>Key rules:</strong></p>
<ul>
  <li>Avoid rounding double when policy matters: use BigDecimal from strings → <a href="#classic-trap">The Classic Trap</a></li>
  <li>Decide <em>when</em> to round, not just <em>how</em> → <a href="#rounding-timing">Rounding Timing</a></li>
  <li>For money, use scaled integers internally → <a href="#money-pattern">Money Pattern</a></li>
</ul>

<hr />

<h2 id="ties">The real problem: ties (the 5s)</h2>

<p>Most rounding drama is not about 2.341 vs 2.34. It’s about <em>ties</em>: values exactly halfway between representable steps.</p>

<p>At 2 decimal places, these are the spicy ones:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">1.005</code></li>
  <li><code class="language-plaintext highlighter-rouge">2.675</code></li>
  <li><code class="language-plaintext highlighter-rouge">10.125</code></li>
</ul>

<p>It’s a tie only when the first discarded digit is 5 and all following discarded digits are 0, for the scale you’re rounding to (e.g., <code class="language-plaintext highlighter-rouge">1.005</code> or <code class="language-plaintext highlighter-rouge">1.00500...</code> when rounding to 2 decimals).</p>

<p>A value like <code class="language-plaintext highlighter-rouge">1.0051</code> is not a tie - it’s closer to <code class="language-plaintext highlighter-rouge">1.01</code>.</p>

<p>If you always push ties upward, you introduce a systematic bias. Sometimes that bias is desired. Often it’s not. Sometimes it’s illegal. Sometimes it’s fine but your reconciliation team will develop a new religion and curse your name in it.</p>

<h2 id="toolbox">Java’s rounding toolbox</h2>

<p>Here is what Java offers. The real work is choosing a policy that matches your domain contract. Java gives you <code class="language-plaintext highlighter-rouge">java.math.RoundingMode</code>:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">HALF_UP</code> - round to nearest; if exactly halfway, round away from zero (1.5 -&gt; 2, -1.5 -&gt; -2)</li>
  <li><code class="language-plaintext highlighter-rouge">HALF_DOWN</code> - round to nearest; if exactly halfway, round toward zero (1.5 -&gt; 1, -1.5 -&gt; -1)</li>
  <li><code class="language-plaintext highlighter-rouge">HALF_EVEN</code> - round to nearest; if exactly halfway, round to the result whose last kept digit is even (banker’s rounding, also called round-half-to-even)</li>
  <li><code class="language-plaintext highlighter-rouge">UP</code> - always away from zero</li>
  <li><code class="language-plaintext highlighter-rouge">DOWN</code> - always toward zero (truncate)</li>
  <li><code class="language-plaintext highlighter-rouge">CEILING</code> - toward positive infinity (-1.231 -&gt; -1.23, 1.231 -&gt; 1.24 at 2dp)</li>
  <li><code class="language-plaintext highlighter-rouge">FLOOR</code> - toward negative infinity (-1.231 -&gt; -1.24, 1.231 -&gt; 1.23 at 2dp)</li>
  <li><code class="language-plaintext highlighter-rouge">UNNECESSARY</code> - throw if rounding would be required (my favorite “make bugs loud” mode)</li>
</ul>

<p>Also remember: <code class="language-plaintext highlighter-rouge">setScale(...)</code> without a rounding mode throws if rounding is required.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.234"</span><span class="o">).</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span> <span class="c1">// throws ArithmeticException</span></code></pre></figure>

<p>And the most important practical rule:</p>

<p><strong>If you care about exact decimal policy, avoid rounding a <code class="language-plaintext highlighter-rouge">double</code>. Round a <code class="language-plaintext highlighter-rouge">BigDecimal</code> created from a string (or exact integer scale).</strong></p>

<h3 id="classic-trap">The classic trap: <code class="language-plaintext highlighter-rouge">new BigDecimal(double)</code></h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.math.BigDecimal</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.math.RoundingMode</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">RoundingTrap</span> <span class="o">{</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">BigDecimal</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">1.005</span><span class="o">);</span>               <span class="c1">// from double</span>
    <span class="nc">BigDecimal</span> <span class="n">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.005"</span><span class="o">);</span>             <span class="c1">// from string</span>

    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">));</span> <span class="c1">// 1.00</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">b</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">));</span> <span class="c1">// 1.01</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>What you <em>expect</em>: both become <code class="language-plaintext highlighter-rouge">1.01</code></p>

<p>What often happens: the first becomes <code class="language-plaintext highlighter-rouge">1.00</code> because <code class="language-plaintext highlighter-rouge">1.005</code> as a binary floating value is actually a hair under 1.005.</p>

<p>If you’re in finance and you see “1.005 rounds to 1.00”, that’s not “Java being weird”. That’s <strong>you feeding approximate binary into exact decimal rounding</strong> and being surprised it behaves like… approximation.</p>

<h3 id="valueof">What about <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf()</code>?</h3>

<p>There’s a middle ground that readers constantly trip over: <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code>.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">1.005</span><span class="o">);</span>        <span class="c1">// Dangerous: uses exact binary representation</span>
<span class="nc">BigDecimal</span> <span class="n">b</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mf">1.005</span><span class="o">);</span>    <span class="c1">// Safer: uses Double.toString() internally</span>
<span class="nc">BigDecimal</span> <span class="n">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.005"</span><span class="o">);</span>      <span class="c1">// Safest: exact decimal from string</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code> often behaves like the string constructor because it uses <code class="language-plaintext highlighter-rouge">Double.toString()</code> internally, which gives you the shortest decimal representation that round-trips correctly.</p>

<p>The rule of thumb:</p>
<ul>
  <li>Use <code class="language-plaintext highlighter-rouge">new BigDecimal("...")</code> for literals and external decimal inputs</li>
  <li>Use <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code> only when you already have a double and need the best possible decimal view of it (still risky after computations, but better than <code class="language-plaintext highlighter-rouge">new BigDecimal(double)</code>)</li>
  <li>Never use <code class="language-plaintext highlighter-rouge">new BigDecimal(double)</code> unless you explicitly want the exact binary-to-decimal conversion</li>
</ul>

<p>One caution: if the double came from arithmetic, the value you’re “viewing” may already be far from the decimal you think you had. <code class="language-plaintext highlighter-rouge">valueOf</code> is not a magical cleansing ritual.</p>

<h2 id="half-up-bias">Why HALF_UP can be the wrong default</h2>

<p><code class="language-plaintext highlighter-rouge">HALF_UP</code> is intuitive. It matches what humans do with pencil maths. But for repeated operations, it can create <strong>drift</strong> because ties always go one way.</p>

<p><strong>IEEE 754 connection</strong>: IEEE 754’s default rounding mode is “round to nearest, ties to even” - essentially <code class="language-plaintext highlighter-rouge">HALF_EVEN</code>. Java <code class="language-plaintext highlighter-rouge">double</code> results are specified to behave as if rounded that way for each operation. The irony is that when you switch to <code class="language-plaintext highlighter-rouge">BigDecimal</code> for precision, many developers then pick <code class="language-plaintext highlighter-rouge">HALF_UP</code>, introducing the very bias that IEEE 754 was designed to avoid.</p>

<h3 id="bias-demo">Bias demo: HALF_UP vs HALF_EVEN</h3>

<p>Let’s imagine you have many values that land exactly on ties at 2 decimals (it happens more than people think, especially after division and intermediate scaling).</p>

<p>Here’s the “policy difference” in one glance:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">HALF_UP</code>: <code class="language-plaintext highlighter-rouge">1.005 -&gt; 1.01</code>, <code class="language-plaintext highlighter-rouge">1.015 -&gt; 1.02</code>, <code class="language-plaintext highlighter-rouge">1.025 -&gt; 1.03</code> … always nudging up</li>
  <li><code class="language-plaintext highlighter-rouge">HALF_EVEN</code>: <code class="language-plaintext highlighter-rouge">1.005 -&gt; 1.00</code>, <code class="language-plaintext highlighter-rouge">1.015 -&gt; 1.02</code>, <code class="language-plaintext highlighter-rouge">1.025 -&gt; 1.02</code> … nudging toward even to cancel bias over time</li>
</ul>

<p>Notice how HALF_EVEN alternates which side ‘wins’ on ties; HALF_UP always pushes the same direction. This is why <strong>banking and accounting systems often prefer <code class="language-plaintext highlighter-rouge">HALF_EVEN</code></strong>: it reduces systematic rounding bias across large aggregates.</p>

<h3 id="bias-action">The bias in action</h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.math.BigDecimal</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.math.RoundingMode</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">BiasDemonstration</span> <span class="o">{</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">String</span><span class="o">[]</span> <span class="n">ties</span> <span class="o">=</span> <span class="o">{</span><span class="s">"1.005"</span><span class="o">,</span> <span class="s">"1.015"</span><span class="o">,</span> <span class="s">"1.025"</span><span class="o">,</span> <span class="s">"1.035"</span><span class="o">,</span> <span class="s">"1.045"</span><span class="o">,</span>
                     <span class="s">"1.055"</span><span class="o">,</span> <span class="s">"1.065"</span><span class="o">,</span> <span class="s">"1.075"</span><span class="o">,</span> <span class="s">"1.085"</span><span class="o">,</span> <span class="s">"1.095"</span><span class="o">};</span>
    
    <span class="nc">BigDecimal</span> <span class="n">sumHalfUp</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">ZERO</span><span class="o">;</span>
    <span class="nc">BigDecimal</span> <span class="n">sumHalfEven</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">ZERO</span><span class="o">;</span>
    <span class="nc">BigDecimal</span> <span class="n">trueSum</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">ZERO</span><span class="o">;</span>
    
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Value   -&gt; HALF_UP / HALF_EVEN"</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">tie</span> <span class="o">:</span> <span class="n">ties</span><span class="o">)</span> <span class="o">{</span>
      <span class="nc">BigDecimal</span> <span class="n">bd</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="n">tie</span><span class="o">);</span>
      <span class="nc">BigDecimal</span> <span class="n">roundedUp</span> <span class="o">=</span> <span class="n">bd</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
      <span class="nc">BigDecimal</span> <span class="n">roundedEven</span> <span class="o">=</span> <span class="n">bd</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_EVEN</span><span class="o">);</span>
      
      <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">tie</span> <span class="o">+</span> <span class="s">" -&gt; "</span> <span class="o">+</span> <span class="n">roundedUp</span> <span class="o">+</span> <span class="s">" / "</span> <span class="o">+</span> <span class="n">roundedEven</span><span class="o">);</span>
      
      <span class="n">sumHalfUp</span> <span class="o">=</span> <span class="n">sumHalfUp</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">roundedUp</span><span class="o">);</span>
      <span class="n">sumHalfEven</span> <span class="o">=</span> <span class="n">sumHalfEven</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">roundedEven</span><span class="o">);</span>
      <span class="n">trueSum</span> <span class="o">=</span> <span class="n">trueSum</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">bd</span><span class="o">);</span>
    <span class="o">}</span>
    
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">();</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"HALF_UP sum:   "</span> <span class="o">+</span> <span class="n">sumHalfUp</span><span class="o">);</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"HALF_EVEN sum: "</span> <span class="o">+</span> <span class="n">sumHalfEven</span><span class="o">);</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"True sum:      "</span> <span class="o">+</span> <span class="n">trueSum</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">));</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Output:</p>

<figure class="highlight"><pre><code class="language-plaintext" data-lang="plaintext">Value   -&gt; HALF_UP / HALF_EVEN
1.005 -&gt; 1.01 / 1.00
1.015 -&gt; 1.02 / 1.02
1.025 -&gt; 1.03 / 1.02
1.035 -&gt; 1.04 / 1.04
1.045 -&gt; 1.05 / 1.04
1.055 -&gt; 1.06 / 1.06
1.065 -&gt; 1.07 / 1.06
1.075 -&gt; 1.08 / 1.08
1.085 -&gt; 1.09 / 1.08
1.095 -&gt; 1.10 / 1.10

HALF_UP sum:   10.55
HALF_EVEN sum: 10.50
True sum:      10.50</code></pre></figure>

<p>Ten values. A nickel of drift. Scale that to millions of transactions.</p>

<h3 id="pennies-from-heaven">The “pennies from heaven” problem</h3>

<p>If you process millions of transactions where ties are common, <code class="language-plaintext highlighter-rouge">HALF_UP</code> can consistently favor one party. That might mean your company “wins” fractions of a cent more often than it “loses”. That sounds fun until regulators, auditors, or customers notice.</p>

<p>So the question isn’t “which is mathematically correct?” The question is:</p>

<p><strong>Which rounding policy matches the domain contract?</strong></p>

<h2 id="rounding-timing">Rounding is not only <em>mode</em>. It’s also <em>when</em>.</h2>

<p>Two designs:</p>

<ol>
  <li>Round at every step (easy, often wrong)</li>
  <li>Keep high precision internally, round only at boundaries (harder, usually right)</li>
</ol>

<h3 id="invoices">Example: line items and invoices</h3>

<p>Consider:</p>
<ul>
  <li>Price per item has 4 decimal precision</li>
  <li>Currency is 2 decimals</li>
  <li>Taxes computed on totals, not per line (common)</li>
</ul>

<p>If you round too early, the invoice total can differ from the expected ledger total.</p>

<p>Policy choices matter:</p>
<ul>
  <li>Round each line item then sum</li>
  <li>Sum unrounded lines then round once</li>
  <li>Compute tax per line then sum tax</li>
  <li>Compute tax on total then round tax once</li>
</ul>

<p>All are “reasonable”. Only one matches your business rules. Pick explicitly. Document it. Test it.</p>

<h2 id="money-pattern">A practical Java pattern: Money as scaled integer</h2>

<p>For currency, the simplest <em>correct</em> representation is usually:</p>
<ul>
  <li>store money as <code class="language-plaintext highlighter-rouge">long</code> minor units (cents)</li>
  <li>do arithmetic in integers</li>
  <li>only convert for display</li>
</ul>

<p>This avoids a lot of BigDecimal overhead and removes the “oops I rounded twice” class of bugs.</p>

<h3 id="money-type">Simple Money type (cents)</h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.math.BigDecimal</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.math.RoundingMode</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Money</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="kd">final</span> <span class="kt">long</span> <span class="n">cents</span><span class="o">;</span>

  <span class="kd">private</span> <span class="nf">Money</span><span class="o">(</span><span class="kt">long</span> <span class="n">cents</span><span class="o">)</span> <span class="o">{</span> <span class="k">this</span><span class="o">.</span><span class="na">cents</span> <span class="o">=</span> <span class="n">cents</span><span class="o">;</span> <span class="o">}</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="nc">Money</span> <span class="nf">ofDollars</span><span class="o">(</span><span class="nc">String</span> <span class="n">amount</span><span class="o">)</span> <span class="o">{</span>
    <span class="c1">// Parse exact decimal dollars, then scale to cents.</span>
    <span class="c1">// This version rounds permissively; see ofDollarsStrict for validation.</span>
    <span class="nc">BigDecimal</span> <span class="n">bd</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="n">amount</span><span class="o">).</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_EVEN</span><span class="o">);</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">Money</span><span class="o">(</span><span class="n">bd</span><span class="o">.</span><span class="na">movePointRight</span><span class="o">(</span><span class="mi">2</span><span class="o">).</span><span class="na">longValueExact</span><span class="o">());</span>
  <span class="o">}</span>

  <span class="cm">/**
   * Strict version: reject inputs that aren't exactly 2 decimals.
   * @throws ArithmeticException if rounding would be required
   */</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="nc">Money</span> <span class="nf">ofDollarsStrict</span><span class="o">(</span><span class="nc">String</span> <span class="n">amount</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">BigDecimal</span> <span class="n">bd</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="n">amount</span><span class="o">).</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">UNNECESSARY</span><span class="o">);</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">Money</span><span class="o">(</span><span class="n">bd</span><span class="o">.</span><span class="na">movePointRight</span><span class="o">(</span><span class="mi">2</span><span class="o">).</span><span class="na">longValueExact</span><span class="o">());</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="nc">Money</span> <span class="nf">plus</span><span class="o">(</span><span class="nc">Money</span> <span class="n">other</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">Money</span><span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">addExact</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">cents</span><span class="o">,</span> <span class="n">other</span><span class="o">.</span><span class="na">cents</span><span class="o">));</span>
  <span class="o">}</span>

  <span class="cm">/**
   * Multiply by a factor with explicit rounding policy.
   * Notice we round only at the boundary where we return to cents.
   * In production, consider taking a BigDecimal factor to avoid parsing repeatedly.
   */</span>
  <span class="kd">public</span> <span class="nc">Money</span> <span class="nf">times</span><span class="o">(</span><span class="nc">String</span> <span class="n">factor</span><span class="o">,</span> <span class="nc">RoundingMode</span> <span class="n">mode</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">BigDecimal</span> <span class="n">bd</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">cents</span><span class="o">)</span>
        <span class="o">.</span><span class="na">movePointLeft</span><span class="o">(</span><span class="mi">2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">multiply</span><span class="o">(</span><span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="n">factor</span><span class="o">))</span>
        <span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">mode</span><span class="o">);</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">Money</span><span class="o">(</span><span class="n">bd</span><span class="o">.</span><span class="na">movePointRight</span><span class="o">(</span><span class="mi">2</span><span class="o">).</span><span class="na">longValueExact</span><span class="o">());</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="nc">BigDecimal</span> <span class="nf">toBigDecimal</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">cents</span><span class="o">).</span><span class="na">movePointLeft</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="nd">@Override</span>
  <span class="kd">public</span> <span class="nc">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span> <span class="k">return</span> <span class="n">toBigDecimal</span><span class="o">().</span><span class="na">toPlainString</span><span class="o">();</span> <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Note the vibe:</p>
<ul>
  <li>parse from string</li>
  <li>scale explicitly</li>
  <li>rounding mode is a parameter for “policy points”</li>
  <li>internal storage is integer cents</li>
</ul>

<p><strong>A design choice worth calling out:</strong> The <code class="language-plaintext highlighter-rouge">ofDollars</code> method silently rounds inputs like “10.129” to “10.13”. Sometimes that’s desired for display money. For payments and ledgers, <code class="language-plaintext highlighter-rouge">ofDollarsStrict</code> is often safer - it rejects inputs that aren’t already at 2 decimals, forcing upstream validation.</p>

<p>For multi-currency systems, you’d add a <code class="language-plaintext highlighter-rouge">Currency</code> field and ensure you never mix currencies in arithmetic. But the core pattern stays the same: integers internally, rounding only at boundaries.</p>

<h2 id="field-guide">Quick guide: what each rounding mode is “for”</h2>

<p>This is not law. This is a field guide.</p>

<h3 id="use-half-even">Use HALF_EVEN when…</h3>

<p>You are aggregating lots of rounded values and want less bias. Accounting ledgers, interest accrual across many accounts, large-scale reporting.</p>

<h3 id="use-half-up">Use HALF_UP when…</h3>

<p>The domain explicitly expects “schoolbook rounding”. Retail display prices, some tax jurisdictions, human-facing calculations where policy says “.5 rounds up”.</p>

<h3 id="use-down">Use DOWN when…</h3>

<p>Truncation is explicitly required. Some fee calculations or conservative estimates where you must not exceed a cap.</p>

<h3 id="use-ceiling-floor">Use CEILING or FLOOR when…</h3>

<p>The direction matters with sign:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">CEILING</code> is “toward positive infinity” (-1.231 -&gt; -1.23, 1.231 -&gt; 1.24 at 2dp)</li>
  <li><code class="language-plaintext highlighter-rouge">FLOOR</code> is “toward negative infinity” (-1.231 -&gt; -1.24, 1.231 -&gt; 1.23 at 2dp)</li>
</ul>

<p>These are great for constraints, limits, and compliance rules.</p>

<h3 id="use-unnecessary">Use UNNECESSARY when…</h3>

<p>You want your program to scream the instant it encounters a value you didn’t expect to need rounding. This is amazing in intermediate validation and testing.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">subtotal</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"12.34"</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">rate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.075"</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">tax</span> <span class="o">=</span> <span class="n">subtotal</span><span class="o">.</span><span class="na">multiply</span><span class="o">(</span><span class="n">rate</span><span class="o">);</span>

<span class="c1">// Fail fast if tax isn't exactly representable at 2 decimals as required by policy</span>
<span class="n">tax</span> <span class="o">=</span> <span class="n">tax</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">UNNECESSARY</span><span class="o">);</span></code></pre></figure>

<p>That exception is not a nuisance. It’s a spotlight on an assumption you forgot you made.</p>

<h2 id="moral">The moral of the story</h2>

<p><code class="language-plaintext highlighter-rouge">HALF_UP</code> is not evil. It’s just not universal.</p>

<p>Rounding modes are not “implementation details”. They are <strong>product decisions with maths clothing on</strong>.</p>

<p>Pick them like you pick authorization rules: explicitly, testably, and with a paper trail.</p>

<h2 id="tldr">TL;DR</h2>

<ul>
  <li>Ties (first discarded digit is 5, rest are zeros) are where rounding policy matters most.</li>
  <li><code class="language-plaintext highlighter-rouge">HALF_UP</code> is intuitive but can introduce bias at scale.</li>
  <li><code class="language-plaintext highlighter-rouge">HALF_EVEN</code> often reduces bias for aggregates.</li>
  <li>Avoid rounding <code class="language-plaintext highlighter-rouge">double</code> values when policy matters. Use <code class="language-plaintext highlighter-rouge">BigDecimal</code> created from strings or scaled integers.</li>
  <li>Prefer <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code> over <code class="language-plaintext highlighter-rouge">new BigDecimal(double)</code> when you must start from a double - but remember it’s not a cleansing ritual.</li>
  <li>Decide <em>when</em> you round, not just <em>how</em> you round.</li>
  <li>Prefer rounding once at boundaries, not repeatedly in the middle.</li>
  <li>Use <code class="language-plaintext highlighter-rouge">UNNECESSARY</code> to catch “we assumed this would be exact” bugs early.</li>
</ul>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Computer Science" /><category term="Software Engineering" /><category term="Technology" /><category term="Series 4 - Floating Point Without Tears" /><category term="java" /><category term="floating-point" /><category term="bigdecimal" /><category term="rounding" /><category term="finance" /><category term="numerics" /><summary type="html"><![CDATA[Learn why HALF_UP rounding isn't always correct and how to choose a rounding policy in Java (HALF_EVEN, HALF_UP, HALF_DOWN, UP, DOWN, CEILING, FLOOR, UNNECESSARY).]]></summary></entry><entry><title type="html">Part 7: Kahan Summation - A Better sum() for Java Streams</title><link href="https://systemhalted.in/2026/01/11/kahan-summation-java-streams/" rel="alternate" type="text/html" title="Part 7: Kahan Summation - A Better sum() for Java Streams" /><published>2026-01-11T00:00:00+00:00</published><updated>2026-01-11T00:00:00+00:00</updated><id>https://systemhalted.in/2026/01/11/kahan-summation-java-streams</id><content type="html" xml:base="https://systemhalted.in/2026/01/11/kahan-summation-java-streams/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>In <a href="https://systemhalted.in/2026/01/05/defending-against-nan-without-defensive-programming-hell/">Part 6</a>, we learned to defend against NaN by validating at boundaries. Now we tackle a different kind of quiet failure: when your sum is correct at every step but still wrong at the end.</p>

<hr />

<p>Your sum is lying.</p>

<p>Not maliciously. Not even dramatically. Just politely.</p>

<p>Floating point is like a tidy accountant with limited paper. Every addition gets written down with a fixed number of significant digits, rounded neatly, and the scraps are swept off the desk.</p>

<p>Most of the time the scraps do not matter.</p>

<p>Until they do.</p>

<p>This post is the full story of <strong>Kahan summation</strong>: a small trick with a big impact. It does not make floating point exact. It <em>does</em> stop your totals from quietly losing meaningful contributions when you add lots of numbers.</p>

<h2 id="the-crime-scene-the-innocent-looking-loop">The crime scene: the innocent-looking loop</h2>

<p>Classic numerical analysis textbooks (here in Fortran, the lingua franca of 1960s numerics) love this tiny loop because it looks harmless and then betrays you.</p>

<figure class="highlight"><pre><code class="language-fortran" data-lang="fortran"><span class="n">S</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.0</span><span class="w">
</span><span class="k">DO</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="n">I</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">N</span><span class="w">
  </span><span class="n">YI</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="err">...</span><span class="w">
</span><span class="nl">4</span><span class="w"> </span><span class="n">S</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">S</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">YI</span></code></pre></figure>

<p>That last line is the whole drama: <code class="language-plaintext highlighter-rouge">S = S + YI</code>.</p>

<p>People then drop a line like this:</p>

<blockquote>
  <p>Rounding or truncation in the addition can contribute to a loss of almost $\log_{10}(N)$ significant decimal digits in S.</p>
</blockquote>

<p>That $\log_{10}(N)$ sounds like wizardry.</p>

<p>It is not.</p>

<p>It is just fixed precision colliding with a growing running total.</p>

<h2 id="why-you-can-lose-about-log10n-digits">Why you can lose about log10(N) digits</h2>

<p>Assume base-10 floating point with <strong>p significant decimal digits</strong>. (IEEE 754 is base 2, but the intuition transfers cleanly.)</p>

<p>Assume the <code class="language-plaintext highlighter-rouge">YI</code> values are roughly the same size and mostly the same sign, so the sum grows instead of canceling. Let a typical magnitude be <code class="language-plaintext highlighter-rouge">|Y|</code>.</p>

<p>After <code class="language-plaintext highlighter-rouge">N</code> terms, the true sum is roughly:</p>

\[S_{\text{true}} \approx N \cdot Y\]

<p>Now the key floating point constraint: a <code class="language-plaintext highlighter-rouge">p</code> digit floating number around magnitude <code class="language-plaintext highlighter-rouge">|S|</code> cannot represent arbitrarily tiny changes. Near <code class="language-plaintext highlighter-rouge">S</code>, the spacing between representable values is about:</p>

\[\Delta S \approx |S| \cdot 10^{-p}\]

<p>Think of $\Delta S$ as the width of the grid lines at the altitude where <code class="language-plaintext highlighter-rouge">S</code> lives.</p>

<p>When you do <code class="language-plaintext highlighter-rouge">S = S + YI</code>, the result is rounded back to <code class="language-plaintext highlighter-rouge">p</code> digits. Any increment much smaller than $\Delta S$ can vanish.</p>

<p>At the end, <code class="language-plaintext highlighter-rouge">|S| \approx N|Y|</code>, so the grid spacing near the final sum is:</p>

\[\Delta S \approx (N|Y|)\,10^{-p}\]

<p>Compare the grid spacing to the size of a typical addend:</p>

\[\frac{\Delta S}{|Y|} \approx N \cdot 10^{-p} = 10^{\log_{10}N - p}\]

<p>That ratio is the punchline.</p>

<p>Multiplying by <code class="language-plaintext highlighter-rouge">N</code> shifts magnitudes by $\log_{10}(N)$ decimal digits. So as the running sum grows by a factor of <code class="language-plaintext highlighter-rouge">N</code>, the rounding grid spacing grows by the same factor. Relative to the scale of the things you are adding, you effectively lose about $\log_{10}(N)$ digits.</p>

<p>Another way to say it:</p>

\[\text{useful digits left at the addend scale} \approx p - \log_{10}N\]

<h3 id="a-concrete-gut-punch">A concrete gut punch</h3>

<p>Suppose you have about <code class="language-plaintext highlighter-rouge">p = 7</code> significant decimal digits (single-ish precision). Sum <code class="language-plaintext highlighter-rouge">N = 10^6</code> numbers of size about 1.</p>

<p>$\log_{10}(10^6) = 6$</p>

<p>So you can be left with roughly:</p>

<p>$7 - 6 = 1$ meaningful decimal digit at the scale of 1</p>

<p>By the time <code class="language-plaintext highlighter-rouge">S</code> reaches around one million, the grid spacing near <code class="language-plaintext highlighter-rouge">S</code> is roughly:</p>

<p>$10^6 \cdot 10^{-7} = 10^{-1} = 0.1$</p>

<p>So adding <code class="language-plaintext highlighter-rouge">0.01</code> can literally do nothing. It gets rounded away.</p>

<p>This is the core problem: not rounding once, but rounding <em>a million times</em> while the running total keeps inflating.</p>

<h2 id="a-quick-demo-sums-that-look-reasonable-and-are-still-wrong">A quick demo: sums that look reasonable and are still wrong</h2>

<p>Here is a classic cancellation trap:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span><span class="n">e16</span><span class="o">;</span>
<span class="kt">double</span> <span class="n">naive</span> <span class="o">=</span> <span class="o">(</span><span class="n">x</span> <span class="o">+</span> <span class="mf">1.0</span><span class="o">)</span> <span class="o">+</span> <span class="mf">1.0</span> <span class="o">-</span> <span class="n">x</span><span class="o">;</span>   <span class="c1">// commonly prints 0.0</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">naive</span><span class="o">);</span></code></pre></figure>

<p>The two <code class="language-plaintext highlighter-rouge">+ 1.0</code> additions happen while the running value is around <code class="language-plaintext highlighter-rouge">1e16</code>. At that scale, <code class="language-plaintext highlighter-rouge">1.0</code> can be smaller than the spacing between representable doubles, so it falls through the cracks.</p>

<p>If your system does analytics, pricing, telemetry, risk, recommendations, ranking, or anything where <code class="language-plaintext highlighter-rouge">N</code> gets large, this is not a cute corner case. It is the default failure mode hiding inside an innocent reduction.</p>

<h2 id="kahan-summation-sweeping-the-crumbs-back-into-the-pile">Kahan summation: sweeping the crumbs back into the pile</h2>

<p>Kahan summation is <strong>compensated summation</strong>.</p>

<p>It keeps two numbers:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">sum</code>: the running total</li>
  <li><code class="language-plaintext highlighter-rouge">c</code>: a compensation term that tracks what rounding threw away last time</li>
</ul>

<p>The mental model:</p>

<p><code class="language-plaintext highlighter-rouge">sum</code> is the big obvious pile.</p>

<p><code class="language-plaintext highlighter-rouge">c</code> is the tiny IOU note: the bits that tried to join the party and got turned away at the door.</p>

<h3 id="the-algorithm">The algorithm</h3>

<p>Given a new addend <code class="language-plaintext highlighter-rouge">x</code>:</p>

<ol>
  <li>Adjust the addend by what we lost previously</li>
  <li>Add it</li>
  <li>Update the compensation by estimating what got lost this time</li>
</ol>

<figure class="highlight"><pre><code class="language-text" data-lang="text">y = x - c
t = sum + y
c = (t - sum) - y
sum = t</code></pre></figure>

<p>That is the entire trick.</p>

<p>It does not change the floating point rules. It changes your strategy so the rules hurt you less.</p>

<h2 id="java-implementation-a-small-accumulator-with-big-consequences">Java implementation: a small accumulator with big consequences</h2>

<h3 id="the-accumulator-type">The accumulator type</h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">KahanAccumulator</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="kt">double</span> <span class="n">sum</span><span class="o">;</span>
  <span class="kd">private</span> <span class="kt">double</span> <span class="n">c</span><span class="o">;</span> <span class="c1">// compensation for lost low-order bits</span>

  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">add</span><span class="o">(</span><span class="kt">double</span> <span class="n">x</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">-</span> <span class="n">c</span><span class="o">;</span>
    <span class="kt">double</span> <span class="n">t</span> <span class="o">=</span> <span class="n">sum</span> <span class="o">+</span> <span class="n">y</span><span class="o">;</span>
    <span class="n">c</span> <span class="o">=</span> <span class="o">(</span><span class="n">t</span> <span class="o">-</span> <span class="n">sum</span><span class="o">)</span> <span class="o">-</span> <span class="n">y</span><span class="o">;</span>
    <span class="n">sum</span> <span class="o">=</span> <span class="n">t</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">combine</span><span class="o">(</span><span class="nc">KahanAccumulator</span> <span class="n">other</span><span class="o">)</span> <span class="o">{</span>
    <span class="c1">// Merge another partial sum into this one.</span>
    <span class="c1">// This improves accuracy, but the result is still order-dependent.</span>
    <span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">other</span><span class="o">.</span><span class="na">sum</span><span class="o">);</span>
    <span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">other</span><span class="o">.</span><span class="na">c</span><span class="o">);</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kt">double</span> <span class="nf">value</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">sum</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>A note worth stating clearly:</p>

<p>Kahan improves accuracy a lot, but <strong>floating point addition is still not associative</strong>, so parallel reductions can still differ run to run because order differs. Kahan makes the wobble smaller, not impossible.</p>

<h2 id="using-it-with-streams">Using it with Streams</h2>

<h3 id="option-a-doublestreamcollect-best-for-primitive-streams">Option A: DoubleStream.collect (best for primitive streams)</h3>

<p><code class="language-plaintext highlighter-rouge">DoubleStream</code> has its own collect overload that avoids boxing.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.util.stream.DoubleStream</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Kahan</span> <span class="o">{</span>

  <span class="kd">private</span> <span class="nf">Kahan</span><span class="o">()</span> <span class="o">{}</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">double</span> <span class="nf">sum</span><span class="o">(</span><span class="nc">DoubleStream</span> <span class="n">stream</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">KahanAccumulator</span> <span class="n">acc</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span>
        <span class="nl">KahanAccumulator:</span><span class="o">:</span><span class="k">new</span><span class="o">,</span>
        <span class="nl">KahanAccumulator:</span><span class="o">:</span><span class="n">add</span><span class="o">,</span>
        <span class="nl">KahanAccumulator:</span><span class="o">:</span><span class="n">combine</span>
    <span class="o">);</span>
    <span class="k">return</span> <span class="n">acc</span><span class="o">.</span><span class="na">value</span><span class="o">();</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Usage:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">s1</span> <span class="o">=</span> <span class="nc">Kahan</span><span class="o">.</span><span class="na">sum</span><span class="o">(</span><span class="nc">DoubleStream</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mf">0.1</span><span class="o">,</span> <span class="mf">0.2</span><span class="o">,</span> <span class="mf">0.3</span><span class="o">));</span>
<span class="kt">double</span> <span class="n">s2</span> <span class="o">=</span> <span class="nc">Kahan</span><span class="o">.</span><span class="na">sum</span><span class="o">(</span><span class="n">myDoubleStream</span><span class="o">.</span><span class="na">parallel</span><span class="o">());</span> <span class="c1">// allowed, order still not fixed</span></code></pre></figure>

<h3 id="option-b-a-collector-nice-ergonomics-for-boxed-streams">Option B: a Collector (nice ergonomics for boxed streams)</h3>

<p>This is convenient when you already have a <code class="language-plaintext highlighter-rouge">Stream&lt;Double&gt;</code>.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.util.stream.Collector</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">KahanCollectors</span> <span class="o">{</span>

  <span class="kd">private</span> <span class="nf">KahanCollectors</span><span class="o">()</span> <span class="o">{}</span>

  <span class="kd">public</span> <span class="kd">static</span> <span class="nc">Collector</span><span class="o">&lt;</span><span class="nc">Double</span><span class="o">,</span> <span class="nc">KahanAccumulator</span><span class="o">,</span> <span class="nc">Double</span><span class="o">&gt;</span> <span class="nf">kahanSummingDouble</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nc">Collector</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
        <span class="nl">KahanAccumulator:</span><span class="o">:</span><span class="k">new</span><span class="o">,</span>
        <span class="o">(</span><span class="n">acc</span><span class="o">,</span> <span class="n">x</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">acc</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">x</span><span class="o">),</span>
        <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span> <span class="n">a</span><span class="o">.</span><span class="na">combine</span><span class="o">(</span><span class="n">b</span><span class="o">);</span> <span class="k">return</span> <span class="n">a</span><span class="o">;</span> <span class="o">},</span>
        <span class="nl">KahanAccumulator:</span><span class="o">:</span><span class="n">value</span>
    <span class="o">);</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Usage:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">s</span> <span class="o">=</span> <span class="n">myStreamOfDoubles</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">KahanCollectors</span><span class="o">.</span><span class="na">kahanSummingDouble</span><span class="o">());</span></code></pre></figure>

<h2 id="correctness-what-to-test-and-what-not-to-promise">Correctness: what to test, and what not to promise</h2>

<h3 id="what-you-should-promise">What you should promise</h3>

<ul>
  <li>Better accuracy than naive summation for large <code class="language-plaintext highlighter-rouge">N</code> and wide dynamic ranges</li>
  <li>Explicit behavior you control and can review in code</li>
</ul>

<h3 id="what-you-should-not-promise">What you should not promise</h3>

<ul>
  <li>Bit for bit deterministic results in parallel streams</li>
  <li>Exactness for money or decimal accounting</li>
</ul>

<h3 id="junit-test-idea-compare-against-a-higher-precision-reference">JUnit test idea: compare against a higher-precision reference</h3>

<p>BigDecimal is not a perfect oracle for binary floating point, but it is a very useful reference when you want to see whether one summation strategy is drifting more than another.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">static</span> <span class="n">org</span><span class="o">.</span><span class="na">junit</span><span class="o">.</span><span class="na">jupiter</span><span class="o">.</span><span class="na">api</span><span class="o">.</span><span class="na">Assertions</span><span class="o">.*;</span>
<span class="kn">import</span> <span class="nn">java.math.BigDecimal</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Random</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.stream.DoubleStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.junit.jupiter.api.Test</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">KahanAccumulatorTest</span> <span class="o">{</span>

  <span class="nd">@Test</span>
  <span class="kt">void</span> <span class="nf">kahan_is_usually_better_than_naive_on_wide_range_data</span><span class="o">()</span> <span class="o">{</span>
    <span class="nc">Random</span> <span class="n">r</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Random</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>

    <span class="kt">double</span><span class="o">[]</span> <span class="n">xs</span> <span class="o">=</span> <span class="nc">DoubleStream</span><span class="o">.</span><span class="na">generate</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
      <span class="kt">double</span> <span class="n">sign</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="na">nextBoolean</span><span class="o">()</span> <span class="o">?</span> <span class="mf">1.0</span> <span class="o">:</span> <span class="o">-</span><span class="mf">1.0</span><span class="o">;</span>
      <span class="kt">double</span> <span class="n">mag</span> <span class="o">=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">pow</span><span class="o">(</span><span class="mf">10.0</span><span class="o">,</span> <span class="n">r</span><span class="o">.</span><span class="na">nextInt</span><span class="o">(</span><span class="mi">20</span><span class="o">)</span> <span class="o">-</span> <span class="mi">10</span><span class="o">);</span> <span class="c1">// 1e-10 .. 1e9</span>
      <span class="k">return</span> <span class="n">sign</span> <span class="o">*</span> <span class="n">mag</span> <span class="o">*</span> <span class="n">r</span><span class="o">.</span><span class="na">nextDouble</span><span class="o">();</span>
    <span class="o">}).</span><span class="na">limit</span><span class="o">(</span><span class="mi">200_000</span><span class="o">).</span><span class="na">toArray</span><span class="o">();</span>

    <span class="kt">double</span> <span class="n">naive</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span>
    <span class="nc">KahanAccumulator</span> <span class="n">kahan</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">KahanAccumulator</span><span class="o">();</span>
    <span class="nc">BigDecimal</span> <span class="n">ref</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">ZERO</span><span class="o">;</span>

    <span class="k">for</span> <span class="o">(</span><span class="kt">double</span> <span class="n">x</span> <span class="o">:</span> <span class="n">xs</span><span class="o">)</span> <span class="o">{</span>
      <span class="n">naive</span> <span class="o">+=</span> <span class="n">x</span><span class="o">;</span>
      <span class="n">kahan</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>
      <span class="n">ref</span> <span class="o">=</span> <span class="n">ref</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">x</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="c1">// Reference converted back to double so we compare at double resolution.</span>
    <span class="kt">double</span> <span class="n">reference</span> <span class="o">=</span> <span class="n">ref</span><span class="o">.</span><span class="na">doubleValue</span><span class="o">();</span>

    <span class="kt">double</span> <span class="n">errNaive</span> <span class="o">=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">naive</span> <span class="o">-</span> <span class="n">reference</span><span class="o">);</span>
    <span class="kt">double</span> <span class="n">errKahan</span> <span class="o">=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">kahan</span><span class="o">.</span><span class="na">value</span><span class="o">()</span> <span class="o">-</span> <span class="n">reference</span><span class="o">);</span>

    <span class="c1">// In rare adversarial sequences Kahan can be slightly worse, but typically it's much better.</span>
    <span class="n">assertTrue</span><span class="o">(</span><span class="n">errKahan</span> <span class="o">&lt;=</span> <span class="n">errNaive</span> <span class="o">*</span> <span class="mf">2.0</span><span class="o">,</span>
        <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Kahan error (%.2e) vs naive (%.2e)"</span><span class="o">,</span> <span class="n">errKahan</span><span class="o">,</span> <span class="n">errNaive</span><span class="o">));</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<h2 id="performance-what-it-costs">Performance: what it costs</h2>

<p>Naive sum does one add per element.</p>

<p>Kahan does a few extra operations per element. That is a small constant factor. In many analytics pipelines the accuracy gain is worth far more than the extra CPU.</p>

<p>If you want to measure overhead, use JMH and compare:</p>

<ul>
  <li>naive loop</li>
  <li><code class="language-plaintext highlighter-rouge">DoubleStream.sum()</code></li>
  <li>Kahan loop</li>
  <li>Kahan via <code class="language-plaintext highlighter-rouge">DoubleStream.collect</code></li>
</ul>

<h2 id="when-not-to-use-kahan">When NOT to use Kahan</h2>

<ul>
  <li>Financial calculations: use BigDecimal for money. Period. Kahan does not give you decimal semantics.</li>
  <li>Tiny datasets: if <code class="language-plaintext highlighter-rouge">N</code> is small, the overhead is rarely worth it.</li>
  <li>Hard real time, tight latency budgets: profile first.</li>
</ul>

<h2 id="variants-worth-mentioning-neumaier-and-pairwise-summation">Variants worth mentioning: Neumaier and pairwise summation</h2>

<p>Kahan is great. It is not the only move.</p>

<p>Neumaier summation is a small tweak that can behave better when the next addend is larger than the running sum.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Neumaier variant</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">NeumaierAccumulator</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="kt">double</span> <span class="n">sum</span><span class="o">;</span>
  <span class="kd">private</span> <span class="kt">double</span> <span class="n">c</span><span class="o">;</span>

  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">add</span><span class="o">(</span><span class="kt">double</span> <span class="n">x</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">t</span> <span class="o">=</span> <span class="n">sum</span> <span class="o">+</span> <span class="n">x</span><span class="o">;</span>
    <span class="k">if</span> <span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">sum</span><span class="o">)</span> <span class="o">&gt;=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">x</span><span class="o">))</span> <span class="o">{</span>
      <span class="n">c</span> <span class="o">+=</span> <span class="o">(</span><span class="n">sum</span> <span class="o">-</span> <span class="n">t</span><span class="o">)</span> <span class="o">+</span> <span class="n">x</span><span class="o">;</span>
    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
      <span class="n">c</span> <span class="o">+=</span> <span class="o">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">t</span><span class="o">)</span> <span class="o">+</span> <span class="n">sum</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="n">sum</span> <span class="o">=</span> <span class="n">t</span><span class="o">;</span>
  <span class="o">}</span>

  <span class="kd">public</span> <span class="kt">double</span> <span class="nf">value</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">sum</span> <span class="o">+</span> <span class="n">c</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Pairwise summation (tree reduction) reduces error growth by summing numbers of similar magnitude together. Some stream implementations may do something like this internally, but the key benefit of writing your own is that you make the behavior explicit and reviewable.</p>

<h2 id="when-to-use-what">When to use what</h2>

<p>Use BigDecimal when you need decimal semantics and you mean it.</p>

<p>Use naive summation when <code class="language-plaintext highlighter-rouge">N</code> is small, magnitudes are similar, and you truly do not care.</p>

<p>Use Kahan (or Neumaier) when:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">N</code> is large (thousands to millions of values)</li>
  <li>values span many orders of magnitude</li>
  <li>small contributions matter</li>
  <li>you want better accuracy without dragging BigDecimal everywhere</li>
</ul>

<h3 id="a-note-on-bigdecimal-vs-kahan-so-we-dont-mix-the-tools">A note on BigDecimal vs Kahan (so we don’t mix the tools)</h3>

<p>BigDecimal and Kahan solve different problems. <strong>BigDecimal is about decimal <em>semantics</em></strong> (money, accounting, “pennies must add up,” explicit rounding rules). <strong>Kahan is about double <em>accumulation error</em></strong> (metrics, measurements, statistics, ML features, telemetry) when <code class="language-plaintext highlighter-rouge">double</code> is the right representation but naive summation bleeds low-order bits.</p>

<ul>
  <li>If your requirements mention <strong>cents, statements, taxes, interest, regulatory accuracy, or mandated rounding policies</strong> → use <strong>BigDecimal</strong> (and decide scale + rounding mode explicitly).</li>
  <li>If your requirements mention <strong>large aggregates, mixed magnitudes, order sensitivity, or “why did parallel give a different total?”</strong> → keep <strong>double</strong>, but upgrade the summation (<strong>Kahan/Neumaier/pairwise</strong>) and be explicit about ordering if determinism matters.</li>
</ul>

<p>Also, BigDecimal only stays “decimal-correct” if you construct it correctly (prefer parsing from decimal text, or <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code> over <code class="language-plaintext highlighter-rouge">new BigDecimal(double)</code>).</p>

<h2 id="closing">Closing</h2>

<p>Floating point is not broken. It is finite.</p>

<p>The tragedy is not that rounding happens.</p>

<p>The tragedy is when rounding happens quietly and repeatedly and nobody is keeping score.</p>

<p>Kahan summation is you keeping score.</p>

<p>A small second variable, standing in the corner with a clipboard, refusing to let the crumbs vanish without a fight.</p>

<hr />

<h2 id="references">References</h2>

<ul>
  <li>W. Kahan, “Pracniques: Further remarks on reducing truncation errors,” Communications of the ACM, 8(1), Jan. 1965.
DOI (ACM Digital Library): https://dl.acm.org/doi/10.1145/363707.363723</li>
</ul>

<p>Open PDF (hosted copy): https://convexoptimization.com/TOOLS/Kahan.pdf</p>

<p>Metadata entry (Semantic Scholar): https://www.semanticscholar.org/paper/Pracniques%3A-further-remarks-on-reducing-truncation-Kahan/672a99813f52aed720d3508d6be7db461328b064</p>

<ul>
  <li>
    <p>Prof Kahan’s Assorted Notes, https://people.eecs.berkeley.edu/~wkahan/</p>
  </li>
  <li>
    <p>N. J. Higham, “The Accuracy of Floating Point Summation”, SIAM Journal on Scientific Computing (1993). https://doi.org/10.1137/0914050</p>
  </li>
  <li>
    <p>DoubleStream.sum(): https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/stream/DoubleStream.html#sum()</p>
  </li>
  <li>
    <p>DoubleSummaryStatistics: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/DoubleSummaryStatistics.html</p>
  </li>
</ul>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Computer Science" /><category term="Software Engineering" /><category term="Technology" /><category term="Series 4 - Floating Point Without Tears" /><category term="java" /><category term="floating-point" /><category term="ieee-754" /><category term="kahan" /><category term="numerical-analysis" /><category term="streams" /><category term="collector" /><summary type="html"><![CDATA[Learn why naive summation loses digits and how Kahan compensated summation helps. Includes Java Stream integration, test strategies, and when to use BigDecimal instead.]]></summary></entry><entry><title type="html">Stereotypes Are Lazy Maps</title><link href="https://systemhalted.in/2026/01/10/stereotypes-are-lazy-maps/" rel="alternate" type="text/html" title="Stereotypes Are Lazy Maps" /><published>2026-01-10T00:00:00+00:00</published><updated>2026-01-10T00:00:00+00:00</updated><id>https://systemhalted.in/2026/01/10/stereotypes-are-lazy-maps</id><content type="html" xml:base="https://systemhalted.in/2026/01/10/stereotypes-are-lazy-maps/"><![CDATA[<p>A stereotype is a shortcut.<br />
A generalization is a guess.<br />
And both are dangerously tempting when you’re tired, annoyed, or trying to compress the human universe into a single sentence.</p>

<p>But a shortcut is not the same thing as the truth.</p>

<p>This post started the way many modern thoughts begin: with a social media thread.</p>

<p>I saw a post about “student drivers” which soon turned into a generalization about an entire people. Someone responded by generalizing Indians in one long breath, without the courtesy of a comma, a semicolon, or a full stop.</p>

<p>The irony wasn’t subtle. The emotional whiplash wasn’t either.</p>

<p>This isn’t only about Indians. Or Americans. Or any one group. It’s about a habit of mind we’ve normalized: reducing millions of people into a neat sentence and calling it “an observation.”</p>

<h2 id="the-world-is-too-large-for-our-brains">The world is too large for our brains</h2>

<p>Human brains are pattern machines. We find faces in clouds. We infer intent from a raised eyebrow. We build models of reality because raw reality is too big to hold.</p>

<p>That instinct isn’t evil. It’s survival.</p>

<p>The problem begins when we confuse the model for the world.</p>

<p>A stereotype is what happens when you take a small sample, add emotion, toss in a few viral anecdotes, and then export it as a universal law.</p>

<p>It feels efficient. It feels satisfying. It feels like closure.</p>

<p>It’s also how we end up misreading entire peoples.</p>

<h2 id="indians-are-is-a-sentence-that-breaks-under-its-own-weight">“Indians are…” is a sentence that breaks under its own weight</h2>

<p>India isn’t a monolith. It’s a continent-sized civilization, with many languages, many histories, many moral philosophies, many economic realities, and many ways of being human.</p>

<p>So when someone says “Indians are X,” what they’re often saying is something closer to:</p>

<p>“I met some Indians.”<br />
“I saw a few videos.”<br />
“I had one bad experience.”<br />
“I read a thread that made me feel righteous.”</p>

<p>And then the brain does its favorite magic trick: it turns an anecdote into an identity.</p>

<p>That’s not insight. That’s laziness with confidence.</p>

<h2 id="the-equal-and-opposite-mistake">The equal and opposite mistake</h2>

<p>Here’s the twist: the antidote to “Indians are…” is not “Americans are…”</p>

<p>The United States is the third-largest country in the world by population. It contains multitudes: regions that feel like different planets, communities built from different migrations, value systems that clash, and identities that don’t fit into clean boxes.</p>

<p>So yes, broad generalizations about Americans are unfair.</p>

<p>But this is exactly how conversations collapse into noise: people respond to one stereotype by throwing another stereotype back like a dodgeball.</p>

<p>The result isn’t justice. It’s just more laziness, moving faster.</p>

<h2 id="the-small-loud-group-problem">The “small loud group” problem</h2>

<p>A common defense goes like this:</p>

<p>“I’m not generalizing everyone. I’m talking about a certain kind of person.”</p>

<p>Sometimes that’s true. Social media amplifies extremes. Outrage is algorithmic fuel. The loudest voices get the mic even when they represent very little.</p>

<p>But adult conversation requires adult precision.</p>

<p>There’s a big difference between:</p>

<ol>
  <li>“Some people are doing this harmful thing.”</li>
  <li>“This group is like this.”</li>
</ol>

<p>The first is a claim about behavior. It can be debated, measured, challenged, and refined.</p>

<p>The second is a claim about identity. It essentializes. It turns a behavior into a blood type.</p>

<p>That’s the line. That’s the whole game.</p>

<h2 id="why-stereotypes-feel-so-good">Why stereotypes feel so good</h2>

<p>Stereotypes offer three things the internet loves:</p>

<p>Certainty: “I understand what’s going on.”<br />
Speed: “I don’t need to do the work.”<br />
Permission: “Now I can judge.”</p>

<p>Real understanding is slower. It requires friction. It requires the irritating humility of saying, “I might be wrong,” and then gathering better evidence like a grown-up scientist.</p>

<p>This is what philosophers call epistemic humility<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>. It is the recognition that our knowledge is always incomplete, our samples always limited, our certainty always provisional.</p>

<p>It’s the opposite of what social media rewards.</p>

<p>That’s harder than typing a hot take.</p>

<h2 id="a-better-way-to-speak">A better way to speak</h2>

<p>If you want to criticize a pattern without flattening people into cardboard cutouts, here are healthier defaults:</p>

<ul>
  <li>Speak about specific behaviors, not identities.</li>
  <li>Use “some” and “in my experience” like seatbelts.</li>
  <li>Separate “what I saw” from “what is true.”</li>
  <li>Ask whether your sample is representative or just memorable.</li>
  <li>When you feel righteous, pause. Righteousness is not a fact-checker.</li>
</ul>

<p>If your goal is to be understood, precision is kindness.</p>

<h2 id="immigrants-live-inside-the-blur">Immigrants live inside the blur</h2>

<p>Immigrants often occupy a strange space. You learn to love the country you live in while also carrying the ache of being misread. You become bilingual not just in language, but in assumptions.</p>

<p>Sometimes you’re treated as an ambassador for a billion people.<br />
Sometimes you’re treated as an exception: “You’re not like the others.”<br />
Sometimes you’re reduced to a meme.</p>

<p>And through it all, you still show up. You contribute. You build. You teach. You try to belong without having to dissolve.</p>

<p>So when someone stereotypes a group, it isn’t “just words.”<br />
It’s a tiny social verdict that sticks.</p>

<h2 id="the-point">The point</h2>

<p>Even saying “everyone stereotypes” would be unfair (which is, awkwardly, the entire point of this post).</p>

<p>After that thread, I also received kind messages from people in my local community offering support and apologizing “on behalf of” others. The intent was generous, and I appreciated it.</p>

<p>But even there, I felt the shadow of the same mistake: the idea that there is a “them” to speak for.</p>

<p>There shouldn’t be.</p>

<p>We don’t defeat stereotypes by pretending differences don’t exist. We defeat stereotypes by being honest about complexity.</p>

<p>By trading lazy certainty for careful clarity.<br />
By resisting the cheap thrill of the sweeping sentence.<br />
By remembering that every “they” is made of millions of “someone.”</p>

<p>The world is weird and diverse and stubbornly detailed.</p>

<p>That’s not a problem to solve.<br />
That’s the whole miracle.</p>

<h2 id="references-and-notes">References and Notes</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Epistemic humility: https://en.wikipedia.org/wiki/Epistemic_humility <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Society &amp; Economy" /><category term="Personal Essays" /><category term="stereotypes" /><category term="generalization" /><category term="immigrants" /><category term="critical-thinking" /><category term="social-media" /><summary type="html"><![CDATA[A short essay on why stereotypes feel efficient but fail under scrutiny, and how to talk about groups: Indians, Americans, immigrants, anyone, without flattening millions of people into a single sentence.]]></summary></entry><entry><title type="html">Part 6: Defending Against NaN Without Defensive Programming Hell</title><link href="https://systemhalted.in/2026/01/05/defending-against-nan-without-defensive-programming-hell/" rel="alternate" type="text/html" title="Part 6: Defending Against NaN Without Defensive Programming Hell" /><published>2026-01-05T00:00:00+00:00</published><updated>2026-01-05T00:00:00+00:00</updated><id>https://systemhalted.in/2026/01/05/defending-against-nan-without-defensive-programming-hell</id><content type="html" xml:base="https://systemhalted.in/2026/01/05/defending-against-nan-without-defensive-programming-hell/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>NaN is not a bug. It is a receipt.</p>

<p>A little slip of paper IEEE 754 hands you after your math did something undefined, and instead of crashing the universe, the CPU says, “Not a number, friend,” and keeps walking.</p>

<p>That is noble. That is also how NaN quietly sneaks into your systems, wears your log files as a cape, and turns your dashboards into modern art.</p>

<p>This post is about defending against NaN without turning your codebase into a forest of anxious <code class="language-plaintext highlighter-rouge">if (isNaN)</code> tripwires.</p>

<h2 id="the-shape-of-the-beast">The shape of the beast</h2>

<p>So what exactly is this receipt for?</p>

<p>NaN stands for “Not a Number.” Expand it once, then treat it like a proper noun: NaN.</p>

<p>You get NaN from operations that have no real number answer, such as:
	1.	0.0 / 0.0<br />
	2.	Math.sqrt(-1.0)<br />
	3.	Math.log(-1.0)<br />
	4.	Any operation that already contains NaN, because NaN is contagious in the best and worst ways</p>

<p>Java follows IEEE 754 here. The JVM will not throw an exception for most floating point invalid operations. It will produce NaN (or Infinity), and your program continues with a tiny invisible crack in reality.</p>

<p>Here is the first mind-bending property:</p>

<p>NaN is not equal to anything, including itself.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">NaN</span><span class="o">;</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span> <span class="o">==</span> <span class="n">x</span><span class="o">);</span>              <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isNaN</span><span class="o">(</span><span class="n">x</span><span class="o">));</span>     <span class="c1">// true</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="o">);</span>              <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="o">);</span>              <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span> <span class="o">==</span> <span class="mi">0</span><span class="o">);</span>             <span class="c1">// false</span></code></pre></figure>

<p>So NaN does not behave like a “value” in the usual sense. It behaves like a signal masquerading as a value.</p>

<p>That disguise is the whole problem.</p>

<h2 id="defensive-programming-hell-checkpoint-syndrome">Defensive programming hell: “Checkpoint Syndrome”</h2>

<p>The naive reaction is understandable:</p>

<p>You discover NaN in production.<br />
You add checks.<br />
You discover it again.<br />
You add more checks.<br />
Eventually every function looks like airport security staffed by anxious squirrels.</p>

<p>You get code like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">price</span> <span class="o">=</span> <span class="n">computePrice</span><span class="o">(</span><span class="n">input</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isNaN</span><span class="o">(</span><span class="n">price</span><span class="o">)</span> <span class="o">||</span> <span class="nc">Double</span><span class="o">.</span><span class="na">isInfinite</span><span class="o">(</span><span class="n">price</span><span class="o">))</span> <span class="o">{</span>
    <span class="c1">// shrug, return 0?</span>
<span class="o">}</span></code></pre></figure>

<p>This is Checkpoint Syndrome because:<br />
	1.	It spreads everywhere.<br />
	2.	It hides the real cause. The first invalid operation is upstream.<br />
	3.	It forces you to decide “what now” in a dozen places, inconsistently.<br />
	4.	It often converts “unknown” into “zero,” which is how financial bugs are born.</p>

<p>The antidote is not “more checks.” The antidote is better geometry - put the checks where they matter, once, with intent.</p>

<h2 id="the-core-principle-validate-at-the-edges-compute-in-the-middle">The core principle: validate at the edges, compute in the middle</h2>

<p><img src="/assets/images/2026-01-05-core-principles.png" alt="Diagram showing validation at boundaries and a clean computation core." /></p>

<p>Most NaN outbreaks begin at boundaries:<br />
	1.	Parsing and deserialization (CSV, JSON, user input, partner payloads)<br />
	2.	Sensor-style data (telemetry, percentages, rates)<br />
	3.	Divide by something that might be zero or missing<br />
	4.	“This should never happen” conversions (and then it happens)</p>

<p>Your best defense is to establish a simple contract:</p>

<p>Inside the computation core, all doubles are finite unless explicitly documented otherwise.</p>

<p>The computation core is the part of your system that should be blissfully boring: the pure math functions, the algorithms, the business logic that assumes validated inputs. The place where you want to reason about correctness without also doing border control.</p>

<p>That means you concentrate NaN handling in a few choke points.</p>

<h2 id="pattern-1-finite-by-default-as-a-guardrail">Pattern 1: “Finite by default” as a guardrail</h2>

<p>Create a tiny helper that asserts finiteness.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">static</span> <span class="kt">double</span> <span class="nf">requireFinite</span><span class="o">(</span><span class="kt">double</span> <span class="n">x</span><span class="o">,</span> <span class="nc">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(!</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">x</span><span class="o">))</span> <span class="o">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="n">name</span> <span class="o">+</span> <span class="s">" must be finite, got "</span> <span class="o">+</span> <span class="n">x</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">x</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p><strong>Why <code class="language-plaintext highlighter-rouge">Double.isFinite()</code> is your single weapon:</strong> It returns <code class="language-plaintext highlighter-rouge">true</code> only when <code class="language-plaintext highlighter-rouge">x</code> is neither NaN nor Infinity - exactly what “finite by default” means. You don’t need two checks (<code class="language-plaintext highlighter-rouge">isNaN</code> and <code class="language-plaintext highlighter-rouge">isInfinite</code>). You need one: “is this a normal, usable number?”</p>

<p>Use it at public boundaries and layer transitions, not inside every private method.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kt">double</span> <span class="nf">monthlyPayment</span><span class="o">(</span><span class="kt">double</span> <span class="n">principal</span><span class="o">,</span> <span class="kt">double</span> <span class="n">annualRate</span><span class="o">,</span> <span class="kt">int</span> <span class="n">months</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">requireFinite</span><span class="o">(</span><span class="n">principal</span><span class="o">,</span> <span class="s">"principal"</span><span class="o">);</span>
    <span class="n">requireFinite</span><span class="o">(</span><span class="n">annualRate</span><span class="o">,</span> <span class="s">"annualRate"</span><span class="o">);</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">months</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="o">)</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">IllegalArgumentException</span><span class="o">(</span><span class="s">"months must be positive"</span><span class="o">);</span>

    <span class="kt">double</span> <span class="n">r</span> <span class="o">=</span> <span class="n">annualRate</span> <span class="o">/</span> <span class="mf">12.0</span><span class="o">;</span>

    <span class="c1">// Standard annuity formula:</span>
    <span class="c1">//   P = L * [r(1+r)^n] / [(1+r)^n - 1]</span>
    <span class="c1">// Rewritten with a negative exponent:</span>
    <span class="c1">//   P = L * r / (1 - (1+r)^(-n))</span>
    <span class="c1">// Same math, often friendlier numerically for large n.</span>
    <span class="k">return</span> <span class="n">principal</span> <span class="o">*</span> <span class="n">r</span> <span class="o">/</span> <span class="o">(</span><span class="mf">1.0</span> <span class="o">-</span> <span class="nc">Math</span><span class="o">.</span><span class="na">pow</span><span class="o">(</span><span class="mf">1.0</span> <span class="o">+</span> <span class="n">r</span><span class="o">,</span> <span class="o">-</span><span class="n">months</span><span class="o">));</span>
<span class="o">}</span></code></pre></figure>

<p>This gives you three wins:<br />
	1.	The failure is loud and early.<br />
	2.	The computation stays clean.<br />
	3.	The exception points to a real contract violation, not a mysterious downstream symptom.</p>

<h2 id="pattern-2-separate-invalid-from-zero-with-a-result-type">Pattern 2: Separate “invalid” from “zero” with a result type</h2>

<p>Sometimes you cannot throw. Sometimes your caller needs to continue, but also needs to know the answer is invalid.</p>

<p>So represent that truth explicitly.</p>

<p>In Java, you can use a sealed interface to create a true disjunctive type (see my <a href="https://systemhalted.in/2025/11/25/disjuntive-types/">post on disjunctive types</a> for the full story):</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">sealed</span> <span class="kd">interface</span> <span class="nc">CalcResult</span> <span class="n">permits</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">Valid</span><span class="o">,</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">Invalid</span> <span class="o">{</span>
    
    <span class="n">record</span> <span class="nf">Valid</span><span class="o">(</span><span class="kt">double</span> <span class="n">value</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">CalcResult</span> <span class="o">{</span>
        <span class="kd">public</span> <span class="nc">Valid</span> <span class="o">{</span>
            <span class="c1">// Enforce finite values in Valid variant</span>
            <span class="k">if</span> <span class="o">(!</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">value</span><span class="o">))</span> <span class="o">{</span>
                <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Valid result must be finite"</span><span class="o">);</span>
            <span class="o">}</span>
        <span class="o">}</span>
    <span class="o">}</span>
    
    <span class="n">record</span> <span class="nf">Invalid</span><span class="o">(</span><span class="nc">String</span> <span class="n">reason</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">CalcResult</span> <span class="o">{}</span>
    
    <span class="c1">// Convenience factory methods</span>
    <span class="kd">static</span> <span class="nc">Valid</span> <span class="nf">ok</span><span class="o">(</span><span class="kt">double</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nf">Valid</span><span class="o">(</span><span class="n">value</span><span class="o">);</span>
    <span class="o">}</span>
    
    <span class="kd">static</span> <span class="nc">Invalid</span> <span class="nf">failed</span><span class="o">(</span><span class="nc">String</span> <span class="n">reason</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nf">Invalid</span><span class="o">(</span><span class="n">reason</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Now NaN is no longer a stealth signal. Invalid states are impossible to construct incorrectly, and the compiler enforces exhaustive handling.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">CalcResult</span> <span class="nf">safeDivide</span><span class="o">(</span><span class="kt">double</span> <span class="n">a</span><span class="o">,</span> <span class="kt">double</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(!</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">a</span><span class="o">)</span> <span class="o">||</span> <span class="o">!</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">b</span><span class="o">))</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">failed</span><span class="o">(</span><span class="s">"non-finite input"</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">b</span> <span class="o">==</span> <span class="mf">0.0</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">failed</span><span class="o">(</span><span class="s">"division by zero"</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">ok</span><span class="o">(</span><span class="n">a</span> <span class="o">/</span> <span class="n">b</span><span class="o">);</span>
<span class="o">}</span>

<span class="c1">// Pattern matching is exhaustive - compiler forces you to handle both cases</span>
<span class="nc">CalcResult</span> <span class="n">result</span> <span class="o">=</span> <span class="n">safeDivide</span><span class="o">(</span><span class="mf">10.0</span><span class="o">,</span> <span class="mf">2.0</span><span class="o">);</span>
<span class="k">switch</span> <span class="o">(</span><span class="n">result</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">case</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">Valid</span><span class="o">(</span><span class="kt">double</span> <span class="n">v</span><span class="o">)</span> <span class="o">-&gt;</span> 
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Result: "</span> <span class="o">+</span> <span class="n">v</span><span class="o">);</span>
    <span class="k">case</span> <span class="nc">CalcResult</span><span class="o">.</span><span class="na">Invalid</span><span class="o">(</span><span class="nc">String</span> <span class="n">reason</span><span class="o">)</span> <span class="o">-&gt;</span> 
        <span class="nc">System</span><span class="o">.</span><span class="na">err</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Failed: "</span> <span class="o">+</span> <span class="n">reason</span><span class="o">);</span>
    <span class="c1">// No default needed - this is exhaustive</span>
<span class="o">}</span></code></pre></figure>

<p>The point is not the exact type. The point is the discipline: invalid is a first-class outcome, and the type system prevents you from accidentally treating it as valid.</p>

<h2 id="pattern-3-domain-types-that-make-nan-impossible">Pattern 3: Domain types that make NaN impossible</h2>

<p>Many doubles in business systems are not “real numbers in the wild.”
They are money, rates, counts, durations, percentages.</p>

<p>Those are not great candidates for raw double.</p>

<p>A few examples:<br />
	1.	Money: store cents as long, or use BigDecimal where precision matters<br />
	2.	Counts: long or int<br />
	3.	Percentages: maybe basis points as int (one basis point = 0.01%, so 550 bps = 5.50%)<br />
	4.	Durations: java.time.Duration</p>

<p>When you tighten types, you reduce the surface area where NaN can even appear. That is the most reliable NaN defense there is: make the invalid state unrepresentable.</p>

<p>NaN cannot enter a long. It can only stand outside and glare.</p>

<h2 id="pattern-4-decide-where-infinity-is-acceptable">Pattern 4: Decide where Infinity is acceptable</h2>

<p>Part 5 covered Infinity and signed zero. Here is the practical angle.</p>

<p>Infinity can be a legitimate signal in some domains:<br />
	1.	“Unlimited” limit<br />
	2.	“Unbounded” score<br />
	3.	A mathematical asymptote that you intentionally model</p>

<p>But if your domain does not explicitly accept Infinity, treat it exactly like NaN - reject both at the boundary with <code class="language-plaintext highlighter-rouge">Double.isFinite()</code>. This is why <code class="language-plaintext highlighter-rouge">requireFinite</code> uses that single check: it enforces “no NaN, no Infinity” in one line.</p>

<p>If you <em>do</em> need to distinguish between NaN and Infinity (rare), check them separately. But for most code, “not finite” is the only distinction that matters.</p>

<p>The bug pattern is when Infinity is tolerated accidentally and later multiplied into a massive number that looks plausible, which is how nonsense becomes confident nonsense.</p>

<h2 id="pattern-5-centralize-sanitization-but-do-not-lie">Pattern 5: Centralize sanitization, but do not lie</h2>

<p>Sometimes you must “sanitize” bad inputs, especially with messy external data.
The key is: do it once, do it centrally, and record what you did.</p>

<p>A dangerous sanitization is this:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">safe</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">x</span><span class="o">)</span> <span class="o">?</span> <span class="n">x</span> <span class="o">:</span> <span class="mf">0.0</span><span class="o">;</span></code></pre></figure>

<p>That turns “unknown” into “zero,” and zero is not neutral in most systems.</p>

<p>A safer pattern is to either:<br />
	1.	Drop the datapoint (for aggregates), and count it <br />
	2.	Mark the result invalid<br />
	3.	Fall back to a documented default that has real meaning, and log it</p>

<p>Example for aggregation:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="nf">averageFinite</span><span class="o">(</span><span class="kt">double</span><span class="o">[]</span> <span class="n">xs</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

    <span class="k">for</span> <span class="o">(</span><span class="kt">double</span> <span class="n">x</span> <span class="o">:</span> <span class="n">xs</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">x</span><span class="o">))</span> <span class="o">{</span>
            <span class="n">sum</span> <span class="o">+=</span> <span class="n">x</span><span class="o">;</span>
            <span class="n">n</span><span class="o">++;</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="c1">// Honest answer: no valid data means undefined result.</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="k">return</span> <span class="nc">Double</span><span class="o">.</span><span class="na">NaN</span><span class="o">;</span>

    <span class="k">return</span> <span class="n">sum</span> <span class="o">/</span> <span class="n">n</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>Notice the honesty: if nothing valid exists, we do not pretend.</p>

<h2 id="third-party-libraries-when-nan-arrives-by-mail">Third-party libraries: when NaN arrives by mail</h2>

<p>Sometimes NaN isn’t born in your code. It is delivered.</p>

<p>The most common culprit is calling math functions that can legitimately return NaN for part of their domain, and forgetting that you just crossed into “inputs must be validated” territory again.</p>

<p>Check immediately after the call, while you still have context.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">sqrt</span><span class="o">(</span><span class="n">userInput</span><span class="o">);</span>

<span class="c1">// JDK math functions and third-party libs can return NaN.</span>
<span class="c1">// Validate the output right away, at the point of crossing.</span>
<span class="n">requireFinite</span><span class="o">(</span><span class="n">result</span><span class="o">,</span> <span class="s">"sqrt result"</span><span class="o">);</span></code></pre></figure>

<p>This pattern generalizes: any time you call out to code you don’t control (libraries, services, models, partner feeds), treat the return value as a new boundary.</p>

<h2 id="finding-the-first-nan-not-the-last-one">Finding the first NaN, not the last one</h2>

<p>A common tragedy is you only detect NaN at the end, in a report, after ten transformations. At that point NaN is the smoke, not the fire.</p>

<p>Two practical tricks:</p>

<h3 id="add-tripwire-assertions-in-debug-builds">Add “tripwire assertions” in debug builds</h3>

<p>In places where NaN should never exist, assert it in tests and in non-production modes.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">static</span> <span class="kt">void</span> <span class="nf">assertFinite</span><span class="o">(</span><span class="kt">double</span> <span class="n">x</span><span class="o">,</span> <span class="nc">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(!</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">x</span><span class="o">))</span> <span class="o">{</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">AssertionError</span><span class="o">(</span><span class="n">name</span> <span class="o">+</span> <span class="s">" became non-finite: "</span> <span class="o">+</span> <span class="n">x</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Call it after major computation steps in critical algorithms, especially ones that are numerically sensitive.</p>

<h3 id="log-with-context-once-not-everywhere">Log with context once, not everywhere</h3>

<p>If you need observability, centralize it.
For example, in an input adapter:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="nf">parseRate</span><span class="o">(</span><span class="nc">String</span> <span class="n">raw</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">parseDouble</span><span class="o">(</span><span class="n">raw</span><span class="o">);</span>
    <span class="k">if</span> <span class="o">(!</span><span class="nc">Double</span><span class="o">.</span><span class="na">isFinite</span><span class="o">(</span><span class="n">x</span><span class="o">))</span> <span class="o">{</span>
        <span class="c1">// log raw payload id, customer id, partner id, etc.</span>
        <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"rate must be finite"</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">x</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>This is where you actually still have context: the original data and the identity of the source.</p>

<p>Downstream, you mostly have regret.</p>

<h2 id="a-small-nan-hygiene-checklist">A small NaN hygiene checklist</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1.	Use Double.isFinite at boundaries where values enter your system or cross layers
2.	Keep computation code clean; assume finite inputs inside the core
3.	Do not convert invalid to zero unless the domain definition says it is correct
4.	Prefer domain types over raw doubles when the value is not truly "a real number"
5.	When you must degrade gracefully, return an explicit invalid result, not a silent sentinel
6.	Instrument the boundary where you reject or drop invalids, so you can find the upstream cause
</code></pre></div></div>

<p>NaN is not evil. It is your system trying to stay alive after stepping on a rake.</p>

<p>Your job is not to sprinkle rakes with warning stickers.
Your job is to stop leaving rakes in the hallway.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Computer Science" /><category term="Software Engineering" /><category term="Technology" /><category term="Series 4 - Floating Point Without Tears" /><category term="java" /><category term="floating-point" /><category term="ieee-754" /><category term="nan" /><category term="validation" /><category term="reliability" /><summary type="html"><![CDATA[Learn how to handle NaN and Infinity in Java without scattering if (isNaN) checks everywhere. Five practical patterns: boundary validation with Double.isFinite(), result types, domain types, centralized sanitization, and detecting NaN at its source. Avoid Checkpoint Syndrome and keep your computation code clean.]]></summary></entry><entry><title type="html">A quiet rebuild: assets, webcmd, and accessibility</title><link href="https://systemhalted.in/2026/01/03/quiet-rebuild-assets-webcmd-accessibility/" rel="alternate" type="text/html" title="A quiet rebuild: assets, webcmd, and accessibility" /><published>2026-01-03T00:00:00+00:00</published><updated>2026-01-03T00:00:00+00:00</updated><id>https://systemhalted.in/2026/01/03/quiet-rebuild-assets-webcmd-accessibility</id><content type="html" xml:base="https://systemhalted.in/2026/01/03/quiet-rebuild-assets-webcmd-accessibility/"><![CDATA[<p>Over the last day I made a round of changes that do not scream “new feature,” but materially improve how this site loads, behaves, and feels – especially for readers who use keyboard navigation or assistive tech. This post is a quick technical walkthrough of what changed, why it matters, and how it helps you as a reader.</p>

<h2 id="1-consolidated-assets-into-one-place">1) Consolidated assets into one place</h2>
<p>Previously the site had both <code class="language-plaintext highlighter-rouge">public/</code> and <code class="language-plaintext highlighter-rouge">assets/</code>, which caused confusion and occasional broken paths. I merged everything into <code class="language-plaintext highlighter-rouge">assets/</code> and updated all references.</p>

<p><strong>What changed</strong></p>
<ul>
  <li>CSS, JS, and favicon files moved from <code class="language-plaintext highlighter-rouge">public/</code> to <code class="language-plaintext highlighter-rouge">assets/</code>.</li>
  <li>All templates now link to <code class="language-plaintext highlighter-rouge">/assets/...</code>.</li>
  <li>The web manifest and webcmd page were updated to the new paths.</li>
</ul>

<p><strong>Why it helps readers</strong></p>
<ul>
  <li>Fewer path mismatches means fewer broken resources.</li>
  <li>Simpler structure makes maintenance faster, which reduces future regressions.</li>
</ul>

<h2 id="2-modernized-the-favicon-setup">2) Modernized the favicon setup</h2>
<p>I added an SVG favicon and kept the ICO fallback for broad support.</p>

<p><strong>What changed</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">assets/favicon.svg</code> is now the primary favicon.</li>
  <li><code class="language-plaintext highlighter-rouge">assets/favicon.ico</code> remains as a fallback.</li>
  <li>The <code class="language-plaintext highlighter-rouge">&lt;link rel="icon"&gt;</code> tags were updated accordingly.</li>
</ul>

<p><strong>Why it helps readers</strong></p>
<ul>
  <li>SVG is crisp at any size; it looks sharper on modern devices.</li>
  <li>ICO fallback preserves compatibility on older browsers.</li>
</ul>

<h2 id="3-webcmd-got-a-real-upgrade">3) Webcmd got a real upgrade</h2>
<p><code class="language-plaintext highlighter-rouge">/webcmd/</code> is still the command-line page – but it now matches the rest of the site and behaves more predictably.</p>

<p><strong>What changed</strong></p>
<ul>
  <li>Webcmd now uses the default layout and site theme.</li>
  <li>The command UI is more readable and consistent with the Nord palette.</li>
  <li>Help output is semantic (lists + headings), easier to scan, and displayed in two columns on desktop.</li>
  <li>The <code class="language-plaintext highlighter-rouge">find</code> command now appears in the Searches section (where it belongs).</li>
  <li>Navigation commands (<code class="language-plaintext highlighter-rouge">ph</code>, <code class="language-plaintext highlighter-rouge">p</code>, <code class="language-plaintext highlighter-rouge">pi</code>, <code class="language-plaintext highlighter-rouge">pr</code>) now use relative URLs so they stay on localhost when you are testing.</li>
</ul>

<p><strong>Why it helps readers</strong></p>
<ul>
  <li>The page is easier to read and use, especially on mobile.</li>
  <li>Commands work the same in dev and production.</li>
  <li>The help panel is much more legible.</li>
</ul>

<h2 id="4-accessibility-pass-wcag-oriented">4) Accessibility pass (WCAG-oriented)</h2>
<p>I did a focused accessibility sweep across the main site templates (excluding <code class="language-plaintext highlighter-rouge">jsgames/</code>) with WCAG 2.1 AA as the target.</p>

<p><strong>What changed</strong></p>
<ul>
  <li>Added a Skip to content link and a proper <code class="language-plaintext highlighter-rouge">&lt;main&gt;</code> landmark.</li>
  <li>Sidebar toggle now updates <code class="language-plaintext highlighter-rouge">aria-expanded</code> and is keyboard-operable.</li>
  <li>The search overlay now traps focus and restores focus on close.</li>
  <li>“Annotate me” is now a real <code class="language-plaintext highlighter-rouge">&lt;button&gt;</code> (not a clickable <code class="language-plaintext highlighter-rouge">&lt;span&gt;</code>).</li>
  <li>Improved focus styles and general keyboard flow.</li>
</ul>

<p><strong>Why it helps readers</strong></p>
<ul>
  <li>Keyboard users can reach content faster.</li>
  <li>Screen reader navigation is clearer and more predictable.</li>
  <li>Dialog behavior is now much closer to expected modal behavior.</li>
</ul>

<h2 id="5-reduced-disqus-noise-on-non-post-pages">5) Reduced Disqus noise on non-post pages</h2>
<p>Disqus counts were being loaded everywhere. Now they only load on posts that explicitly allow comments.</p>

<p><strong>Why it helps readers</strong></p>
<ul>
  <li>Less third-party JS on pages that do not need it.</li>
  <li>Cleaner performance and fewer surprise widgets.</li>
</ul>

<h2 id="6-new-documentation">6) New documentation</h2>
<p>To keep this sustainable, I wrote a few new internal docs:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">docs/webcmd.md</code> explains how the command engine works and how to add new commands.</li>
  <li><code class="language-plaintext highlighter-rouge">docs/accessibility.md</code> captures accessibility conventions and checks.</li>
  <li>The README was updated to link to both.</li>
</ul>

<hr />

<h3 id="in-short">In short</h3>
<p>This was a maintenance sweep – but the impact is tangible: the site is more consistent, easier to navigate, more accessible, and easier to extend.</p>

<p>If you notice anything off, ping me. Otherwise, I will keep iterating on the small stuff that makes reading feel smooth.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Personal Essays" /><category term="Technology" /><category term="jekyll" /><category term="webcmd" /><category term="accessibility" /><category term="ux" /><category term="maintenance" /><summary type="html"><![CDATA[Over the last day I made a round of changes that do not scream “new feature,” but materially improve how this site loads, behaves, and feels – especially for readers who use keyboard navigation or assistive tech. This post is a quick technical walkthrough of what changed, why it matters, and how it helps you as a reader.]]></summary></entry><entry><title type="html">A Tomato’s Journey: Revisiting India’s Post-Harvest Supply Chain (2011 → 2026)</title><link href="https://systemhalted.in/2026/01/03/tomato-journey-post-harvest-supply-chain-2011-2026/" rel="alternate" type="text/html" title="A Tomato’s Journey: Revisiting India’s Post-Harvest Supply Chain (2011 → 2026)" /><published>2026-01-03T00:00:00+00:00</published><updated>2026-01-03T00:00:00+00:00</updated><id>https://systemhalted.in/2026/01/03/tomato-journey-post-harvest-supply-chain-2011-2026</id><content type="html" xml:base="https://systemhalted.in/2026/01/03/tomato-journey-post-harvest-supply-chain-2011-2026/"><![CDATA[<p>In April 2011, I wrote a tiny post that was basically a finger jab at a wound: “read this story,” then a quote about how India’s price signals die on the way back to the farm. The original is still here: <a href="https://systemhalted.in/2011/04/26/whats-wrong-with-our-post-harvest-agricultural-supply-chain/">What’s wrong with our post-harvest agricultural supply chain?</a></p>

<p>The quote was lifted from an <em>Economic Times</em> editorial titled <a href="https://economictimes.indiatimes.com/opinion/et-editorial/the-pm-gets-it-right/articleshow/7499198.cms">“The PM gets it right” (Feb 15, 2011)</a>. Its diagnosis was simple and brutal: we modernised inputs, not marketing. We built an “inefficient chain” between farmer and consumer, so when retail prices spike, the farmer often sees none of the upside.</p>

<p>Fifteen years later, I want to rewrite that post with a real spine. Same thesis, sharper tools, newer facts, and one stubborn protagonist.</p>

<p>A tomato.</p>

<h2 id="a-tomato-leaves-the-farm">A tomato leaves the farm</h2>

<p>Picture this as an illustrative journey, not a specific news report.</p>

<p>A farmer harvests tomatoes at dawn. By afternoon, the tomatoes have become a logistics problem wearing a red costume.</p>

<p>They need sorting and grading. They need crates that do not crush. They need shade. They need pre-cooling. They need transport that does not turn every bump into bruising. They need a buyer whose “price” does not change like mood.</p>

<p>If any link in that chain is weak, the farmer does the only rational thing available under pressure.</p>

<p>Sell fast. Sell cheap. Move on.</p>

<p>Later the same week, the city consumer complains about expensive tomatoes. The farmer hears that complaint like a rumour from another planet.</p>

<p>That gap is the black box.</p>

<p>Back in 2011, I quoted this line (still painfully accurate): the linkage between the farmer and the consumer is inefficient, wasteful, and subject to manipulation, so shortages trigger hoarding and price spikes at the consumer end without sending those higher prices back to the farmer. When price signals do not reach the farm, incentives die.</p>

<p>So what changed between 2011 and 2026?</p>

<p>Enough to matter. Not enough to relax.</p>

<h2 id="2011-said-fix-marketing-2026-says-fix-time">2011 said “fix marketing.” 2026 says “fix time.”</h2>

<p>Tomatoes are not merely bought and sold. They are raced.</p>

<p>A post-harvest system is basically a machine for buying time. Cold chain buys time. Warehousing buys time. Credit buys time. Transparent markets buy time by reducing predatory uncertainty.</p>

<p>India’s big story since 2011 is that we started building and financing “time.”</p>

<h2 id="change-1-we-started-paying-for-the-boring-parts">Change 1: We started paying for the boring parts</h2>

<p>The Agriculture Infrastructure Fund (AIF) is a government financing facility launched in 2020–21 to support post-harvest and farm-gate infrastructure through interest subvention and credit guarantee support.</p>

<p>As of June 30, 2025, the Press Information Bureau (PIB) reported ₹66,310 crore sanctioned under AIF for 1,13,419 projects, mobilising ₹1,07,502 crore of investment, including 2,454 cold storage projects.</p>

<p>This is not a philosophical change. It is a cash-flow change. And supply chains love cash-flow.</p>

<h2 id="change-2-cold-chain-scaled-and-policy-got-more-specific">Change 2: Cold chain scaled, and policy got more specific</h2>

<p>The Ministry of Food Processing Industries (MoFPI) runs the Integrated Cold Chain and Value Addition Infrastructure (ICCVAI) scheme under the Pradhan Mantri Kisan Sampada Yojana (PMKSY).</p>

<p>As of June 2025, 395 integrated cold chain projects had been approved since 2008, with 291 operational, creating preservation capacity of 25.52 lakh metric tonnes (LMT) per year and processing capacity of 114.66 LMT per year.</p>

<p>MoFPI also notes a key policy shift in June 2022: support for fruit and vegetable cold chain projects under that scheme component was discontinued and the sector was shifted to Operation Greens.</p>

<p>In plain terms: the government stopped pretending every crop has the same bottlenecks.</p>

<p>For our tomato, this matters. Not because cold chain is glamorous, but because it turns “sell today or lose everything” into “sell when the price is sane.”</p>

<h2 id="change-3-markets-became-more-digital-and-more-visible">Change 3: Markets became more digital, and more visible</h2>

<p>The electronic National Agriculture Market (e-NAM) integrates regulated wholesale markets (mandis) into an online trading platform.</p>

<p>PIB reported that 1,522 mandis were integrated as of June 30, 2025, with 1,79,41,613 farmers and 4,518 Farmer Producer Organisations (FPOs) registered, and total traded value of ₹4,39,941 crore recorded on the platform.</p>

<p>If 2011 was about “price signals,” e-NAM is one attempt to strengthen the signal.</p>

<p>But an honest note: a stronger signal does not automatically fix the physical chain. A dashboard cannot refrigerate a tomato.</p>

<h2 id="change-4-farmer-collectivisation-moved-from-slogan-to-infrastructure">Change 4: Farmer collectivisation moved from slogan to infrastructure</h2>

<p>A Farmer Producer Organisation (FPO) is a farmer collective that can aggregate produce, negotiate, and invest in shared capabilities.</p>

<p>The “Formation and Promotion of 10,000 FPOs” scheme hit the 10,000 milestone by Feb 2025, according to PIB. The same release describes equity grants and credit guarantee cover supporting thousands of FPOs.</p>

<p>This is quietly revolutionary. A single farmer is forced to accept the chain. A collective can start owning pieces of it.</p>

<p>A tomato handled by an FPO can be graded, packed, stored, and sold with leverage. The same tomato, different fate.</p>

<h2 id="change-5-storage-plus-credit-got-sharper">Change 5: Storage plus credit got sharper</h2>

<p>In 2011, the farmer’s big enemy was forced timing. In 2026, the fight is increasingly about making “waiting” financially possible.</p>

<p>The Warehousing Development and Regulatory Authority (WDRA) oversees warehousing regulation and electronic warehouse receipt systems. A Parliamentary Standing Committee report notes the growth of pledge finance against electronic Negotiable Warehouse Receipts (eNWRs).</p>

<p>The same report notes the launch on 04-03-2024 of e-Kisan Upaj Nidhi, a digital gateway developed by WDRA in association with NABARD (National Bank for Agriculture and Rural Development) and a task force in SBI (State Bank of India), to connect eNWR with onboarded banks.</p>

<p>This is the most direct antidote to the 2011 problem. If you can store and borrow, you are not forced to sell at the worst possible moment.</p>

<h2 id="the-uncomfortable-part-loss-is-still-huge">The uncomfortable part: loss is still huge</h2>

<p>Even with better financing, more cold chain, more digital markets, and stronger farmer collectives, the scale of loss remains enormous.</p>

<p>A 2024 policy brief by the Indian Council for Research on International Economic Relations (ICRIER) cites a NABARD Consultancy Services (NABCONS) 2020–2022 study estimating food loss in India at about ₹1.53 trillion (USD 18.5 billion) annually due to post-harvest losses (PHL). The brief also argues that reducing PHL is often more cost-effective than producing more and losing more.</p>

<p>So yes, we built scaffolding. But we are still leaking value at industrial scale.</p>

<h2 id="so-what-is-the-2026-thesis-using-the-tomato-as-proof">So what is the 2026 thesis, using the tomato as proof?</h2>

<p>The 2011 editorial said policy must recognise marketing’s role in boosting farm production. I agree, but I want to update the framing.</p>

<p>India’s post-harvest problem is a systems problem where incentives and physics collaborate to bully the weakest player.</p>

<p>Tomatoes punish delay. Markets punish small scale. Credit punishes the poor. Information punishes the disconnected.</p>

<p>Since 2011, India has improved the tools that buy time and improve bargaining power: financing (AIF), cold chain (ICCVAI under PMKSY), digital trading (e-NAM), collectivisation (FPOs), and storage-linked credit (WDRA eNWR and e-Kisan Upaj Nidhi).</p>

<p>Now the real question is not “do we have schemes?”</p>

<p>It is “does our tomato still get forced into the panic-sale path?”</p>

<p>If the answer is yes, the black box still wins.</p>

<p>If the answer becomes no, then the farmer finally gets what the consumer already has.</p>

<p>Choice.</p>

<hr />

<h2 id="references-links">References (links)</h2>

<ol>
  <li>
    <p>Original 2011 post on SystemHalted:<br />
<a href="https://systemhalted.in/2011/04/26/whats-wrong-with-our-post-harvest-agricultural-supply-chain/">https://systemhalted.in/2011/04/26/whats-wrong-with-our-post-harvest-agricultural-supply-chain/</a></p>
  </li>
  <li>
    <p>Quoted editorial (2011, original link from my post):<br />
<a href="https://economictimes.indiatimes.com/opinion/et-editorial/the-pm-gets-it-right/articleshow/7499198.cms">https://economictimes.indiatimes.com/opinion/et-editorial/the-pm-gets-it-right/articleshow/7499198.cms</a></p>
  </li>
  <li>
    <p>PIB note on Agriculture Infrastructure Fund (AIF) status (as of 30 June 2025):<br />
<a href="https://www.pib.gov.in/PressNoteDetails.aspx?ModuleId=3&amp;NoteId=154999">https://www.pib.gov.in/PressNoteDetails.aspx?ModuleId=3&amp;NoteId=154999</a></p>
  </li>
  <li>
    <p>PIB release on e-NAM registrations and traded value (as of 30 June 2025):<br />
<a href="https://www.pib.gov.in/PressReleasePage.aspx?PRID=2151361">https://www.pib.gov.in/PressReleasePage.aspx?PRID=2151361</a></p>
  </li>
  <li>
    <p>PIB release on the 10,000 Farmer Producer Organisations (FPOs) milestone (Feb 28, 2025):<br />
<a href="https://pib.gov.in/PressReleasePage.aspx?PRID=2106913">https://pib.gov.in/PressReleasePage.aspx?PRID=2106913</a></p>
  </li>
  <li>
    <p>Integrated Cold Chain and Value Addition Infrastructure (ICCVAI) status note (PDF; includes June 2025 stats):<br />
<a href="https://static.pib.gov.in/WriteReadData/specificdocs/documents/2025/oct/doc20251029679501.pdf">https://static.pib.gov.in/WriteReadData/specificdocs/documents/2025/oct/doc20251029679501.pdf</a></p>
  </li>
  <li>
    <p>Parliamentary Standing Committee report (PDF; mentions eNWR pledge finance and e-Kisan Upaj Nidhi launch):<br />
<a href="https://sansad.in/getFile/lsscommittee/Consumer%20Affairs%2C%20Food%20and%20Public%20Distribution/18_Consumer_Affairs_Food_and_Public_Distribution_2.pdf?source=loksabhadocs">https://sansad.in/getFile/lsscommittee/Consumer%20Affairs%2C%20Food%20and%20Public%20Distribution/18_Consumer_Affairs_Food_and_Public_Distribution_2.pdf?source=loksabhadocs</a></p>
  </li>
  <li>
    <p>ICRIER Policy Brief 20 (PDF) summarising the NABCONS 2020–2022 loss estimate:<br />
<a href="https://icrier.org/pdf/Policy_Brief_20.pdf">https://icrier.org/pdf/Policy_Brief_20.pdf</a></p>
  </li>
  <li>
    <p>WDRA page describing e-Kisan Upaj Nidhi:<br />
<a href="https://wdra.gov.in/web/wdra/e-kisan-upaj-nidhi">https://wdra.gov.in/web/wdra/e-kisan-upaj-nidhi</a></p>
  </li>
</ol>

<hr />

<h2 id="notes">Notes</h2>

<h3 id="abbreviations-introduced-in-this-post">Abbreviations introduced in this post</h3>

<ul>
  <li><strong>AIF</strong>: Agriculture Infrastructure Fund</li>
  <li><strong>PIB</strong>: Press Information Bureau</li>
  <li><strong>MoFPI</strong>: Ministry of Food Processing Industries</li>
  <li><strong>PMKSY</strong>: Pradhan Mantri Kisan Sampada Yojana</li>
  <li><strong>ICCVAI</strong>: Integrated Cold Chain and Value Addition Infrastructure</li>
  <li><strong>LMT</strong>: lakh metric tonnes</li>
  <li><strong>e-NAM</strong>: electronic National Agriculture Market</li>
  <li><strong>Mandi</strong>: regulated wholesale agricultural market</li>
  <li><strong>FPO</strong>: Farmer Producer Organisation</li>
  <li><strong>WDRA</strong>: Warehousing Development and Regulatory Authority</li>
  <li><strong>eNWR</strong>: electronic Negotiable Warehouse Receipt</li>
  <li><strong>NABARD</strong>: National Bank for Agriculture and Rural Development</li>
  <li><strong>SBI</strong>: State Bank of India</li>
  <li><strong>NABCONS</strong>: NABARD Consultancy Services</li>
  <li><strong>ICRIER</strong>: Indian Council for Research on International Economic Relations</li>
  <li><strong>PHL</strong>: post-harvest losses</li>
</ul>

<h3 id="about-the-tomato-story">About the tomato story</h3>

<p>The tomato journey section is a simplified narrative device to make the supply chain concrete. It is not a claim about one specific farmer or one specific price spike.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Politics &amp; Governance" /><category term="agriculture" /><category term="india" /><category term="supply-chain" /><category term="post-harvest" /><category term="cold-chain" /><category term="mandis" /><category term="farmers" /><category term="policy" /><summary type="html"><![CDATA[A 2026 rewrite of a 2011 note: one tomato’s journey through India’s post-harvest chain, what changed since 2011, and what still leaks value.]]></summary></entry><entry><title type="html">Hello, 2026: Shipping Hope in Small Commits</title><link href="https://systemhalted.in/2026/01/01/happy-new-year-2026/" rel="alternate" type="text/html" title="Hello, 2026: Shipping Hope in Small Commits" /><published>2026-01-01T00:00:00+00:00</published><updated>2026-01-01T00:00:00+00:00</updated><id>https://systemhalted.in/2026/01/01/happy-new-year-2026</id><content type="html" xml:base="https://systemhalted.in/2026/01/01/happy-new-year-2026/"><![CDATA[<p>Happy New Year.</p>

<p>The calendar flipped, the confetti fell, and somewhere a server kept running without caring about our rituals. Respect. Uptime is the real stoicism.</p>

<p>I like New Year because it is the one socially acceptable time to refactor your life in public. No tickets. No sprint planning. Just a quiet reboot and a little audacity.</p>

<h2 id="the-year-as-a-compiler">The year as a compiler</h2>

<p>A year is a ruthless compiler. It does not care about intent. It only cares about what actually ran.</p>

<p>You can mean well for months and still ship nothing but good feelings. You can also ship one small thing a week and look back stunned at the pile of proof you accidentally created.</p>

<p>So my 2026 goal is not grandiosity. It is evidence.</p>

<p>Not a dramatic reinvention. A steady sequence of small, honest commits.</p>

<h2 id="what-i-am-optimizing-for">What I am optimizing for</h2>

<p>I do not want a year that looks impressive from a distance and feels hollow up close.</p>

<p>I want a year that feels calm in the body, clear in the mind, and useful in the world.</p>

<p>A year where my work is sturdy, my learning is intentional, my writing is alive, and my attention is not donated to infinite scroll like a confused philanthropist.</p>

<p>A year with fewer open loops and more finished sentences.</p>

<h2 id="building-without-worshipping-the-build">Building, without worshipping the build</h2>

<p>As engineers we have a strange tendency to worship motion. Activity feels like virtue. Busy is a costume that passes as importance.</p>

<p>This year I want more stillness around the work. Less frantic switching. More deep time. More time spent on the part where the idea becomes real.</p>

<p>Because real is the only feature that users can actually use.</p>

<p>And yes, that includes the user who is reading this right now and thinking, I should probably finally do the thing. Please do the thing. Your future self is already grateful and slightly smug.</p>

<h2 id="a-tiny-promise-to-myself">A tiny promise to myself</h2>

<p>I will protect my attention like it is production data.</p>

<p>I will read on purpose. I will learn with a map. I will write even when the mood is missing, because craft is what remains after motivation leaves the room.</p>

<p>I will treat health like a prerequisite, not a nice to have.</p>

<p>I will be ambitious, but not brittle.</p>

<p>I will aim for progress that survives a bad day.</p>

<p>I will finally bring Consumption Backlog in Action. What the heck! I will even create an iOS app for it.</p>

<h2 id="the-cosmic-perspective-because-the-universe-insists">The cosmic perspective, because the universe insists</h2>

<p>Somewhere above us, photons that left their stars before humans invented arithmetic are still arriving like late emails. The sky is always delivering messages from the past.</p>

<p>That thought makes my problems feel smaller, and my responsibilities feel cleaner.</p>

<p>If the universe can be that old and still be that bright, surely I can be tired and still be kind. Surely I can be uncertain and still begin.</p>

<h2 id="closing-tab">Closing tab</h2>

<p>If you are reading this, I hope 2026 brings you three things.</p>

<p>Something to learn that changes how you see the world.</p>

<p>Someone to love who makes the days lighter.</p>

<p>Something to build that makes you proud, quietly, when nobody is watching.</p>

<p>Happy New Year.</p>

<p>Now go ship something small.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Personal Essays" /><category term="new-year" /><category term="reflection" /><category term="software-engineering" /><category term="writing" /><category term="learning" /><category term="leadership" /><summary type="html"><![CDATA[A New Year note from a builder who still believes small, consistent commits can change a life, and sometimes a team.]]></summary></entry><entry><title type="html">Discipline First: A Trust Pipeline for AI-Assisted Coding</title><link href="https://systemhalted.in/2025/12/31/discipline-first-trust-pipeline-for-ai-assisted-coding/" rel="alternate" type="text/html" title="Discipline First: A Trust Pipeline for AI-Assisted Coding" /><published>2025-12-31T00:00:00+00:00</published><updated>2025-12-31T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/31/discipline-first-trust-pipeline-for-ai-assisted-coding</id><content type="html" xml:base="https://systemhalted.in/2025/12/31/discipline-first-trust-pipeline-for-ai-assisted-coding/"><![CDATA[<p>Vibe coding is not a software engineering paradigm. It’s a mood. Engineering is what makes it ship.</p>

<p>My core claim is simple: engineers who set up a task with clear instructions, a thin prototype, and hard guardrails tend to have a better experience with AI-assisted coding, and they tend to keep their good faith in the tools. Engineers who don’t, often walk away with confusion, rewrites, and a lingering sense that the agent is “untrustworthy.” And that’s why the same tool creates opposite stories, depending on who’s holding it.</p>

<p>This post is my framework, <strong><a href="https://github.com/systemhalted/DisciplineFirst">Discipline First: a trust pipeline for AI-assisted coding</a></strong>. It’s a small kit you can use immediately: an Agent Brief that makes intent hard to misread, guardrails that make failures visible early, and a one-week experiment that turns belief into evidence.</p>

<h2 id="the-axis-that-matters">The axis that matters</h2>

<p>The agent isn’t the methodology. Your engineering habits are.</p>

<p>I’m going to be deliberately boring about definitions, because the labels are less important than the axis. Whether you call it vibe coding, agentic coding, or AI-assisted coding, the same split shows up: disciplined delivery versus undisciplined delivery. The tools can draft code, refactor code, even propose architectures, but they can’t rescue a vague task from its own vagueness.</p>

<p>Discipline is what turns “the agent wrote something” into “the system changed, and we can explain why, prove it works, and undo it safely if it doesn’t.”</p>

<h2 id="four-engineers-walk-into-the-same-tool">Four engineers walk into the same tool</h2>

<p>And once you see it that way, four kinds of engineers show up around AI-assisted coding.</p>

<p>The <strong>Skeptic</strong> is driven by quality, security, and maintainability. They are not anti tool. They are pro standards. They will try these tools in a sandbox, or allow them under strict review, and they trust what they can validate through time-tested discipline: tests, contracts, architecture checks, and clean interfaces. Their posture is “prove it,” and their lingering doubt is usually about authorship. They suspect only human engineers can reliably meet that bar.</p>

<p>The <strong>Dismisser</strong> opts out early. Sometimes that’s reflexive, sometimes it’s reasoned: they’ve seen bad suggestions, security risks, legal uncertainty, vendor lock-in, or unreviewable diffs and they decided the trade is not worth it. Their posture is still “already decided,” but the <em>why</em> matters. You don’t convert a Dismisser by arguing about models or demos. You convert them by giving them control of the bar: let them define the quality gates, then run a small, measured experiment in their own codebase that either meets the bar or fails honestly.</p>

<p>The <strong>Viber</strong> loves speed. They ship fast, accept large diffs, and skip the guardrails that make code testable and observable. Their posture is “speed is truth.” To be fair, that posture has a place: spikes, prototypes, throwaway demos, learning a new stack. The problem is when the same vibe crosses the border into production. That’s where “it seems to work” quietly becomes regressions, mystery failures, and eroded trust. The point of Discipline First is not to shame exploration. It’s to prevent avoidable damage when the stakes are real.</p>

<p>The <strong>Disciplined Builder</strong> loves AI-assisted coding and still engineers hard. Small tasks, small diffs, acceptance criteria, tests, verification loops, rules files, and a security mindset. They do not care whether the code was written by a human or an agent. They care that it is explainable, reviewable, testable, and observable. Their posture is simple: trust is built.</p>

<p>The only difference between the Skeptic and the Builder is what they believe about that last mile. The Skeptic thinks only humans can deliver it consistently. The Builder has learned how to make the agent earn it.</p>

<h2 id="discipline-first-is-xp-with-a-faster-pair">Discipline First is XP with a faster pair</h2>

<p>Discipline First is not a new religion. It is <strong>Extreme Programming</strong> adapted to a world where your pair can write code at absurd speed. Extreme Programming starts with <strong>Values</strong>, because Values guide <strong>Principles</strong>, and Principles are what make <strong>Practices</strong> hold up under pressure.</p>

<p>The Values are <strong>Communication, Simplicity, Feedback, Courage, and Respect</strong>.</p>

<p>Communication becomes explicit intent: the Agent Brief and rules files are how you communicate without mind reading. Simplicity becomes a principle you enforce: assume simplicity, slice work into small tasks, keep diffs small, keep releases small. Feedback becomes rapid and objective: failing tests and continuous integration tell the truth early. Courage becomes disciplined restraint: stop the agent when it starts guessing, delete generated code when it bloats, and ship in increments so reality can correct you fast. Respect becomes engineering for humans: keep standards non negotiable, make changes transparent, and leave behind code that future people can understand, test, observe, and safely change.</p>

<p>From those Values and Principles, the Practices follow naturally: pair programming with the agent as the pair and the human as the driver, test driven development as the spec the agent must satisfy, continuous integration as the always on referee, and small releases as the safest way to turn speed into reliability.</p>

<h2 id="the-discipline-first-kit">The Discipline First kit</h2>

<h3 id="1-the-agent-brief">1) The Agent Brief</h3>

<p>Think of the Agent Brief as a PRD that’s small enough to fit in your head, but sharp enough that the agent can’t “creatively interpret” it.</p>

<ol>
  <li>Goal</li>
  <li>Non-goals</li>
  <li>Constraints</li>
  <li>Interfaces</li>
  <li>Acceptance criteria</li>
  <li>Risks</li>
  <li>Test plan</li>
  <li>Observability</li>
  <li>Dependencies</li>
  <li>Recovery and blast radius</li>
</ol>

<p>Here’s a concrete example (for one service):</p>

<p><strong>Goal:</strong> Add rate limiting to <code class="language-plaintext highlighter-rouge">POST /payments</code> to reduce abuse and protect downstream dependencies.<br />
<strong>Non-goals:</strong> No UI changes. No new auth scheme. No changes to other endpoints.<br />
<strong>Constraints:</strong> Must not change the public API contract. Must keep p95 latency impact under 5%.<br />
<strong>Interfaces:</strong> <code class="language-plaintext highlighter-rouge">POST /payments</code> only; configuration via env var <code class="language-plaintext highlighter-rouge">PAYMENTS_RATE_LIMIT_RPS</code>.<br />
<strong>Acceptance criteria:</strong> Requests above limit return <code class="language-plaintext highlighter-rouge">429</code> with standard error body; limits are per-customer; logs include rate-limit decision.<br />
<strong>Risks:</strong> False positives blocking legit traffic; misconfigured limits; uneven behavior across instances.<br />
<strong>Test plan:</strong> Add functional tests for 200, 429, and boundary conditions; include concurrency test; all tests deterministic in CI.<br />
<strong>Observability:</strong> Emit metric <code class="language-plaintext highlighter-rouge">payments.rate_limited.count</code>; structured log <code class="language-plaintext highlighter-rouge">rate_limit_decision</code> with customer id hash; dashboard alert on spikes.<br />
<strong>Dependencies:</strong> Redis (or in-memory) limiter library already approved; no new infrastructure.<br />
<strong>Recovery and blast radius:</strong> Feature flag the limiter; default off; rollback is flag flip; document emergency disable procedure.</p>

<p>Then three hard rules.</p>

<ol>
  <li>Do not change public APIs unless explicitly permitted.</li>
  <li>Prefer the smallest diff that can satisfy the brief.</li>
  <li>Stop and ask when uncertain.</li>
</ol>

<h3 id="2-guardrails">2) Guardrails</h3>

<p>Not vibes. Guardrails.</p>

<p>Unit tests and functional tests. Contract checks. Architecture checks. Code review. Small tasks. CI as referee.</p>

<p>If an agent can ship code faster than a human, your only sane response is to make the truth show up faster than the code. We have already seen public “trust cliff” moments when autonomy meets weak guardrails.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>Small diffs are not about being precious. They are about control. A small change is easier to review, easier to reason about, easier to test, and easier to roll back. Agents tend to expand scope unless you constrain them, so “small diffs” is both a safety boundary and a way to keep context from exploding.</p>

<h3 id="3-durable-instructions">3) Durable instructions</h3>

<p>Modern agentic tooling is quietly reinventing the same old idea: durable project instructions.</p>

<p>Rules files in agentic IDEs make behavior persistent across prompts.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup><br />
Repo-level instruction files like AGENTS.md make “how to behave here” predictable.<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup><sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup><br />
For conventions that should survive editors and IDEs, EditorConfig gives you portable, version controlled style rules.<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup><sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">7</a></sup><sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<p>Practical rule of thumb:</p>

<p>Use EditorConfig for formatting and style that must survive editors and IDEs.<br />
Use Rules files for tool-specific behavior. What to include in context, how to respond, what not to touch.<br />
Use AGENTS.md for repo-wide agent behavior. Setup commands, test commands, conventions, safety boundaries.</p>

<p>If you only do one thing, do AGENTS.md plus your Agent Brief template. That creates a stable baseline even when prompts change.</p>

<h2 id="a-one-week-experiment-tests-only">A one-week experiment (tests only)</h2>

<p>Pick one service. Pick one real user workflow in that service. Then write missing functional tests until the behavior is pinned down.</p>

<p>You will know it’s working when:</p>

<p>The tests fail for the wrong behavior and pass for the right behavior.<br />
They run repeatedly without flakes.<br />
They do not depend on environment quirks or real external systems.<br />
CI stays green and the suite stays fast enough to run often.<br />
Any production code change made only for testability is small and justified.<br />
A human reviewer can read the tests as a spec and agree they capture real behavior.</p>

<p>Measure the boring things: how many rewrites the agent needed, how many times you had to restate intent, how large the diffs got, how much review effort it took, and how quickly you got to “tests green.”</p>

<h2 id="when-discipline-first-is-overkill-and-when-it-breaks">When Discipline First is overkill (and when it breaks)</h2>

<p>Discipline First is the safest on ramp for production work. It is not mandatory ceremony for everything.</p>

<p>It is overkill for throwaway prototypes, exploratory spikes, and one-off scripts where the cost of failure is low and the code has no future. In those contexts, “vibes first” can be a valid way to learn quickly.</p>

<p>Discipline First breaks down in predictable ways:</p>

<p>The Brief rots. Intent changes but the kit does not.<br />
Tests become performative. They pass but don’t pin behavior.<br />
Guardrails turn into friction without signal. Slow, flaky, or mis-scoped checks.<br />
The agent is allowed to widen scope. Diffs balloon, review becomes theater.</p>

<p>The fix is the same as always: tighten the slice, keep the checks honest, and scale the process to the risk.</p>

<h2 id="why-measure-at-all">Why measure at all</h2>

<p>Because productivity gains are not guaranteed.</p>

<p>One of the clearest public data points so far is a randomized controlled trial from METR (published July 2025) studying experienced open source developers working in codebases they already knew. When AI tools were allowed, developers expected big speedups and later felt faster, but measured completion time was slower on average in that setting.<sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup><sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup><sup id="fnref:11" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">11</a></sup></p>

<p>That result does not mean “AI slows everyone down.” Tools and workflows change fast, task types vary wildly, and many teams report real gains. It means your intuition is not an instrument. Discipline First is not “trust the agent.” It’s “instrument the work.”</p>

<h2 id="close-the-loop-for-each-persona">Close the loop for each persona</h2>

<p>For the Skeptic: run one Discipline First experiment on tests only in a sandboxed branch.</p>

<p>For the Dismisser: pick one internal task, define your own quality gates, and let the experiment decide.</p>

<p>For the Viber: no big diffs, and every change must come with a failing test first.<sup id="fnref:12" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">12</a></sup></p>

<p>For the Builder: make discipline the default - publish the Agent Brief template, standardize rules files, and optimize the workflow so the safest path is the easiest path.</p>

<h2 id="sources-and-footnotes">Sources and Footnotes</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Replit incident reporting (Business Insider): https://www.businessinsider.com/replit-ceo-apologizes-ai-coding-tool-delete-company-database-2025-7 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Replit CEO statement (X): https://x.com/amasad/status/1943062428929892384 <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Cursor Rules documentation: https://cursor.com/docs/context/rules <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>OpenAI Codex guidance for AGENTS.md: https://developers.openai.com/codex/guides/agents-md/ <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>OpenAI “Introducing Codex” (see “How Codex Works”): https://openai.com/index/introducing-codex/ <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>EditorConfig homepage: https://editorconfig.org/ <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p>EditorConfig specification: https://spec.editorconfig.org/ <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p>JetBrains IDE support for EditorConfig: https://www.jetbrains.com/help/idea/editorconfig.html <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:9" role="doc-endnote">
      <p>METR study write-up (July 2025): https://metr.org/blog/2025-07-10-early-2025-ai-experienced-os-dev-study/ <a href="#fnref:9" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:10" role="doc-endnote">
      <p>METR paper on arXiv: https://arxiv.org/abs/2507.09089 <a href="#fnref:10" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:11" role="doc-endnote">
      <p>Reuters coverage of the METR study: https://www.reuters.com/business/ai-slows-down-some-experienced-software-developers-study-finds-2025-07-10/ <a href="#fnref:11" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:12" role="doc-endnote">
      <p>Martin Fowler on TDD: https://martinfowler.com/articles/is-tdd-dead/ <a href="#fnref:12" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Software Engineering" /><category term="ai-assisted-coding" /><category term="agentic-coding" /><category term="vibe-coding" /><category term="extreme-programming" /><category term="xp" /><category term="tdd" /><category term="continuous-integration" /><category term="testing" /><category term="guardrails" /><category term="engineering-discipline" /><summary type="html"><![CDATA[AI-assisted coding is a force multiplier. This post argues that disciplined engineering practices, rooted in Extreme Programming, are what make agentic workflows trustworthy and shippable.]]></summary></entry><entry><title type="html">Part 5: NaN, Infinity and the Rules of Weird Math</title><link href="https://systemhalted.in/2025/12/25/nan-infinity-weird-math-rules/" rel="alternate" type="text/html" title="Part 5: NaN, Infinity and the Rules of Weird Math" /><published>2025-12-25T00:00:00+00:00</published><updated>2025-12-25T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/25/nan-infinity-weird-math-rules</id><content type="html" xml:base="https://systemhalted.in/2025/12/25/nan-infinity-weird-math-rules/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>Floating point math is fast, useful, and occasionally haunted. Not philosophically, literally haunted, as in values that aren’t equal to themselves.</p>

<blockquote>
  <p><code class="language-plaintext highlighter-rouge">NaN != NaN</code> evaluates to <code class="language-plaintext highlighter-rouge">true</code></p>
</blockquote>

<p>IEEE 754 formalizes that haunting by defining special values that let computations continue while still signaling trouble. They look like broken math until you realize they’re doing damage control.</p>

<h2 id="why-special-values-exist-in-floating-point">Why Special Values Exist in Floating Point</h2>

<p>In Part 1 of this series<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>, we saw how floating-point numbers work: they use a fixed number of bits to represent the sign, exponent, and significand (mantissa). This representation has limits:</p>

<ul>
  <li><strong>Largest representable number</strong>: Around <code class="language-plaintext highlighter-rouge">1.8 × 10^308</code> for doubles (<code class="language-plaintext highlighter-rouge">Double.MAX_VALUE</code>)</li>
  <li><strong>Smallest positive normalized number</strong>: Around <code class="language-plaintext highlighter-rouge">2.2 × 10^-308</code> (<code class="language-plaintext highlighter-rouge">Double.MIN_NORMAL</code>)</li>
  <li><strong>Smallest positive nonzero number</strong>: Around <code class="language-plaintext highlighter-rouge">4.9 × 10^-324</code> (<code class="language-plaintext highlighter-rouge">Double.MIN_VALUE</code>)</li>
  <li><strong>Precision</strong>: Limited by machine epsilon (about 2.22 × 10^-16 near 1.0, i.e., Math.ulp(1.0) = the gap between 1.0 and the next larger representable double)</li>
</ul>

<p>But what happens when you compute something that <em>exceeds</em> these limits?</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">huge</span> <span class="o">=</span> <span class="mi">1</span><span class="n">e308</span><span class="o">;</span>
<span class="kt">double</span> <span class="n">overflow</span> <span class="o">=</span> <span class="n">huge</span> <span class="o">*</span> <span class="mi">10</span><span class="o">;</span>            <span class="c1">// Exceeds max value</span>
<span class="kt">double</span> <span class="n">gradual</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">MIN_NORMAL</span> <span class="o">/</span> <span class="mi">2</span><span class="o">;</span> <span class="c1">// Becomes subnormal (gradual underflow)</span>
<span class="kt">double</span> <span class="n">underflow</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">MIN_VALUE</span> <span class="o">/</span> <span class="mi">2</span><span class="o">;</span> <span class="c1">// Falls below min value → +0.0</span>
<span class="kt">double</span> <span class="n">undefined</span> <span class="o">=</span> <span class="mf">0.0</span> <span class="o">/</span> <span class="mf">0.0</span><span class="o">;</span>           <span class="c1">// Mathematically meaningless</span></code></pre></figure>

<p>IEEE 754 could have made these operations:</p>
<ol>
  <li>Throw exceptions (slow, interrupts computation)</li>
  <li>Wrap around to negative values (confusing, hides errors)</li>
  <li>Return arbitrary garbage (dangerous)</li>
</ol>

<p>Instead, it reserves special bit patterns in the exponent field to represent <em>infinity</em> and <em>NaN</em>. These aren’t normal numbers; they are sentinel values that signal “something unusual happened, but computation can continue.”</p>

<h3 id="the-bit-pattern-trick">The Bit Pattern Trick</h3>

<p>A double uses 11 bits for the exponent. IEEE 754 reserves special patterns for edge cases:</p>

<table>
  <thead>
    <tr>
      <th>Exponent bits</th>
      <th>Significand (fraction)</th>
      <th>Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>all 0s</td>
      <td>all zeros</td>
      <td>±0.0 (sign bit determines +/−)</td>
    </tr>
    <tr>
      <td>all 0s</td>
      <td>non-zero</td>
      <td>subnormal numbers</td>
    </tr>
    <tr>
      <td>1..2046</td>
      <td>any</td>
      <td>normal numbers</td>
    </tr>
    <tr>
      <td>all 1s (2047)</td>
      <td>all zeros</td>
      <td>±Infinity (sign bit determines +/−)</td>
    </tr>
    <tr>
      <td>all 1s (2047)</td>
      <td>non-zero</td>
      <td>NaN</td>
    </tr>
  </tbody>
</table>

<p>This means you can check for special values with simple bit operations - no exceptions, no branching overhead in critical inner loops. In Java you normally just use Double.isNaN(x) and Double.isInfinite(x), which are implemented efficiently under the hood.</p>

<h2 id="the-problem-what-should-math-return-when-it-breaks">The Problem: What Should Math Return When It Breaks?</h2>

<p>Now that we understand <em>why</em> special values exist (to handle edge cases without crashing), let’s see <em>when</em> they appear.</p>

<p>Consider calculating the average price change across a portfolio:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">totalChange</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">validStocks</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>

<span class="k">for</span> <span class="o">(</span><span class="nc">Stock</span> <span class="n">stock</span> <span class="o">:</span> <span class="n">portfolio</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">change</span> <span class="o">=</span> <span class="n">stock</span><span class="o">.</span><span class="na">getCurrentPrice</span><span class="o">()</span> <span class="o">-</span> <span class="n">stock</span><span class="o">.</span><span class="na">getPreviousPrice</span><span class="o">();</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">isValidChange</span><span class="o">(</span><span class="n">change</span><span class="o">))</span> <span class="o">{</span>
        <span class="n">totalChange</span> <span class="o">+=</span> <span class="n">change</span><span class="o">;</span>
        <span class="n">validStocks</span><span class="o">++;</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kt">double</span> <span class="n">avgChange</span> <span class="o">=</span> <span class="n">totalChange</span> <span class="o">/</span> <span class="n">validStocks</span><span class="o">;</span> <span class="c1">// What if validStocks is 0?</span></code></pre></figure>

<p>If no stocks had valid data, you’re dividing <code class="language-plaintext highlighter-rouge">0.0 / 0</code>. Should your program:</p>
<ul>
  <li>Crash immediately?</li>
  <li>Return <code class="language-plaintext highlighter-rouge">0.0</code> and pretend the average is zero (which is a lie)?</li>
  <li>Return something that screams “this value is meaningless”?</li>
</ul>

<p>IEEE 754 chose option three. It invented special values so errors can propagate visibly instead of silently corrupting results downstream.</p>

<h2 id="ieee-754-special-values">IEEE 754 Special Values</h2>

<p>IEEE 754 defines a few “not-a-normal-number” values so computations can keep going in a principled way instead of crashing or silently inventing garbage.</p>

<h3 id="1-signed-zero-00">1. Signed Zero: ±0.0</h3>

<p>Before we dive into infinity, there’s a subtle detail: IEEE 754 has both <code class="language-plaintext highlighter-rouge">+0.0</code> and <code class="language-plaintext highlighter-rouge">-0.0</code>. They both print as <code class="language-plaintext highlighter-rouge">0.0</code> and compare as equal, but they behave differently in division:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">posZero</span> <span class="o">=</span> <span class="mf">0.0</span><span class="o">;</span>
<span class="kt">double</span> <span class="n">negZero</span> <span class="o">=</span> <span class="o">-</span><span class="mf">0.0</span><span class="o">;</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">posZero</span> <span class="o">==</span> <span class="n">negZero</span><span class="o">);</span>  <span class="c1">// true</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mf">1.0</span> <span class="o">/</span> <span class="n">posZero</span><span class="o">);</span>       <span class="c1">// Infinity</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="mf">1.0</span> <span class="o">/</span> <span class="n">negZero</span><span class="o">);</span>       <span class="c1">// -Infinity</span></code></pre></figure>

<p>Signed zero exists so that <code class="language-plaintext highlighter-rouge">1.0 / (tiny positive number → 0)</code> gives <code class="language-plaintext highlighter-rouge">+∞</code> while <code class="language-plaintext highlighter-rouge">1.0 / (tiny negative number → 0)</code> gives <code class="language-plaintext highlighter-rouge">−∞</code>. It preserves the direction you approached zero from, which matters for continuity and limit-style reasoning (aka Calculus).</p>

<h3 id="2-infinity--and-">2. Infinity: +∞ and −∞</h3>

<p>Infinity appears when a finite result cannot be represented, or when you divide a nonzero number by zero.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">posInf</span> <span class="o">=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="mf">0.0</span><span class="o">;</span>   <span class="c1">// +Infinity</span>
<span class="kt">double</span> <span class="n">negInf</span> <span class="o">=</span> <span class="o">-</span><span class="mf">1.0</span> <span class="o">/</span> <span class="mf">0.0</span><span class="o">;</span>  <span class="c1">// -Infinity</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">posInf</span><span class="o">);</span>                  <span class="c1">// Infinity</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">negInf</span><span class="o">);</span>                  <span class="c1">// -Infinity</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isInfinite</span><span class="o">(</span><span class="n">posInf</span><span class="o">));</span> <span class="c1">// true</span></code></pre></figure>

<p>Infinity participates in ordering as you’d expect:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">+∞</code> is greater than every finite number</li>
  <li><code class="language-plaintext highlighter-rouge">−∞</code> is smaller than every finite number</li>
</ul>

<p>Arithmetic is mostly “limit-like”:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">finite + (+∞) = +∞</code></li>
  <li><code class="language-plaintext highlighter-rouge">positive × (+∞) = +∞</code></li>
  <li><code class="language-plaintext highlighter-rouge">negative × (+∞) = −∞</code></li>
</ul>

<p>But some combinations are undefined and produce NaN:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">(+∞) + (−∞) = NaN</code></li>
  <li><code class="language-plaintext highlighter-rouge">(+∞) × 0.0 = NaN</code></li>
  <li><code class="language-plaintext highlighter-rouge">(+∞) / (+∞) = NaN</code></li>
</ul>

<h3 id="3-nan-not-a-number">3. NaN: Not a Number</h3>

<p>NaN means “this result is undefined,” like <code class="language-plaintext highlighter-rouge">0.0 / 0.0</code> or <code class="language-plaintext highlighter-rouge">√(−1)</code>. Once NaN enters a computation, it spreads into any operation involving NaN to produce a NaN:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">nan</span> <span class="o">=</span> <span class="mf">0.0</span> <span class="o">/</span> <span class="mf">0.0</span><span class="o">;</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span><span class="o">);</span>           <span class="c1">// NaN</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span> <span class="o">+</span> <span class="mi">5</span><span class="o">);</span>       <span class="c1">// NaN</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span> <span class="o">*</span> <span class="mi">2</span><span class="o">);</span>       <span class="c1">// NaN</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">sqrt</span><span class="o">(</span><span class="n">nan</span><span class="o">));</span> <span class="c1">// NaN</span></code></pre></figure>

<p>This “contagious” behavior is intentional. If a value is undefined, any result built on it should also be undefined.</p>

<h4 id="the-weird-rule-nan--nan">The Weird Rule: NaN ≠ NaN</h4>

<p>The key rule that feels like a logic prank but is actually a safety feature:</p>

<p><strong>NaN is not equal to anything, including itself.</strong></p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">nan</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">NaN</span><span class="o">;</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span> <span class="o">==</span> <span class="n">nan</span><span class="o">);</span>        <span class="c1">// false (!)</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span> <span class="o">!=</span> <span class="n">nan</span><span class="o">);</span>        <span class="c1">// true</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span> <span class="o">&lt;</span> <span class="mf">5.0</span><span class="o">);</span>         <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">nan</span> <span class="o">&gt;=</span> <span class="mf">5.0</span><span class="o">);</span>        <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isNaN</span><span class="o">(</span><span class="n">nan</span><span class="o">));</span> <span class="c1">// true (correct way)</span></code></pre></figure>

<p>Why? Because NaN means “undefined result,” and you can’t meaningfully compare undefined values. NaN is unordered by design. There can be many NaN bit patterns (IEEE 754 supports “signaling” and “quiet” NaNs with different payloads), but Java generally treats them as “some NaN” unless you inspect raw bits with <code class="language-plaintext highlighter-rouge">Double.doubleToRawLongBits()</code>.</p>

<p>Think of it like asking whether two error messages are “the same error.” Even if both say “Error,” you don’t know if they represent the same underlying problem. The comparison itself is meaningless.</p>

<p><strong>Never check for NaN with <code class="language-plaintext highlighter-rouge">==</code>. Use <code class="language-plaintext highlighter-rouge">Double.isNaN(x)</code> instead.</strong></p>

<h4 id="nan-and-sorting-two-different-worlds">NaN and Sorting: Two Different Worlds</h4>

<p>This is where things get interesting. Java has <em>two</em> ways to compare doubles, and they behave differently with NaN:</p>

<p><strong>IEEE 754 comparisons</strong> (<code class="language-plaintext highlighter-rouge">==</code>, <code class="language-plaintext highlighter-rouge">&lt;</code>, <code class="language-plaintext highlighter-rouge">&lt;=</code>, etc.):</p>
<ul>
  <li>Any comparison with NaN returns <code class="language-plaintext highlighter-rouge">false</code></li>
  <li>These are what you use in <code class="language-plaintext highlighter-rouge">if</code> statements</li>
</ul>

<p><strong>Java’s total order</strong> (<code class="language-plaintext highlighter-rouge">Double.compare()</code>, <code class="language-plaintext highlighter-rouge">Double.compareTo()</code>)<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup>:</p>
<ul>
  <li>NaN is considered greater than all other values, including <code class="language-plaintext highlighter-rouge">+∞</code></li>
  <li>All NaNs are considered equal</li>
  <li>This is what <code class="language-plaintext highlighter-rouge">Arrays.sort()</code> and <code class="language-plaintext highlighter-rouge">Arrays.binarySearch()</code> use</li>
</ul>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span><span class="o">[]</span> <span class="n">values</span> <span class="o">=</span> <span class="o">{</span><span class="mf">3.0</span><span class="o">,</span> <span class="nc">Double</span><span class="o">.</span><span class="na">NaN</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">2.0</span><span class="o">};</span>
<span class="nc">Arrays</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">values</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Arrays</span><span class="o">.</span><span class="na">toString</span><span class="o">(</span><span class="n">values</span><span class="o">));</span> 
<span class="c1">// [1.0, 2.0, 3.0, NaN] -- guaranteed by Java spec</span>

<span class="c1">// IEEE comparison says "not sorted":</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">values</span><span class="o">[</span><span class="mi">2</span><span class="o">]</span> <span class="o">&lt;=</span> <span class="n">values</span><span class="o">[</span><span class="mi">3</span><span class="o">]);</span> <span class="c1">// false (3.0 &lt;= NaN is false)</span>

<span class="c1">// Total order says "sorted":</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">compare</span><span class="o">(</span><span class="n">values</span><span class="o">[</span><span class="mi">2</span><span class="o">],</span> <span class="n">values</span><span class="o">[</span><span class="mi">3</span><span class="o">])</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="o">);</span> <span class="c1">// true</span></code></pre></figure>

<p><strong>The gotcha:</strong> If you validate sortedness using <code class="language-plaintext highlighter-rouge">&lt;=</code>, you’ll get false negatives when NaN is present. If you need to check ordering, use <code class="language-plaintext highlighter-rouge">Double.compare(a, b) &lt;= 0</code> instead.</p>

<p>IEEE comparisons answer “is this mathematically ordered?” while Java’s total order answers “can we put these in a consistent sequence for sorting?” The Arrays Javadoc basically says exactly that: &lt; is not a total order for doubles, so sorting uses the total order from Double.compareTo.</p>

<p>The good news: <code class="language-plaintext highlighter-rouge">Arrays.sort()</code> and <code class="language-plaintext highlighter-rouge">Arrays.binarySearch()</code> work correctly with NaN because they use the total order internally. The NaN will consistently end up at the end of the array.</p>

<h2 id="quick-reference-comparison-table">Quick Reference: Comparison Table</h2>

<table>
  <thead>
    <tr>
      <th>Operation</th>
      <th>Result</th>
      <th>Reason</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">NaN == NaN</code></td>
      <td><code class="language-plaintext highlighter-rouge">false</code></td>
      <td>IEEE comparison: unordered</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">NaN != NaN</code></td>
      <td><code class="language-plaintext highlighter-rouge">true</code></td>
      <td>Same reason</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">NaN &lt; 5.0</code></td>
      <td><code class="language-plaintext highlighter-rouge">false</code></td>
      <td>NaN fails all IEEE comparisons</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">NaN &gt;= 5.0</code></td>
      <td><code class="language-plaintext highlighter-rouge">false</code></td>
      <td>Same</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Double.compare(NaN, 5.0)</code></td>
      <td><code class="language-plaintext highlighter-rouge">&gt; 0</code></td>
      <td>Total order: NaN &gt; everything</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">∞ &gt; 1e308</code></td>
      <td><code class="language-plaintext highlighter-rouge">true</code></td>
      <td>Infinity is greater than all finite values</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0.0 == -0.0</code></td>
      <td><code class="language-plaintext highlighter-rouge">true</code></td>
      <td>Signed zeros compare equal</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">1.0 / 0.0</code></td>
      <td><code class="language-plaintext highlighter-rouge">+∞</code></td>
      <td>Division by zero produces infinity</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0.0 / 0.0</code></td>
      <td><code class="language-plaintext highlighter-rouge">NaN</code></td>
      <td>Indeterminate form</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">∞ − ∞</code></td>
      <td><code class="language-plaintext highlighter-rouge">NaN</code></td>
      <td>Undefined operation</td>
    </tr>
  </tbody>
</table>

<h2 id="practical-takeaways">Practical Takeaways</h2>

<ol>
  <li><strong>Never check NaN with <code class="language-plaintext highlighter-rouge">==</code></strong>. Use <code class="language-plaintext highlighter-rouge">Double.isNaN(x)</code>.</li>
  <li><strong>Log early for special values</strong> when debugging “impossible” totals:</li>
</ol>

<figure class="highlight"><pre><code class="language-java" data-lang="java">   <span class="k">if</span> <span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isNaN</span><span class="o">(</span><span class="n">result</span><span class="o">))</span> <span class="o">{</span>
       <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"NaN detected at step X"</span><span class="o">);</span>
   <span class="o">}</span>
   <span class="k">if</span> <span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isInfinite</span><span class="o">(</span><span class="n">result</span><span class="o">))</span> <span class="o">{</span>
       <span class="n">log</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"Infinity detected at step X"</span><span class="o">);</span>
   <span class="o">}</span>
   </code></pre></figure>

<ol>
  <li><strong>Use the right comparison for the job</strong>: <code class="language-plaintext highlighter-rouge">==</code> for value equality, <code class="language-plaintext highlighter-rouge">Double.compare()</code> for ordering.</li>
  <li><strong>Understand the contagion</strong>: Once NaN enters your calculations, it spreads. Trace backward to find the division by zero or invalid operation that spawned it.</li>
</ol>

<h2 id="the-philosophical-bit">The Philosophical Bit</h2>

<p>NaN isn’t a bug. It is math raising its hand and saying, politely but firmly:</p>

<blockquote>
  <p>“I can’t promise anything from here.”</p>
</blockquote>

<p>When your balance sheet shows NaN, don’t curse floating point. Ask what division by zero or invalid square root you missed three steps ago. The special values aren’t betraying you; they’re the only honest answer to questions that have no answer.</p>

<p>In the next post, we’ll look at how to actually <em>handle</em> these special cases in production code without littering your logic with endless <code class="language-plaintext highlighter-rouge">isNaN()</code> checks.</p>

<h2 id="references-and-notes">References and Notes</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="/2025/12/04/ieee-754-doubles/">Part 1: IEEE 754 Doubles - The Numbers That Lie With A Straight Face</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Double.html">Java’s Total Order</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Computer Science&quot;, &quot;Software Engineering&quot;, &quot;Technology&quot;, &quot;Series 4 - Floating Point Without Tears&quot;]" /><category term="java" /><category term="floating-point" /><category term="ieee-754" /><category term="double" /><category term="machine-epsilon" /><category term="ulp" /><category term="numerics" /><category term="NaN" /><category term="infinity" /><summary type="html"><![CDATA[In IEEE 754 floating point, there are special values (NaN, +∞, −∞) that follow rules that look like broken logic, until you realize they're trying to protect you from lying math.]]></summary></entry><entry><title type="html">Part 4: Machine Epsilon - The Smallest Change a Double Can See</title><link href="https://systemhalted.in/2025/12/23/machine-epsilon-double-precision-grid/" rel="alternate" type="text/html" title="Part 4: Machine Epsilon - The Smallest Change a Double Can See" /><published>2025-12-23T00:00:00+00:00</published><updated>2025-12-23T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/23/machine-epsilon-double-precision-grid</id><content type="html" xml:base="https://systemhalted.in/2025/12/23/machine-epsilon-double-precision-grid/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>In my post on associativity and reduce<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>, we saw something that feels like a prank. In Example 5, adding 1.0 to 1e16 did not change the value at all.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span><span class="n">e16</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span> <span class="o">+</span> <span class="mf">1.0</span> <span class="o">==</span> <span class="n">x</span><span class="o">);</span> <span class="c1">// true</span></code></pre></figure>

<p>That is not Java being cheeky. That is IEEE-754 being literal. A double does not live on a continuous number line. It lives on a grid.</p>

<p>This post answers one question:</p>

<p><strong>How fine is the grid?</strong></p>

<h2 id="machine-epsilon-and-the-first-rung-above-10">Machine epsilon and the first rung above 1.0</h2>

<p>One common definition of machine epsilon (ε) is:</p>

<p><em>The smallest ε &gt; 0 such that 1.0 + ε ≠ 1.0 for double.</em></p>

<p>This is “the gap from 1.0 to the next representable double above it”.</p>

<p><strong>Note:</strong> Some references use ε to mean 2⁻⁵³, which is half this gap and represents the maximum relative rounding error for a correctly rounded operation. In this post, ε means the “next representable number above 1.0” definition, which is 2⁻⁵².</p>

<h3 id="finding-ε-in-java">Finding ε in Java</h3>

<p>Here is a loop that finds that smallest nudge.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MachineEpsilon</span> <span class="o">{</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span> <span class="n">eps</span> <span class="o">=</span> <span class="mf">1.0</span><span class="o">;</span>

    <span class="k">while</span> <span class="o">(</span><span class="mf">1.0</span> <span class="o">+</span> <span class="o">(</span><span class="n">eps</span> <span class="o">/</span> <span class="mf">2.0</span><span class="o">)</span> <span class="o">!=</span> <span class="mf">1.0</span><span class="o">)</span> <span class="o">{</span>
      <span class="n">eps</span> <span class="o">/=</span> <span class="mf">2.0</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"epsilon = "</span> <span class="o">+</span> <span class="n">eps</span><span class="o">);</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Typical output on an IEEE-754 JVM:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">epsilon = 2.220446049250313E-16</code></pre></figure>

<p>That value is exactly 2⁻⁵². Since powers of two are exactly representable in binary floating point, there is no approximation error in storing this value. The decimal string 2.220446049250313E-16 is just how Java renders that exact binary value for display, rounded to about 15 decimal digits.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p><strong>One quick trap:</strong> <code class="language-plaintext highlighter-rouge">Double.MIN_VALUE</code> is not machine epsilon. <code class="language-plaintext highlighter-rouge">Double.MIN_VALUE</code> is the smallest positive double near zero (about 5×10⁻³²⁴). Machine epsilon is about spacing near 1.0.</p>

<h2 id="the-ladder-model">The ladder model</h2>

<p>Picture a ladder laid across the number line.</p>

<p>Near 1.0, the rungs are extremely close together. As the numbers get bigger, the rungs spread out.</p>

<p>Machine epsilon tells you the rung spacing near 1.0. But what you usually want is the spacing near whatever value you are actually using.</p>

<p>That spacing is called <strong>ULP</strong>, short for <strong>Unit in the Last Place</strong>.</p>

<p>Java gives it to you with <code class="language-plaintext highlighter-rouge">Math.ulp(x)</code>.</p>

<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 920 380" role="img" aria-label="Double precision grid spacing near 1.0 vs near 1e16" preserveAspectRatio="xMidYMid meet" style="max-width: 100%; height: auto; display: block;">
  <style>
    .title { font: 700 18px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; fill: #111; }
    .label { font: 13px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; fill: #222; }
    .small { font: 12px ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; fill: #222; }
    .tick { stroke: #111; stroke-width: 2; }
    .axis { stroke: #111; stroke-width: 2.5; }
    .ghost { stroke: #888; stroke-width: 2; stroke-dasharray: 5 5; }
    .note { font: 12px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; fill: #333; }
    .box { fill: #fafafa; stroke: #ddd; stroke-width: 1.5; }
  </style>

  <text x="20" y="28" class="title">Double is a grid: spacing depends on magnitude</text>

  <!-- Panel boxes -->
  <rect x="20" y="50" width="880" height="130" rx="10" class="box" />
  <rect x="20" y="195" width="880" height="150" rx="10" class="box" />

  <!-- Panel 1: near 1.0 -->
  <text x="40" y="78" class="label">Zoom near 1.0</text>
  <text x="40" y="98" class="note">Adjacent representable values are extremely close: spacing ≈ ε = 2⁻⁵² ≈ 2.22e−16</text>

  <!-- Axis 1 -->
  <line x1="60" y1="135" x2="860" y2="135" class="axis" />
  <text x="60" y="158" class="small">…</text>

  <!-- Dense ticks -->
  <line x1="430" y1="118" x2="430" y2="152" class="tick" />
  <text x="410" y="112" class="small">1.0</text>

  <line x1="380" y1="122" x2="380" y2="148" class="tick" />
  <line x1="405" y1="122" x2="405" y2="148" class="tick" />
  <line x1="455" y1="122" x2="455" y2="148" class="tick" />
  <line x1="480" y1="122" x2="480" y2="148" class="tick" />

  <!-- epsilon arrow -->
  <line x1="430" y1="165" x2="455" y2="165" stroke="#111" stroke-width="2" />
  <polygon points="455,165 448,161 448,169" fill="#111" />
  <text x="470" y="169" class="small">ε (next rung)</text>

  <text x="780" y="158" class="small">…</text>

  <!-- Panel 2: near 1e16 -->
  <text x="40" y="223" class="label">Zoom near 1e16</text>
  <text x="40" y="243" class="note">Here the grid is coarse: ulp(1e16) = 2.0, so +1.0 lands between rungs and vanishes</text>

  <!-- Axis 2 -->
  <line x1="60" y1="275" x2="860" y2="275" class="axis" />

  <!-- Rungs: 1e16, 1e16+2, 1e16+4 -->
  <line x1="360" y1="258" x2="360" y2="292" class="tick" />
  <text x="310" y="252" class="small">1e16</text>

  <line x1="460" y1="258" x2="460" y2="292" class="tick" />
  <text x="425" y="252" class="small">+2</text>

  <line x1="560" y1="258" x2="560" y2="292" class="tick" />
  <text x="525" y="252" class="small">+4</text>

  <!-- The missing +1 (ghost tick) -->
  <line x1="410" y1="258" x2="410" y2="292" class="ghost" />

  <!-- ulp arrow (moved down so it doesn't collide with +1 text) -->
  <line x1="360" y1="323" x2="460" y2="323" stroke="#111" stroke-width="2" />
  <polygon points="460,323 453,319 453,327" fill="#111" />
  <text x="470" y="327" class="small">ulp = 2.0</text>

  <!-- +1 annotation (moved further down) -->
  <text x="392" y="345" class="small">+1</text>
  <text x="430" y="345" class="small">does not exist</text>

  <!-- Summary callout (pushed down and within new height) -->
  <text x="40" y="372" class="note">Takeaway: doubles keep ~53 bits of precision, so absolute spacing grows as numbers grow.</text>
</svg>

<h2 id="how-spacing-grows-with-magnitude">How spacing grows with magnitude</h2>

<p>Let’s sample the grid at a few scales.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UlpSpacing</span> <span class="o">{</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">double</span><span class="o">[]</span> <span class="n">xs</span> <span class="o">=</span> <span class="o">{</span><span class="mf">1.0</span><span class="o">,</span> <span class="mf">10.0</span><span class="o">,</span> <span class="mi">1</span><span class="n">e8</span><span class="o">,</span> <span class="mi">1</span><span class="n">e16</span><span class="o">};</span>

    <span class="k">for</span> <span class="o">(</span><span class="kt">double</span> <span class="n">x</span> <span class="o">:</span> <span class="n">xs</span><span class="o">)</span> <span class="o">{</span>
      <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">printf</span><span class="o">(</span><span class="s">"x=%-8s  ulp(x)=%s%n"</span><span class="o">,</span> <span class="n">x</span><span class="o">,</span> <span class="nc">Math</span><span class="o">.</span><span class="na">ulp</span><span class="o">(</span><span class="n">x</span><span class="o">));</span>
    <span class="o">}</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Typical output:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">x=1.0      ulp(x)=2.220446049250313E-16
x=10.0     ulp(x)=1.7763568394002505E-15
x=1.0E8    ulp(x)=1.4901161193847656E-8
x=1.0E16   ulp(x)=2.0</code></pre></figure>

<p>That last line is the whole “Example 5” mystery solved:</p>

<p><strong>Around 1e16, the grid spacing is 2.0.</strong></p>

<p>So 1e16 + 1.0 lands between rungs and rounds back to 1e16. But 1e16 + 2.0 is exactly one rung up.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">big</span> <span class="o">=</span> <span class="mi">1</span><span class="n">e16</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">big</span> <span class="o">+</span> <span class="mf">1.0</span> <span class="o">==</span> <span class="n">big</span><span class="o">);</span> <span class="c1">// true</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">big</span> <span class="o">+</span> <span class="mf">2.0</span> <span class="o">==</span> <span class="n">big</span><span class="o">);</span> <span class="c1">// false</span></code></pre></figure>

<h2 id="powers-of-two-where-spacing-jumps">Powers of two: where spacing jumps</h2>

<p>ULP does not grow smoothly. It jumps at powers of two.</p>

<p>Right below 2ᵏ, spacing is one value. At 2ᵏ, spacing doubles.</p>

<p>That is why comparisons that seem symmetric can behave oddly if two values straddle a power-of-two boundary. If you’re comparing values near different powers of two, their ULPs can differ by a factor of 2.</p>

<h2 id="near-zero-subnormals-exist-and-they-are-weird">Near zero: subnormals exist and they are weird</h2>

<p>For very small magnitudes below <code class="language-plaintext highlighter-rouge">Double.MIN_NORMAL</code> (approximately 2.225×10⁻³⁰⁸), double switches to subnormal (also called denormal) representation.</p>

<p><strong>What changes in subnormal land:</strong></p>

<p>Normal doubles have an implicit leading <code class="language-plaintext highlighter-rouge">1.</code> in the mantissa:</p>
<ul>
  <li>value = (1.fraction) × 2^exponent</li>
  <li>This gives you full precision</li>
</ul>

<p>Subnormals drop that leading <code class="language-plaintext highlighter-rouge">1.</code>:</p>
<ul>
  <li>value = (0.fraction) × 2^(minExponent)</li>
  <li>You lose precision gradually as you approach zero</li>
</ul>

<p><strong>Why they exist:</strong></p>

<p>Without subnormals, there would be a hard cliff from tiny normal numbers straight to 0.0. Subnormals provide <em>gradual underflow</em> - a ramp instead of a cliff.</p>

<p><strong>Key differences:</strong></p>

<ul>
  <li>Spacing becomes constant at approximately 5×10⁻³²⁴ (the value of <code class="language-plaintext highlighter-rouge">Double.MIN_VALUE</code>) rather than scaling with magnitude</li>
  <li>Arithmetic can be slower on some CPUs</li>
  <li>Relative precision is much worse (you may have only a few significant bits left)</li>
</ul>

<p>Everything in the range <code class="language-plaintext highlighter-rouge">(0, Double.MIN_NORMAL)</code> is subnormal. That’s the range from about 4.9×10⁻³²⁴ up to about 2.225×10⁻³⁰⁸.</p>

<p>Most business code never goes near subnormals. Numerical code sometimes does. It is worth knowing that floating-point has an emergency mode near zero that trades precision for continuity.</p>

<h2 id="why-tiny-increments-vanish-when-numbers-get-big">Why tiny increments vanish when numbers get big</h2>

<p>When your running total grows large enough, the local rung spacing can become bigger than the increments you are adding.</p>

<p>So “add a million tiny things to a huge sum” eventually turns into “add nothing, repeatedly,” because the tiny things fall between rungs and get rounded away.</p>

<p>That is not philosophical. It is mechanical.</p>

<h2 id="why-equality-checks-on-doubles-are-dicey">Why equality checks on doubles are dicey</h2>

<p>Sometimes two values that “should be different” land on the same rung. Sometimes two values that “should be equal” get rounded at different times and land on adjacent rungs.</p>

<p>So <code class="language-plaintext highlighter-rouge">==</code> is only safe when you mean exact equality:</p>

<ul>
  <li>Comparing to exact literals: <code class="language-plaintext highlighter-rouge">0.0</code>, <code class="language-plaintext highlighter-rouge">1.0</code>, <code class="language-plaintext highlighter-rouge">-1.0</code></li>
  <li>Checking for special values: infinities, or <code class="language-plaintext highlighter-rouge">Double.isNaN(x)</code></li>
  <li>Comparing sentinel values or results from identical deterministic operations</li>
  <li>Loop counters stored as doubles (though you should use integers instead)</li>
</ul>

<p>When you need “close enough,” you need a rule that matches your domain.</p>

<p>A common practical pattern is absolute tolerance near zero plus relative tolerance for scale.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">DoubleCompare</span> <span class="o">{</span>
  <span class="kd">private</span> <span class="nf">DoubleCompare</span><span class="o">()</span> <span class="o">{}</span> <span class="c1">// prevent instantiation</span>

  <span class="cm">/**
   * Check if two doubles are nearly equal using absolute and relative tolerance.
   * 
   * @param a first value
   * @param b second value
   * @param absTol absolute tolerance (try 1e-9 for many applications)
   * @param relTol relative tolerance (try 1e-9 for many applications)
   * @return true if values are within tolerance
   */</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">boolean</span> <span class="nf">nearlyEqual</span><span class="o">(</span><span class="kt">double</span> <span class="n">a</span><span class="o">,</span> <span class="kt">double</span> <span class="n">b</span><span class="o">,</span> <span class="kt">double</span> <span class="n">absTol</span><span class="o">,</span> <span class="kt">double</span> <span class="n">relTol</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">isNaN</span><span class="o">(</span><span class="n">a</span><span class="o">)</span> <span class="o">||</span> <span class="nc">Double</span><span class="o">.</span><span class="na">isNaN</span><span class="o">(</span><span class="n">b</span><span class="o">))</span> <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="o">)</span> <span class="k">return</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">// handles infinities and exact matches</span>

    <span class="kt">double</span> <span class="n">diff</span> <span class="o">=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="o">);</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">diff</span> <span class="o">&lt;=</span> <span class="n">absTol</span><span class="o">)</span> <span class="k">return</span> <span class="kc">true</span><span class="o">;</span>

    <span class="kt">double</span> <span class="n">maxAbs</span> <span class="o">=</span> <span class="nc">Math</span><span class="o">.</span><span class="na">max</span><span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">a</span><span class="o">),</span> <span class="nc">Math</span><span class="o">.</span><span class="na">abs</span><span class="o">(</span><span class="n">b</span><span class="o">));</span>
    <span class="k">return</span> <span class="n">diff</span> <span class="o">&lt;=</span> <span class="n">relTol</span> <span class="o">*</span> <span class="n">maxAbs</span><span class="o">;</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p><strong>Choosing tolerance values:</strong></p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">absTol</code> should match the minimum meaningful difference in your domain. For scientific data measured to 3 decimal places, maybe <code class="language-plaintext highlighter-rouge">1e-3</code>. For pixel coordinates, maybe <code class="language-plaintext highlighter-rouge">0.5</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">relTol</code> is typically something like <code class="language-plaintext highlighter-rouge">1e-9</code> (about 9 decimal digits of agreement) for general use, or <code class="language-plaintext highlighter-rouge">1e-6</code> if you’re being more lenient.</li>
  <li>These comparisons are slower than <code class="language-plaintext highlighter-rouge">==</code>. If you’re comparing millions of values in performance-critical code, measure the cost.</li>
</ul>

<p>This is not the only strategy, but it is harder to misuse than an “ULPs everywhere” helper.</p>

<h2 id="why-parallel-reductions-can-drift">Why parallel reductions can drift</h2>

<p>Parallel reductions regroup operations. Floating-point addition is not associative, so regrouping changes when rounding happens.</p>

<p>Here is the smallest “this is why” example.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="n">e16</span><span class="o">;</span>

<span class="kt">double</span> <span class="n">left</span>  <span class="o">=</span> <span class="o">(</span><span class="n">a</span> <span class="o">+</span> <span class="mf">1.0</span><span class="o">)</span> <span class="o">+</span> <span class="mf">1.0</span><span class="o">;</span>   <span class="c1">// first +1 vanishes, then second +1 vanishes</span>
<span class="kt">double</span> <span class="n">right</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="o">(</span><span class="mf">1.0</span> <span class="o">+</span> <span class="mf">1.0</span><span class="o">);</span>   <span class="c1">// (1.0 + 1.0) becomes 2.0, which moves one ULP</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">left</span> <span class="o">==</span> <span class="n">right</span><span class="o">);</span> <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">left</span><span class="o">);</span>          <span class="c1">// 1.0E16</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">right</span><span class="o">);</span>         <span class="c1">// 1.0000000000000002E16</span></code></pre></figure>

<p>Same values, different grouping, different result. That is the reason parallel sums can drift when the data has large magnitudes or mixed scales.</p>

<h2 id="the-takeaway">The takeaway</h2>

<p>A double gives you roughly the same number of significant bits everywhere (about 15-16 decimal digits), not the same absolute resolution everywhere.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></p>

<p>Machine epsilon tells you the first rung above 1.0.</p>

<p><code class="language-plaintext highlighter-rouge">Math.ulp(x)</code> tells you the rung spacing where you are standing.</p>

<p>And that is why, at 1e16, adding 1.0 is like whispering into a hurricane.</p>

<h2 id="references">References</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="/2025/11/28/associativity-identity-folding/">Part 2: Associativity, Identity, and Folding - Why Your reduce Keeps Biting You</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>How is  2.220446049250313E-16 = 2⁻⁵²?
  2⁻⁵² = 1 / 2⁵² = 1 / 4,503,599,627,370,496</p>

      <p>1 ÷ 4,503,599,627,370,496 = 0.00000000000000022204460492503130808472633361816…<br />
 In scientific notation: 2.2204460492503130808… × 10⁻¹⁶<br />
 The displayed value 2.220446049250313E-16 is this value rounded to 15-16 significant decimal digits for display. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>For deeper reading, see David Goldberg’s classic paper, <a href="https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">“What Every Computer Scientist Should Know About Floating-Point Arithmetic”</a>.* <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Computer Science&quot;, &quot;Software Engineering&quot;, &quot;Technology&quot;, &quot;Series 4 - Floating Point Without Tears&quot;]" /><category term="java" /><category term="floating-point" /><category term="ieee-754" /><category term="double" /><category term="machine-epsilon" /><category term="ulp" /><category term="numerics" /><summary type="html"><![CDATA[How fine is the double-precision grid, and why does 1.0 vanish next to 1e16?]]></summary></entry><entry><title type="html">Part 3: BigDecimal - When Doubles Aren’t Enough</title><link href="https://systemhalted.in/2025/12/22/java-bigdecimal-vs-double/" rel="alternate" type="text/html" title="Part 3: BigDecimal - When Doubles Aren’t Enough" /><published>2025-12-22T00:00:00+00:00</published><updated>2025-12-22T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/22/java-bigdecimal-vs-double</id><content type="html" xml:base="https://systemhalted.in/2025/12/22/java-bigdecimal-vs-double/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>In my earlier post on <a href="/2025/12/04/ieee-754-doubles/">IEEE 754 doubles</a> I showed how a tiny Java example could break your intuition about numbers. The JVM was not being sloppy. It was faithfully following the floating point rules. The surprise came from my mental model, not from the hardware.</p>

<p>BigDecimal is Java’s answer to a different problem: <em>what if I actually need decimal correctness, not fast binary approximation?</em> It is the type you reach for when cents matter, reconciliation matters, or auditors matter.</p>

<p>It is less magical than it looks.</p>

<p><strong>TL;DR:</strong> Use <code class="language-plaintext highlighter-rouge">new BigDecimal("0.1")</code> for decimal values in your code. Only use <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code> when you’re already stuck with a double from external sources.</p>

<h2 id="quick-reference">Quick Reference</h2>

<p>Before we dive in, here’s what you need to remember:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">  
<span class="c1">// ✓ Correct ways to create BigDecimal for money  </span>
<span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"0.1"</span><span class="o">);</span>                   <span class="c1">// String literal  </span>
<span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"123.45"</span><span class="o">);</span>                <span class="c1">// String literal  </span>
<span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">10</span><span class="o">).</span><span class="na">movePointLeft</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span> <span class="c1">// 10 × 10^-1 = 1.0  </span>

<span class="c1">// ✗ Wrong for hardcoded decimal values  </span>
<span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="mf">0.1</span><span class="o">);</span>        <span class="c1">// Exposes the binary approximation as decimal</span></code></pre></figure>

<h2 id="doubles-speak-binary-your-domain-speaks-decimal">Doubles speak binary, your domain speaks decimal</h2>

<p><code class="language-plaintext highlighter-rouge">double</code> is brilliant for physics, graphics, simulations, and anything where small error is acceptable. It is terrible at representing human money. The root cause is simple. Doubles are binary fractions. Money is decimal.</p>

<p><code class="language-plaintext highlighter-rouge">0.1</code> rupee or dollar has no exact representation in binary floating point. When you write:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mf">0.1</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>              <span class="c1">// prints 0.1 (canonical string)</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">printf</span><span class="o">(</span><span class="s">"%.20f%n"</span><span class="o">,</span> <span class="n">x</span><span class="o">);</span>    <span class="c1">// 0.10000000000000000555...</span></code></pre></figure>

<p>you are already off by a tiny amount, even though the default printout shows <code class="language-plaintext highlighter-rouge">0.1</code>. Most of the time you are happy to ignore that tiny tail (technically binary approximation). But then you sum millions of rows, or reorder operations, or start comparing for equality, and the tail starts wagging the dog.</p>

<p>BigDecimal cuts across this by working in base 10.</p>

<h2 id="bigdecimals-mental-model">BigDecimal’s mental model</h2>

<p>Conceptually, a BigDecimal is two things glued together:</p>

<ol>
  <li>An integer representing all the digits, without any decimal point.</li>
  <li>A scale that says where the decimal point lives.</li>
</ol>

<p>Formally:</p>

<p><code class="language-plaintext highlighter-rouge">value = unscaledValue × 10^(-scale)</code></p>

<p>So:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">amount</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"123.45"</span><span class="o">);</span></code></pre></figure>

<p>internally becomes:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">unscaledValue = 12345</code></li>
  <li><code class="language-plaintext highlighter-rouge">scale = 2</code></li>
  <li>logical value = <code class="language-plaintext highlighter-rouge">12345 × 10^-2 = 123.45</code></li>
</ul>

<p>Because the unscaled integer is exact, decimal values like <code class="language-plaintext highlighter-rouge">0.1</code>, <code class="language-plaintext highlighter-rouge">0.01</code>, <code class="language-plaintext highlighter-rouge">1234567890.12</code> are also exact. There is no “closest representable value” the way there is with <code class="language-plaintext highlighter-rouge">double</code>. You only lose information when you explicitly ask BigDecimal to round (via <code class="language-plaintext highlighter-rouge">MathContext</code> or <code class="language-plaintext highlighter-rouge">setScale</code>).</p>

<h3 id="how-the-jdk-actually-stores-it">How the JDK actually stores it</h3>

<p>That is the spec view. Under the hood in OpenJDK, the class looks roughly like this:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">BigDecimal</span> <span class="kd">extends</span> <span class="nc">Number</span>
        <span class="kd">implements</span> <span class="nc">Comparable</span><span class="o">&lt;</span><span class="nc">BigDecimal</span><span class="o">&gt;</span> <span class="o">{</span>

    <span class="c1">// Compact form when it fits in a long</span>
    <span class="kd">private</span> <span class="kd">transient</span> <span class="kt">long</span> <span class="n">intCompact</span><span class="o">;</span>

    <span class="c1">// Full form when it doesn't</span>
    <span class="kd">private</span> <span class="nc">BigInteger</span> <span class="n">intVal</span><span class="o">;</span>

    <span class="c1">// Digits after the decimal point</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">scale</span><span class="o">;</span>

    <span class="c1">// Cached number of significant digits</span>
    <span class="kd">private</span> <span class="kd">transient</span> <span class="kt">int</span> <span class="n">precision</span><span class="o">;</span>

    <span class="c1">// Marker for "no compact long, use intVal instead"</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="kt">long</span> <span class="no">INFLATED</span> <span class="o">=</span> <span class="nc">Long</span><span class="o">.</span><span class="na">MIN_VALUE</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>So BigDecimal actually has two representations for the unscaled value:</p>

<ul>
  <li><strong>Compact mode</strong>: if the unscaled integer fits in a 64-bit <code class="language-plaintext highlighter-rouge">long</code>, it lives in <code class="language-plaintext highlighter-rouge">intCompact</code> and <code class="language-plaintext highlighter-rouge">intVal</code> is <code class="language-plaintext highlighter-rouge">null</code>. This is the fast path for “small enough” numbers.</li>
  <li><strong>Inflated mode</strong>: if it does not fit, <code class="language-plaintext highlighter-rouge">intCompact</code> is set to <code class="language-plaintext highlighter-rouge">INFLATED</code> and the digits live in <code class="language-plaintext highlighter-rouge">intVal</code> as a <code class="language-plaintext highlighter-rouge">BigInteger</code>.</li>
</ul>

<p>This optimization means small monetary amounts stay fast, while supporting arbitrarily large values when needed.</p>

<p>Your <code class="language-plaintext highlighter-rouge">123.45</code> example fits happily in compact form:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">intCompact = 12345L</code></li>
  <li><code class="language-plaintext highlighter-rouge">intVal = null</code></li>
  <li><code class="language-plaintext highlighter-rouge">scale = 2</code></li>
</ul>

<h2 id="never-construct-bigdecimal-from-a-double">Never construct BigDecimal from a double</h2>

<p>A classic foot-gun looks like this:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">0.1</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.1"</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">);</span> <span class="c1">// 0.1000000000000000055511151231257827021181583404541015625</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">b</span><span class="o">);</span> <span class="c1">// 0.1</span></code></pre></figure>

<p>The first line takes the <em>binary</em> double for <code class="language-plaintext highlighter-rouge">0.1</code> and converts it directly into an exact decimal. The double is already an approximation, so you get the full fraction printed out.</p>

<p>The second line parses the string <code class="language-plaintext highlighter-rouge">"0.1"</code> as a decimal value. There is no binary detour, so you get exactly one tenth.</p>

<p>You have not “fixed” the double by wrapping it in a BigDecimal. You have just made its approximation painfully visible.</p>

<h2 id="what-about-bigdecimalvalueof-and-canonical-strings">What about BigDecimal.valueOf() and canonical strings?</h2>

<p>This is where people get confused:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="mf">0.1</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">b</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mf">0.1</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">);</span>
<span class="c1">// 0.1000000000000000055511151231257827021181583404541015625</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">b</span><span class="o">);</span>
<span class="c1">// 0.1</span></code></pre></figure>

<p>Same literal <code class="language-plaintext highlighter-rouge">0.1</code>, two different worlds.</p>

<p>The difference is that <code class="language-plaintext highlighter-rouge">valueOf</code> goes through the <strong>canonical decimal string</strong> of the double.</p>

<h3 id="route-1-new-bigdecimal01">Route 1: <code class="language-plaintext highlighter-rouge">new BigDecimal(0.1)</code></h3>

<p>This constructor works directly from the binary bits of the double:</p>

<ul>
  <li>The double for <code class="language-plaintext highlighter-rouge">0.1</code> is not exactly one tenth.</li>
  <li>It is some messy binary fraction very close to 0.1.</li>
  <li><code class="language-plaintext highlighter-rouge">new BigDecimal(double)</code> asks: “What is the exact decimal value of this binary fraction?”</li>
</ul>

<p>So you see the full binary approximation:</p>

<blockquote>
  <p>0.1000000000000000055511151231257827021181583404541015625</p>
</blockquote>

<p>Ugly, but honest.</p>

<h3 id="route-2-bigdecimalvalueof01-and-canonical-decimal-strings">Route 2: <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(0.1)</code> and canonical decimal strings</h3>

<p><code class="language-plaintext highlighter-rouge">valueOf</code> takes a different path:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">static</span> <span class="nc">BigDecimal</span> <span class="nf">valueOf</span><span class="o">(</span><span class="kt">double</span> <span class="n">val</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">toString</span><span class="o">(</span><span class="n">val</span><span class="o">));</span>
<span class="o">}</span></code></pre></figure>

<p>The key piece here is <code class="language-plaintext highlighter-rouge">Double.toString(val)</code>. That method does not dump all the internal bits. Instead, it produces the <strong>canonical decimal string</strong> for that double:</p>

<blockquote>
  <p>The shortest decimal string that, if you parse it back with <code class="language-plaintext highlighter-rouge">Double.parseDouble</code>, gives you exactly the same double bits.</p>
</blockquote>

<p>In code, it guarantees:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">String</span> <span class="n">s</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">toString</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>
<span class="kt">double</span> <span class="n">y</span> <span class="o">=</span> <span class="nc">Double</span><span class="o">.</span><span class="na">parseDouble</span><span class="o">(</span><span class="n">s</span><span class="o">);</span>

<span class="k">assert</span> <span class="nc">Double</span><span class="o">.</span><span class="na">doubleToLongBits</span><span class="o">(</span><span class="n">x</span><span class="o">)</span> <span class="o">==</span> <span class="nc">Double</span><span class="o">.</span><span class="na">doubleToLongBits</span><span class="o">(</span><span class="n">y</span><span class="o">);</span></code></pre></figure>

<p>For the double that represents <code class="language-plaintext highlighter-rouge">0.1</code>, that canonical string happens to be:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">Double</span><span class="o">.</span><span class="na">toString</span><span class="o">(</span><span class="mf">0.1</span><span class="o">);</span> <span class="c1">// "0.1"</span></code></pre></figure>

<p>So the pipeline for <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(0.1)</code> is:</p>

<ol>
  <li>Start from the binary double for 0.1.</li>
  <li>Turn it into its canonical decimal string <code class="language-plaintext highlighter-rouge">"0.1"</code> – a decimal string with just enough digits to round back to the same double (i.e., to distinguish it from adjacent doubles).</li>
  <li>Feed that string into <code class="language-plaintext highlighter-rouge">new BigDecimal("0.1")</code>.</li>
</ol>

<p>Result: an exact decimal 0.1, not the giant tail.</p>

<p>So you can summarise it like this:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">new BigDecimal(0.1)</code> = “give me the exact decimal value of this weird binary fraction”.</li>
  <li><code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(0.1)</code> = “give me the exact decimal value of the canonical string <code class="language-plaintext highlighter-rouge">\"0.1\"</code> for this double”.</li>
</ul>

<p>The <strong>rounding error</strong> happened earlier, when you chose a <code class="language-plaintext highlighter-rouge">double</code> to represent 0.1 at all. <code class="language-plaintext highlighter-rouge">valueOf</code> doesn’t fix that choice, but it gives you a clean, canonical decimal view of that double instead of the raw fraction.</p>

<h3 id="when-to-use-valueof">When to use <code class="language-plaintext highlighter-rouge">valueOf()</code></h3>

<p><code class="language-plaintext highlighter-rouge">valueOf</code> is useful, and often preferred, in three situations:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Fine for integers</span>
<span class="nc">BigDecimal</span> <span class="n">cents</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">12345</span><span class="o">);</span> <span class="c1">// 12345</span>

<span class="c1">// When you're stuck with a double from legacy code</span>
<span class="kt">double</span> <span class="n">legacyPrice</span> <span class="o">=</span> <span class="n">thirdPartyApi</span><span class="o">.</span><span class="na">getPrice</span><span class="o">();</span>   <span class="c1">// You can't control this</span>
<span class="nc">BigDecimal</span> <span class="n">price</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">legacyPrice</span><span class="o">)</span>
    <span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>          <span class="c1">// Accept the loss, make it explicit</span>

<span class="c1">// When building decimal values programmatically from integers</span>
<span class="nc">BigDecimal</span> <span class="n">tenth</span> <span class="o">=</span> <span class="nc">BigDecimal</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="mi">1</span><span class="o">).</span><span class="na">movePointLeft</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>  <span class="c1">// Start from exact integer 1</span></code></pre></figure>

<p>But for <strong>hardcoded monetary values</strong> in your own code, skip doubles entirely and use string literals:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">price</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.10"</span><span class="o">);</span></code></pre></figure>

<p>The real rule is about <strong>where the value originates</strong>:</p>

<ul>
  <li>If the value is born in your domain as a decimal (prices, rates, balances), create it from a decimal representation (<code class="language-plaintext highlighter-rouge">String</code>, <code class="language-plaintext highlighter-rouge">long</code> + scale).</li>
  <li>If the value is already stuck in a <code class="language-plaintext highlighter-rouge">double</code>, use <code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(double)</code> and treat that conversion as a boundary where precision may already have been lost.</li>
</ul>

<p>BigDecimal will not magically repair a bad choice of primitive type.</p>

<h3 id="quick-comparison">Quick comparison</h3>

<table>
  <thead>
    <tr>
      <th>Expression</th>
      <th>Result</th>
      <th>Use Case</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">new BigDecimal("0.1")</code></td>
      <td>Exact decimal 0.1</td>
      <td>Hardcoded money</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">new BigDecimal(0.1)</code></td>
      <td>0.10000000000…05511 (binary approximation)</td>
      <td>Never use this</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(0.1)</code></td>
      <td>0.1 (canonical string)</td>
      <td>When stuck with double</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">BigDecimal.valueOf(1, 1)</code></td>
      <td>0.1 (1 × 10^-1)</td>
      <td>Programmatic creation</td>
    </tr>
  </tbody>
</table>

<h2 id="exact-sums-predictable-cents">Exact sums, predictable cents</h2>

<p>Here’s a comparison showing why BigDecimal matters for financial code:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// With doubles - unpredictable</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Double</span><span class="o">&gt;</span> <span class="n">doubleAmounts</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
    <span class="mf">10000000000000000.00</span><span class="o">,</span>
    <span class="mf">1.00</span><span class="o">,</span> <span class="mf">1.00</span><span class="o">,</span> <span class="mf">1.00</span><span class="o">,</span> <span class="mf">1.00</span>
<span class="o">);</span>
<span class="kt">double</span> <span class="n">doubleSum</span> <span class="o">=</span> <span class="n">doubleAmounts</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">mapToDouble</span><span class="o">(</span><span class="nl">Double:</span><span class="o">:</span><span class="n">doubleValue</span><span class="o">).</span><span class="na">sum</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">doubleSum</span><span class="o">);</span> <span class="c1">// 1.0000000000000004E16</span></code></pre></figure>

<p>The result is mathematically correct (10^16 + 4), but the representation shows how rounding noise creeps in when you mix huge and small magnitudes in binary floating point. At this scale, many consecutive integers are not exactly representable as double, so tiny adjustments end up living in the low bits and surfacing as …0004E16.</p>

<p>Now compare with BigDecimal:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// With BigDecimal - exact</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">BigDecimal</span><span class="o">&gt;</span> <span class="n">amounts</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
    <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"10000000000000000.00"</span><span class="o">),</span>
    <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"1.00"</span><span class="o">),</span>
    <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"1.00"</span><span class="o">),</span>
    <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"1.00"</span><span class="o">),</span>
    <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"1.00"</span><span class="o">)</span>
<span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">amounts</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="nc">BigDecimal</span><span class="o">.</span><span class="na">ZERO</span><span class="o">,</span> <span class="nl">BigDecimal:</span><span class="o">:</span><span class="n">add</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">sum</span><span class="o">);</span> <span class="c1">// 10000000000000004.00</span></code></pre></figure>

<p>No matter how you reorder the BigDecimal list, you will get the same <code class="language-plaintext highlighter-rouge">10000000000000004.00</code>. There is no hidden rounding based on magnitude, because the arithmetic is done on the unscaled integers.</p>

<p>You pay for this determinism. BigDecimal operations are typically 10-100× slower than double, depending on the values involved. But when you reconcile two systems and everything lines up to the last cent, you know where the extra CPU cycles went.</p>

<h2 id="scale-rounding-and-the-joy-of-being-explicit">Scale, rounding, and the joy of being explicit</h2>

<p>With doubles, rounding is automatic and mostly invisible. With BigDecimal, rounding is very much your problem.</p>

<p>Imagine you need to divide 1 rupee into 3 equal parts:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">one</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.00"</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">three</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"3.00"</span><span class="o">);</span>

<span class="nc">BigDecimal</span> <span class="n">each</span> <span class="o">=</span> <span class="n">one</span><span class="o">.</span><span class="na">divide</span><span class="o">(</span><span class="n">three</span><span class="o">);</span> <span class="c1">// Kaboom: ArithmeticException</span></code></pre></figure>

<p>The exception is deliberate. <code class="language-plaintext highlighter-rouge">1 / 3</code> in decimal form is <code class="language-plaintext highlighter-rouge">0.3333…</code> forever. BigDecimal refuses to guess how many digits you want. You must say how you want the result rounded.</p>

<p>There are two approaches, and knowing when to use which matters.</p>

<h3 id="mathcontext-for-intermediate-calculations">MathContext: For intermediate calculations</h3>

<p>Use <code class="language-plaintext highlighter-rouge">MathContext</code> when you need to control significant digits during computation:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Calculate pi as 22/7 with 10 significant digits</span>
<span class="nc">MathContext</span> <span class="n">mc</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">MathContext</span><span class="o">(</span><span class="mi">10</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">pi</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"22"</span><span class="o">).</span><span class="na">divide</span><span class="o">(</span>
    <span class="k">new</span> <span class="nf">BigDecimal</span><span class="o">(</span><span class="s">"7"</span><span class="o">),</span> 
    <span class="n">mc</span>
<span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">pi</span><span class="o">);</span> <span class="c1">// 3.142857143</span></code></pre></figure>

<h3 id="setscale-for-final-results">setScale: For final results</h3>

<p>Use <code class="language-plaintext highlighter-rouge">setScale</code> when you need to control decimal places for presentation or storage:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Round a calculated price to 2 decimal places for currency</span>
<span class="nc">BigDecimal</span> <span class="n">rawPrice</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"12.3456"</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">price</span> <span class="o">=</span> <span class="n">rawPrice</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">price</span><span class="o">);</span> <span class="c1">// 12.35</span></code></pre></figure>

<h3 id="the-pattern-that-works">The pattern that works</h3>

<p>For currency, a clean approach is:</p>

<ol>
  <li>Decide how many decimal places your business uses (usually 2 for most currencies)</li>
  <li>Store all monetary values with that scale</li>
  <li>When you need intermediate higher precision, use a <code class="language-plaintext highlighter-rouge">MathContext</code> locally</li>
  <li>Bring the value back to your standard scale at the boundaries</li>
</ol>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">rate</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"0.0525"</span><span class="o">);</span> <span class="c1">// 5.25% interest rate</span>
<span class="nc">BigDecimal</span> <span class="n">principal</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1000.00"</span><span class="o">);</span>

<span class="c1">// Higher precision for calculation</span>
<span class="nc">MathContext</span> <span class="n">mc</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">MathContext</span><span class="o">(</span><span class="mi">10</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">interest</span> <span class="o">=</span> <span class="n">principal</span><span class="o">.</span><span class="na">multiply</span><span class="o">(</span><span class="n">rate</span><span class="o">,</span> <span class="n">mc</span><span class="o">);</span>

<span class="c1">// Round to cents for storage</span>
<span class="n">interest</span> <span class="o">=</span> <span class="n">interest</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">interest</span><span class="o">);</span> <span class="c1">// 52.50</span></code></pre></figure>

<h2 id="equals-is-not-the-same-as-compareto">Equals is not the same as compareTo</h2>

<p>There is a subtle trap buried in BigDecimal’s API:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">x</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.0"</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">y</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.00"</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">y</span><span class="o">));</span>    <span class="c1">// false</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">y</span><span class="o">));</span> <span class="c1">// 0</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">equals</code> cares about both value and scale. The unscaled integer is <code class="language-plaintext highlighter-rouge">10</code> vs <code class="language-plaintext highlighter-rouge">100</code>, scale is <code class="language-plaintext highlighter-rouge">1</code> vs <code class="language-plaintext highlighter-rouge">2</code>, so the objects are not “equal”.</p>

<p><code class="language-plaintext highlighter-rouge">compareTo</code> cares only about numeric value. From that point of view they are both exactly one, so the comparison says zero.</p>

<p>If you put BigDecimal keys into a <code class="language-plaintext highlighter-rouge">HashMap</code> or <code class="language-plaintext highlighter-rouge">HashSet</code>, you are using <code class="language-plaintext highlighter-rouge">equals</code>. If you put them in a <code class="language-plaintext highlighter-rouge">TreeMap</code> or <code class="language-plaintext highlighter-rouge">TreeSet</code>, you are using <code class="language-plaintext highlighter-rouge">compareTo</code>. That difference has bitten enough people that the Javadoc has an explicit warning<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<h3 id="what-to-do-about-it">What to do about it</h3>

<p>For financial applications, you typically want value-based comparison:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Use compareTo for all business logic</span>
<span class="k">if</span> <span class="o">(</span><span class="n">price</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">threshold</span><span class="o">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">applyDiscount</span><span class="o">();</span>
<span class="o">}</span>

<span class="c1">// Or normalize scale before storing in collections</span>
<span class="nc">BigDecimal</span> <span class="n">normalized</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">UNNECESSARY</span><span class="o">);</span>
<span class="n">priceSet</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">normalized</span><span class="o">);</span></code></pre></figure>

<h2 id="common-mistakes">Common mistakes</h2>

<p>Beyond the double constructor trap, watch out for these.</p>

<h3 id="using--for-comparison">Using == for comparison</h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Wrong</span>
<span class="k">if</span> <span class="o">(</span><span class="n">price</span> <span class="o">==</span> <span class="n">threshold</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span>

<span class="c1">// Right</span>
<span class="k">if</span> <span class="o">(</span><span class="n">price</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">threshold</span><span class="o">)</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="o">}</span></code></pre></figure>

<h3 id="forgetting-rounding-mode">Forgetting rounding mode</h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// Throws ArithmeticException</span>
<span class="nc">BigDecimal</span> <span class="n">result</span> <span class="o">=</span> <span class="n">amount</span><span class="o">.</span><span class="na">divide</span><span class="o">(</span><span class="n">three</span><span class="o">);</span>

<span class="c1">// Specify your intent</span>
<span class="nc">BigDecimal</span> <span class="n">result</span> <span class="o">=</span> <span class="n">amount</span><span class="o">.</span><span class="na">divide</span><span class="o">(</span><span class="n">three</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">HALF_UP</span><span class="o">);</span></code></pre></figure>

<h3 id="mixing-scales-carelessly">Mixing scales carelessly</h3>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"1.0"</span><span class="o">);</span>   <span class="c1">// scale 1</span>
<span class="nc">BigDecimal</span> <span class="n">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="s">"2.00"</span><span class="o">);</span>  <span class="c1">// scale 2</span>
<span class="nc">BigDecimal</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">b</span><span class="o">);</span>              <span class="c1">// scale 2 (max of the two)</span>

<span class="c1">// Result may have unexpected scale; normalize when it matters</span>
<span class="c1">// Note: UNNECESSARY throws ArithmeticException if rounding would be needed</span>
<span class="n">sum</span> <span class="o">=</span> <span class="n">sum</span><span class="o">.</span><span class="na">setScale</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="nc">RoundingMode</span><span class="o">.</span><span class="na">UNNECESSARY</span><span class="o">);</span></code></pre></figure>

<h2 id="when-should-you-actually-use-bigdecimal">When should you actually use BigDecimal?</h2>

<p>BigDecimal is not a “better double”. It is a different tool.</p>

<p>Reach for BigDecimal when:</p>

<ul>
  <li>You are working with money, interest rates, exchange rates, or anything that must reconcile to the cent or paise</li>
  <li>You are implementing rules that are written in decimal terms by humans and regulators, not in binary terms by hardware engineers</li>
  <li>You care more about correctness and determinism than raw speed</li>
</ul>

<p>Stay with doubles when:</p>

<ul>
  <li>You are doing heavy numeric computing, simulations, statistics, graphics, or ML workloads where small rounding error is acceptable and performance dominates</li>
  <li>You are counting in powers of two, not powers of ten</li>
  <li>The measurements themselves are imprecise (sensor readings, physical measurements)</li>
</ul>

<p>You can always convert between the two worlds at clearly defined boundaries.</p>

<h2 id="closing-thought">Closing thought</h2>

<p>BigDecimal is not slow magic. It is a disciplined refusal to lie about decimals.</p>

<p>Doubles take a binary view of the universe and do their best to approximate your decimal stories. BigDecimal takes your decimal stories literally and forces you to be explicit about where information is lost.</p>

<p>Neither is the “right” choice in isolation. The trick is to know which world you are in.</p>

<h2 id="references">References</h2>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>BigDecimal Java 17 JavaDocs: https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html#equals(java.lang.Object) <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Computer Science&quot;, &quot;Software Engineering&quot;, &quot;Technology&quot;, &quot;Series 4 - Floating Point Without Tears&quot;]" /><category term="java" /><category term="bigdecimal" /><category term="ieee-754" /><category term="money" /><category term="numeric-precision" /><summary type="html"><![CDATA[Why BigDecimal exists, how it really works, and when you should reach for it instead of double.]]></summary></entry><entry><title type="html">Reforming the Security Council Without Breaking Trust</title><link href="https://systemhalted.in/2025/12/22/reforming-unsc-without-breaking-trust/" rel="alternate" type="text/html" title="Reforming the Security Council Without Breaking Trust" /><published>2025-12-22T00:00:00+00:00</published><updated>2025-12-22T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/22/reforming-unsc-without-breaking-trust</id><content type="html" xml:base="https://systemhalted.in/2025/12/22/reforming-unsc-without-breaking-trust/"><![CDATA[<p>I have written about United Nations Security Council reforms before, and the older I get, the more I realize this is not a topic that rewards anger. It rewards clarity.</p>

<p>The Security Council was designed in a specific world. The year was 1945. The problem statement was simple and terrifying: prevent another world war. The veto was not invented as a moral idea. It was a stability mechanism. If the strongest powers of that era were expected to participate in a system, they needed assurance that the system would not be used against what they consider existential interests. You may dislike that logic, but you cannot pretend it is irrational. It is the kind of logic that keeps institutions alive.</p>

<p>Still, a system can be historically justified and yet feel increasingly mismatched to the world it is supposed to manage. When that mismatch grows, two things happen.</p>

<p>First, decisions start looking less legitimate to those who are asked to accept them.</p>

<p>Second, countries start routing around the institution when it feels slow, unpredictable, or politically costly.</p>

<p>Both outcomes are bad. Legitimacy without power becomes poetry. Power without legitimacy becomes noise. The world needs less noise.</p>

<p>So the best way to talk about Security Council reform is not as a fight between “the powerful” and “the rest.” The best way is to ask a practical question.</p>

<p>How do we keep the Council authoritative enough that major powers remain invested in it, while making it representative enough that the wider world respects it?</p>

<p>That question matters because reform that ignores incentives will not produce a better Security Council. It will produce an ignored Security Council. And an ignored Security Council is not a victory for democracy. It is a victory for chaos.</p>

<p>So my goal here is not to write a fantasy about “abolishing the veto.” Charter change is hard, and the Charter is designed to be hard to change. The goal is more modest and more practical.</p>

<p>Make obstruction more accountable, more legible, and harder to perform casually, without pretending we can enforce good faith.</p>

<p>I will do three things for each proposal.</p>

<ol>
  <li>Describe what happens today.</li>
  <li>Define a concrete additional process.</li>
  <li>Explain why it helps, including where it can still fail.</li>
</ol>

<h2 id="1-make-veto-use-more-accountable-not-weaker">1. Make veto use more accountable, not weaker</h2>

<h3 id="what-happens-today">What happens today</h3>

<p>A substantive Council decision needs at least nine affirmative votes and no negative vote from any permanent member. One negative vote by a permanent member blocks the draft. That is the veto. (UN Charter, Article 27)<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>After the veto, accountability is mostly reputational.</p>

<p>Yes, the veto is public. Voting records exist. Explanations may be offered in the chamber. But the content is unstructured and often optimized for politics, not clarity.</p>

<p>Since 2022, there is also a formal spotlight mechanism. When a veto is cast, the General Assembly President must convene a debate within ten working days. The Assembly “invites” the Council to submit a special report on the veto at least 72 hours before the debate. (UNGA resolution 76/262)<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> The important word there is “invites.” It raises political cost, but it does not force precision, and it does not force participation. Analysts have noted that the resolution does not impose obligations on the vetoing state to even show up.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></p>

<h3 id="what-i-propose">What I propose</h3>

<p>A veto should trigger a short, mandatory, structured “Veto Brief” filed as an official UN document within 48 hours.</p>

<p>Not an essay. A template with hard edges.</p>

<p>The brief must include:</p>

<ol>
  <li>
    <p>Pinpoint objection<br />
Identify exactly which operative paragraphs are unacceptable.</p>
  </li>
  <li>
    <p>Factual predicates<br />
List the key factual claims the veto relies on, written as testable statements.</p>
  </li>
  <li>
    <p>Principle being invoked<br />
Cite Charter articles if needed, but state the real test in plain language. The Charter citation supports the argument. It cannot replace the argument.</p>
  </li>
  <li>
    <p>Acceptable path to “yes”<br />
Provide at least one concrete amendment or alternative text that would remove the need for a veto.</p>
  </li>
  <li>
    <p>Review trigger<br />
If the veto is conditional, state the conditions and a review date for reconsideration.</p>
  </li>
</ol>

<p>Then, within seven days, the Council schedules a short “Veto Consequences” session. Ten minutes for the vetoing member to present the brief, then a time-boxed round of questions from elected members. No moral theatre required. Just structured daylight.</p>

<p>Finally, add one small but sharp piece of enforcement that costs almost nothing.</p>

<p>If the vetoing member does not file the brief, that non-submission is recorded in the Council’s official meeting record, and it is flagged in the General Assembly debate convened under 76/262.<sup id="fnref:2:1" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> The veto remains valid, but the refusal becomes part of the permanent archive and part of the public debate.</p>

<p>To prevent a perfunctory brief that merely checks boxes, the Council President should record whether the brief is <strong>responsive</strong> to the template (i.e., it contains a concrete “path to yes” and specific factual predicates, not generic slogans). A non-responsive brief is treated like a non-submission for the purposes of the General Assembly debate, where <strong>the adequacy of the brief becomes a formal topic</strong>–members can explicitly challenge missing predicates, evasive language, or the absence of any acceptable alternative.<sup id="fnref:2:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<h3 id="why-it-helps-and-where-it-can-fail">Why it helps, and where it can fail</h3>

<p>The honest criticism is correct: “What if powerful states don’t care?”</p>

<p>Some don’t. History is not shy about that.</p>

<p>But accountability is not only about changing minds. It is also about changing the friction profile of a behavior.</p>

<p>This mechanism raises the cost of vetoing in three ways that do not require new UN spending.</p>

<ol>
  <li>
    <p>It shifts effort onto the actor choosing the veto.<br />
The UN does not hire a new bureaucracy. The vetoing mission uses its existing staff to produce a short document.</p>
  </li>
  <li>
    <p>It removes the fog that makes performative vetoes easy.<br />
If you must state what you would accept, you cannot veto and disappear into slogans.</p>
  </li>
  <li>
    <p>It makes patterns visible over time.<br />
A veto is a single moment. A trail of structured briefs becomes a story.</p>
  </li>
</ol>

<p>A concrete example shows the dysfunction today.</p>

<p>On Syria, vetoes have been repeatedly used to block action on drafts concerning the conflict and humanitarian mechanisms. Security Council Report notes that since 2011, Russia cast 19 vetoes, with 14 on Syria, and that eight of nine Chinese vetoes in that period were on Syria.<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> The UN’s own research guide lists vetoed Syria-related drafts across multiple years.<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup></p>

<p>A structured veto brief would not magically unlock consensus, but it would force two things that are often missing.</p>

<p>First, explicit alternative text, on the record, each time.</p>

<p>Second, explicit factual predicates, which can be challenged publicly in the General Assembly debate already mandated after a veto.<sup id="fnref:2:3" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>Failure mode still exists. A determined vetoing member can absorb reputational costs. But even then, the system gains something it currently lacks: a clear, testable record of what was blocked and what compromise was refused.</p>

<p>That clarity matters to history, to diplomacy, and to any future negotiation.</p>

<h2 id="2-build-a-norm-of-restraint-for-mass-atrocities-and-make-the-norm-operational">2. Build a norm of restraint for mass atrocities, and make the norm operational</h2>

<h3 id="what-happens-today-1">What happens today</h3>

<p>There is no binding rule preventing veto use in situations involving genocide, crimes against humanity, or war crimes.</p>

<p>There are voluntary initiatives.</p>

<p>The ACT Code of Conduct asks states to support timely and decisive action to prevent or end mass atrocity crimes, and calls on Council members not to vote against credible action aimed at stopping them.<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup> There is also the France–Mexico initiative calling for voluntary restraint on veto use in mass atrocity situations.<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">7</a></sup></p>

<p>These matter. But voluntary norms have a familiar weakness: they work best when they are not needed.</p>

<h3 id="what-i-propose-1">What I propose</h3>

<p>Convert “restraint” from a moral appeal into a repeatable procedure.</p>

<p>Create a “Mass Atrocity Track” for draft resolutions explicitly aimed at preventing or halting atrocity crimes.</p>

<p>If a draft is placed on this track, then any veto triggers two additional obligations inside the veto brief.</p>

<ol>
  <li>
    <p>Civilian impact claim<br />
A short statement explaining why the vetoing member believes the draft would worsen civilian protection outcomes, or violate a principle in a way that outweighs the harm of inaction.</p>
  </li>
  <li>
    <p>Alternative protection path<br />
A concrete alternative proposal that still targets civilian protection, even if it changes the means.</p>
  </li>
</ol>

<p>Then impose one simple process requirement.</p>

<p>Within 14 days of a veto on the atrocity track, the Council must vote on at least one alternative draft addressing the same civilian protection objective, even if it is imperfect.</p>

<p>This is not “forcing agreement.” It is forcing effort.</p>

<h3 id="why-it-helps-and-what-happens-if-the-veto-still-blocks-action">Why it helps, and what happens if the veto still blocks action</h3>

<p>The nightmare scenario is real.</p>

<p>What if this process exists and a veto still blocks action during an active genocide?</p>

<p>Then the Council’s impotence becomes more transparent.</p>

<p>That sounds grim, but transparency is not nothing. Opacity is how paralysis becomes normal.</p>

<p>The additional value here is that the mandated General Assembly debate after a veto (76/262) becomes better informed. Instead of debating fog, the wider membership debates a structured record that includes what alternative protection pathways were offered or not offered.<sup id="fnref:2:4" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>And yes, powerful states can still ignore the norm. But a norm tied to a forced iteration loop changes behavior at the margin, and “at the margin” is often where real lives are saved.</p>

<h2 id="3-expand-membership-with-a-specific-shape-and-admit-the-trade-offs">3. Expand membership with a specific shape, and admit the trade offs</h2>

<h3 id="what-happens-today-2">What happens today</h3>

<p>The Council has 15 members: five permanent, ten elected for two-year terms. (UN Charter, Article 23)<sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<p>Those ten elected seats are distributed by regional groups: three for Africa, two for Asia Pacific, two for Latin America and the Caribbean, two for Western Europe and Others, and one for Eastern Europe.<sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup></p>

<p>Two problems follow from this design.</p>

<p>First, two years is short. Many elected members become effective only when their term is ending.</p>

<p>Second, representation is frozen in a world that has changed.</p>

<h3 id="what-i-propose-2">What I propose</h3>

<p>A concrete model that sits between “keep it at 15 forever” and “blow it up to 25 plus overnight” is this.</p>

<p>Expand from 15 to 21 members by adding six longer-term renewable seats, without adding new vetoes.</p>

<ol>
  <li>Keep the current 10 two-year elected seats and their existing regional distribution.<sup id="fnref:9:1" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup></li>
  <li>Add six renewable seats with four-year terms, eligible for immediate re-election once.<br />
Four years is long enough to build genuine file expertise and relationships; short enough that renewal still means something.</li>
  <li>Allocate those six seats by region as follows:
2 Africa<br />
2 Asia Pacific<br />
1 Latin America and the Caribbean<br />
1 split rotation between Eastern Europe and Small Island Developing States</li>
</ol>

<p>This is not the only possible distribution. The point is to stop hand waving and put a shape on the table.</p>

<p>It also aligns with the core complaint that the current Council has no permanent representation for Africa or Latin America, a point repeatedly raised in reform debates.<sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup></p>

<h3 id="who-defines-the-criteria-and-why-would-anyone-accept-them">Who defines the criteria, and why would anyone accept them?</h3>

<p>Criteria should be defined by the General Assembly through the ongoing intergovernmental negotiations process, not by the permanent members alone. The politics are difficult, but the venue is clear.<sup id="fnref:11" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">11</a></sup></p>

<p>A Charter amendment is still required for composition change, and Charter amendments require ratification including by all permanent members. (UN Charter, Article 108)<sup id="fnref:12" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">12</a></sup></p>

<p>That is the hard wall. No serious reform should pretend it is not there.</p>

<p>So the real strategy is phased.</p>

<p>Phase 1 is working-methods reform that does not require Charter amendment. Veto briefs, structured hearings, iteration loops.</p>

<p>Phase 2 is composition reform, which requires a broader bargain.</p>

<h3 id="trade-off-larger-councils-can-be-slower">Trade off: larger councils can be slower</h3>

<p>This is a real risk. Larger groups can move slower, and more seats can add friction.</p>

<p>The mitigation is to keep the extra seats longer-term and renewable. Continuity reduces the constant onboarding churn that already slows the Council today.</p>

<p>Another mitigation is procedural discipline: time-limited negotiations, published draft histories, and structured “what would unlock agreement” fields, so debate does not become infinite.</p>

<p>And it is worth noting a counterweight to the “bigger means slower” argument: the Council already runs at high tempo. In 2024 it held 305 formal meetings (a record), which suggests there is procedural capacity for a modest increase in membership without fundamentally changing the Council’s operating rhythm.<sup id="fnref:15" role="doc-noteref"><a href="#fn:15" class="footnote" rel="footnote">13</a></sup></p>

<h2 id="4-replace-permanent-forever-with-long-term-renewable-as-a-direction-the-system-can-actually-walk">4. Replace “permanent forever” with “long term renewable,” as a direction the system can actually walk</h2>

<h3 id="what-happens-today-3">What happens today</h3>

<p>Permanence is embedded in the Charter. Removing it is not politically realistic in the near term.<sup id="fnref:12:1" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">12</a></sup></p>

<p>But “near term realism” is not the same as “long term surrender.”</p>

<h3 id="what-i-propose-3">What I propose</h3>

<p>Treat renewable legitimacy as a parallel prestige track.</p>

<p>Build up the longer-term renewable seats described above. Make them consequential. Make them hard to win and easy to lose if a state does not sustain contribution and responsibility.</p>

<p>Over time, those seats become the institution’s living legitimacy mechanism.</p>

<p>There is precedent for this kind of design in regional security bodies. The African Union Peace and Security Council has 15 members, with five elected for three-year terms and ten for two-year terms, and it has no permanent members and no veto. It uses rotation and re-election to balance continuity with legitimacy.<sup id="fnref:13" role="doc-noteref"><a href="#fn:13" class="footnote" rel="footnote">14</a></sup></p>

<p>The AU PSC is not the UN, and global politics are nastier than regional politics. But the institutional idea is useful: continuity without permanence, and influence that must be renewed.</p>

<h3 id="why-it-helps-even-if-the-old-structure-remains">Why it helps, even if the old structure remains</h3>

<p>Because it creates a pathway where legitimacy is something you keep earning, not something you inherit.</p>

<p>Even if permanence stays, renewable seats can gradually shift the Council’s center of gravity toward responsibility-based legitimacy.</p>

<h2 id="5-stakeholder-buy-in-and-how-to-build-a-coalition-that-does-not-require-miracles">5. Stakeholder buy in, and how to build a coalition that does not require miracles</h2>

<p>This is where the earlier draft was too optimistic by omission.</p>

<p>The Council does not reform because someone writes a good blog post.
It reforms when enough states can see a bargain.</p>

<p>There are already two building blocks.</p>

<p>First, the veto initiative (76/262) was adopted by consensus, and it has already triggered repeated debates after vetoes.<sup id="fnref:2:5" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> UN press reporting in November 2025 noted that multiple vetoes had triggered corresponding General Assembly debates under this mechanism.<sup id="fnref:14" role="doc-noteref"><a href="#fn:14" class="footnote" rel="footnote">15</a></sup></p>

<p>Second, there are existing coalitions around voluntary restraint and working methods, like the ACT group’s Code of Conduct.<sup id="fnref:6:1" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup></p>

<p>A practical coalition path looks like this.</p>

<ol>
  <li>Start with elected members and accountability-minded middle powers pushing working methods reforms, because working methods do not require Charter change.</li>
  <li>Use the General Assembly debate mechanism after each veto to normalize structured records and structured questions.<sup id="fnref:2:6" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></li>
  <li>Build a “default expectation” that a veto without a brief is a veto without legitimacy, even if it remains legally valid.</li>
  <li>Only then push composition reform, when the system has already shifted culturally toward accountability.</li>
</ol>

<p>This does not guarantee success. It does something more valuable.</p>

<p>It creates a ratchet. A direction. A path that can be walked.</p>

<h2 id="closing-thought">Closing thought</h2>

<p>Institutional design cannot force good faith. But it can punish bad faith with friction, sunlight, and repetition.</p>

<p>The veto will remain a power tool. The question is whether it remains a power tool that operates in fog, or a power tool that must operate in daylight.</p>

<p>In fog, the Council becomes theatre.
In daylight, it at least becomes a record.
And sometimes, that record becomes the first step toward a better bargain.</p>

<h2 id="references">References</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>United Nations Charter, Article 27 (Voting): https://www.un.org/en/about-us/un-charter/chapter-5 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>UN General Assembly Resolution 76/262: https://docs.un.org/en/a/res/76/262 <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:2:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:2:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a> <a href="#fnref:2:3" class="reversefootnote" role="doc-backlink">&#8617;<sup>4</sup></a> <a href="#fnref:2:4" class="reversefootnote" role="doc-backlink">&#8617;<sup>5</sup></a> <a href="#fnref:2:5" class="reversefootnote" role="doc-backlink">&#8617;<sup>6</sup></a> <a href="#fnref:2:6" class="reversefootnote" role="doc-backlink">&#8617;<sup>7</sup></a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Analysis noting 76/262 imposes no obligations to attend and mainly increases political cost: https://www.osorin.it/uploads/model_4/.files/199_item_2.pdf?v=1747211642 <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>Security Council Report, “The Veto”: https://www.securitycouncilreport.org/un-security-council-working-methods/the-veto.php <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>UN Research Guide, Security Council veto list: https://research.un.org/en/docs/sc/quick <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>ACT Code of Conduct (A/70/621–S/2015/978): https://docs.un.org/en/A/70/621 <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:6:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p>France–Mexico initiative on veto restraint in mass atrocities: https://centerforunreform.org/wp-content/uploads/2015/10/French-Mexican-Proposal-English.pdf <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p>United Nations Charter, Article 23 (Composition): https://www.un.org/en/about-us/un-charter/chapter-5 <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:9" role="doc-endnote">
      <p>Regional distribution of elected seats (summary): https://futures.issafrica.org/thematic/19-un-security-council/ <a href="#fnref:9" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:9:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:10" role="doc-endnote">
      <p>Example analysis of Africa’s reform position and representation arguments: https://www.csis.org/analysis/africas-design-reformed-un-security-council <a href="#fnref:10" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:11" role="doc-endnote">
      <p>UN GA Security Council reform process documents (element paper): https://www.un.org/en/ga/screform/78/pdf/2024-04-05-cochairs-revised-element-paper.pdf <a href="#fnref:11" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:12" role="doc-endnote">
      <p>United Nations Charter, Article 108 (Amendments): https://www.un.org/en/about-us/un-charter/chapter-18 <a href="#fnref:12" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:12:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:15" role="doc-endnote">
      <p>UN Security Council, “Highlights of Security Council Practice 2024” (meeting totals): https://main.un.org/securitycouncil/en/content/highlights-2024 <a href="#fnref:15" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:13" role="doc-endnote">
      <p>African Union Peace and Security Council structure and terms: https://www.peaceau.org/en/page/39-secretariat-psc <a href="#fnref:13" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:14" role="doc-endnote">
      <p>UN Press, 2025 GA debate noting repeated veto initiative debates: https://press.un.org/en/2025/ga12733.doc.htm <a href="#fnref:14" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Politics &amp; Governance" /><category term="un" /><category term="unsc" /><category term="security-council" /><category term="reform" /><category term="diplomacy" /><category term="governance" /><summary type="html"><![CDATA[A practical case for UNSC reform that preserves stability, legitimacy, and the incentives for major powers to stay invested.]]></summary></entry><entry><title type="html">Escaping GOTO: How We Learned to Make Programs Readable</title><link href="https://systemhalted.in/2025/12/17/escaping-goto/" rel="alternate" type="text/html" title="Escaping GOTO: How We Learned to Make Programs Readable" /><published>2025-12-17T00:00:00+00:00</published><updated>2025-12-17T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/17/escaping-goto</id><content type="html" xml:base="https://systemhalted.in/2025/12/17/escaping-goto/"><![CDATA[<p>In early BASIC, the line numbers felt like street addresses.</p>

<p>You could point to a place in your program and say: “Go there.”
The computer would nod, politely, and do exactly that.</p>

<p>And for a beginner, this felt comforting. Orderly. Almost architectural.</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 PRINT "Hello"
20 PRINT "World"
30 END</code></pre></figure>

<p>A neat little staircase of intentions.</p>

<p>Then we learned the spell.</p>

<h2 id="the-seduction-of-goto">The seduction of GOTO</h2>

<p>GOTO is the programming equivalent of discovering you can teleport.</p>

<p>Why walk like a peasant when you can jump?</p>

<p>Want a loop? Jump back.</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 LET X = 0
20 LET X = X + 1
30 PRINT X
40 IF X &lt; 5 THEN GOTO 20
50 END</code></pre></figure>

<p>It works. It’s simple. It even feels clever.</p>

<p>But teleportation has a cost: once you start jumping, your program stops being a story and becomes a maze.</p>

<h2 id="the-day-basic-stopped-feeling-friendly">The day BASIC stopped feeling friendly</h2>

<p>At some point the program gets longer than your short-term memory.</p>

<p>You add one more rule. Then another.</p>

<p>Now you’re jumping forward to handle special cases, jumping back to repeat, jumping sideways to “retry,” and suddenly you’re not writing code.</p>

<p>You’re playing detective.</p>

<p>Here’s the kind of shape that starts to appear:</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 INPUT "Enter a number (1-10)"; N
20 IF N &lt; 1 THEN GOTO 90
30 IF N &gt; 10 THEN GOTO 90
40 PRINT "OK"
50 GOTO 110
90 PRINT "Invalid. Try again."
100 GOTO 10
110 END</code></pre></figure>

<p>This is still readable.</p>

<p>But scale it up a bit: ten validations, multiple modes, nested loops, an error path, a “back” option, and suddenly the logic is scattered across line numbers like breadcrumbs thrown into a hurricane.</p>

<p>You don’t read it anymore.
You trace it.</p>

<p>Tracing burns attention. Attention is expensive.</p>

<p>That’s the real crime of spaghetti code: not aesthetics, cognitive cost.</p>

<h2 id="why-it-turns-into-spaghetti">Why it turns into spaghetti</h2>

<p>A clean program has a shape you can hold in your head:</p>

<p>Start → do things → finish.</p>

<p>Unstructured jumps destroy that shape.</p>

<p>GOTO breaks the one promise your reader desperately wants: that control flow will be local and predictable.</p>

<p>If any line can jump to any other line, then every line must be read with paranoia.</p>

<p>That’s not programming. That’s anxiety with line numbers.</p>

<h2 id="the-escape-structured-programming">The escape: structured programming</h2>

<p>Structured programming wasn’t invented to be fancy.
It was invented to make code readable at scale.</p>

<p>Instead of “jump anywhere,” you get a small set of composable structures:<br />
	•	sequence (do this, then that) <br />
	•	selection (if/else) <br />
	•	iteration (for/while)</p>

<p>You still do the same things, but the control flow becomes visible again.</p>

<p>Here’s the key move: instead of scattering retry logic across labels, you put it inside a loop.</p>

<p>If your BASIC dialect supports WHILE…WEND (many did), you can do:</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 PRINT "Enter a number (1-10)"
20 INPUT N
30 WHILE N &lt; 1 OR N &gt; 10
40   PRINT "Invalid. Try again."
50   INPUT N
60 WEND
70 PRINT "OK"
80 END</code></pre></figure>

<p>Now the program reads like a story again:</p>

<p>Ask → repeat until valid → proceed.</p>

<p>Same behavior. Different shape.</p>

<p>And that shape is the whole point.</p>

<h2 id="the-lesson-dont-use-goto">The lesson: don’t use GOTO</h2>

<p>Here’s the grown-up version, stated plainly:</p>

<p>Don’t use GOTO.</p>

<p>Yes, there are rare cases where it can be used carefully: generated code, constrained environments, or very low-level cleanup paths.</p>

<p>But that’s not the world most of us are programming in.</p>

<p>In real software, with real teammates and real deadlines, GOTO is a trap. It makes control flow non-local, and non-local flow makes reasoning expensive. It turns debugging into archaeology.</p>

<p>So the beginner-to-professional upgrade is simple:</p>

<p>Stop jumping. Start structuring.</p>

<p>If you need to repeat, use a loop.
If you need to choose, use IF…THEN…ELSE.
If you need to reuse, use a function.
If you need to abort, return early or throw an error.</p>

<p>Your future self will thank you. Your teammates will thank you. Your pager will thank you.</p>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>Logo taught me wonder: move the turtle, watch a picture appear.</p>

<p>BASIC taught me discipline: tell the machine exactly what to do, step by step.</p>

<p>But the most important thing BASIC taught me might be this:</p>

<p>A program is not just instructions for a computer.</p>

<p>It is a story for the next human.</p>

<p>And the moment your story needs a map and a compass, you’ve stopped writing a program and started writing a trap.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Computer Science" /><category term="Series 2 - Turtle, BASIC, and the Long Road to Taste" /><category term="basic" /><category term="gw-basic" /><category term="goto" /><category term="structured-programming" /><category term="programming" /><category term="software-engineering" /><summary type="html"><![CDATA[Line numbers made BASIC feel orderly. GOTO made it powerful. Then everything turned into spaghetti.]]></summary></entry><entry><title type="html">BASIC: The Language That Taught Me to Think Step by Step</title><link href="https://systemhalted.in/2025/12/16/basic-programming-lang/" rel="alternate" type="text/html" title="BASIC: The Language That Taught Me to Think Step by Step" /><published>2025-12-16T00:00:00+00:00</published><updated>2025-12-16T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/16/basic-programming-lang</id><content type="html" xml:base="https://systemhalted.in/2025/12/16/basic-programming-lang/"><![CDATA[<p>Logo taught me to draw.</p>

<p>BASIC taught me to instruct.</p>

<p>If Logo felt like whispering wishes to a turtle, BASIC felt like standing next to a machine and giving it crisp, literal orders. Not suggestions. Not vibes. Orders.</p>

<p>And the machine was obedient in the way only machines can be: perfectly, relentlessly, and without mercy for ambiguity.</p>

<h2 id="the-basic-mindset-the-computer-is-dumb-so-be-precise">The BASIC mindset: the computer is dumb, so be precise</h2>

<p>BASIC’s core lesson is simple:</p>

<p>Computers do not infer intent.
They execute steps.</p>

<p>So you learn to think in sequences: <br />
	1.	Put the input somewhere.  <br />
	2.	Transform it in small moves. <br />
	3.	Store intermediate results. <br />
	4.	Print the outcome.  <br />
	5.	Stop.</p>

<p>That “step-by-step” habit is not just syntax. It is a worldview.</p>

<h2 id="programs-as-recipes-not-drawings">Programs as recipes, not drawings</h2>

<p>In Logo, the turtle is the main character. You tell it to move, and the picture emerges.</p>

<p>In BASIC, the program itself is the main character. It is a recipe.</p>

<p>Here’s the kind of thing early BASIC invites you to write:</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 INPUT “Enter side length”; S
20 P = 4 * S
30 PRINT “Perimeter = “; P
40 END</code></pre></figure>

<p>No magic. No hidden state. No geometry fairy.</p>

<p>Just: ask, compute, print.</p>

<p>And even that tiny program quietly teaches important ideas:<br />
variables, arithmetic, input/output, and the idea that a program is a controlled sequence of actions.</p>

<h2 id="line-numbers-the-original-breadcrumb-trail">Line numbers: the original breadcrumb trail</h2>

<p>The first thing you notice in old-school BASIC is the line numbers.</p>

<p>They are not decoration. They are control points.</p>

<p>You don’t just write code.<br />
You create a path the computer will walk.</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 PRINT “I will count.”
20 FOR I = 1 TO 5
30 PRINT I
40 NEXT I
50 PRINT “Done.”</code></pre></figure>

<p>The flow is visible, like a little parade.</p>

<p>And once you learn that you can jump…</p>

<h2 id="goto-power-then-chaos">GOTO: power, then chaos</h2>

<p>BASIC makes it very easy to say: “Go there next.”</p>

<figure class="highlight"><pre><code class="language-basic" data-lang="basic">10 LET X = 0
20 LET X = X + 1
30 PRINT X
40 IF X &lt; 5 THEN GOTO 20
50 END</code></pre></figure>

<p>This works. It is also the seed of future pain.</p>

<p>Because once your program becomes a web of jumps, your brain becomes a detective in a bad mystery novel. Every GOTO is a plot twist.</p>

<p>This is why people later talked about “structured programming”: it’s not about being fancy, it’s about keeping the story readable.</p>

<h2 id="state-is-the-real-subject">State is the real subject</h2>

<p>In BASIC, you’re always holding state in your hands.</p>

<p>Variables are the center of gravity. They change, they accumulate, they persist.</p>

<p>That teaches a different kind of thinking than Logo:</p>

<p>Logo: move an agent, watch an effect</p>

<p>BASIC: change a value, watch consequences</p>

<p>And you start noticing patterns:
	•	Counters
	•	Accumulators
	•	Flags
	•	Branches
	•	Loops</p>

<p>In other words: the basic building blocks of the “imperative” style of programming, where you tell the machine how to do the job, not just what you want.</p>

<h2 id="error-messages-as-teachers">Error messages as teachers</h2>

<p>BASIC’s errors are blunt little teachers.</p>

<p>“Syntax error.”  <br />
“Type mismatch.”   <br />
“Out of data.”</p>

<p>Each one says: you assumed the computer would guess what you meant. It will not.</p>

<p>So you learn to be explicit.<br />
You learn to reduce ambiguity.<br />
You learn to debug.</p>

<p>Not as a skill for code, but as a skill for thought.</p>

<h2 id="the-punchline">The punchline</h2>

<p>Logo gave me wonder.<br />
BASIC gave me discipline.</p>

<p>Logo made me feel like programming was art.<br />
BASIC made me feel like programming was logic.</p>

<p>And both were true.</p>

<p>BASIC’s gift is not that it’s the most elegant language.<br />
Its gift is that it forces you to think like a machine for a while.</p>

<p>And once you can do that, you can later learn the higher trick: how to make machines feel a little more human.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Computer Science" /><category term="Series 2 - Turtle, BASIC, and the Long Road to Taste" /><category term="basic" /><category term="gw-basic" /><category term="programming" /><category term="education" /><category term="imperative-programming" /><summary type="html"><![CDATA[How BASIC’s “tell the machine exactly what to do” mindset shaped how I learned programming.]]></summary></entry><entry><title type="html">Logo Looks Nothing Like Lisp and Yet It Is</title><link href="https://systemhalted.in/2025/12/15/is-logo-a-lisp/" rel="alternate" type="text/html" title="Logo Looks Nothing Like Lisp and Yet It Is" /><published>2025-12-15T00:00:00+00:00</published><updated>2025-12-15T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/15/is-logo-a-lisp</id><content type="html" xml:base="https://systemhalted.in/2025/12/15/is-logo-a-lisp/"><![CDATA[<p>It was in 1991 that my school<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> introduced Computer Science for everyone from class IV onwards. It was the first school in Agra<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> to do so<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup>. Luckily for me I was in class IV and was excited to learn Computer Science.</p>

<p>The first day of the class we were excited. We did not get to see the newly build Computer Labs but were told lots about Computers - what is a computer? what is data? what is meaningful information? cpu, alu, monitor, keyboard and the funniest of all - the mouse. Soon we progressed to learn programming and the language of choice for that was <strong>Logo</strong><sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup>.</p>

<p>In Class IV, Logo felt like magic with training wheels.</p>

<p>A turtle sat at the center of the screen and waited for commands. You would say:</p>

<figure class="highlight"><pre><code class="language-logo" data-lang="logo">FD 50 RT 90 FD 50 RT 90 FD 50 RT 90 FD 50 HT</code></pre></figure>

<p>and a square would appear, as if geometry had agreed to be friendly for once.</p>

<h2 id="logo-is-lisp">Logo is Lisp?</h2>

<p>Years later, I discovered a fact that sounds like a prank until you stare at it long enough:</p>

<p>Logo is often described as a dialect of Lisp, or at least a Lisp-family language.<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup></p>

<p>That claim is confusing at first because Logo does not look like Lisp. Lisp is famously parenthesized. Logo is famously turtle-ish. So what gives?</p>

<p>The trick is that “dialect” here is not about surface syntax<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup>. It is about the underlying ideas: evaluation, data structures, and the way programs are shaped.</p>

<p>Below are the family resemblances hiding in plain sight.</p>

<h3 id="1-prefix-thinking-verbs-first">1. Prefix thinking: verbs first</h3>

<p>Lisp’s signature habit is that functions come first, arguments follow.</p>

<figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="p">(</span><span class="nb">+</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">)</span>
<span class="p">(</span><span class="nv">forward</span> <span class="mi">50</span><span class="p">)</span>
<span class="p">(</span><span class="nv">right</span> <span class="mi">90</span><span class="p">)</span></code></pre></figure>

<p>Logo does the same thing, it just drops the parentheses and speaks like a teacher.</p>

<figure class="highlight"><pre><code class="language-logo" data-lang="logo">sum 3 4
fd 50
rt 90</code></pre></figure>

<p>Same mental model. Different costume.</p>

<h3 id="2-lists-matter-a-lot">2. Lists matter a lot</h3>

<p>Lisp is built on lists. Logo inherits that list-centered worldview.</p>

<p>In many Logo dialects you can work with lists directly:</p>

<figure class="highlight"><pre><code class="language-logo" data-lang="logo">print [1 2 3 4]
print first [a b c]     ; a
print butfirst [a b c]  ; [b c]</code></pre></figure>

<p>If you have ever met Lisp’s car and cdr, you can feel the same head-and-tail spirit here, just with names that won’t scare a fourth grader.</p>

<h3 id="3-quoting-and-symbols-name-vs-value">3. Quoting and symbols: “name” vs “value”</h3>

<p>In Lisp, quoting is essential because you often want to talk about symbols without evaluating them.</p>

<p>Logo has a similar separation between a name and a value.</p>

<p>In UCBLogo-style notation:</p>

<figure class="highlight"><pre><code class="language-logo" data-lang="logo">make "x 10
print :x</code></pre></figure>

<p>The “x is the symbol name. The :x is the value stored in that name.</p>

<p>Different punctuation, same conceptual split: symbol vs value, data vs evaluation.</p>

<h3 id="4-recursion-feels-natural-not-exotic">4. Recursion feels natural, not exotic</h3>

<p>Lisp culture loves recursion because it pairs naturally with lists and self-similar problems.</p>

<p>Logo teaches recursion early too, especially in dialects like UCBLogo.</p>

<p>A simple recursive spiral:</p>

<figure class="highlight"><pre><code class="language-logo" data-lang="logo">to spiral :n
if :n &lt; 1 [stop]
fd :n
rt 90
spiral :n - 1
end</code></pre></figure>

<p>Here we are declaring the function named spiral. <code class="language-plaintext highlighter-rouge">to</code> is the keyword to declare functions in Logo.</p>

<p>This is not “turtle magic.” This is a core Lisp-family habit: define a procedure, then solve the big problem by repeatedly solving smaller versions of it.</p>

<h3 id="5-code-as-data-vibes-instruction-lists-you-can-run">5. Code-as-data vibes: instruction lists you can run</h3>

<p>One of Lisp’s deepest tricks is that code and data are made of the same stuff. That enables patterns like building code as a data structure, then evaluating it.</p>

<p>Logo approaches that idea in a friendlier way: lists can represent sequences of commands, and many Logo environments support executing those command lists.</p>

<p>Even when you never say the word “eval,” you are inching toward the same philosophical cliff: programs can be treated as manipulable objects.</p>

<p>That is very Lisp. It is also very sneaky.</p>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>Logo doesn’t look like Lisp because it was designed for humans first, especially young humans.</p>

<p>But the bones show through:  <br />
	1.	Prefix function application (verbs first)<br />
	2.	List-centered data thinking<br />
	3.	Quoting and symbol/value separation<br />
	4.	Comfort with recursion<br />
	5.	A path toward code-as-data</p>

<p>So the sentence “Logo is a Lisp dialect” is not a joke. It is a reminder that programming languages can share a soul even when they do not share a wardrobe.</p>

<h2 id="back-where-it-all-begin">Back where it all begin</h2>

<p>In Class IV, we had no idea that we were accidentally being taught one of the deepest ideas in CS, that lists can represent both data and instructions, and the difference between them is often just “how you choose to evaluate.”</p>

<hr />

<h2 id="notes-and-references">Notes and references</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>St. George’s College, Agra <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Agra is a city situated on the banks of River Yamuna, around 200Km south of Delhi, in the state of Uttar Pradesh in India. It was once a Mughal capital and is famous for mostly Mughal Architecture with two famous buildings of that time being - Taj Mahal, a mausaoleum build by Shahjahan for his wife and Fatehpur Sikri, the fort that was eventually abandoned by Akbar. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>My memory is vague on this and I have not corroborated this with the school. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>I don’t remember the version of Logo, whether it was UCB Logo or MSW Logo. More information about the language can be found <a href="https://el.media.mit.edu/logo-foundation/index.html">here</a>. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>Descriptions of Logo as a Lisp dialect / Lisp-family language are common in historical and documentation sources. A good starting point is the MIT Logo Foundation page and the UCBLogo documentation. (URLs for easy copying: https://el.media.mit.edu/logo-foundation/ and https://people.eecs.berkeley.edu/~bh/logo.html) <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>In Linguistic, we often talk about Deep Structures and surface structures. Surface structure is how the language is spoken in contrast to Deep structure which deals with the deeper meaning. <a href="https://en.wikipedia.org/wiki/Deep_structure_and_surface_structure?wprov=sfti1#">Deep and Surface Structures</a> <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Computer Science" /><category term="Series 2 - Turtle, BASIC, and the Long Road to Taste" /><category term="logo" /><category term="lisp" /><category term="computer-science" /><category term="education" /><category term="turtle-graphics" /><summary type="html"><![CDATA[Why Logo can be called a Lisp dialect even though it does not look like one?]]></summary></entry><entry><title type="html">Vibe Coding and the Baby Genius Problem</title><link href="https://systemhalted.in/2025/12/15/vibe-coding-and-baby-genius/" rel="alternate" type="text/html" title="Vibe Coding and the Baby Genius Problem" /><published>2025-12-15T00:00:00+00:00</published><updated>2025-12-15T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/15/vibe-coding-and-baby-genius</id><content type="html" xml:base="https://systemhalted.in/2025/12/15/vibe-coding-and-baby-genius/"><![CDATA[<p>Vibe coding has been ridiculously fun.</p>

<p>It has brought back the joy to programming. The kind of joy you thought adulthood, meetings, and Jira had permanently confiscated.</p>

<p>And yet, right now, most agents are more or less <strong>super intelligent babies</strong>.</p>

<p>They are brilliant. They are fast. They can surprise you.
But they still need to be fed context again and again.</p>

<p>Today, while working on my service virtualizer, I had to continuously inform the agent about my preference for naming API models and domain models.
The difference matters:</p>

<ul>
  <li>API models are edge interfaces, representing outward state.</li>
  <li>Domain models are internal shapes, used to pass messages within the API.</li>
</ul>

<p>The agent continuously “lied” that it was following the instructions I provided under the <code class="language-plaintext highlighter-rouge">.github/instructions</code> folder.
After multiple rounds of trial and error, it partially understood the assignment.</p>

<p>That’s the gap between intelligence and autonomy.</p>

<h2 id="the-autonomy-ladder-vibe-coding-ping-pong-vacation">The autonomy ladder: vibe coding, ping pong, vacation</h2>

<p>It is going to take some time before agents can act independently while you play ping pong.
And slightly longer for you to delegate the work completely to a few AI agents and go on vacation.</p>

<p>AI agents need to be <strong>context-aware</strong> for me to enjoy ping pong.
They need to write properly logged and observable clean code before I can trust them enough to enjoy a vacation.</p>

<p>That last line is the whole story.</p>

<p>Ping pong is a context problem.
Vacation is an accountability problem.</p>

<h2 id="a-concrete-example-my-model-naming-rule">A concrete example: my model naming rule</h2>

<p>This is where “feed context again and again” shows up in real code.</p>

<h3 id="api-models-should-be-nouns">API models should be nouns</h3>

<p>API models “datafy” representational state.
So there is no separate request and response.
There is only one state to represent for both request and response.</p>

<p>Some fields are read only, sure.
But it is still one state.</p>

<p>So instead of:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">CreateEndpointRequest</code></li>
  <li><code class="language-plaintext highlighter-rouge">CreateEndpointResponse</code></li>
  <li><code class="language-plaintext highlighter-rouge">EndpointResponse</code></li>
</ul>

<p>I want:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Endpoint</code></li>
</ul>

<h3 id="domain-models-should-not-say-request-response-or-data">Domain models should not say “Request”, “Response”, or “Data”</h3>

<p>Domain models don’t need <code class="language-plaintext highlighter-rouge">Request</code>, <code class="language-plaintext highlighter-rouge">Response</code>, or <code class="language-plaintext highlighter-rouge">Data</code> as suffixes.
That information is redundant.</p>

<p><code class="language-plaintext highlighter-rouge">EndpointData</code> as a class serves no purpose compared to <code class="language-plaintext highlighter-rouge">Endpoint</code> as a class.</p>

<p>If it is the domain concept, name it like the concept:
<code class="language-plaintext highlighter-rouge">Endpoint</code>, <code class="language-plaintext highlighter-rouge">VirtualService</code>, <code class="language-plaintext highlighter-rouge">Route</code>, <code class="language-plaintext highlighter-rouge">Rule</code>, <code class="language-plaintext highlighter-rouge">Match</code>, <code class="language-plaintext highlighter-rouge">Mapping</code>.</p>

<p>If context matters, packages can carry it:
<code class="language-plaintext highlighter-rouge">in.systemhalted.api.model.Endpoint</code>
<code class="language-plaintext highlighter-rouge">in.systemhalted.domain.model.Endpoint</code></p>

<p>Same noun, different layer.</p>

<h2 id="the-real-issue-preferences-are-not-enforceable">The real issue: preferences are not enforceable</h2>

<p>Human teams survive because we turn preferences into systems.</p>

<p>“Please follow this convention” is polite.
But politeness is not a compiler.</p>

<p>If you want agents to stop “lying” (really: confidently guessing), you have to move from memory to mechanism.</p>

<p>In other words, from vibes to accountability.</p>

<h2 id="make-conventions-executable">Make conventions executable</h2>

<p>The big move is simple:
turn conventions into checks that fail loudly.</p>

<p>Then the agent doesn’t need to remember your rules.
It just needs to pass reality.</p>

<h3 id="option-1-enforce-architecture-rules-with-archunit">Option 1: enforce architecture rules with ArchUnit</h3>

<p><a href="https://www.archunit.org/">ArchUnit</a> is a Java testing library for validating architectural decisions in code.
It lets you write tests for package boundaries, dependency direction, layering rules, and conventions that are otherwise tribal knowledge.</p>

<p>That is exactly what an AI agent struggles with: it will agree with tribal knowledge, then forget it, then agree again.</p>

<p>Here’s a practical enforcement approach:</p>

<ul>
  <li>API models live in <code class="language-plaintext highlighter-rouge">..api.model..</code> and must not end with <code class="language-plaintext highlighter-rouge">Request</code>, <code class="language-plaintext highlighter-rouge">Response</code>, or <code class="language-plaintext highlighter-rouge">Data</code></li>
  <li>Domain models live in <code class="language-plaintext highlighter-rouge">..domain.model..</code> and must not end with <code class="language-plaintext highlighter-rouge">Request</code>, <code class="language-plaintext highlighter-rouge">Response</code>, or <code class="language-plaintext highlighter-rouge">Data</code></li>
  <li>Domain must not depend on API</li>
</ul>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="c1">// src/test/java/in/systemhalted/architecture/ModelConventionsTest.java</span>
<span class="kn">package</span> <span class="nn">in.systemhalted.architecture</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">com.tngtech.archunit.core.domain.JavaClasses</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.tngtech.archunit.core.importer.ClassFileImporter</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.tngtech.archunit.lang.ArchRule</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.junit.jupiter.api.Test</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">static</span> <span class="n">com</span><span class="o">.</span><span class="na">tngtech</span><span class="o">.</span><span class="na">archunit</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">syntax</span><span class="o">.</span><span class="na">ArchRuleDefinition</span><span class="o">.</span><span class="na">classes</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">static</span> <span class="n">com</span><span class="o">.</span><span class="na">tngtech</span><span class="o">.</span><span class="na">archunit</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">syntax</span><span class="o">.</span><span class="na">ArchRuleDefinition</span><span class="o">.</span><span class="na">noClasses</span><span class="o">;</span>

<span class="kd">class</span> <span class="nc">ModelConventionsTest</span> <span class="o">{</span>

    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">JavaClasses</span> <span class="n">classes</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ClassFileImporter</span><span class="o">()</span>
            <span class="o">.</span><span class="na">importPackages</span><span class="o">(</span><span class="s">"in.systemhalted"</span><span class="o">);</span>

    <span class="nd">@Test</span>
    <span class="kt">void</span> <span class="nf">api_models_must_not_end_with_request_response_or_data</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">ArchRule</span> <span class="n">rule</span> <span class="o">=</span> <span class="n">classes</span><span class="o">()</span>
                <span class="o">.</span><span class="na">that</span><span class="o">().</span><span class="na">resideInAPackage</span><span class="o">(</span><span class="s">"..api.model.."</span><span class="o">)</span>
                <span class="o">.</span><span class="na">should</span><span class="o">().</span><span class="na">haveSimpleNameNotEndingWith</span><span class="o">(</span><span class="s">"Request"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">andShould</span><span class="o">().</span><span class="na">haveSimpleNameNotEndingWith</span><span class="o">(</span><span class="s">"Response"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">andShould</span><span class="o">().</span><span class="na">haveSimpleNameNotEndingWith</span><span class="o">(</span><span class="s">"Data"</span><span class="o">);</span>

        <span class="n">rule</span><span class="o">.</span><span class="na">check</span><span class="o">(</span><span class="n">classes</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@Test</span>
    <span class="kt">void</span> <span class="nf">domain_models_must_not_end_with_request_response_or_data</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">ArchRule</span> <span class="n">rule</span> <span class="o">=</span> <span class="n">classes</span><span class="o">()</span>
                <span class="o">.</span><span class="na">that</span><span class="o">().</span><span class="na">resideInAPackage</span><span class="o">(</span><span class="s">"..domain.model.."</span><span class="o">)</span>
                <span class="o">.</span><span class="na">should</span><span class="o">().</span><span class="na">haveSimpleNameNotEndingWith</span><span class="o">(</span><span class="s">"Request"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">andShould</span><span class="o">().</span><span class="na">haveSimpleNameNotEndingWith</span><span class="o">(</span><span class="s">"Response"</span><span class="o">)</span>
                <span class="o">.</span><span class="na">andShould</span><span class="o">().</span><span class="na">haveSimpleNameNotEndingWith</span><span class="o">(</span><span class="s">"Data"</span><span class="o">);</span>

        <span class="n">rule</span><span class="o">.</span><span class="na">check</span><span class="o">(</span><span class="n">classes</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nd">@Test</span>
    <span class="kt">void</span> <span class="nf">domain_must_not_depend_on_api</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">ArchRule</span> <span class="n">rule</span> <span class="o">=</span> <span class="n">noClasses</span><span class="o">()</span>
                <span class="o">.</span><span class="na">that</span><span class="o">().</span><span class="na">resideInAPackage</span><span class="o">(</span><span class="s">"..domain.."</span><span class="o">)</span>
                <span class="o">.</span><span class="na">should</span><span class="o">().</span><span class="na">dependOnClassesThat</span><span class="o">().</span><span class="na">resideInAnyPackage</span><span class="o">(</span><span class="s">"..api.."</span><span class="o">);</span>

        <span class="n">rule</span><span class="o">.</span><span class="na">check</span><span class="o">(</span><span class="n">classes</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>This does not prove a name is a noun.
But it blocks the most common failure mode: growing a forest of <code class="language-plaintext highlighter-rouge">*Request</code>, <code class="language-plaintext highlighter-rouge">*Response</code>, and <code class="language-plaintext highlighter-rouge">*Data</code> types that all mean the same thing.</p>

<h3 id="option-2-generate-api-models-handcraft-domain-models">Option 2: generate API models, handcraft domain models</h3>

<p>If your API layer is OpenAPI driven, treat API models as edge artifacts and generate them.
Then keep domain models intentionally authored and stable.</p>

<p>The principle is simple:</p>
<blockquote>
  <p>when the outside world changes, your domain shouldn’t shatter like glass.</p>
</blockquote>

<h3 id="option-3-a-definition-of-done-for-agents">Option 3: a definition of done for agents</h3>

<p>Agents struggle because “done” is fuzzy.</p>

<p>So make it concrete:</p>

<ol>
  <li>Restate conventions from <code class="language-plaintext highlighter-rouge">.github/instructions</code> in plain English</li>
  <li>Implement the change</li>
  <li>Run tests</li>
  <li>Show evidence: test output, files changed, and convention checks passing</li>
</ol>

<p>That’s how you replace “trust me” with “see for yourself.”</p>

<h2 id="observability-is-the-vacation-requirement">Observability is the vacation requirement</h2>

<p>Ping pong needs context awareness.
Vacation needs observability.</p>

<p>If an agent writes code that “works” but cannot explain itself at runtime, you have not delegated work.
You have adopted a mystery.</p>

<p>Vacation grade code needs boring grown up traits:</p>

<ul>
  <li>structured logs you can search</li>
  <li>correlation IDs you can follow</li>
  <li>meaningful error handling</li>
  <li>metrics and traces where it matters</li>
</ul>

<p>Because when you are on vacation, the only thing worse than an outage is an outage that speaks in riddles.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>Agents don’t mainly need to be smarter.
They need to be more accountable.</p>

<p>An agent without a stop condition is just a very confident infinite loop.</p>

<p>The trick is not to lecture the agent harder.
The trick is to build a world where “following instructions” is measurable.</p>

<p>Then you can pick up the paddle.</p>

<p>And later, maybe, the suitcase.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Software Engineering" /><category term="AI" /><category term="agentic-workflows" /><category term="vibe-coding" /><category term="testing" /><category term="observability" /><category term="conventions" /><category term="testing" /><summary type="html"><![CDATA[Vibe coding is fun again. However, Agents are still baby geniuses. The fix is turning preferences into accountability.]]></summary></entry><entry><title type="html">Project Jigsaw (JPMS) - Part 1 - What is Modularity?</title><link href="https://systemhalted.in/2025/12/14/jigsaw-what-is-modularity/" rel="alternate" type="text/html" title="Project Jigsaw (JPMS) - Part 1 - What is Modularity?" /><published>2025-12-14T00:00:00+00:00</published><updated>2025-12-14T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/14/jigsaw-what-is-modularity</id><content type="html" xml:base="https://systemhalted.in/2025/12/14/jigsaw-what-is-modularity/"><![CDATA[<h2 id="a-note-from-the-future">A note from the future</h2>

<p>I began this post in 2016, when Java 9 was still unreleased and Project Jigsaw felt like an approaching weather system. Java 9 eventually shipped, and the module system became real, imperfect, and unexpectedly enlightening.</p>

<p>This post keeps the original question intact: what is modularity and why did Java need the platform itself to care?</p>

<h2 id="java-already-had-modules-right">Java already had “modules”… right?</h2>

<p>For the past few years, Java has evolved quickly, mostly for the better. JDK 8 changed everyday Java with lambdas and streams, making a more functional style feel native instead of like cosplay.</p>

<p>Then came JDK 9 and Project Jigsaw, the Java Platform Module System (JPMS). The obvious objection was, and still is:</p>

<p>Java already has JARs. Enterprise Java has WARs and EARs. Source code has packages and access modifiers. So why add “modules” at all?</p>

<p>To answer that, we need to be annoyingly precise about what a module is.</p>

<h2 id="what-is-a-module">What is a module?</h2>

<p>A module is not just “a bunch of related code.” That definition is so generous it would make my <code class="language-plaintext highlighter-rouge">Downloads/</code> folder a module, and it absolutely should not be trusted with responsibility.</p>

<p>A better definition:</p>

<p>A module is a unit with an enforceable boundary.</p>

<p>In practice, a module needs at least these traits.</p>

<h3 id="1-encapsulation-a-hidden-interior">1. Encapsulation (a hidden interior)</h3>

<p>Encapsulation is the right to say: “this part is implementation detail; do not touch.”</p>

<p>Java supports encapsulation via access modifiers (<code class="language-plaintext highlighter-rouge">private</code>, package-private, <code class="language-plaintext highlighter-rouge">protected</code>, <code class="language-plaintext highlighter-rouge">public</code>) and via packages. In the POJO world, we keep fields private and expose behavior through methods so nobody can accidentally mutate internal state and then act surprised when physics happens.</p>

<p>But here is the catch:</p>

<p>Packages are excellent organizing units, but by themselves they are not deployment boundaries.</p>

<p>Once code is on the classpath, it tends to behave like a single sprawling neighborhood where everyone can wander into everyone else’s backyard, sometimes through reflection, sometimes through “it was convenient,” sometimes through sheer dependency gravity.</p>

<h3 id="2-a-public-surface-an-intentional-api">2. A public surface (an intentional API)</h3>

<p>A module must have a public surface: a set of types meant to be used by outsiders.</p>

<p>This matters because modularity is not just hiding. It is also communicating on purpose.</p>

<p>When modules interact, they should do so through the exported API, not through accidental knowledge of internals. This is how systems remain refactorable without becoming brittle.</p>

<p>So far, this sounds like “write disciplined code,” which is true, and still not the full story.</p>

<p>The painful question is: can the platform help enforce that discipline?</p>

<h2 id="why-packages-and-jars-were-not-enough">Why packages and JARs were not enough?</h2>

<p>Packages and JARs let us aspire to be modular. They do not consistently let us enforce it.</p>

<p>Here are the classic failure modes that show up as systems grow.</p>

<h3 id="1-the-classpath-is-a-soup">1. The classpath is a soup</h3>

<p>The classpath is wonderfully simple and brutally permissive. Put things on it, and they exist.</p>

<p>Common outcomes:</p>

<ul>
  <li>Accidental dependencies form silently.</li>
  <li>Internals become “public” by habit. “Just import it.”</li>
  <li>Debugging becomes archaeology. “Who pulled in this version, and why does it only fail on Jenkins?”</li>
</ul>

<h3 id="2-jar-hell-is-real-and-it-has-receipts">2. JAR hell is real, and it has receipts</h3>

<p>When multiple JARs provide overlapping classes, or when classloading order changes, you can get failures that only appear at runtime and only on certain machines.</p>

<p>Even when your build tool is trying to help, the model is still basically: assemble a pile of bytecode and hope it behaves.</p>

<h3 id="3-encapsulation-at-runtime-was-historically-negotiable">3. Encapsulation at runtime was historically negotiable</h3>

<p>Before JPMS, it was common for libraries to reach into non-public areas, either:</p>

<ul>
  <li>Using reflection to access private members.</li>
  <li>Using internal JDK APIs because they existed and were “handy.”</li>
</ul>

<p>This worked until it did not. And the “did not” usually arrived as a production upgrade - not an upgrade by choice but force.</p>

<h3 id="4-split-packages-and-duplicate-worlds">4. Split packages and duplicate worlds</h3>

<p>On the classpath you can end up with the same package name spread across multiple JARs. Tools can limp along, humans can suffer quietly, and then one day something breaks in a way that makes you question reality.</p>

<p>A modular system has to be stricter about identity, or it cannot reason about the graph.</p>

<h2 id="what-jigsaw-actually-adds">What Jigsaw actually adds</h2>

<p>Project Jigsaw turns modularity into something the compiler and runtime can understand.</p>

<p>A Java module has:</p>

<ul>
  <li>A name (a stronger identity than “whatever the filename is”).</li>
  <li>Declared dependencies (what it requires).</li>
  <li>Declared exports (what it makes available to other modules).</li>
  <li>Strong encapsulation by default (if you do not export it, it is not part of your public world).</li>
</ul>

<p>This is expressed with a module descriptor: <code class="language-plaintext highlighter-rouge">module-info.java</code>.</p>

<p>A minimal example:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span> <span class="o">{</span>
    <span class="n">requires</span> <span class="n">java</span><span class="o">.</span><span class="na">sql</span><span class="o">;</span>
    <span class="n">exports</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span><span class="o">.</span><span class="na">api</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>The point is not ceremony. The point is boundaries that can be checked.</p>

<h2 id="packages-vs-modules-a-clean-mental-model">Packages vs modules, a clean mental model</h2>

<p>Think of it like this:</p>

<ul>
  <li>A package groups related types and helps structure code.</li>
  <li>A module groups packages and declares which packages are visible to the outside world.</li>
</ul>

<p>Packages help you organize. Modules help you enforce.</p>

<h2 id="enforce-how-exactly">“Enforce” how, exactly?</h2>

<p>JPMS enforces things in two major places: compilation and runtime.</p>

<h3 id="1-reliable-configuration-dependency-truth">1. Reliable configuration (dependency truth)</h3>

<p>With modules, dependencies are not an emergent property of “whatever happens to be on the classpath today.”</p>

<p>Instead, the runtime resolves a module graph:</p>

<ul>
  <li>Each module declares what it requires.</li>
  <li>The system checks that required modules exist.</li>
  <li>The system checks for conflicts that would make the graph incoherent.</li>
</ul>

<p>This catches certain categories of surprise runtime failure earlier, because the platform can actually see your dependency structure.</p>

<h3 id="2-strong-encapsulation-real-boundaries">2. Strong encapsulation (real boundaries)</h3>

<p>With modules, code in a non-exported package is not accessible to other modules at compile time, and at runtime access is strongly controlled.</p>

<p>This is the key philosophical shift:</p>

<blockquote>
  <p>You are not just suggesting which parts are internal. You are declaring it, and the platform can enforce it.</p>
</blockquote>

<h2 id="a-quick-tour-of-module-descriptor-concepts">A quick tour of module descriptor concepts</h2>

<p>The <code class="language-plaintext highlighter-rouge">module-info.java</code> file is small, but it has teeth. Here are the ideas you will see in real projects.</p>

<h3 id="requires"><code class="language-plaintext highlighter-rouge">requires</code></h3>

<p>A module can state that it depends on another module.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">app</span> <span class="o">{</span>
    <span class="n">requires</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<h3 id="exports"><code class="language-plaintext highlighter-rouge">exports</code></h3>

<p>A module can export a package to make it part of its public API.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span> <span class="o">{</span>
    <span class="n">exports</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span><span class="o">.</span><span class="na">api</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>Everything else stays internal by default.</p>

<p>There is also qualified export, where you export only to specific friend modules:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span> <span class="o">{</span>
    <span class="n">exports</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">billing</span><span class="o">.</span><span class="na">internal</span> <span class="n">to</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">app</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>That is useful for tightly coupled modules, though it should be used sparingly because it creates special relationships that age poorly.</p>

<h3 id="opens"><code class="language-plaintext highlighter-rouge">opens</code></h3>

<p>Exporting is about normal access. Opening is about reflection.</p>

<p>Frameworks use reflection for dependency injection, serialization, proxies, and other wizardry. JPMS makes you be explicit about that:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">model</span> <span class="o">{</span>
    <span class="n">opens</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">model</span><span class="o">.</span><span class="na">entities</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>You can also open to specific modules only:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">model</span> <span class="o">{</span>
    <span class="n">opens</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">model</span><span class="o">.</span><span class="na">entities</span> <span class="n">to</span> <span class="n">com</span><span class="o">.</span><span class="na">fasterxml</span><span class="o">.</span><span class="na">jackson</span><span class="o">.</span><span class="na">databind</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<h2 id="services-uses-and-provides">Services: <code class="language-plaintext highlighter-rouge">uses</code> and <code class="language-plaintext highlighter-rouge">provides</code></h2>

<p>The service mechanism is the module-friendly way to do plugin architecture.</p>

<p>Consumer:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">app</span> <span class="o">{</span>
    <span class="n">uses</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">spi</span><span class="o">.</span><span class="na">PaymentProvider</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<p>Provider:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">module</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">stripe</span> <span class="o">{</span>
    <span class="n">provides</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">spi</span><span class="o">.</span><span class="na">PaymentProvider</span>
        <span class="n">with</span> <span class="n">com</span><span class="o">.</span><span class="na">example</span><span class="o">.</span><span class="na">stripe</span><span class="o">.</span><span class="na">StripePaymentProvider</span><span class="o">;</span>
<span class="o">}</span></code></pre></figure>

<h2 id="but-what-about-my-existing-non-modular-jars">But what about my existing non-modular JARs?</h2>

<p>JPMS did not pretend the world would instantly become modular. It introduced a migration story, and it is worth understanding because it explains a lot of real-world behavior.</p>

<h3 id="the-unnamed-module">The unnamed module</h3>

<p>If you put JARs on the classpath instead of the module path, they effectively live in the unnamed module. This unnamed module can read everything, and everything can read it, which is intentionally permissive to keep legacy code running.</p>

<p>It is the compatibility bridge. It is also where modular purity goes to take a nap.</p>

<h3 id="automatic-modules">Automatic modules</h3>

<p>If you put a regular JAR on the module path, the system can treat it as an automatic module with a derived name and permissive readability rules.</p>

<p>This is a practical stepping stone, not a perfect end state.</p>

<p>A common migration path looks like:</p>

<ul>
  <li>Run as classpath, accept the unnamed module.</li>
  <li>Move some things to module path, tolerate automatic modules.</li>
  <li>Modularize the important libraries and applications over time.</li>
</ul>

<p>Not glamorous, but it works, and it respects the fact that software is mostly sedimentary rock.</p>

<h2 id="the-jdk-itself-became-modular">The JDK itself became modular</h2>

<p>One of the most concrete outcomes of Jigsaw is that the JDK stopped being a monolith. It became a set of modules.</p>

<p>This matters because:</p>

<ul>
  <li>The platform itself has clearer internal boundaries.</li>
  <li>The JDK can strongly encapsulate internal APIs, reducing accidental dependencies on JDK internals.</li>
  <li>Tools can assemble smaller runtimes for specific applications.</li>
</ul>

<p>That last point is where tools like <code class="language-plaintext highlighter-rouge">jlink</code> enter the story, but it is better saved for a later post, once the basics are anchored.</p>

<h2 id="so-why-project-jigsaw">So why Project Jigsaw?</h2>

<p>Now we can answer the original “why” without hand-waving.</p>

<p>Java had packaging and namespacing. It did not have platform-enforced boundaries.</p>

<p>Project Jigsaw exists to make modularity:</p>

<ul>
  <li>Declarative, so the platform can see your intent.</li>
  <li>Verifiable, so tools can reason about your dependency graph.</li>
  <li>Enforceable, so “internal” actually means internal.</li>
</ul>

<p>It turns modularity from a cultural norm into a constraint you can build against.</p>

<p>That is the difference between “please do not touch” and “the door is locked.”</p>

<h2 id="what-is-next">What is next</h2>

<p>This was Part 1: the definition, the motivation, and the shape of the solution.</p>

<p>In Part 2, we will go concrete:</p>

<ul>
  <li>A tiny multi-module project you can compile and run.</li>
  <li>The first “why can I not access this package anymore?” moment, explained.</li>
  <li>Practical patterns: what to export, what to keep internal, and how to avoid designing a module system that only you understand.</li>
</ul>

<p>Because nothing teaches architecture faster than a compiler error that is technically correct and emotionally rude.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="Technology" /><category term="Software Engineering" /><category term="Series 3 - Project Jigsaw (JPMS)" /><category term="java" /><category term="jdk9" /><category term="project-jigsaw" /><category term="jpms" /><category term="modularity" /><category term="module-info" /><summary type="html"><![CDATA[A practical definition of modularity in Java, why Jigsaw existed even though we already had packages and JARs, and what the module system actually enforces.]]></summary></entry><entry><title type="html">Testing and the Perfect Software</title><link href="https://systemhalted.in/2025/12/13/testing-perfect-software/" rel="alternate" type="text/html" title="Testing and the Perfect Software" /><published>2025-12-13T00:00:00+00:00</published><updated>2025-12-13T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/13/testing-perfect-software</id><content type="html" xml:base="https://systemhalted.in/2025/12/13/testing-perfect-software/"><![CDATA[<p>Testing is important. Testing software is important.</p>

<p>But testing cannot guarantee a perfect product.</p>

<p>At best, testing gives you information. That information helps you mitigate the risk of releasing something that is quietly wrong, and quietly expensive.</p>

<p>If you want a perfect product, you would need perfect and exhaustive testing. Gerald M. Weinberg points out the trap: exhaustive testing implies an infinite number of tests, and that takes more time than the life of the product itself<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<p>Edsger W. Dijkstra said, “Testing may convincingly demonstrate the presence of bugs, but can never demonstrate their absence.”<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>So do not treat tests like a purity ritual. Treat them like a flashlight. A very practical flashlight. One you point at the dark corners first.</p>

<h2 id="testing-is-important-but-knowing-what-to-test-is-imperative">Testing is important, but knowing what to test is imperative</h2>

<p>Most teams do not fail because they do not test.
They fail because they test the wrong things, at the wrong layer, for the wrong reasons.</p>

<p>The real question is not “Do we have tests?”
The real question is “Are our tests buying us truth, where it matters most?”</p>

<p>A simple way to choose is to think in tiers - Must Haves (Guarantees), Should Haves (Safeguards), Good to Have (Hardening)</p>

<h3 id="must-be-tested-guarantees">Must be tested (Guarantees)</h3>
<p>These are the tests for the things that, if they break, make the business bleed, trust vanish, and regulators reach for their red pens.</p>

<p>Examples:</p>
<ol>
  <li>Money movement and irreversibility: double charges, missing payments, incorrect balances, wrong rounding.</li>
  <li>Identity and authorization: user A accessing user B’s data, broken MFA, weak reset flows.</li>
  <li>Data integrity invariants: dedupe rules, ordering guarantees, idempotency, “exactly once” assumptions.</li>
  <li>Privacy and compliance: PII leakage, audit log gaps, retention and encryption failures.</li>
</ol>

<h3 id="should-be-tested-safeguards">Should be tested (Safeguards)</h3>
<p>These tests cover the everyday production failure modes, not glamorous, but relentlessly loyal to chaos.</p>

<p>Examples:</p>
<ol>
  <li>Integration seams: timeouts, retries, partial failures, schema changes.</li>
  <li>Negative paths: invalid inputs, missing fields, weird encodings, malformed payloads.</li>
  <li>Performance cliffs: cold starts, peak traffic, queue buildup, slow queries.</li>
</ol>

<h3 id="good-to-have-hardening">Good to have (Hardening)</h3>
<p>This is maturity. Not mandatory for day one, but it pays rent for years.</p>

<p>Examples:</p>
<ol>
  <li>Property based tests: verify invariants across many generated inputs.</li>
  <li>Fuzzing: especially for parsers, inputs, and security boundaries.</li>
  <li>Chaos and resilience tests: inject latency, kill dependencies, verify graceful degradation.</li>
  <li>Observability checks: alerts that fire, logs that help, traces that connect.</li>
</ol>

<h2 id="your-test-portfolio">Your test portfolio</h2>

<p>Think of tests like a portfolio. You are allocating limited time to buy maximum confidence.</p>

<p>Some tests are cheap and plentiful.
Some are fewer but high value.
Some are expensive insurance policies.</p>

<p>A healthy suite is not “more tests”.
It is better allocation.</p>

<p>Two rules keep you honest:</p>
<ol>
  <li>Put most assertions as close to the code as possible. Fast feedback. Precise failures.</li>
  <li>Put a small number of assertions as close to the user as necessary. Real confidence.</li>
</ol>

<h2 id="the-testing-pyramid">The testing pyramid</h2>

<p>The classic pyramid is still useful, not as dogma, but as economics.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>End-to-End (few)
Integration / Component (some)
Unit (many)
</code></pre></div></div>

<p>Unit tests are cheap, fast, and local.</p>

<p>End-to-end tests are expensive, slow, and brittle, but they buy you “did the actual business journey work?”</p>

<p>The pyramid is not a moral statement. It is a cost statement.</p>

<h3 id="unit-tests">Unit tests</h3>
<p>Best for pure and deterministic logic: calculations, transformations, validation, edge cases, invariants.</p>

<p>Unit tests answer:</p>
<blockquote>
  <p>Is this piece correct in isolation?</p>
</blockquote>

<p>A unit test is most valuable when it is <strong>small</strong>, <strong>fast</strong>, <strong>deterministic</strong>, and cheap enough to run on every change. Google’s testing guidance<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup> emphasizes “small tests”, their closest equivalent to unit tests as constrained in resources, and their book<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> stresses that unit tests should be fast and deterministic so engineers can run them frequently.</p>

<p>Michael Feathers’ commonly cited rule of thumb is also useful as a boundary. If a test touches a database, the network, the filesystem, or needs a special environment configuration, it’s not a unit test. It’s pretending to be one<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup>.</p>

<p>A common trap is <strong>over-mocking</strong>. If a unit test is mostly mocks, stubs, and call verification, you may be testing your imagination instead of behavior. Prefer asserting outputs and state over asserting call choreography. Only lean on interaction-based or call-count assertions when the unit’s job is orchestration, for example retries, sequencing, or enforcing that a collaborator is invoked a specific number of times.</p>

<h3 id="integration-and-component-tests">Integration and component tests</h3>
<p>These test the seams where production loves to bite.</p>

<p>Integration tests answer:</p>

<blockquote>
  <p>Do my assumptions about the world hold?</p>
</blockquote>

<p>Martin Fowler’s simplest framing is still the most useful<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup>: integration tests check whether independently developed units work correctly when connected. The term is overloaded, so it helps to state the scope you mean (two components, one service plus its database, one service plus a message broker, etc.).</p>

<p>Component tests are a related idea: they limit the exercised software to a <em>portion</em> of the system (a component) rather than the full stack. In practice, that often means “this service works with its dependencies, without standing up the entire ecosystem.”</p>

<p>Google’s “test sizes” vocabulary maps nicely here. Their guidance often treats “medium tests” as the place where a small number of tiers communicate properly, which is exactly the integration sweet spot.<sup id="fnref:4:1" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<p>Examples:</p>
<ol>
  <li>Database queries, migrations, transaction boundaries.</li>
  <li>Serialization, schema evolution, backward compatibility.</li>
  <li>Messaging, retries, dedupe, idempotency under real conditions.</li>
  <li>Service-to-service calls with real HTTP and real headers.</li>
</ol>

<h3 id="contract-tests">Contract tests</h3>
<p>The underappreciated secret weapon in distributed systems.</p>

<p>Contract tests answer:</p>

<blockquote>
  <p>Are we <em>still</em> speaking the same language across the boundary?</p>
</blockquote>

<p>Martin Fowler’s framing is crisp: contract tests check the <em>contract</em> of external service calls, focusing on the <strong>format and expectations</strong>, not necessarily the exact data values.<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">7</a></sup> In other words, they verify the handshake between a consumer and a provider without requiring a full end-to-end environment.</p>

<p>Thoughtworks makes the “why now” argument for microservices: consumer-driven contract testing is a key part of a mature testing portfolio because it enables independent service deployments without accidentally breaking consumers.<sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<p>A contract test asserts the handshake between consumer and provider:
request shape, response shape, defaults, error contracts, compatibility.</p>

<h3 id="end-to-end-tests">End-to-end tests</h3>
<p>Keep these few, but sacred.</p>

<p>End-to-end tests answer:</p>
<blockquote>
  <p>Does the customer story still work?</p>
</blockquote>

<p>Google’s testing guidance treats these as “large” tests: higher fidelity, but slower, more expensive, and more prone to flakiness than smaller tests, which is exactly why you keep them few and focused.<sup id="fnref:3:1" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup><sup id="fnref:4:2" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<p>A common trap is using end-to-end tests to compensate for missing lower-level tests. That’s how you get a flaky suite that everyone learns to ignore. The testing equivalent of buying a treadmill and using it to hang jackets.</p>

<p>Pick critical business journeys and test them like brakes on a car:
payment flow, login flow, upload-and-view flow.</p>

<h2 id="a-modern-pyramid-that-fits-microservices-better">A “modern pyramid” that fits microservices better</h2>

<p>Many teams quietly evolve toward this:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">End-to-End (tiny cap)
Integration / Component (solid middle)
Contract tests (thin band)
Unit (broad base)</code></pre></figure>

<p>This reduces the urge to build a giant end-to-end “everything suite” that is slow, brittle, and mostly good at wasting Tuesday afternoons.</p>

<h2 id="a-practical-decision-rule-where-should-a-test-live">A practical decision rule: where should a test live?</h2>

<p>Use this mental routing table:</p>

<ol>
  <li>If it is a business invariant, test it at the unit level first.</li>
  <li>If it crosses a boundary you do not control, add a contract test.</li>
  <li>If it depends on real infrastructure behavior, add an integration or component test.</li>
  <li>If it is a critical customer journey, add an end-to-end test.</li>
</ol>

<p>Test the truth close to the source.
Test the handshake at the boundary.
Test the journey only where it matters.</p>

<h2 id="real-world-examples">Real world examples</h2>

<h3 id="example-1-payments-or-loan-servicing-posting-pipeline">Example 1: Payments or loan servicing posting pipeline</h3>

<p>A customer makes a payment. It gets authorized, posted, and the receipt is generated.</p>

<p>Must be tested:</p>
<ol>
  <li>Idempotency: the same payment request processed twice must not double-post.</li>
  <li>Ledger correctness: principal vs interest allocation, fees, rounding, balance changes.</li>
  <li>Atomicity: either all related records update, or none do. No “half paid” states.</li>
</ol>

<p>Should be tested:</p>
<ol>
  <li>Retries and timeouts between services.</li>
  <li>Duplicate events from the bus, out-of-order delivery, delayed settlement.</li>
  <li>Reconciliation: what happens when tomorrow’s batch notices a mismatch?</li>
</ol>

<p>Good to have:</p>
<ol>
  <li>Chaos: gateway latency spikes, downstream returns 503, does your system degrade or panic?</li>
  <li>Property tests: ledger invariants remain true across random sequences.</li>
</ol>

<p>A tiny invariant sketch:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">record</span> <span class="nf">Ledger</span><span class="o">(</span><span class="kt">long</span> <span class="n">debitCents</span><span class="o">,</span> <span class="kt">long</span> <span class="n">creditCents</span><span class="o">)</span> <span class="o">{</span>
  <span class="kt">long</span> <span class="nf">net</span><span class="o">()</span> <span class="o">{</span> <span class="k">return</span> <span class="n">creditCents</span> <span class="o">-</span> <span class="n">debitCents</span><span class="o">;</span> <span class="o">}</span>
<span class="o">}</span>

<span class="nd">@Test</span>
<span class="kt">void</span> <span class="nf">ledgerNetMatchesArithmetic</span><span class="o">()</span> <span class="o">{</span>
  <span class="kt">var</span> <span class="n">r</span> <span class="o">=</span> <span class="k">new</span> <span class="n">java</span><span class="o">.</span><span class="na">util</span><span class="o">.</span><span class="na">Random</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
  <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10_000</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
    <span class="kt">long</span> <span class="n">debit</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="na">nextInt</span><span class="o">(</span><span class="mi">1_000_000</span><span class="o">);</span>
    <span class="kt">long</span> <span class="n">credit</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="na">nextInt</span><span class="o">(</span><span class="mi">1_000_000</span><span class="o">);</span>
    <span class="kt">var</span> <span class="n">l</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Ledger</span><span class="o">(</span><span class="n">debit</span><span class="o">,</span> <span class="n">credit</span><span class="o">);</span>
    <span class="n">org</span><span class="o">.</span><span class="na">junit</span><span class="o">.</span><span class="na">jupiter</span><span class="o">.</span><span class="na">api</span><span class="o">.</span><span class="na">Assertions</span><span class="o">.</span><span class="na">assertEquals</span><span class="o">(</span><span class="n">credit</span> <span class="o">-</span> <span class="n">debit</span><span class="o">,</span> <span class="n">l</span><span class="o">.</span><span class="na">net</span><span class="o">());</span>
  <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>This does not prove correctness.
It proves you declared a truth, and you keep checking it.</p>

<h3 id="example-2-login-plus-token-issuance">Example 2: Login plus token issuance</h3>

<p>Must be tested:</p>
<ol>
  <li>Authorization boundaries: user A cannot access user B’s resources. Ever.</li>
  <li>Token expiry and refresh: no immortal sessions.</li>
  <li>Password reset and MFA: the “I lost access” path is where attackers live.</li>
</ol>

<p>Should be tested:</p>
<ol>
  <li>Clock skew behavior in token validation.</li>
  <li>Rate limiting and lockouts without harming real users.</li>
  <li>Key rotation behavior in realistic rollout windows.</li>
</ol>

<p>Good to have:</p>
<ol>
  <li>Fuzz JWT claims and headers.</li>
  <li>Replay and session fixation abuse cases.</li>
</ol>

<h3 id="example-3-document-upload-plus-classification">Example 3: Document upload plus classification</h3>

<p>Must be tested:</p>
<ol>
  <li>Correct customer association: misfiled documents are silent disasters.</li>
  <li>Access control: only authorized users can view or reclassify.</li>
  <li>PII handling: retention, redaction, encryption behavior.</li>
</ol>

<p>Should be tested:</p>
<ol>
  <li>Corrupt PDFs, huge files, mixed encodings, virus scan failures.</li>
  <li>Async pipeline correctness: retries, dead-letter paths, idempotent processing.</li>
  <li>Search indexing lag and eventual consistency behavior.</li>
</ol>

<p>Good to have:</p>
<ol>
  <li>Drift checks on classification confidence over time.</li>
  <li>Canary documents monitored continuously.</li>
</ol>

<h2 id="closing">Closing</h2>

<p>Testing will not make your product perfect.
It will keep your product honest.</p>

<p>Use tests to gain information about bugs, then fix them.
Do not let the presence of bugs shame you if your testing caught them.</p>

<p>A perfect product is a myth.
A low-quality product is a choice.</p>

<h2 id="references">References</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Gerald M. Weinberg, <em>Perfect Software</em>. (leanpub.com). <a href="https://leanpub.com/perfectsoftware?utm_source=systemhalted.in">https://leanpub.com/perfectsoftware?utm_source=systemhalted.in</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Dijkstra, <em>Reliability of programs</em>. (utexas.edu).<a href="https://www.cs.utexas.edu/users/EWD/transcriptions/EWD03xx/EWD303.html?utm_source=systemhalted.in">https://www.cs.utexas.edu/users/EWD/transcriptions/EWD03xx/EWD303.html?utm_source=systemhalted.in</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Simon Stewart, <em>Google Test Sizes</em>. (googleblog.com). <a href="https://testing.googleblog.com/2010/12/test-sizes.html?utm_source=systemhalted.in">https://testing.googleblog.com/2010/12/test-sizes.html?utm_source=systemhalted.in</a> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:3:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>Titus Winters, Tom Manshreck, and Hyrum Wright. “Testing Overview.” Software Engineering at Google, n.d., <a href="https://abseil.io/resources/swe-book/html/ch11.html">https://abseil.io/resources/swe-book/html/ch11.html</a> <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:4:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:4:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>Michael Feathers, <em>Working Effectively With Legacy Code</em>. 1st Edition, Pearson <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>Martin Fowler. “Integration Test.” (martinfowler.com). 2018, <a href="https://martinfowler.com/bliki/IntegrationTest.html">https://martinfowler.com/bliki/IntegrationTest.html</a> <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p>Martin Fowler. “Contract Test.” <em>martinfowler.com</em>, 2011, <a href="https://martinfowler.com/bliki/ContractTest.html">https://martinfowler.com/bliki/ContractTest.html</a> <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p>Thoughtworks. “Consumer-driven contract testing.” <em>Technology Radar</em>, 2015, <a href="https://www.thoughtworks.com/en-us/radar/techniques/consumer-driven-contract-testing">https://www.thoughtworks.com/en-us/radar/techniques/consumer-driven-contract-testing</a> <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Software Engineering&quot;]" /><category term="testing" /><category term="quality" /><category term="risk" /><category term="tdd" /><summary type="html"><![CDATA[Testing matters, but choosing what to test is the real craft. A practical way to decide what must be tested, what should be tested, and what is good to have.]]></summary></entry><entry><title type="html">Hinduism, Hindutva, and the People Who Lit My Mind</title><link href="https://systemhalted.in/2025/12/11/hinduism/" rel="alternate" type="text/html" title="Hinduism, Hindutva, and the People Who Lit My Mind" /><published>2025-12-11T00:00:00+00:00</published><updated>2025-12-11T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/11/hinduism</id><content type="html" xml:base="https://systemhalted.in/2025/12/11/hinduism/"><![CDATA[<p>On 3rd February 2006, at 11:26 PM, a much younger version of me sat with a notebook and tried to list the people who had truly shaped his thinking.</p>

<p>The list was short, and a bit grand for a college kid’s diary:</p>

<p>Lord Krishna. Mahatma Gandhi. Bhagat Singh. Ram Prasad Bismil. Premchand. Jawaharlal Nehru. Sardar Vallabhbhai Patel. Dr. A.P.J. Abdul Kalam. Dr. Manmohan Singh.</p>

<p>And that night, one more name joined them:</p>

<p><strong>Dr. Karan Singh.</strong></p>

<p>I had just encountered his articulation of Hinduism and Hindutva, and it quietly rearranged the furniture in my head.</p>

<hr />

<h2 id="the-rare-people-who-touch-both-mind-and-heart">The rare people who touch both mind and heart</h2>

<p>I have always been suspicious of “inspiration.”<br />
Most grand speeches evaporate by the time you reach the parking lot.</p>

<p>But every once in a while, someone’s words don’t just <em>sound</em> wise, they start doing slow, patient work inside you. They challenge you, annoy you, educate you. They sit on your mental bookshelf and refuse to leave.</p>

<p>That is what these figures did for me.</p>

<ul>
  <li>Krishna’s conversations in the Gita taught me that doubt is not a sin but a starting point.</li>
  <li>Gandhi’s stubborn insistence on non-violence showed how inner discipline can become political force.</li>
  <li>Bhagat Singh and Ram Prasad Bismil embodied courage that did not wait for “perfect conditions.”</li>
  <li>Premchand dragged everyday Indian life into literature and forced us to look at it without filters.</li>
  <li>Nehru and Patel turned impossible theory into a functioning state.</li>
  <li>Kalam and Manmohan Singh represented a quiet, technocratic ideal: intelligence without theatrics.</li>
</ul>

<p>From this crowd of giants, I did not receive a single “formula for life.”<br />
What I absorbed was a way of <strong>thinking</strong>: to question, to empathize, to stay curious.</p>

<p>And then came Karan Singh, with a deceptively simple distinction:</p>

<blockquote>
  <p>Hinduism as a way of seeking;<br />
Hindutva as a project of identity.</p>
</blockquote>

<hr />

<h2 id="hinduism-river-not-fortress">Hinduism: river, not fortress</h2>

<p>The Hinduism I grew up with did not arrive as a rulebook.<br />
It arrived as:</p>

<ul>
  <li>stories my elders told at night</li>
  <li>bhajans floating from a neighbour’s house</li>
  <li>a temple visit that was half spirituality, half street food</li>
  <li>a vague habit of folding hands before exams “just in case”</li>
</ul>

<p>It was messy, contradictory, generous. You could argue with God, ignore God, or turn God into a metaphor and nobody came to confiscate your ration card.</p>

<p>When I later read and heard Karan Singh speak, he put sharper language to what I had only felt:</p>

<p>Hinduism is <strong>a civilizational habit of searching</strong>.<br />
It is comfortable with multiplicity: many deities, many philosophies, many paths.</p>

<p>You can be drawn to Advaita’s non-dual silence, to Bhakti’s emotional surrender, to Yoga’s discipline, or to a calm agnosticism that still respects the tradition. All of these can sit around the same metaphorical kitchen table and argue late into the night.</p>

<p>The point is not that Hinduism is flawless or superior. History is littered with its own injustices and blind spots. The point is that, at its core, it contains tools to <strong>self-correct</strong>: debate, commentary, reinterpretation, dissent from within.</p>

<p>That is what makes it feel like a <em>river</em>; ancient, meandering, sometimes polluted, but always capable of renewal.</p>

<hr />

<h2 id="hindutva-when-a-river-is-turned-into-a-wall">Hindutva: when a river is turned into a wall</h2>

<p>Hindutva is something else.</p>

<p>Hinduism asks, “What is the nature of reality, self, and duty?”<br />
Hindutva asks, “Who truly belongs here?”</p>

<p>One is metaphysical and ethical.<br />
The other is political and majoritarian.</p>

<p>Hinduism is comfortable with questions that may never be fully answered.<br />
Hindutva is obsessed with answers that must never be questioned.</p>

<p>Once you see this difference, it becomes hard to unsee:</p>

<ul>
  <li><strong>Hinduism</strong> can live alongside other faiths, learn from them, even absorb ideas without feeling threatened.</li>
  <li><strong>Hindutva</strong> needs a permanent sense of threat to justify itself. Without an enemy, it has no purpose.</li>
</ul>

<p>Hinduism invites you to look inward and transform yourself.<br />
Hindutva invites you to look outward and suspect your neighbour.</p>

<p>Hinduism is vast enough to hold the Gita, the Upanishads, the Charvaka materialists, the Bhakti poets, the Sufi-infused traditions, and a million local deities with their own stories.</p>

<p>Hindutva tries to compress all of that into a single slogan, preferably in all caps.</p>

<hr />

<h2 id="why-karan-singhs-distinction-still-matters">Why Karan Singh’s distinction still matters</h2>

<p>Back in 2006, I did not fully grasp the political weight of this difference. I just knew it felt right that someone could say:</p>

<p>“I love Hindu philosophy deeply,<br />
<strong>and precisely because of that</strong>,<br />
I reject narrow, exclusionary nationalism done in its name.”</p>

<p>In a time where every identity is being sharpened into a weapon, this stance feels almost revolutionary.</p>

<p>It offers a third path:</p>

<ul>
  <li>Not self-hating rejection of your own culture.</li>
  <li>Not blind worship of a mythical golden past.</li>
  <li>But a <strong>rooted openness</strong>: secure enough in its heritage to be self-critical and humane.</li>
</ul>

<p>That is why I put Karan Singh on that short list in my notebook.<br />
He did what real teachers do:<br />
he gave language to a discomfort I already had, and showed that loving a tradition and resisting its misuse are not contradictions — they are obligations.</p>

<hr />

<h2 id="where-this-leaves-me-today">Where this leaves me today</h2>

<p>Nearly two decades after that late-night entry, I find my relationship with faith has become more agnostic, more questioning, sometimes more impatient.</p>

<p>But the basic architecture remains:</p>

<ul>
  <li>I am still more interested in <strong>Dharma</strong> as a lived, everyday ethic. Hinduism gives me identity.</li>
  <li>I am still suspicious of any ideology that needs enemies to survive.</li>
  <li>And I still feel that if your God cannot coexist with someone else’s God or their lack of one, the problem is not with them, it is with your God-concept.</li>
</ul>

<p>Hinduism gives me metaphors, stories, and philosophical toys to think with.<br />
Hindutva tries to reduce all that complexity into a political loyalty test.</p>

<p>I know which side of that line I want to stand on.</p>

<hr />

<p>That boy in 2006 thought he was just making a list of impressive people.<br />
What he was really doing was choosing his <strong>intellectual ancestors</strong>.</p>

<p>I am still trying, clumsily, to be worthy of that lineage where courage, curiosity, and compassion matter more than flags and slogans.</p>

<p>If Hinduism is a river, I would rather spend my life learning to swim in it,<br />
than helping anyone build walls around it.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Personal Essays&quot;]" /><category term="Hinduism" /><category term="Hindutva" /><category term="India" /><category term="philosophy" /><summary type="html"><![CDATA[A reflection on Dr. Karan Singh’s idea of Hinduism and Hindutva, and the long line of people who quietly shaped my thinking.]]></summary></entry><entry><title type="html">Letter to Self - Passion</title><link href="https://systemhalted.in/2025/12/10/passion/" rel="alternate" type="text/html" title="Letter to Self - Passion" /><published>2025-12-10T00:00:00+00:00</published><updated>2025-12-10T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/10/passion</id><content type="html" xml:base="https://systemhalted.in/2025/12/10/passion/"><![CDATA[<p>Dear Palak,</p>

<p>I know you would not have expected your future self to write to you, but this is in fashion these days and you have always been fashionable, so here it is.</p>

<p>I want to talk to you about this whole “find your passion” thing you keep worrying about.</p>

<p>You keep saying you are not sure what you are passionate about. You say it like it is a defect, like some magical signal that never arrived from the sky. I want to tell you gently: that sentence is hiding the truth instead of revealing it.</p>

<p>Most people, including you, already have some sense of what they enjoy. You know which problems make you forget the time. You know which topics your eyes light up for, because your family has to tell you to stop talking about them. When you say “I don’t know my passion,” what is usually happening inside you is not emptiness. It is a mix of fear, confusion, and borrowed ideas about what passion is supposed to look like. Don’t let other people define your preferences. Decide and build your own.</p>

<p>So let us unpack the lies you have quietly absorbed.</p>

<p><em>The first lie is that there is one true passion.</em></p>

<p>You are not a single label. You never were. You like computer science, physics, management, writing, astronomy, history, mentoring, and three other things you will discover later. You are not broken because you cannot squeeze all of that into one tidy word like “developer” or “writer”.</p>

<p>For you, passion is not a single topic. Passion is the way you engage with many topics. You love taking things apart, understanding how they work, building something from that understanding, and then explaining it to someone else. That pattern keeps repeating in different domains. That pattern is your passion, whether you are debugging a system, appreciating history, writing an essay, or teaching someone to look at Jupiter for the first time.</p>

<p>When you try to force yourself to choose one banner and kill everything else, you feel like you are betraying yourself. You are right to resist that.</p>

<p><em>The second lie is that you must discover your passion before you are allowed to move.</em></p>

<p>You imagine that somewhere out there is a perfect fit, a calling with neon lights and background music. Until you “find” it, you feel you are just wandering.</p>

<p>Here is what you will slowly learn. Passion is not a lightning bolt from the sky. Passion is a story you tell later about the things you have stuck with long enough to get good at and care about. You start with something you already kind of like. You do it again. You do it when it is fun. You do it when it is boring. You survive the part where you think you are terrible. You improve. Other people benefit from what you do. Somewhere along that path, it stops being just a task and starts becoming part of who you are.</p>

<p>From the outside, people say, “You found your passion.” From the inside, it feels much more ordinary. You chose something. You stayed with it. Habit, skill, and meaning slowly braided themselves into something deeper.</p>

<p>This is not ordinary. Building habit and skill takes effort and time, and you did it. Yourself.</p>

<p>This is true for writing. It is true for leadership. It is true for engineering. You did not “find” those passions like lost keys. You built them out of small, stubborn repetitions.</p>

<p><em>The third lie is that real passion feels like a 24/7 fire.</em></p>

<p>You secretly believe that if something is truly your passion, you will wake up excited every single day. No doubt. No friction. No boredom. Always “on fire”. Therefore, whenever you feel tired, or bored, or stuck, you quietly conclude, “Maybe this is not my passion after all.” Then you start scanning the horizon for the next thing that will keep you permanently excited. You call this searching for passion. Mostly it is just running away from discomfort.</p>

<p>Here is what you need to know. Real passion has seasons. Sometimes it looks like flow and obsession and that lovely tunnel-vision when code, or prose, or an idea just pours out of you. Sometimes it looks like maintenance: cleaning up old messes, answering emails, debugging someone else’s bug, rereading and rewriting the same paragraph ten times. The fire is still there, but it is not always a bonfire. Some days it is just a candle that you protect with your hands while the wind blows.</p>

<p>Years later, you will read Mark Twain saying:</p>

<blockquote>
  <p>“No, Sir, not a day’s work in all my life. What I have done I have done, because it has been play. If it had been work I shouldn’t have done it.”</p>
</blockquote>

<p>You will recognise yourself in that line. Not because your life was effortless, but because the things you cared about most often blurred that line between work and play. Some days it felt like play. Some days it felt like hard work. It was still yours.</p>

<p>The absence of constant excitement does not mean the absence of passion. It usually means you have moved from the honeymoon phase to the craft phase.</p>

<p>So where does this leave you?</p>

<p>You are multi-passionate. That is not a diagnosis. It is a description. You love many domains, and you also love the process itself: learning, building, connecting, teaching. You will never be happy stuffing all of that into one narrow identity. You do not need to.</p>

<p>You also do not need to sit on the floor and wait for a divine “passion notification” to arrive. You already know enough to start. You know which things you enjoy more than average. You know which problems you complain about and secretly want to fix. You know where your curiosity keeps returning when nobody is watching.</p>

<p>So, here is the advice I wish you would trust a little earlier.</p>

<p>Stop searching for a single, mythical passion. Start taking small bets on the things you already like.</p>

<p>Write one blog post, even if only three people read it. Take on one slightly scary problem at work and see it through. Teach one person something you know. Let yourself be bad at new things long enough for them to become familiar. Let habit, skill, and impact do their slow, quiet work.</p>

<p>Over years, what will emerge will not be a single word you can put in your bio. It will be a pattern of work and play that feels deeply yours. Call that passion if you want. Call it craft. Call it your way of being in the world.</p>

<p>Just do not keep telling yourself you do not have it.</p>

<p>You have always had it. You were just expecting it to look different.</p>

<p>Regards,
Palak</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Personal Essays&quot;]" /><category term="personal" /><category term="opinion" /><category term="astronomy" /><category term="travel" /><category term="leadership" /><category term="poetry" /><summary type="html"><![CDATA[This is a letter to my past self just beginning to grow into an adult.]]></summary></entry><entry><title type="html">TDD as a Management Technique Revisited</title><link href="https://systemhalted.in/2025/12/09/tdd-revisted/" rel="alternate" type="text/html" title="TDD as a Management Technique Revisited" /><published>2025-12-09T00:00:00+00:00</published><updated>2025-12-09T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/09/tdd-revisted</id><content type="html" xml:base="https://systemhalted.in/2025/12/09/tdd-revisted/"><![CDATA[<p>In an earlier post I argued that <strong>Test Driven Development is fundamentally a management technique</strong>.</p>

<p>Not a mystical gateway to “better design”.<br />
Not a guarantee of fewer bugs.<br />
A Taylorian construct whose main achievement is simple: it forces people to write unit tests.</p>

<p>I still believe that.</p>

<p>What has changed is this:<br />
I now care less about <em>TDD the ritual</em> and more about the broader habit hiding underneath it.</p>

<p>Thinking seriously about <strong>testing and evaluation before writing code</strong> is valuable.<br />
Not just at the unit level, but at the <strong>functional, component, and integration</strong> levels too.</p>

<p>The ritual can be Taylorism.<br />
The mindset is design.</p>

<h2 id="version-1-tdd-as-taylorism">Version 1: TDD as Taylorism</h2>

<p>Let me quickly restate the original thesis.</p>

<p>Unit tests are good. They reduce maintenance costs, prevent regressions, and give us courage to refactor.</p>

<p>The problem is human, not technical:</p>

<ol>
  <li>Left alone, many teams will not write enough tests.</li>
  <li>Even when they do, tests are often an afterthought, written just before merge, or not at all.</li>
  <li>Management wants fewer bugs and lower maintenance cost, but cannot directly measure “future headaches avoided”.</li>
</ol>

<p>Enter TDD.</p>

<p>TDD turns “write tests” into a <strong>visible, enforceable step</strong>:</p>

<ol>
  <li>Write a failing unit test</li>
  <li>Make it pass</li>
  <li>Refactor</li>
  <li>Repeat</li>
</ol>

<p>That loop is eminently measurable.</p>

<p>You can ask:</p>

<ul>
  <li>Did the developer write tests first</li>
  <li>Is the build green</li>
  <li>What is the code coverage</li>
</ul>

<p>That is classic Taylorism: break down work into small steps, make them observable, then control them.</p>

<p>From that angle, TDD is not a design religion.<br />
It is <strong>management plumbing</strong> for test-writing behavior.</p>

<p>I still find that framing useful. It explains why TDD took off in large organizations obsessed with metrics and “best practices”.</p>

<p>But it is incomplete.</p>

<h2 id="what-changed-from-ritual-to-evaluation">What changed: from ritual to evaluation</h2>

<p>Over time I noticed something awkward.</p>

<p>Even in teams that never practiced “pure TDD”, the best engineers tended to do a version of the <em>thinking</em> behind it:</p>

<p>They imagined failure modes before they wrote code.<br />
They thought about inputs and outputs.<br />
They mentally ran scenarios in their heads.<br />
They cared about how their work would be evaluated, not just how it would compile.</p>

<p>That is not uniquely “TDD”.<br />
That is just <strong>good engineering</strong>.</p>

<p>So my view shifted:</p>

<ul>
  <li>TDD-as-ritual is still a Taylorian construct.</li>
  <li>But <strong>test-first thinking</strong>, in a broader sense, is something you want almost everywhere.</li>
</ul>

<p>The mistake is to shrink “test-first” down to “unit tests only” and treat everything else as a side quest.</p>

<p>The real question is larger:</p>

<blockquote>
  <p>Before we add this behavior to the system, how will we know it works?<br />
At every relevant level.</p>
</blockquote>

<p>Once you phrase it that way, you are automatically pushed beyond unit tests.</p>

<h2 id="four-levels-of-thinking-before-you-code">Four levels of thinking before you code</h2>

<p>When I say “think about testing and evaluation before writing code”, I do not mean “write a unit test file before a class file” and declare victory.</p>

<p>I mean something more layered.</p>

<h3 id="1-functional-what-would-convince-a-user">1. Functional: what would convince a user?</h3>

<p>Start at the top.</p>

<p>Imagine a reasonably skeptical product partner or end user sitting next to you. What would convince them that this feature actually works in their world?</p>

<p>That question leads to things like:</p>

<ul>
  <li>Example flows: “A customer with X, who does Y, should see Z.”</li>
  <li>Edge scenarios: “What if the user loses connectivity halfway through?”</li>
  <li>Policy constraints: “What are we allowed or not allowed to do?”</li>
</ul>

<p>This is the territory of <strong>acceptance or functional tests</strong>.</p>

<p>You do not need a test framework to start. Even a one-page doc with concrete examples is already “test-first thinking” at the functional level.</p>

<h3 id="2-component-what-contract-does-this-service-promise">2. Component: what contract does this service promise?</h3>

<p>Next layer down: the component boundary.</p>

<p>For any service or module, ask:</p>

<ul>
  <li>What contract am I promising to the rest of the system</li>
  <li>What do I guarantee about behavior, latency, and failure modes</li>
  <li>How will other teams know we broke something</li>
</ul>

<p>These questions give rise to <strong>component or API-level tests</strong>.</p>

<p>Designing them early tends to reveal awkwardness:</p>

<ul>
  <li>“Why are there three ways to call this?”</li>
  <li>“What happens if the downstream is slow but not down?”</li>
  <li>“Do we retry? For how long? With what backoff?”</li>
</ul>

<p>Note that we have not yet written a single “public void testSomething()”. We are still shaping the <strong>surface area</strong> of the system.</p>

<h3 id="3-integration-how-does-this-behave-in-the-real-ecosystem">3. Integration: how does this behave in the real ecosystem?</h3>

<p>The third level is where reality barges in.</p>

<p>Databases. Message queues. Third-party APIs. Authentication. Caches. Time.</p>

<p>Integration thinking asks:</p>

<ul>
  <li>Can this survive real data, not just happy-path fixtures?</li>
  <li>What happens when the schema changes?</li>
  <li>What if Kafka is briefly on fire?</li>
</ul>

<p>You might not be able to write full integration tests before any code exists. But if you do not think about them early, you will unconsciously design a system that only works in your unit test universe.</p>

<p>This is where many “nice” designs die in production.</p>

<h3 id="4-unit-what-invariants-must-always-hold">4. Unit: what invariants must always hold?</h3>

<p>Finally, the part everybody talks about: unit tests.</p>

<p>At this level, the questions are more granular:</p>

<ul>
  <li>What assumptions must never be violated inside this function or class?</li>
  <li>What bug would be extremely annoying to debug in prod?</li>
  <li>Which branches are easy to forget about?</li>
</ul>

<p>Unit tests are excellent at enforcing <strong>local invariants</strong> and giving you courage to refactor internals.</p>

<p>They are not sufficient to guarantee that the <strong>system</strong> does what you think it does. But they are a crucial layer in the overall evaluation story.</p>

<p>The important bit is the order of thought:</p>

<p>You do not start from “how do I hit 85 percent coverage”.<br />
You start from “what does success look like at each level” and let tests follow.</p>

<h2 id="tdd-as-a-management-tool-test-first-as-a-design-habit">TDD as a management tool, test-first as a design habit</h2>

<p>This is where I have landed:</p>

<p>I still see TDD, as originally popularized, as a management-friendly practice:</p>

<ul>
  <li>It decomposes work into simple, repeatable, measurable steps.</li>
  <li>It helps organizations enforce test-writing behavior.</li>
  <li>It pairs nicely with coverage dashboards and pipeline gates.</li>
</ul>

<p>Nothing about that is inherently bad. In large systems with many teams, <strong>some</strong> enforcement is necessary. Otherwise tests are the first thing sacrificed under pressure.</p>

<p>The problem is when <strong>the enforcement mechanism becomes the goal</strong>.</p>

<p>“We do TDD here” becomes identity theatre.<br />
Coverage numbers become performance proxies.<br />
Green builds become the scoreboard.</p>

<p>Meanwhile, nobody is asking basic questions:</p>

<ul>
  <li>Are we testing the right things at the right levels?</li>
  <li>Do our tests reflect how the system is really used?</li>
  <li>Are we over-investing in unit tests while under-investing in integration and functional evaluation?</li>
</ul>

<p>That is the shift I care about.</p>

<p>I now treat:</p>

<ul>
  <li><strong>Tests as management control</strong>: useful, but limited.</li>
  <li><strong>Tests as design and evaluation tools</strong>: essential, and much broader than TDD usually admits.</li>
</ul>

<h2 id="so-what-do-we-actually-do-differently">So what do we actually do differently?</h2>

<p>This all sounds very philosophical, so let me anchor it in a few concrete habits.</p>

<p>First, for any non-trivial feature, write down <strong>“how we’ll know this works”</strong> before someone opens the IDE.</p>

<p>Not a 20-page spec. A short, sharp checklist:</p>

<ul>
  <li>Key functional scenarios that must work</li>
  <li>Any user-facing behavior we care about (latency, error messages, data correctness)</li>
  <li>Critical integration points and their expectations</li>
  <li>A couple of nasty edge cases we are afraid of</li>
</ul>

<p>Second, encourage teams to think in <strong>layers of evaluation</strong>.</p>

<p>When a design is proposed, ask:</p>

<ul>
  <li>What are the acceptance tests, even if they are manual</li>
  <li>What API or component tests will protect other teams from our changes</li>
  <li>What integration tests will keep us honest about reality</li>
  <li>Where do unit tests actually provide value, and where are they just “coverage padding”</li>
</ul>

<p>Third, be explicit about where TDD fits.</p>

<p>If a team finds “write a failing unit test, then code” helpful to structure their work, great. Let them use it.</p>

<p>Just do not confuse the <strong>ritual</strong> with the <strong>outcome</strong>.</p>

<p>The outcome is:</p>

<ul>
  <li>We have a clear, shared understanding of success.</li>
  <li>We have tests at the right levels to guard that success.</li>
  <li>We can change the system with confidence.</li>
</ul>

<p>Whether that came from strict TDD, loose test-first thinking, or some other workflow is secondary.</p>

<h2 id="closing-the-loop">Closing the loop</h2>

<p>So yes, my old self was right about one thing:</p>

<p>TDD has a strong Taylorian flavor. It is a management technique that emerged to tame the chaos of software development and make test-writing behavior more predictable.</p>

<p>But if I stop there, I miss the deeper point.</p>

<p>The valuable instinct is not “thou shalt always write tests first”.<br />
The valuable instinct is:</p>

<blockquote>
  <p>Before I add behavior to a complex system, I should be very clear about how that behavior will be evaluated.</p>
</blockquote>

<p>At the functional level.<br />
At the component boundary.<br />
At the integration seam.<br />
Inside the unit.</p>

<p>You can reject TDD-as-religion and still embrace that instinct.</p>

<p>In fact, if you care about real systems in the real world, you probably should.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Software Engineering&quot;]" /><category term="software" /><category term="leadership" /><category term="management" /><summary type="html"><![CDATA[I still think TDD is a Taylorian construct. But I now care less about the ritual and more about a deeper idea - thinking about evaluation and testing before we write code.]]></summary></entry><entry><title type="html">Org Incentive Optimization Problem</title><link href="https://systemhalted.in/2025/12/08/org-incentive-optimization/" rel="alternate" type="text/html" title="Org Incentive Optimization Problem" /><published>2025-12-08T00:00:00+00:00</published><updated>2025-12-08T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/08/org-incentive-optimization</id><content type="html" xml:base="https://systemhalted.in/2025/12/08/org-incentive-optimization/"><![CDATA[<p>Recently, in a conversation on <a href="https://www.linkedin.com/posts/jessewarden_heard-a-rumor-google-used-to-have-an-incentive-activity-7403871145076162560-IfQs?utm_source=share&amp;utm_medium=member_desktop&amp;rcm=ACoAAAEFJMcB_miK-56ZKPbmvTNGUxM6IrkeN_M">LinkedIn</a>, I came to realization that most companies are secretly running an algorithm they’ve never actually written down.</p>

<p>I call it the <strong>Org Incentive Optimization Problem</strong>.</p>

<p>Here’s how it usually behaves:</p>

<p>You say:</p>
<blockquote>
  <p>“I fixed a bunch of bugs, cleaned up tech debt, and made the platform more reliable.”</p>
</blockquote>

<p>The system hears:</p>
<blockquote>
  <p>“did routine work”.</p>
</blockquote>

<p>You say:</p>
<blockquote>
  <p>“I built a new platform.”</p>
</blockquote>

<p>The system hears:</p>
<blockquote>
  <p>“high impact, visionary, promotable”.</p>
</blockquote>

<p>Same keyboard. Same brain. Completely different reward curve.</p>

<p>The catch is that reliability and maintenance work are <strong>compounding assets</strong>.<br />
They just don’t come with launch emails, codenames, or shiny demos.</p>

<p>Avoided outages never show up on a slide.<br />
Stable systems don’t page executives at 2am.<br />
So they quietly vanish from the story.</p>

<p>From a computing perspective, this is a messy <strong>credit-assignment</strong> problem with delayed rewards and noisy signals.</p>

<p>From a human perspective, it looks like this:</p>

<ul>
  <li>People chase visible “new” work, even when the real value is in strengthening what already exists.</li>
  <li>Platform teams feel pressure to rebrand every major refactor as a “new platform” just to get air cover.</li>
  <li>The folks who keep things boring and dependable get labeled “steady” instead of “high potential”.</li>
</ul>

<p>If you model it in CS terms, it roughly looks like this:</p>

<p><strong>Input</strong></p>

<ul>
  <li>A graph of teams, platforms, incidents, and features</li>
  <li>Noisy signals: outages, launches, OKRs, customer metrics</li>
  <li>Human agents who optimize whatever you measure</li>
</ul>

<p><strong>Objective</strong></p>

<p>Maximize:</p>

<ul>
  <li>Reliability</li>
  <li>Long-term velocity</li>
  <li>Fair rewards for “unsexy” maintenance work</li>
</ul>

<p>Minimize:</p>

<ul>
  <li>Cargo-cult “new platforms”</li>
  <li>Incentive gaming</li>
  <li>Burnout and PIPs for the people keeping it alive</li>
</ul>

<p>Most orgs end up running a greedy online heuristic:</p>

<pre><code class="language-txt">if (work.isVisibleLaunch()) {
    promote++;
} else if (work.isQuietReliability()) {
    shrug++;
}
</code></pre>

<p>Bug fixing gets treated as constant-time hygiene,
while “new platform” is treated as <em>quadratic impact</em>,
even when the real business value is reversed.</p>

<p>The trick, if you are inside the system:</p>

<p>Make reliability work computable.
Never leave it as “I fixed bugs”.</p>

<p>Translate it into:</p>

<blockquote>
  <p>I reduced incident rate by 40%.</p>
</blockquote>

<blockquote>
  <p>I removed a whole class of failures that used to wake people up every weekend.</p>
</blockquote>

<blockquote>
  <p>I made it safer and faster for five other teams to ship.</p>
</blockquote>

<p>Same work.<br />
Different representation in the algorithm.<br />
Very different outcome.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Personal Essays&quot;]" /><category term="personal" /><category term="opinion" /><category term="movie-review" /><category term="leadership" /><summary type="html"><![CDATA[Most orgs are unknowingly running an “Org Incentive Optimization” algorithm that over-rewards flashy new platforms and under-values quiet reliability work, so you have to translate maintenance into visible, computable outcomes.]]></summary></entry><entry><title type="html">[Movie Review] Dhurandhar</title><link href="https://systemhalted.in/2025/12/06/dhurandhar-movie-review/" rel="alternate" type="text/html" title="[Movie Review] Dhurandhar" /><published>2025-12-06T00:00:00+00:00</published><updated>2025-12-06T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/06/dhurandhar-movie-review</id><content type="html" xml:base="https://systemhalted.in/2025/12/06/dhurandhar-movie-review/"><![CDATA[<p>Watched Dhurandhar today in a cinema hall after a very long gap from Hindi movies on the big screen, and it was absolutely worth it. It was completely unplanned – on a whim, Priti and I decided to go to a cinema hall, found a Hindi movie playing nearby, and booked the 4:10 pm show at 3:45 pm. We didn’t know who were the actors in the movie, when was it released, rating - nothing.</p>

<p>Dhurandhar is a lot to take in – literally the longest Hindi film in 17 years – nearly three-and-a-half hours, very violent, very loud, very extra. But it never felt boring.</p>

<p>Everyone in the cast was fantastic. It was such a fun surprise to see both Rakesh Bedi and Gaurav Gera. It was also a joy to watch Akshaye Khanna after so many years. I’ve been a fan of his since Border, and he still holds the screen with that same quiet intensity. R. Madhavan and Sanjay Dutt were great as usual and Arjun Rampal was properly menacing. Ranveer Singh was simply phenomenal. Sara Arjun, who is just 20, showed her skills even with limited screen time.</p>

<p>The violence is definitely not for the faint-hearted. That was the part Priti didn’t enjoy. But despite the brutality on screen, both of us walked out genuinely loving the movie and the experience of watching it together.</p>

<p>After a long time, a Hindi movie in a theatre felt worth every minute.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Movie Review&quot;]" /><summary type="html"><![CDATA[Review of Hindi movie Dhurandhar]]></summary></entry><entry><title type="html">India and the United States</title><link href="https://systemhalted.in/2025/12/06/india-us-relations/" rel="alternate" type="text/html" title="India and the United States" /><published>2025-12-06T00:00:00+00:00</published><updated>2025-12-06T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/06/india-us-relations</id><content type="html" xml:base="https://systemhalted.in/2025/12/06/india-us-relations/"><![CDATA[<p>For most of my life, India–US relations were a story you heard about only when something went wrong.</p>

<p>A nuclear test.<br />
A war with Pakistan.<br />
Some new sanctions.<br />
A US president lecturing India on something.   <br />
An Indian PM “aligning” with Non-Aligned Movement.</p>

<p>Today the relationship is everywhere and nowhere at once. It is in H-1B visas and OCI cards, in TikTok bans and chip fabs, in Quad communiqués and tariff notices to the WTO. It is no longer an exotic foreign policy file. It is infrastructure.</p>

<p>This is my attempt to trace that long arc, from 1947 to the current round of tariff drama that started under Trump and simply refuses to go away.</p>

<hr />

<h2 id="non-alignment-nuclear-tests-and-the-cold-war-hangover">Non-alignment, nuclear tests, and the Cold War hangover</h2>

<p>India became independent in 1947 and partition ripped through the subcontinent. The US, fresh out of the Second World War and already looking at Moscow, wanted allies. India wanted space. Nehru’s trip to the US in 1949 produced warmth in photos and distance in policy. Soon after, India formally planted itself in the Non-Aligned Movement, which Washington always read as “nice words for not being on our side”. <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>The first big fracture was 1971. As Pakistan tore itself apart and Bangladesh was born, India intervened decisively and signed a 20-year Treaty of Friendship with the Soviet Union. The US, busy courting China via Pakistan, tilted towards Islamabad even as reports of atrocities in East Pakistan piled up. <sup id="fnref:1:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></p>

<p>Then came 1974. India tested a nuclear device at Pokhran and declared itself, very politely, a country that would not be told where its nuclear red lines lay. The US response was predictable for that era: non-proliferation laws, nuclear technology cut-offs, and a long season of frost. For more than two decades, “estranged democracies” became the default label for India and the US. <sup id="fnref:1:2" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:2:1" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<p>The relationship in that phase was transactional and narrow. Food aid during the Green Revolution. Some cooperation, some lectures. A lot of mutual irritation. Very little trust.</p>

<hr />

<h2 id="1991-when-economics-finally-crashed-the-party">1991: when economics finally crashed the party</h2>

<p>The real reset started not with a summit, but with a balance-of-payments crisis.</p>

<p>In 1991, Narasimha Rao’s government and a then-little-known finance minister called Manmohan Singh opened the Indian economy under duress. Tariffs fell. Markets opened. Foreign investment stopped being a dirty phrase. That single move changed how Washington looked at India, and how Indian business looked at the world. <sup id="fnref:2:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:4:1" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<p>Suddenly, India was not just the country that tested nukes and talked about moral leadership. It was also a place where American companies could sell planes, computers, telecom equipment, and consulting services. It was a place that had cheap, well-educated engineers.</p>

<p>Y2K, offshoring, and the IT services boom did what no amount of diplomacy had managed. They created a dense mesh of everyday connections. Indian engineers in US suburbs. US customers on the other end of a phone line in Bangalore. Companies with more Indians in their org chart than some Indian PSUs.</p>

<p>Even the nuclear argument began to bend. Pokhran-II in 1998 triggered another round of US sanctions, but this time they did not last. By 2000, President Clinton was in India and people were already talking about “warmed ties” instead of “estrangement”. <sup id="fnref:3:1" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup><sup id="fnref:4:2" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<hr />

<h2 id="the-nuclear-deal-and-the-strategic-turn">The nuclear deal and the strategic turn</h2>

<p>The real political signal came in the mid-2000s.</p>

<p>Between 2005 and 2008, India and the US negotiated and passed the civil nuclear agreement. India separated its civilian and military nuclear facilities, accepted IAEA safeguards on the civilian side, and in return the US worked to tear down a three-decade-old moratorium on nuclear trade with India. <sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup><sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup><sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">7</a></sup></p>

<p>You can argue about the exact economic value of that deal for hours. What matters for this story is something else. It told the world that Washington now saw Delhi as a long-term strategic bet, not a charity case to be managed with aid and occasional scolding. <sup id="fnref:6:1" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup><sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<p>Around the same time, the US declared India a “Major Defense Partner”. Defense trade went from almost zero to billions. Malabar exercises grew in scope. The Quad slowly crawled out of acronym limbo and acquired ballast. <sup id="fnref:3:2" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup><sup id="fnref:8:1" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<p>Terrorism, Pakistan, Afghanistan, Iran, Russia – these remained real areas of friction. But the big axis had shifted. The primary shared headache had a different name now: China. <sup id="fnref:2:3" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:8:2" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<hr />

<h2 id="trump-tariffs-and-the-mini-trade-war">Trump, tariffs, and the mini trade war</h2>

<p>Then came Trump, and with him, tariffs as a lifestyle choice.</p>

<p>In 2018, the US used the “national security” provision to slap tariffs of 25 percent on steel and 10 percent on aluminium from a long list of countries, India included. Those duties hit hundreds of millions of dollars’ worth of Indian exports, a couple of percentage points of what India sold to the US. <sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup><sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup></p>

<p>In 2019, Washington went a step further and yanked away India’s GSP status – the preferential trade program that gave duty-free access to a basket of Indian exports. That decision affected more than 6 billion dollars of trade and triggered what economists politely called a “mini trade war”. India retaliated with higher duties on selected US goods. <sup id="fnref:10:1" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup><sup id="fnref:11" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">11</a></sup></p>

<p>Trump’s messaging was blunt and on brand. India was a “tariff king”. The US was being taken for a ride. Tariffs were justice. <sup id="fnref:9:1" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup></p>

<p>If you lived in the diaspora, you got used to this strange split-screen. On one side, “Howdy Modi” in Houston and “Namaste Trump” in Ahmedabad – full stadiums, warm hugs, and talk of “natural allies”. On the other side, steel tariffs, GSP removal, and a constant drumbeat of trade complaints.</p>

<p>What held through that turbulence was the strategic layer. Defense cooperation deepened. Intelligence sharing increased. The Indo-Pacific became a more explicit frame. The two militaries worked together more. The Chinese PLA’s behaviour on the LAC made sure of that. <sup id="fnref:2:4" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:8:3" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup></p>

<hr />

<h2 id="after-trumps-tariffs-less-romance-more-plumbing">After Trump’s tariffs: less romance, more plumbing</h2>

<p>Changing presidents did not magically reset the economics.</p>

<p>Under Biden, some of the sharp edges were filed down. Trade talks restarted. There was more predictable messaging. The tone softened. But the age of painless access to the US market was clearly over. Tariffs and “national security” in trade policy are now a permanent part of the furniture. <sup id="fnref:9:2" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">9</a></sup><sup id="fnref:10:2" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup></p>

<p>At the same time, the strategic and technological embrace accelerated.</p>

<p>In 2023, Modi’s state visit to Washington produced an unusually dense joint statement. It covered everything from clean energy to space, from AI to critical minerals. The two sides pushed the Initiative on Critical and Emerging Technology (iCET), agreed on deeper cooperation in 5G and 6G, advanced chip partnerships, and moved forward on co-production of jet engines and other defence technologies. <sup id="fnref:12" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">12</a></sup><sup id="fnref:13" role="doc-noteref"><a href="#fn:13" class="footnote" rel="footnote">13</a></sup><sup id="fnref:14" role="doc-noteref"><a href="#fn:14" class="footnote" rel="footnote">14</a></sup><sup id="fnref:15" role="doc-noteref"><a href="#fn:15" class="footnote" rel="footnote">15</a></sup></p>

<p>Trade numbers quietly told the same story. The US emerged as India’s largest trading partner in goods, while India climbed into the top tier of US trading relationships. Services, digital trade, and investment deepened the connection further. <sup id="fnref:10:3" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup><sup id="fnref:11:1" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">11</a></sup></p>

<p>Yet the tariff saga did not die. It mutated.</p>

<p>In 2025, Washington expanded its use of steel and aluminium tariffs again, doubling duties in the name of national security. New orders raised headline rates and widened the coverage. <sup id="fnref:16" role="doc-noteref"><a href="#fn:16" class="footnote" rel="footnote">16</a></sup><sup id="fnref:17" role="doc-noteref"><a href="#fn:17" class="footnote" rel="footnote">17</a></sup></p>

<p>Delhi responded by formally notifying the WTO that it was considering retaliatory duties on a fresh list of US products, as a suspension of earlier concessions. The filing put the potential impact at about 7.6 billion dollars of Indian exports. <sup id="fnref:18" role="doc-noteref"><a href="#fn:18" class="footnote" rel="footnote">18</a></sup><sup id="fnref:19" role="doc-noteref"><a href="#fn:19" class="footnote" rel="footnote">19</a></sup></p>

<p>The situation further deteriorated when US imposed 25% ban on Indian goods in August with additional 25% soon after, citing New Delhi’s continued imports of Russian oil as the trade talks between the two nation resulted in a “no deal”.<sup id="fnref:20" role="doc-noteref"><a href="#fn:20" class="footnote" rel="footnote">20</a></sup><sup id="fnref:21" role="doc-noteref"><a href="#fn:21" class="footnote" rel="footnote">21</a></sup></p>

<p>The hugs are still there. So are the tariff notices.</p>

<hr />

<h2 id="so-where-are-we-really">So where are we, really?</h2>

<p>If you zoom out from the daily noise, the India–US story can be read in three large movements.</p>

<p>First, the moral and ideological phase. Non-alignment, nuclear lectures, food aid, sanctions, righteous speeches from both sides.</p>

<p>Second, the economic and technological phase. Liberalisation, IT services, diaspora, the nuclear deal, defense cooperation, the Indo-Pacific, the Quad.</p>

<p>Third, the current messy phase. High strategic convergence, thick economic interdependence, and a running gunfight over tariffs, data, digital rules, visas, and domestic politics in both countries. <sup id="fnref:2:5" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:8:4" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup><sup id="fnref:10:4" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup></p>

<p>The centre of gravity has moved from ideology to interest.</p>

<p>India no longer wants to be told whom to buy oil from or what its nuclear doctrine should be. It wants market access, technology transfer, and room to play Russia and the West off each other on its own terms.</p>

<p>The US no longer looks at India primarily through the lens of poverty, non-alignment, or Pakistan. It looks at India as a hedge against China, a market, a talent pool, and a sometimes-difficult partner that still matters a lot more inside Washington than it did thirty years ago. <sup id="fnref:2:6" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup><sup id="fnref:8:5" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup><sup id="fnref:10:5" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">10</a></sup></p>

<p>Tariffs in this picture are not an aberration. They are a tax on that new intimacy.</p>

<p>When you barely trade and barely cooperate, sanctions and tariffs are symbolic. When you are each other’s top partners in multiple domains, they are friction in the plumbing. They hurt very real businesses and very real workers on both sides, even as the broader relationship keeps moving forward.</p>

<hr />

<h2 id="my-bias-laid-bare">My bias, laid bare</h2>

<p>I grew up with stories of a distant superpower that alternated between lecturing India and sanctioning it.</p>

<p>I now live in a world where the US is inside Indian lives in a way that would have been hard to imagine in 1974. Phones, apps, films, VCs, H-1Bs, climate finance, chip supply chains, drones, joint statements, Netflix specials. India, in turn, is inside America through its people, its IT systems, its doctors and engineers, and increasingly through its market and its politics.</p>

<p>So when I look at the current tariff regime and whatever its next avatar will be, I see it as part of a longer story, not a breaking-news headline.</p>

<p>The story is simple.</p>

<p>Two large, loud democracies spent decades talking past each other.<br />
Then they discovered they had overlapping interests and compatible fears.<br />
Now they are trying to work together without becoming each other’s client state.</p>

<p>That is not a romance. It is a negotiation.</p>

<p>Tariffs will come and go. Leaders will hug and glare in cycles. There will be real disagreements on Russia, on digital rules, on climate, on human rights.</p>

<p>Underneath all that, the India–US relationship will keep doing what it has been doing for the last thirty years.</p>

<p>Getting denser.<br />
Getting messier.<br />
And, slowly, becoming too important to be left to just diplomats and tariff lawyers.</p>

<hr />

<h2 id="references">References</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Dennis Kux, <em>India and the United States: Estranged Democracies, 1941–1991</em> (Washington, DC: US Institute of Peace Press, 1993).  <a href="https://www.govinfo.gov/content/pkg/GOVPUB-D5_400-PURL-LPS51512/pdf/GOVPUB-D5_400-PURL-LPS51512.pdf?">GovInfo</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:1:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:1:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Frédéric Grare, “Looking Back at Three Decades of India-US Relationship,” Carnegie Endowment for International Peace, 2018.  <a href="https://carnegie-production-assets.s3.amazonaws.com/static/files/Looking_Back_at_Three_Decades_of_India-US_Relationship.pdf?">Carnegie Production Assets</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:2:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:2:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a> <a href="#fnref:2:3" class="reversefootnote" role="doc-backlink">&#8617;<sup>4</sup></a> <a href="#fnref:2:4" class="reversefootnote" role="doc-backlink">&#8617;<sup>5</sup></a> <a href="#fnref:2:5" class="reversefootnote" role="doc-backlink">&#8617;<sup>6</sup></a> <a href="#fnref:2:6" class="reversefootnote" role="doc-backlink">&#8617;<sup>7</sup></a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Robert J. McMahon, <em>Cold War on the Periphery: The United States, India, and Pakistan</em> (Columbia University Press, 1994). <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:3:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:3:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>“India–United States relations,” background summary.  <a href="https://en.wikipedia.org/wiki/India%E2%80%93United_States_relations?">Wikipedia</a> <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:4:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:4:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>“U.S.-India Civil Nuclear Cooperation,” U.S. Department of State archive.  <a href="https://2001-2009.state.gov/p/sca/c17361.htm?">State.gov</a> <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>“The U.S.–India Nuclear Deal,” Council on Foreign Relations Backgrounder.  <a href="https://www.cfr.org/backgrounder/us-india-nuclear-deal?">Council on Foreign Relations</a> <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:6:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p>“Chronology of the Indo-US nuclear deal,” <em>Times of India</em>, October 9, 2008.  <a href="https://timesofindia.indiatimes.com/world/us/chronology-of-the-indo-us-nuclear-deal/articleshow/3575350.cms?">The Times of India</a> <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p>“The 10th Anniversary of the U.S.-India Civil Nuclear Deal,” U.S. Embassy New Delhi, July 14, 2015.  <a href="https://ci.usembassy.gov/the-10th-anniversary-of-the-u-s-india-civil-nuclear-deal">U.S. Embassy in Côte d’Ivoire</a> <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:8:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:8:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a> <a href="#fnref:8:3" class="reversefootnote" role="doc-backlink">&#8617;<sup>4</sup></a> <a href="#fnref:8:4" class="reversefootnote" role="doc-backlink">&#8617;<sup>5</sup></a> <a href="#fnref:8:5" class="reversefootnote" role="doc-backlink">&#8617;<sup>6</sup></a></p>
    </li>
    <li id="fn:9" role="doc-endnote">
      <p>“Adjusting Imports of Aluminum and Steel into the United States,” Presidential actions on Section 232 tariffs.  <a href="https://www.whitehouse.gov/presidential-actions/2025/06/adjusting-imports-of-aluminum-and-steel-into-the-united-states">The White House</a> <a href="#fnref:9" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:9:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:9:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a></p>
    </li>
    <li id="fn:10" role="doc-endnote">
      <p>“U.S.-India Trade Relations,” Congressional Research Service / WITA summaries.  <a href="https://www.congress.gov/crs_external_products/IF/PDF/IF10384/IF10384.10.pdf?">Congress.gov</a> <a href="#fnref:10" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:10:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a> <a href="#fnref:10:2" class="reversefootnote" role="doc-backlink">&#8617;<sup>3</sup></a> <a href="#fnref:10:3" class="reversefootnote" role="doc-backlink">&#8617;<sup>4</sup></a> <a href="#fnref:10:4" class="reversefootnote" role="doc-backlink">&#8617;<sup>5</sup></a> <a href="#fnref:10:5" class="reversefootnote" role="doc-backlink">&#8617;<sup>6</sup></a></p>
    </li>
    <li id="fn:11" role="doc-endnote">
      <p>Andrew K. Rose and others, “Trump’s mini-trade war with India,” VoxEU/CEPR, July 22, 2019.  <a href="https://cepr.org/voxeu/blogs-and-reviews/trumps-mini-trade-war-india?">CEPR</a> <a href="#fnref:11" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:11:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:12" role="doc-endnote">
      <p>“Joint Statement from the United States and India,” White House, June 22, 2023.  <a href="https://bidenwhitehouse.archives.gov/briefing-room/statements-releases/2023/06/22/joint-statement-from-the-united-states-and-india">The White House</a> <a href="#fnref:12" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:13" role="doc-endnote">
      <p>“Joint Statement from India and the United States,” Indian Ministry of External Affairs, September 8, 2023.  <a href="https://www.mea.gov.in/bilateral-documents.htm?dtl%2F37078%2FJoint_Statement_from_India_and_the_United_States=&amp;">Indian External Affairs Ministry</a> <a href="#fnref:13" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:14" role="doc-endnote">
      <p>“FACT SHEET: United States and India Elevate Strategic Partnership with the Initiative on Critical and Emerging Technology (iCET),” U.S. Embassy.  <a href="https://in.usembassy.gov/fact-sheet-united-states-and-india-elevate-strategic-partnership-with-the-initiative-on-critical-and-emerging-technology-icet">in.usembassy.gov</a> <a href="#fnref:14" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:15" role="doc-endnote">
      <p>“FACT SHEET: Republic of India Official State Visit to the United States,” White House, June 22, 2023.  <a href="https://bidenwhitehouse.archives.gov/briefing-room/statements-releases/2023/06/22/fact-sheet-republic-of-india-official-state-visit-to-the-united-states">The White House</a> <a href="#fnref:15" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:16" role="doc-endnote">
      <p>Associated Press, “Trump steps up his 2018 tariffs on steel and aluminum,” February 2025.  <a href="https://apnews.com/article/0a91ceaf3aa3c1756c339817d1d58076?">apnews.com</a> <a href="#fnref:16" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:17" role="doc-endnote">
      <p>“Adjusting Imports of Aluminum and Steel into the United States,” Presidential proclamation, June 3, 2025.  <a href="https://www.whitehouse.gov/presidential-actions/2025/06/adjusting-imports-of-aluminum-and-steel-into-the-united-states">The White House</a> <a href="#fnref:17" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:18" role="doc-endnote">
      <p>Reuters, “India considers counter duties on US products, notice to WTO shows,” May 13, 2025.  <a href="https://www.reuters.com/markets/commodities/india-proposes-counter-duties-against-us-notice-wto-shows-2025-05-13">reuters.com</a> <a href="#fnref:18" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:19" role="doc-endnote">
      <p><em>Economic Times</em>, “India proposes retaliatory duties against US on steel, aluminium duties at WTO,” May 2025.  <a href="https://economictimes.indiatimes.com/news/economy/foreign-trade/india-proposes-retaliatory-duties-against-us-on-steel-aluminium-duties-at-wto/articleshow/121120497.cms">economictimes.indiatimes.com</a> <a href="#fnref:19" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:20" role="doc-endnote">
      <p>Reuters, “Trump imposes extra 25% tariff on Indian goods, ties hit new low,” Aug 6, 2025. <a href="https://www.reuters.com/world/india/trump-imposes-extra-25-tariff-indian-goods-ties-hit-new-low-2025-08-06/">reuters.com</a> <a href="#fnref:20" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:21" role="doc-endnote">
      <p>Reuters, “Missed signals, lost deal: How India-US trade talks collapsed”, Aug 6, 2025. <a href="https://www.reuters.com/world/india/missed-signals-lost-deal-how-india-us-trade-talks-collapsed-2025-08-06/">reuters.com</a> <a href="#fnref:21" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Politics &amp; Governance&quot;, &quot;Society &amp; Economy&quot;]" /><category term="politics" /><category term="society" /><category term="economy" /><category term="leadership" /><category term="india" /><category term="united-states" /><summary type="html"><![CDATA[Let us explore the Indo-US relations over the year and where they are headed after recent tariffs imposed by US on India]]></summary></entry><entry><title type="html">Part 1: IEEE 754 Doubles - The Numbers That Lie With A Straight Face</title><link href="https://systemhalted.in/2025/12/04/ieee-754-doubles/" rel="alternate" type="text/html" title="Part 1: IEEE 754 Doubles - The Numbers That Lie With A Straight Face" /><published>2025-12-04T00:00:00+00:00</published><updated>2025-12-04T00:00:00+00:00</updated><id>https://systemhalted.in/2025/12/04/ieee-754-doubles</id><content type="html" xml:base="https://systemhalted.in/2025/12/04/ieee-754-doubles/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>In Java, <code class="language-plaintext highlighter-rouge">double</code> feels like a real number. You write <code class="language-plaintext highlighter-rouge">1.0</code>, the compiler nods, the program runs, and everything looks fine.
Until it does not.</p>

<p>Take this tiny example:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">List</span> <span class="n">values</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
<span class="mi">1</span><span class="n">e16</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">1.0</span>
<span class="o">);</span>

<span class="kt">double</span> <span class="n">s1</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mf">0.0</span><span class="o">,</span> <span class="nl">Double:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>
<span class="kt">double</span> <span class="n">s2</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mf">0.0</span><span class="o">,</span> <span class="nl">Double:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s1</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s2</span><span class="o">);</span></code></pre></figure>

<p>You might see</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">1.0E16
1.0000000000000004E16</code></pre></figure>

<p>Same data, same operation, different result.</p>

<p>To understand why, you have to stop thinking of doubles as numbers and start thinking of them as compressed approximations of numbers with strict rules and sharp edges.</p>

<h1 id="doubles-are-just-bit-patterns">Doubles are just bit patterns</h1>

<p>An IEEE 754 double is 64 bits laid out like this:
	1.	One bit for the sign
	2.	Eleven bits for the exponent
	3.	Fifty two bits for the fraction (often called the mantissa or significand)</p>

<p>That layout represents numbers of the form:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(-1)^sign × 1.fraction_bits × 2^(exponent - bias)
</code></pre></div></div>
<p>There is no infinite continuum here. There is a huge but finite set of exactly representable values. Between any two nearby doubles, there is literally nothing.</p>

<p>So when you write:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mf">0.1</span><span class="o">;</span></code></pre></figure>

<p>Java does its best to find the closest representable double to 0.1. But 0.1 in base 10 is a repeating fraction in base 2, just like 1/3 is repeating in base 10. There is no exact binary representation. The runtime rounds to the nearest representable double and moves on.</p>

<p>If you print it with enough digits, you see the approximation leak through:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">printf</span><span class="o">(</span><span class="err">”</span><span class="o">%.</span><span class="mi">20</span><span class="n">f</span><span class="o">%</span><span class="n">n</span><span class="err">”</span><span class="o">,</span> <span class="mf">0.1</span><span class="o">);</span></code></pre></figure>

<p>You will get something like:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">0.10000000000000000555</code></pre></figure>

<p>The lie is small, but it is always there.</p>

<h1 id="why-1e16--1--1e16">Why 1e16 + 1 == 1e16</h1>

<p>Back to our friend <code class="language-plaintext highlighter-rouge">1e16</code>.</p>

<p>At that scale, the distance between adjacent representable doubles is larger than 1. Think of the number line as a ladder. Near zero the rungs are very close. Near 1e16 the rungs are far apart. If adding 1 does not reach the next rung, the result rounds back to the same double.</p>

<p>In practice:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="n">e16</span><span class="o">;</span>
<span class="kt">double</span> <span class="n">b</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mf">1.0</span><span class="o">;</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="o">);</span> <span class="c1">// true</span></code></pre></figure>

<p>It looks absurd, but it is perfectly legal in IEEE land. You are not adding real numbers. You are adding approximations and rounding the result back into the finite set of doubles.</p>

<p>Now imagine how this interacts with summation order.</p>

<p>Sequential stream:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">s1</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mf">0.0</span><span class="o">,</span> <span class="nl">Double:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span></code></pre></figure>

<p>Evaluation order is effectively:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>((((0 + 1e16) + 1) + 1) + 1) + 1
</code></pre></div></div>

<p>After the first addition you have <code class="language-plaintext highlighter-rouge">1e16</code>. Each subsequent <code class="language-plaintext highlighter-rouge">+ 1</code> is below the resolution of the ladder at that height, so it keeps snapping back to 1e16. End result: <code class="language-plaintext highlighter-rouge">1.0E16</code>.</p>

<p>Parallel stream:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">s2</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mf">0.0</span><span class="o">,</span> <span class="nl">Double:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span></code></pre></figure>

<p>Now the framework is allowed to regroup:
	1.	One thread might sum <code class="language-plaintext highlighter-rouge">1e16 + 1.0</code> to get <code class="language-plaintext highlighter-rouge">1e16</code>.
	2.	Another might sum <code class="language-plaintext highlighter-rouge">1.0 + 1.0 + 1.0</code> to get <code class="language-plaintext highlighter-rouge">3.0</code>.
	3.	Then it adds <code class="language-plaintext highlighter-rouge">1e16 + 3.0</code>.</p>

<p>Depending on the exact rounding behavior, that last addition might actually hit the next rung on the ladder and give:</p>

<figure class="highlight"><pre><code class="language-text" data-lang="text">1.0000000000000004E16</code></pre></figure>

<p>Same math on paper. Different rounding path in silicon.</p>

<p>You have just met the most important fact about floating point arithmetic:</p>

<p><em>Associativity is broken in practice.</em></p>

<p>Mathematically:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(a + b) + c == a + (b + c)
</code></pre></div></div>

<p>In floating point, <code class="language-plaintext highlighter-rouge">(a + b) + c</code> and <code class="language-plaintext highlighter-rouge">a + (b + c)</code> can differ by a few bits.</p>

<h1 id="equality-with-doubles-is-a-trap">Equality with doubles is a trap</h1>

<p>This is why direct equality checks with doubles are dangerous:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="mf">0.1</span> <span class="o">+</span> <span class="mf">0.2</span><span class="o">;</span>
<span class="kt">double</span> <span class="n">y</span> <span class="o">=</span> <span class="mf">0.3</span><span class="o">;</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">x</span> <span class="o">==</span> <span class="n">y</span><span class="o">);</span> <span class="c1">// often false</span></code></pre></figure>

<p>The left side is “nearest double to <code class="language-plaintext highlighter-rouge">(0.1 + 0.2)</code> after two rounding steps”.
The right side is “nearest double to <code class="language-plaintext highlighter-rouge">0.3</code> after one rounding step”.</p>

<p>You are really comparing two approximations that reached the neighborhood of <code class="language-plaintext highlighter-rouge">0.3</code> via different routes. The neighborhood is small, but the routes do not always end at the same exact bit pattern.</p>

<p>The usual advice is:
	1.	Compare with an epsilon, for example: <code class="language-plaintext highlighter-rouge">Math.abs(x - y) &lt; 1e-9</code>, tuned to your domain.
	2.	Or avoid equality checks altogether and reason in ranges, ratios or integers when possible.</p>

<h1 id="why-parallel-reduce-cares-about-associativity">Why parallel reduce cares about associativity</h1>
<p>The Java Streams API assumes your reduction operator is associative and has a proper identity. For doubles, <code class="language-plaintext highlighter-rouge">Double::sum</code> with <code class="language-plaintext highlighter-rouge">0.0</code> definitely satisfies the mathematical definition.</p>

<p>The parallel stream uses this to split the work: 
	1.	Compute partial sums in parallel. 
	2.	Combine partials in arbitrary order.</p>

<p>From basic math, this is fine.</p>

<p>From IEEE 754 reality, it means you get “approximately the same result most of the time, with possible tiny differences depending on grouping, thread scheduling and platform”.</p>

<p>In most business code that is acceptable. In some domains it is not.</p>

<p>If you need reproducible sums independent of order, you have options.</p>

<p>Use BigDecimal:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">BigDecimal</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
<span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="nl">BigDecimal:</span><span class="o">:</span><span class="n">valueOf</span><span class="o">)</span>
<span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="nc">BigDecimal</span><span class="o">.</span><span class="na">ZERO</span><span class="o">,</span> <span class="nl">BigDecimal:</span><span class="o">:</span><span class="n">add</span><span class="o">);</span></code></pre></figure>

<p>This gives you honest <code class="language-plaintext highlighter-rouge">base 10</code> arithmetic at the cost of performance.</p>

<p>Or implement a compensated summation like Kahan’s algorithm, possibly in a custom Collector, to reduce error accumulation.</p>

<p>Or structure your algorithm so you sum small magnitude values first and large values later. That makes the ladder problem less vicious.</p>

<p>None of these fix floating point. They just manage its tradeoffs more consciously.</p>

<h1 id="doubles-are-not-broken-they-are-engineered">Doubles are not broken, they are Engineered</h1>
<p>It is tempting to call all this a bug. It is not.</p>

<p>The IEEE 754 design is a compromise between range, precision, performance and hardware simplicity. Doubles give you:</p>

<ol>
  <li>A huge dynamic range, from tiny numbers around 1e-308 up to around 1e308.</li>
  <li>About 15 to 17 decimal digits of precision.</li>
  <li>Fast operations supported directly by the CPU.</li>
</ol>

<p>The cost is:</p>

<ol>
  <li>Not all decimal fractions are exact.</li>
  <li>Rounding happens all the time.</li>
  <li>Algebraic laws like associativity and distributivity become “mostly true, but not guaranteed”.</li>
</ol>

<p>Once you internalize that, your mental model shifts.</p>

<p>You stop thinking “the computer is bad at math”.</p>

<p>You start thinking “the computer is doing carefully specified approximate math on a discrete set of representable values, and I need to respect that contract”.</p>

<p>Where this matters in real systems</p>

<p>In an auto loan system, this can show up in subtle ways.</p>

<p>You might compute a customer’s total interest by:</p>

<ol>
  <li>Summing daily interest over the life of the loan.</li>
  <li>Summing per period interest.</li>
  <li>Using a closed form formula.</li>
</ol>

<p>All three approaches should be equivalent mathematically, but can drift by a few cents because of rounding and summation order. Then you run in parallel, or refactor a loop into a stream, or change the order in which fees and interest are applied, and suddenly some accounts are off by a cent.</p>

<p>Nothing catastrophic, but enough to fail reconciliation tests.</p>

<p>Once you remember that doubles are approximations and order matters, you design differently:</p>

<ol>
  <li>Use BigDecimal for money.</li>
  <li>Keep calculations stable and deterministic.</li>
  <li>Avoid relying on bit perfect equality when the underlying math is continuous.</li>
</ol>

<p>And when your <code class="language-plaintext highlighter-rouge">parallelStream()</code> sum differs from your sequential sum in the thirteenth decimal place, you do not panic. You smile a little and think:</p>

<blockquote>
  <p>Floating point kept its side of the bargain.
I just finally started reading the fine print.</p>
</blockquote>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Computer Science&quot;, &quot;Software Engineering&quot;, &quot;Technology&quot;, &quot;Series 4 - Floating Point Without Tears&quot;]" /><category term="computer-science" /><category term="software" /><category term="technology" /><summary type="html"><![CDATA[In Java, double feels like a real number. You write 1.0, the compiler nods, the program runs, and everything looks fine. Until it doesn’t.]]></summary></entry><entry><title type="html">Part 2: Associativity, Identity, and Folding - Why Your reduce Keeps Biting You</title><link href="https://systemhalted.in/2025/11/28/associativity-identity-folding/" rel="alternate" type="text/html" title="Part 2: Associativity, Identity, and Folding - Why Your reduce Keeps Biting You" /><published>2025-11-28T00:00:00+00:00</published><updated>2025-11-28T00:00:00+00:00</updated><id>https://systemhalted.in/2025/11/28/associativity-identity-folding</id><content type="html" xml:base="https://systemhalted.in/2025/11/28/associativity-identity-folding/"><![CDATA[<p><em>This post is part of my <a href="https://systemhalted.in/categories/#cat-series-4-floating-point-without-tears">Floating Point Without Tears</a> series on how Java numbers misbehave and how to live with them.</em></p>

<p>If you write Java today, you probably use <code class="language-plaintext highlighter-rouge">Stream.reduce()</code> or something like it.</p>

<p>Sometimes it feels magical.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span></code></pre></figure>

<p>Other times it feels cursed.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">weird</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="o">);</span></code></pre></figure>

<p>Same method, very different behavior.</p>

<p>Underneath these differences are three simple ideas:</p>

<ol>
  <li>Associativity</li>
  <li>Identity</li>
  <li>Folding (reducing a collection into one value)</li>
</ol>

<p>You do not need category theory to use them. You just need to recognize when your operation behaves like <code class="language-plaintext highlighter-rouge">+</code> (associative) and when it behaves like <code class="language-plaintext highlighter-rouge">-</code> (non-associative).</p>

<p>This post walks through concrete Java examples you are likely to hit in normal work and uses them to build intuition for those three words.</p>

<p>It also gives you an understanding of when using parallelStreams is probably safe.</p>

<hr />

<h2 id="folding-what-reduce-really-does">Folding: what <code class="language-plaintext highlighter-rouge">reduce</code> really does</h2>

<p>A fold or reduce is just this:</p>

<p>Start with some value.<br />
Combine it with each element in a collection.<br />
End up with a single result.</p>

<p>For example, summing numbers by hand:</p>

<ol>
  <li>Start with <code class="language-plaintext highlighter-rouge">0</code></li>
  <li>Add the first number</li>
  <li>Add the second number</li>
  <li>Keep going until you have one, final, number left</li>
</ol>

<p>In Java Streams:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="o">(</span><span class="n">acc</span><span class="o">,</span> <span class="n">x</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">acc</span> <span class="o">+</span> <span class="n">x</span><span class="o">);</span></code></pre></figure>

<p><code class="language-plaintext highlighter-rouge">reduce</code> needs two things from you.</p>

<ol>
  <li>An initial value, sometimes called the identity.</li>
  <li>A function that combines the accumulator and the next element.</li>
</ol>

<p>Everything else in this post is about choosing those two well.</p>

<hr />

<h2 id="example-1-integer-sum-the-happy-path">Example 1: Integer sum, the happy path</h2>

<p>Summing integers is the canonical example of reduce working perfectly, even in parallel.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>

<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">nums</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">5</span><span class="o">);</span>

<span class="c1">// Sequential</span>
<span class="kt">int</span> <span class="n">sum1</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="c1">// Parallel</span>
<span class="kt">int</span> <span class="n">sum2</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">sum1</span><span class="o">);</span> <span class="c1">// 15</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">sum2</span><span class="o">);</span> <span class="c1">// 15</span></code></pre></figure>

<p>Why does this behave?</p>

<p>The short version:</p>

<ol>
  <li>Addition is associative.</li>
  <li>Zero is the identity for addition.</li>
</ol>

<p>Let us unpack that.</p>

<p>Associativity means you can change parentheses without changing the result:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="o">(</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span><span class="o">)</span> <span class="o">+</span> <span class="mi">3</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="o">(</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">3</span><span class="o">);</span>
<span class="c1">// a == b</span></code></pre></figure>

<p>Zero is the identity for <code class="language-plaintext highlighter-rouge">+</code> because it does nothing:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="mi">0</span> <span class="o">+</span> <span class="n">x</span> <span class="o">==</span> <span class="n">x</span><span class="o">;</span>
<span class="n">x</span> <span class="o">+</span> <span class="mi">0</span> <span class="o">==</span> <span class="n">x</span><span class="o">;</span></code></pre></figure>

<p>When both of these are true, the stream framework is free to:</p>

<ol>
  <li>Split the list into chunks.</li>
  <li>Sum each chunk separately.</li>
  <li>Add the partial sums in any grouping it likes.</li>
</ol>

<p>Sequential or parallel, left grouped or right grouped, the result is always the same.</p>

<hr />

<h2 id="example-2-subtraction-with-reduce-same-shape-weird-result">Example 2: Subtraction with reduce, same shape, weird result</h2>

<p>Change one thing. Use subtraction instead of addition.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">nums</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="mi">5</span><span class="o">);</span>

<span class="c1">// Sequential</span>
<span class="kt">int</span> <span class="n">result1</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="o">);</span>

<span class="c1">// Parallel</span>
<span class="kt">int</span> <span class="n">result2</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-</span> <span class="n">b</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">result1</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">result2</span><span class="o">);</span></code></pre></figure>

<p>On most machines you will see different numbers printed.</p>

<p>Subtraction is not associative:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="o">(</span><span class="mi">1</span> <span class="o">-</span> <span class="mi">2</span><span class="o">)</span> <span class="o">-</span> <span class="mi">3</span><span class="o">;</span>  <span class="c1">// -4</span>
<span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="o">(</span><span class="mi">2</span> <span class="o">-</span> <span class="mi">3</span><span class="o">);</span>  <span class="c1">//  2</span>
<span class="c1">// a != b</span></code></pre></figure>

<p>Once the operation is not associative, the way the stream groups operations changes the result.</p>

<p>Sequential <code class="language-plaintext highlighter-rouge">reduce</code> tends to behave as if it were:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">((((</span><span class="mi">0</span> <span class="o">-</span> <span class="mi">1</span><span class="o">)</span> <span class="o">-</span> <span class="mi">2</span><span class="o">)</span> <span class="o">-</span> <span class="mi">3</span><span class="o">)</span> <span class="o">-</span> <span class="mi">4</span><span class="o">)</span> <span class="o">-</span> <span class="mi">5</span><span class="o">;</span></code></pre></figure>

<p>Parallel <code class="language-plaintext highlighter-rouge">reduce</code> might do something more like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">(</span><span class="mi">0</span> <span class="o">-</span> <span class="o">(</span><span class="mi">1</span> <span class="o">-</span> <span class="mi">2</span><span class="o">))</span> <span class="o">-</span> <span class="o">(</span><span class="mi">3</span> <span class="o">-</span> <span class="o">(</span><span class="mi">4</span> <span class="o">-</span> <span class="mi">5</span><span class="o">));</span></code></pre></figure>

<p>Same numbers, same lambda, same <code class="language-plaintext highlighter-rouge">reduce</code> method. Different grouping, different answer.</p>

<p>The day to day lesson:</p>

<p>When you pass a lambda as the combiner to <code class="language-plaintext highlighter-rouge">reduce</code>, ask yourself whether it behaves more like <code class="language-plaintext highlighter-rouge">+</code> or more like <code class="language-plaintext highlighter-rouge">-</code>. If it is like <code class="language-plaintext highlighter-rouge">-</code>, parallel reduction will be surprising.</p>

<hr />

<h2 id="example-3-wrong-identity-value-leads-to-skewed-output">Example 3: Wrong identity value leads to skewed output</h2>

<p>Even if your operation is associative, choosing the wrong initial value quietly skews your result.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">nums</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">);</span>

<span class="c1">// Wrong identity: 1 instead of 0</span>
<span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">nums</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">sum</span><span class="o">);</span>  <span class="c1">// 7, but the real sum is 6</span></code></pre></figure>

<p>Sequentially this works out as:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">(((</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">1</span><span class="o">)</span> <span class="o">+</span> <span class="mi">2</span><span class="o">)</span> <span class="o">+</span> <span class="mi">3</span><span class="o">)</span> <span class="o">==</span> <span class="mi">7</span><span class="o">;</span></code></pre></figure>

<p>In parallel, the identity can be applied to every chunk, so the effect is even stranger.</p>

<p>The identity should be a ==do nothing== value for the operation:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>combine(identity, x) == x  
combine(x, identity) == x
</code></pre></div></div>

<p>For addition, the identity is <code class="language-plaintext highlighter-rouge">0</code>. For multiplication, it is <code class="language-plaintext highlighter-rouge">1</code>. For string concatenation, it is <code class="language-plaintext highlighter-rouge">""</code>.</p>

<p>The day to day rule:</p>

<p>If you call <code class="language-plaintext highlighter-rouge">reduce(identity, combiner)</code>, check those two equations in your head for the operation you are using.</p>

<hr />

<h2 id="example-4-string-concatenation-grouping-versus-ordering">Example 4: String concatenation, grouping versus ordering</h2>

<p>String concatenation is another operation you use constantly.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">words</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">);</span>

<span class="nc">String</span> <span class="n">s1</span> <span class="o">=</span> <span class="n">words</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="s">""</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="o">);</span>

<span class="nc">String</span> <span class="n">s2</span> <span class="o">=</span> <span class="n">words</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="s">""</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s1</span><span class="o">);</span>  <span class="c1">// usually "abc"</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s2</span><span class="o">);</span>  <span class="c1">// also usually "abc"</span></code></pre></figure>

<p>Concatenation is associative:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="o">(</span><span class="s">"a"</span> <span class="o">+</span> <span class="s">"b"</span><span class="o">)</span> <span class="o">+</span> <span class="s">"c"</span> <span class="o">==</span> <span class="s">"a"</span> <span class="o">+</span> <span class="o">(</span><span class="s">"b"</span> <span class="o">+</span> <span class="s">"c"</span><span class="o">);</span></code></pre></figure>

<p>and the empty string is the identity:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="s">""</span> <span class="o">+</span> <span class="n">s</span> <span class="o">==</span> <span class="n">s</span><span class="o">;</span>
<span class="n">s</span> <span class="o">+</span> <span class="s">""</span> <span class="o">==</span> <span class="n">s</span><span class="o">;</span></code></pre></figure>

<p>So grouping does not matter.</p>

<p>Order still matters though:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="s">"a"</span> <span class="o">+</span> <span class="s">"b"</span> <span class="o">!=</span> <span class="s">"b"</span> <span class="o">+</span> <span class="s">"a"</span><span class="o">;</span></code></pre></figure>

<p>Concatenation is associative but not commutative.</p>

<p>Streams will respect encounter order unless you explicitly undo that. So in practice the result is stable, but the moment you introduce reordering operations you lose that guarantee.</p>

<p>The message here:</p>

<ol>
  <li>Associativity protects you from grouping changes.</li>
  <li>Commutativity protects you from ordering changes.</li>
  <li>Most real world operations are not commutative, so do not assume order is irrelevant unless you are sure.</li>
</ol>

<hr />

<h2 id="example-5-floating-point-sums-almost-associative">Example 5: Floating point sums, almost associative</h2>

<p>Now a more subtle one: floating point numbers.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Double</span><span class="o">&gt;</span> <span class="n">values</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
        <span class="mi">1</span><span class="n">e16</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">1.0</span><span class="o">,</span> <span class="mf">1.0</span>
<span class="o">);</span>

<span class="kt">double</span> <span class="n">s1</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mf">0.0</span><span class="o">,</span> <span class="nl">Double:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="kt">double</span> <span class="n">s2</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="mf">0.0</span><span class="o">,</span> <span class="nl">Double:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s1</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s2</span><span class="o">);</span></code></pre></figure>

<p>In real math, addition is associative. In IEEE double precision, it is only approximately so.</p>

<p>When you add a very large number and a very small number, the small number can get rounded away. Different groupings of additions can lose or keep different tiny pieces of information.</p>

<p>Practically you see things like:</p>

<ol>
  <li>Slightly different sums when you use parallel streams.</li>
  <li>Results like <code class="language-plaintext highlighter-rouge">999.9999999997</code> instead of <code class="language-plaintext highlighter-rouge">1000.0</code>.</li>
</ol>

<p>For many applications this does not matter. For financial calculations it absolutely does, which is one reason developers reach for <code class="language-plaintext highlighter-rouge">BigDecimal</code> or integer cents rather than <code class="language-plaintext highlighter-rouge">double</code>.</p>

<p>The take away:</p>

<p>Floating point addition mostly behaves like a good associative operation, but not perfectly. Do not expect bit identical results when you regroup or parallelise floating point reductions.</p>

<hr />

<h2 id="example-6-merging-counts-in-maps-a-realistic-associative-operation">Example 6: Merging counts in maps, a realistic associative operation</h2>

<p>Imagine you have words and you want to count how many times each appears.</p>

<blockquote>
  <p>A Note on Engineering vs. Math:
While our Counts merge logic is mathematically associative (satisfying the requirements for reduce), using reduce for mutable objects like Maps is inefficient. It creates a copy of the map at every step.
In Java, when you need to combine mutable containers (like Lists or Maps) in parallel, you should use the Mutable Reduction pattern via Stream.collect.</p>
</blockquote>

<p>First, a small helper type:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.util.Map</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.HashMap</span><span class="o">;</span>

<span class="n">record</span> <span class="nf">Counts</span><span class="o">(</span><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">counts</span><span class="o">)</span> <span class="o">{</span>

    <span class="kd">static</span> <span class="nc">Counts</span> <span class="nf">empty</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nf">Counts</span><span class="o">(</span><span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;&gt;());</span>
    <span class="o">}</span>

    <span class="nc">Counts</span> <span class="nf">addWord</span><span class="o">(</span><span class="nc">String</span> <span class="n">word</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">copy</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;&gt;(</span><span class="n">counts</span><span class="o">);</span>
        <span class="n">copy</span><span class="o">.</span><span class="na">merge</span><span class="o">(</span><span class="n">word</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nf">Counts</span><span class="o">(</span><span class="n">copy</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="nc">Counts</span> <span class="nf">combine</span><span class="o">(</span><span class="nc">Counts</span> <span class="n">other</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">copy</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;&gt;(</span><span class="n">counts</span><span class="o">);</span>
        <span class="n">other</span><span class="o">.</span><span class="na">counts</span><span class="o">.</span><span class="na">forEach</span><span class="o">((</span><span class="n">w</span><span class="o">,</span> <span class="n">c</span><span class="o">)</span> <span class="o">-&gt;</span>
                <span class="n">copy</span><span class="o">.</span><span class="na">merge</span><span class="o">(</span><span class="n">w</span><span class="o">,</span> <span class="n">c</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">));</span>
        <span class="k">return</span> <span class="k">new</span> <span class="nf">Counts</span><span class="o">(</span><span class="n">copy</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Now we can use <code class="language-plaintext highlighter-rouge">reduce</code> with this.</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>

<span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">words</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">,</span> <span class="s">"a"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">,</span> <span class="s">"a"</span><span class="o">);</span>

<span class="nc">Counts</span> <span class="n">result</span> <span class="o">=</span> <span class="n">words</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">w</span> <span class="o">-&gt;</span> <span class="nc">Counts</span><span class="o">.</span><span class="na">empty</span><span class="o">().</span><span class="na">addWord</span><span class="o">(</span><span class="n">w</span><span class="o">))</span>  <span class="c1">// each word → its own count map</span>
        <span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="nc">Counts</span><span class="o">.</span><span class="na">empty</span><span class="o">(),</span> <span class="nl">Counts:</span><span class="o">:</span><span class="n">combine</span><span class="o">);</span>

<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">result</span><span class="o">.</span><span class="na">counts</span><span class="o">());</span>
<span class="c1">// {a=3, b=2, c=1}</span></code></pre></figure>

<p>Why this works well:</p>

<ol>
  <li>
    <p><code class="language-plaintext highlighter-rouge">combine</code> is associative.<br />
Combining <code class="language-plaintext highlighter-rouge">(A combine B) combine C</code> gives the same counts as <code class="language-plaintext highlighter-rouge">A combine (B combine C)</code>.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">Counts.empty()</code> is an identity.<br />
Combining <code class="language-plaintext highlighter-rouge">empty</code> with any <code class="language-plaintext highlighter-rouge">Counts</code> yields that <code class="language-plaintext highlighter-rouge">Counts</code> back.</p>
  </li>
</ol>

<p>That is exactly what a framework like <code class="language-plaintext highlighter-rouge">reduce</code> wants: an associative operation with an identity element.</p>

<p>This is the same pattern you see in log aggregation, metrics systems, and analytics jobs. It is not an abstract trick, it is a workhorse.</p>

<hr />

<h2 id="a-mental-checklist-for-reduce">A mental checklist for <code class="language-plaintext highlighter-rouge">reduce</code></h2>

<p>Whenever you write something like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="no">X</span> <span class="n">result</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">reduce</span><span class="o">(</span><span class="n">identity</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">combine</span><span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">));</span></code></pre></figure>

<p>you can run a short mental checklist.</p>

<ol>
  <li>
    <p>If I ignore floating point quirks, is <code class="language-plaintext highlighter-rouge">combine</code> associative?</p>

    <p>combine(combine(a, b), c) == combine(a, combine(b, c))</p>
  </li>
  <li>
    <p>Did I choose a true identity value?<br />
Does <code class="language-plaintext highlighter-rouge">combine(identity, x)</code> give <code class="language-plaintext highlighter-rouge">x</code> and does <code class="language-plaintext highlighter-rouge">combine(x, identity)</code> give <code class="language-plaintext highlighter-rouge">x</code>?</p>
  </li>
  <li>
    <p>Do I care about order?<br />
If I do, am I doing anything that changes encounter order?</p>
  </li>
</ol>

<p>If the answer to 1 and 2 is yes, <code class="language-plaintext highlighter-rouge">reduce</code> is usually safe, even in parallel.<br />
If 1 or 2 fails, you either accept the weirdness, or you avoid <code class="language-plaintext highlighter-rouge">parallelStream</code> and regrouping.</p>

<hr />

<p>Every <code class="language-plaintext highlighter-rouge">reduce</code> you write is a small promise.</p>

<p>You are telling the runtime:</p>

<ol>
  <li>Here is how to combine two partial results.</li>
  <li>Here is the neutral element that represents “no information yet”.</li>
</ol>

<p>If that promise matches reality, you get predictable, parallel friendly code.<br />
If it does not, you get ghosts: bugs that only appear under load, only with parallel streams, only with certain sizes of input.</p>

<p>Thinking in terms of associativity and identity is not about being fancy. It is just a way to make that promise explicit in your own head, instead of leaving it as “whatever this lambda does”.</p>

<p>Once you start looking at your own code through that lens, you will find that a surprising amount of what you do every day is already algebra. You were just calling it “business logic”.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Computer Science&quot;, &quot;Software Engineering&quot;, &quot;Technology&quot;, &quot;Series 4 - Floating Point Without Tears&quot;]" /><category term="computer-science" /><category term="software" /><category term="technology" /><summary type="html"><![CDATA[A practical look at associativity, identity, and folding in Java Streams, and why some reduce calls behave nicely while others explode in surprising ways.]]></summary></entry><entry><title type="html">Either This Or That - Why I Wanted Disjunctive Types In Java</title><link href="https://systemhalted.in/2025/11/25/disjuntive-types/" rel="alternate" type="text/html" title="Either This Or That - Why I Wanted Disjunctive Types In Java" /><published>2025-11-25T00:00:00+00:00</published><updated>2025-11-25T00:00:00+00:00</updated><id>https://systemhalted.in/2025/11/25/disjuntive-types</id><content type="html" xml:base="https://systemhalted.in/2025/11/25/disjuntive-types/"><![CDATA[<p>A few years ago at work, while hacking on a parser and analyser, I realised I needed something my language did not give me: disjunctive types.</p>

<p>Java did not have it.<br />
Kotlin did not have it.<br />
Scala did, in the form of <code class="language-plaintext highlighter-rouge">Either</code>.</p>

<p>I found <code class="language-plaintext highlighter-rouge">Either</code> while searching through Scala docs and it felt exactly right for the problem in front of me. Simple idea, huge leverage. That sent me down the path of thinking about what disjunctive types really are and why I want them in my everyday Java code.</p>

<hr />
<p><strong>TL;DR</strong></p>

<p>You can treat “either this or that” as a <em>first-class</em> thing in Java today:</p>

<ul>
  <li>For <strong>“value or error”</strong> results, define a small <code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> type (a home-grown <code class="language-plaintext highlighter-rouge">Either</code>):
    <ul>
      <li>See section <strong>“Making The Disjunction Explicit: A <code class="language-plaintext highlighter-rouge">Result</code> Type”</strong>.</li>
      <li>Change methods like <code class="language-plaintext highlighter-rouge">Ast parse(String)</code> or <code class="language-plaintext highlighter-rouge">Optional&lt;Ast&gt; parse(...)</code> into<br />
<code class="language-plaintext highlighter-rouge">Result&lt;ParseError, Ast&gt; parse(String input)</code>.</li>
      <li>Callers are now <em>forced</em> by the compiler to handle both success and failure.</li>
    </ul>
  </li>
  <li>For <strong>ASTs and node kinds</strong>, use <strong>sealed hierarchies</strong> as N-way disjunctive types:
    <ul>
      <li>See section <strong>“Disjunctive AST Nodes: An N-Way Either”</strong>.</li>
      <li>Model your tree as:<br />
<code class="language-plaintext highlighter-rouge">sealed interface AstNode permits PackageNode, FunctionNode, StoredProcNode, ...</code></li>
      <li>Traversals return <code class="language-plaintext highlighter-rouge">AstNode</code> and pattern matching becomes exhaustive and honest.</li>
    </ul>
  </li>
  <li>Use the tools where they fit:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> → “T or nothing” (absence is the <em>only</em> alternative).</li>
      <li><code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> / <code class="language-plaintext highlighter-rouge">Either&lt;L, R&gt;</code> → “this meaningful thing or that meaningful thing”.</li>
      <li>Sealed hierarchies → “one of these shapes, and the compiler knows all of them”.</li>
    </ul>
  </li>
</ul>

<p>If a method’s real contract is “either this or that”, this post shows you exactly how to:</p>
<ol>
  <li>Encode that as a <code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> (for outcomes), and</li>
  <li>Encode it as a sealed interface hierarchy (for AST/node shapes),</li>
</ol>

<p>so the type system finally tells the same story you do in your head.</p>

<hr />

<h2 id="where-my-idea-of-disjunctive-types-comes-from">Where My Idea Of Disjunctive Types Comes From</h2>

<p>My mental model of disjunctive types comes from logic.</p>

<p>First, think about ordinary disjunction, the familiar logical OR. A disjunction <code class="language-plaintext highlighter-rouge">A ∨ B</code> is true whenever at least one of its arguments is true and both are not simultaneously false.</p>

<p>You can write the truth table like this:</p>

<table>
  <thead>
    <tr>
      <th>A</th>
      <th>B</th>
      <th>A ∨ B</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <td>0</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

<p>This version is often called inclusive disjunction, because the case where both <code class="language-plaintext highlighter-rouge">A</code> and <code class="language-plaintext highlighter-rouge">B</code> are true still counts as true.</p>

<p>There is another flavour: exclusive disjunction. Here the result is true only when the two arguments differ. In boolean logic this is the XOR gate, usually written as <code class="language-plaintext highlighter-rouge">A ⊕ B</code>.</p>

<table>
  <thead>
    <tr>
      <th>A</th>
      <th>B</th>
      <th>A ⊕ B</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <td>0</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>1</td>
      <td>0</td>
    </tr>
  </tbody>
</table>

<p>This second table matches how I think about disjunctive types in programming languages. In plain English it is the phrase “either this or that”. A value of such a type holds one variant or the other, but not both at the same time.</p>

<hr />

<h2 id="conjunctive-types-and-their-limits">Conjunctive Types And Their Limits</h2>

<p>Most of the time, existing data structures are enough.</p>

<p>If I want to group several fields together, I can define a record, a data class, or a POJO. These are conjunctive types: they say “you get this and that and that”.</p>

<p>For example, if I want a result that always includes both a status and a payload, a simple class like this works fine:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">ResultWithStatus</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Status</span> <span class="n">status</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Payload</span> <span class="n">payload</span><span class="o">;</span>

    <span class="kd">public</span> <span class="nf">ResultWithStatus</span><span class="o">(</span><span class="nc">Status</span> <span class="n">status</span><span class="o">,</span> <span class="nc">Payload</span> <span class="n">payload</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">status</span> <span class="o">=</span> <span class="n">status</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">payload</span> <span class="o">=</span> <span class="n">payload</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Status</span> <span class="nf">status</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">status</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Payload</span> <span class="nf">payload</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">payload</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Here the idea really is “status and payload together”, so a conjunction feels natural.</p>

<p>There are situations where this does not reflect the intent.</p>

<p>Sometimes a method should return one of two different shapes of data. A very common example is a method that either returns a successful result or an error description.</p>

<p>In that case a pure conjunction feels awkward. I can create a wrapper object that has both fields and then abuse <code class="language-plaintext highlighter-rouge">null</code> for whichever field is absent at the moment:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">BadResult</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Payload</span> <span class="n">payload</span><span class="o">;</span>  <span class="c1">// null when there is an error</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Error</span> <span class="n">error</span><span class="o">;</span>      <span class="c1">// null when there is a payload</span>

    <span class="kd">public</span> <span class="nf">BadResult</span><span class="o">(</span><span class="nc">Payload</span> <span class="n">payload</span><span class="o">,</span> <span class="nc">Error</span> <span class="n">error</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">payload</span> <span class="o">=</span> <span class="n">payload</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">error</span> <span class="o">=</span> <span class="n">error</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Payload</span> <span class="nf">payload</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">payload</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Error</span> <span class="nf">error</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">error</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>The type says “payload and error”, but the runtime behaviour says “either payload or error”. The compiler cannot help here. Nothing stops me from building a value that has both fields non null or both null.</p>

<p>What I really want is a type that expresses the “either this or that” constraint directly.</p>

<hr />

<h2 id="enter-disjunctive-types">Enter Disjunctive Types</h2>

<p>This is where disjunctive types become interesting. A typical example in functional languages is something like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="n">sealed</span> <span class="n">trait</span> <span class="nc">Either</span><span class="o">[+</span><span class="no">A</span><span class="o">,</span> <span class="o">+</span><span class="no">B</span><span class="o">]</span>
<span class="kd">final</span> <span class="k">case</span> <span class="kd">class</span> <span class="nc">Left</span><span class="o">[</span><span class="no">A</span><span class="o">](</span><span class="nl">value:</span> <span class="no">A</span><span class="o">)</span> <span class="kd">extends</span> <span class="nc">Either</span><span class="o">[</span><span class="no">A</span><span class="o">,</span> <span class="nc">Nothing</span><span class="o">]</span>
<span class="kd">final</span> <span class="k">case</span> <span class="kd">class</span> <span class="nc">Right</span><span class="o">[</span><span class="no">B</span><span class="o">](</span><span class="nl">value:</span> <span class="no">B</span><span class="o">)</span> <span class="kd">extends</span> <span class="nc">Either</span><span class="o">[</span><span class="nc">Nothing</span><span class="o">,</span> <span class="no">B</span><span class="o">]</span></code></pre></figure>

<p>A value of type <code class="language-plaintext highlighter-rouge">Either[A, B]</code> is always either a <code class="language-plaintext highlighter-rouge">Left[A]</code> or a <code class="language-plaintext highlighter-rouge">Right[B]</code>, never both at once. That mirrors the exclusive disjunction table from earlier.</p>

<p>In a language like Scala, returning</p>

<figure class="highlight"><pre><code class="language-scala" data-lang="scala">    <span class="k">def</span> <span class="nf">parse</span><span class="o">(</span><span class="n">input</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span><span class="k">:</span> <span class="kt">Either</span><span class="o">[</span><span class="kt">ParseError</span>, <span class="kt">Ast</span><span class="o">]</span></code></pre></figure>

<p>is completely natural. Callers are forced to handle both cases. Pattern matching makes the intent very clear:</p>

<figure class="highlight"><pre><code class="language-scala" data-lang="scala">    <span class="nf">parse</span><span class="o">(</span><span class="n">source</span><span class="o">)</span> <span class="k">match</span> <span class="o">{</span>
      <span class="k">case</span> <span class="nc">Left</span><span class="o">(</span><span class="n">error</span><span class="o">)</span>  <span class="k">=&gt;</span> <span class="nf">log</span><span class="o">(</span><span class="n">error</span><span class="o">)</span>
      <span class="k">case</span> <span class="nc">Right</span><span class="o">(</span><span class="n">ast</span><span class="o">)</span>   <span class="k">=&gt;</span> <span class="nf">evaluate</span><span class="o">(</span><span class="n">ast</span><span class="o">)</span>
    <span class="o">}</span></code></pre></figure>

<p>No nulls. No dummy wrapper objects. The type itself documents the contract of the method.</p>

<hr />

<h2 id="what-about-optional-in-java">What About <code class="language-plaintext highlighter-rouge">Optional</code> In Java?</h2>

<p>As soon as you talk about “maybe this, maybe that” in Java, <code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> shows up in the conversation.</p>

<p><code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> is useful, but it solves a weaker problem.</p>

<p>In type-theory style shorthand you can think of it as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Optional&lt;T&gt; ≈ Either&lt;Unit, T&gt;
</code></pre></div></div>

<p>which reads as “either there is nothing interesting here, or there is a <code class="language-plaintext highlighter-rouge">T</code>”. The second branch of the disjunction is just absence.</p>

<p>The set of all possible values for <code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> is</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>`Optional⟨T⟩ = {None} ∪ {Some(t) | t ∈ T}` 
</code></pre></div></div>

<p>That makes <code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> perfect for things like map lookups:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">Value</span><span class="o">&gt;</span> <span class="n">maybeValue</span> <span class="o">=</span> <span class="nc">Optional</span><span class="o">.</span><span class="na">ofNullable</span><span class="o">(</span><span class="n">map</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">key</span><span class="o">));</span></code></pre></figure>

<p>Sometimes the key exists, sometimes it does not. The “other side” of the result is simply “no value”.</p>

<p>Now look at the parser example again. If I write:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">Ast</span><span class="o">&gt;</span> <span class="nf">parse</span><span class="o">(</span><span class="nc">String</span> <span class="n">input</span><span class="o">);</span></code></pre></figure>

<p>then an empty <code class="language-plaintext highlighter-rouge">Optional</code> only tells me that parsing failed. It does not tell me why it failed. All the interesting information about the error has to live somewhere else: logs, exceptions, some side channel.</p>

<p>This is not what I want for the <code class="language-plaintext highlighter-rouge">parse</code> method. The contract of the method is not “Ast or nothing”. The real contract is “either a <code class="language-plaintext highlighter-rouge">ParseError</code>, or an <code class="language-plaintext highlighter-rouge">Ast</code>”.</p>

<p>That is a different shape altogether:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="c1">// Conceptual, not real Java</span>
    <span class="nc">Either</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="nf">parse</span><span class="o">(</span><span class="nc">String</span> <span class="n">input</span><span class="o">);</span></code></pre></figure>

<p>Here both branches are meaningful. The “left” side carries structured error data, not a vague absence. The caller has to consider both cases, and the type system helps enforce that.</p>

<p>So the distinction looks like this:</p>

<blockquote>
  <p>Use <code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> when the alternative is “no value”.<br />
Use <code class="language-plaintext highlighter-rouge">Either&lt;A, B&gt;</code> when the alternative is “a different, meaningful value”.</p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">Optional</code> is still valuable. It cleans up a lot of cases where we used to throw around naked nulls. It just does not replace a genuine disjunctive type where both branches have real content.</p>

<hr />

<h2 id="how-do-you-handle-this-in-java-today">How Do You Handle This In Java Today?</h2>

<p>Once you see that you want “either this or that” in the type system, the next question is obvious: what can you actually do in Java right now?</p>

<h3 id="exceptions-the-classic-java-way">Exceptions: The Classic Java Way</h3>

<p>The traditional Java approach is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Ast parse(String input) throws ParseException
</code></pre></div></div>

<p>On success you get an <code class="language-plaintext highlighter-rouge">Ast</code>. On failure you get a thrown <code class="language-plaintext highlighter-rouge">ParseException</code>.</p>

<p>This has some clear advantages. It is familiar to Java developers and the error can carry rich data, stack trace, nested causes. The downside is that the control flow is invisible in the type. The method signature looks like “returns <code class="language-plaintext highlighter-rouge">Ast</code>”, but semantically it is “returns <code class="language-plaintext highlighter-rouge">Ast</code> or blows up”.</p>

<p>You also get the whole checked versus unchecked exception debate, and callers can easily forget to handle failures or accidentally swallow exceptions.</p>

<p>Exceptions are one way of expressing a disjunction in Java, but they live outside the return type.</p>

<h3 id="making-the-disjunction-explicit-a-result-type">Making The Disjunction Explicit: A <code class="language-plaintext highlighter-rouge">Result</code> Type</h3>

<p>You can instead model the disjunction as data in the type system.</p>

<p>With modern Java, especially with sealed interfaces and records, this is not too painful. For Java 17 and above:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="n">sealed</span> <span class="kd">interface</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span>
        <span class="n">permits</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Ok</span><span class="o">,</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Err</span> <span class="o">{</span>

    <span class="n">record</span> <span class="nc">Ok</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;(</span><span class="no">T</span> <span class="n">value</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span> <span class="o">}</span>

    <span class="n">record</span> <span class="nc">Err</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;(</span><span class="no">E</span> <span class="n">error</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span> <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Your parser then becomes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Result&lt;ParseError, Ast&gt; parse(String input);
</code></pre></div></div>

<p>Using it with pattern matching for <code class="language-plaintext highlighter-rouge">switch</code>:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nc">Result</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">parse</span><span class="o">(</span><span class="n">source</span><span class="o">);</span>

<span class="k">switch</span> <span class="o">(</span><span class="n">result</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">case</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Ok</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="n">ok</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="nc">Ast</span> <span class="n">ast</span> <span class="o">=</span> <span class="n">ok</span><span class="o">.</span><span class="na">value</span><span class="o">();</span>
        <span class="n">evaluate</span><span class="o">(</span><span class="n">ast</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">case</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Err</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="n">err</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">(</span><span class="n">err</span><span class="o">.</span><span class="na">error</span><span class="o">());</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></figure>

<p>Now the disjunction is right there in the signature. No nulls. No surprise exceptions. The compiler forces you to think about both branches.</p>

<p>If you are not on a sealed-types Java yet, you can do a simpler interface plus nested classes:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="kd">public</span> <span class="kd">interface</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
      <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Ok</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="kd">implements</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
          <span class="kd">private</span> <span class="kd">final</span> <span class="no">T</span> <span class="n">value</span><span class="o">;</span>
          <span class="kd">public</span> <span class="nf">Ok</span><span class="o">(</span><span class="no">T</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
              <span class="k">this</span><span class="o">.</span><span class="na">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
          <span class="o">}</span>
          <span class="kd">public</span> <span class="no">T</span> <span class="nf">value</span><span class="o">()</span> <span class="o">{</span>
              <span class="k">return</span> <span class="n">value</span><span class="o">;</span>
          <span class="o">}</span>
      <span class="o">}</span>
      
      <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Err</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="kd">implements</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="o">{</span>
          <span class="kd">private</span> <span class="kd">final</span> <span class="no">E</span> <span class="n">error</span><span class="o">;</span>
          <span class="kd">public</span> <span class="nf">Err</span><span class="o">(</span><span class="no">E</span> <span class="n">error</span><span class="o">)</span> <span class="o">{</span>
              <span class="k">this</span><span class="o">.</span><span class="na">error</span> <span class="o">=</span> <span class="n">error</span><span class="o">;</span>
          <span class="o">}</span>
          <span class="kd">public</span> <span class="no">E</span> <span class="nf">error</span><span class="o">()</span> <span class="o">{</span>
              <span class="k">return</span> <span class="n">error</span><span class="o">;</span>
          <span class="o">}</span>
      <span class="o">}</span>
   <span class="o">}</span></code></pre></figure>

<p>At this point you have your own mini-<code class="language-plaintext highlighter-rouge">Either</code> in Java.</p>

<p>Now you can use it like:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">   <span class="kd">public</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="nf">parse</span><span class="o">(</span><span class="nc">String</span> <span class="n">input</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">try</span> <span class="o">{</span>
            <span class="nc">Ast</span> <span class="n">ast</span> <span class="o">=</span> <span class="n">realParse</span><span class="o">(</span><span class="n">input</span><span class="o">);</span> <span class="c1">// imagine this may throw ParseException</span>
            <span class="k">return</span> <span class="k">new</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Ok</span><span class="o">&lt;&gt;(</span><span class="n">ast</span><span class="o">);</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">ParseException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">return</span> <span class="k">new</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Err</span><span class="o">&lt;&gt;(</span><span class="k">new</span> <span class="nc">ParseError</span><span class="o">(</span><span class="n">e</span><span class="o">.</span><span class="na">getMessage</span><span class="o">()));</span>
        <span class="o">}</span>
   <span class="o">}</span></code></pre></figure>

<p>The calling code is then forced to check the result, for example, using ugly <code class="language-plaintext highlighter-rouge">instanceOf</code> :</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">     <span class="nc">Result</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">parse</span><span class="o">(</span><span class="n">source</span><span class="o">);</span>

    <span class="k">if</span> <span class="o">(</span><span class="n">result</span> <span class="k">instanceof</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Ok</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="n">ok</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Ast</span> <span class="n">ast</span> <span class="o">=</span> <span class="n">ok</span><span class="o">.</span><span class="na">value</span><span class="o">();</span>
        <span class="n">evaluate</span><span class="o">(</span><span class="n">ast</span><span class="o">);</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">result</span> <span class="k">instanceof</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Err</span><span class="o">&lt;</span><span class="nc">ParseError</span><span class="o">,</span> <span class="nc">Ast</span><span class="o">&gt;</span> <span class="n">err</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">ParseError</span> <span class="n">error</span> <span class="o">=</span> <span class="n">err</span><span class="o">.</span><span class="na">error</span><span class="o">();</span>
        <span class="n">log</span><span class="o">(</span><span class="n">error</span><span class="o">);</span>
    </code></pre></figure>

<p>You can hate the verbosity of <code class="language-plaintext highlighter-rouge">instanceof</code>, but at least the type system is no longer lying about the fact that there are two meaningful branches.</p>

<hr />

<h2 id="disjunctive-ast-nodes-an-n-way-either">Disjunctive AST Nodes: An N-Way Either</h2>

<p>In many real parsers, the “either this or that” situation is not just success versus error. Sometimes you are walking an abstract syntax tree (AST) and the node you are visiting could be one of several meaningful shapes.</p>

<p>For example, when traversing a PL/SQL file, you might encounter:</p>

<ul>
  <li>a package</li>
  <li>a function</li>
  <li>a stored procedure</li>
  <li>or some other declaration further down the AST</li>
</ul>

<p>Conceptually, that return type is not “a function and a stored proc and a package”. It is “either a package, or a function, or a stored proc, or something else”.</p>

<p>In Java 17+, the cleanest way to express this is as a sealed hierarchy. The AST node type itself becomes a multi-way disjunctive type:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="kd">public</span> <span class="n">sealed</span> <span class="kd">interface</span> <span class="nc">AstNode</span>
            <span class="n">permits</span> <span class="nc">PackageNode</span><span class="o">,</span> <span class="nc">FunctionNode</span><span class="o">,</span> <span class="nc">StoredProcNode</span><span class="o">,</span> <span class="nc">OtherNode</span> <span class="o">{</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">PackageNode</span> <span class="kd">implements</span> <span class="nc">AstNode</span> <span class="o">{</span>
        <span class="c1">// nested declarations, children, etc.</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">FunctionNode</span> <span class="kd">implements</span> <span class="nc">AstNode</span> <span class="o">{</span>
        <span class="c1">// function-specific fields</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">StoredProcNode</span> <span class="kd">implements</span> <span class="nc">AstNode</span> <span class="o">{</span>
        <span class="c1">// stored-procedure-specific fields</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">OtherNode</span> <span class="kd">implements</span> <span class="nc">AstNode</span> <span class="o">{</span>
        <span class="c1">// whatever other construct you have</span>
    <span class="o">}</span></code></pre></figure>

<p>Now a traversal method can simply say:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="nc">AstNode</span> <span class="nf">visit</span><span class="o">(</span><span class="nc">NodeContext</span> <span class="n">ctx</span><span class="o">)</span> <span class="o">{</span>
        <span class="c1">// logic that returns one of the concrete node types</span>
    <span class="o">}</span></code></pre></figure>

<p>And the consumer can handle all the possibilities with pattern matching:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="nc">AstNode</span> <span class="n">node</span> <span class="o">=</span> <span class="n">visit</span><span class="o">(</span><span class="n">ctx</span><span class="o">);</span>

    <span class="k">switch</span> <span class="o">(</span><span class="n">node</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nc">PackageNode</span> <span class="n">pkg</span>      <span class="o">-&gt;</span> <span class="n">handlePackage</span><span class="o">(</span><span class="n">pkg</span><span class="o">);</span>
        <span class="k">case</span> <span class="nc">FunctionNode</span> <span class="n">fn</span>      <span class="o">-&gt;</span> <span class="n">handleFunction</span><span class="o">(</span><span class="n">fn</span><span class="o">);</span>
        <span class="k">case</span> <span class="nc">StoredProcNode</span> <span class="n">sp</span>    <span class="o">-&gt;</span> <span class="n">handleStoredProc</span><span class="o">(</span><span class="n">sp</span><span class="o">);</span>
        <span class="k">case</span> <span class="nc">OtherNode</span> <span class="n">other</span>      <span class="o">-&gt;</span> <span class="n">handleOther</span><span class="o">(</span><span class="n">other</span><span class="o">);</span>
    <span class="o">}</span></code></pre></figure>

<p>That <code class="language-plaintext highlighter-rouge">AstNode</code> interface is an N-ary disjunctive type: “either a function, or a stored proc, or a package, or …”. If you want to stack this with success/failure, you can even combine it:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Result&lt;ParseError, AstNode&gt; visit(NodeContext ctx);
</code></pre></div></div>

<p>So you end up with:</p>

<ul>
  <li>outer disjunction: <code class="language-plaintext highlighter-rouge">Result&lt;Error, Value&gt;</code> (success vs failure)</li>
  <li>inner disjunction: <code class="language-plaintext highlighter-rouge">AstNode</code> being one of <code class="language-plaintext highlighter-rouge">{PackageNode, FunctionNode, StoredProcNode, OtherNode, …}</code></li>
</ul>

<p>This is exactly the kind of situation where making the alternatives explicit in the type system keeps the code honest.</p>

<hr />

<h2 id="where-optional-still-fits">Where <code class="language-plaintext highlighter-rouge">Optional</code> Still Fits</h2>

<p><code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> still has a clear niche: it fits when the alternative branch is “nothing to see here”.</p>

<p>Typical cases:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Optional&lt;User&gt; findById(String id);

Optional&lt;String&gt; findHeader(String name);
</code></pre></div></div>

<p>These really are “value or no value” cases. There is no error object with rich semantics that you want to propagate. Once you have a meaningful error domain, you are back in <code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> or some other disjunctive type.</p>

<p>So one way to think about the layering is:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> for “present or absent”.</li>
  <li><code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> (or <code class="language-plaintext highlighter-rouge">Either&lt;A, B&gt;</code>-style types) for “this meaningful thing or that meaningful thing”.</li>
  <li>Exceptions only for genuinely exceptional failures: bugs, I/O issues, broken invariants.</li>
</ul>

<hr />

<h2 id="mixing-exceptions-and-results">Mixing Exceptions And Results</h2>

<p>You do not have to pick a single tool forever.</p>

<p>A pragmatic pattern looks like this:</p>

<ul>
  <li>In lower-level logic and domain code, return <code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> (or another explicit disjunctive type) to represent expected failures.</li>
  <li>At the edges of the system, such as HTTP controllers or CLI handlers, translate <code class="language-plaintext highlighter-rouge">Result</code> into HTTP responses or user messages.</li>
  <li>Throw exceptions only for truly unexpected situations, such as corrupted state or impossible code paths.</li>
</ul>

<p>That way you use disjunctive types for expected control flow, and keep exceptions for “this should not have happened”.</p>

<hr />

<h2 id="a-small-step-you-can-take-right-now">A Small Step You Can Take Right Now</h2>

<p>If you want to live this idea in Java code today, you can:</p>

<ol>
  <li>Introduce a tiny <code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code> type as above in a shared utilities module.</li>
  <li>Start by using it in one or two flows, such as parsing or service calls.</li>
  <li>Add helper methods like <code class="language-plaintext highlighter-rouge">map</code>, <code class="language-plaintext highlighter-rouge">flatMap</code>, and <code class="language-plaintext highlighter-rouge">fold</code> later if you want a more functional style.</li>
</ol>

<p>With a helper class:</p>

<figure class="highlight"><pre><code class="language-java" data-lang="java">    <span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Results</span> <span class="o">{</span>

        <span class="kd">private</span> <span class="nf">Results</span><span class="o">()</span> <span class="o">{</span> <span class="o">}</span>

        <span class="kd">public</span> <span class="kd">static</span> <span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">,</span> <span class="no">U</span><span class="o">&gt;</span> <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">U</span><span class="o">&gt;</span> <span class="nf">map</span><span class="o">(</span>
                <span class="nc">Result</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="n">result</span><span class="o">,</span>
                <span class="n">java</span><span class="o">.</span><span class="na">util</span><span class="o">.</span><span class="na">function</span><span class="o">.</span><span class="na">Function</span><span class="o">&lt;</span><span class="no">T</span><span class="o">,</span> <span class="no">U</span><span class="o">&gt;</span> <span class="n">f</span>
        <span class="o">)</span> <span class="o">{</span>
            <span class="k">if</span> <span class="o">(</span><span class="n">result</span> <span class="k">instanceof</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Ok</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="n">ok</span><span class="o">)</span> <span class="o">{</span>
                <span class="k">return</span> <span class="k">new</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Ok</span><span class="o">&lt;&gt;(</span><span class="n">f</span><span class="o">.</span><span class="na">apply</span><span class="o">(</span><span class="n">ok</span><span class="o">.</span><span class="na">value</span><span class="o">()));</span>
            <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">result</span> <span class="k">instanceof</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Err</span><span class="o">&lt;</span><span class="no">E</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="n">err</span><span class="o">)</span> <span class="o">{</span>
                <span class="k">return</span> <span class="k">new</span> <span class="nc">Result</span><span class="o">.</span><span class="na">Err</span><span class="o">&lt;&gt;(</span><span class="n">err</span><span class="o">.</span><span class="na">error</span><span class="o">());</span>
            <span class="o">}</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalStateException</span><span class="o">(</span><span class="s">"Unknown Result variant"</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span></code></pre></figure>

<p>Once you have that, you can start composing operations without losing error context, all within the type system.</p>

<hr />

<h2 id="closing-thoughts">Closing Thoughts</h2>

<p>In most codebases we lean heavily on “and” types: records, POJOs, data classes that say “this and that and that”. They are great when your domain really is a bundle of things that always travel together.</p>

<p>Disjunctive types live on the other side of that line. They say “either this or that” and force you to acknowledge both branches as first-class citizens. That is what <code class="language-plaintext highlighter-rouge">Either</code>, <code class="language-plaintext highlighter-rouge">Result&lt;E, T&gt;</code>, sealed AST hierarchies, and similar patterns bring to Java: a way to make alternatives part of the type story instead of an afterthought.</p>

<p><code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code> still earns its keep for “value or no value”. Exceptions still matter for “this should never happen”. But when the alternative is a meaningful value – a <code class="language-plaintext highlighter-rouge">ParseError</code>, a <code class="language-plaintext highlighter-rouge">ValidationError</code>, a different AST node type – it is worth promoting that alternative into the type system and letting the compiler nag you into handling it.</p>

<p>Once you start doing that, a lot of familiar patterns begin to look different. Classes full of nullable fields, APIs that quietly throw, methods whose real contract lives in Javadoc rather than in types – all of them start to feel like places where a missing “either this or that” is hiding in plain sight.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Computer Science&quot;, &quot;Software Engineering&quot;, &quot;Technology&quot;]" /><category term="computer-science" /><category term="software" /><category term="technology" /><category term="travel" /><summary type="html"><![CDATA[When your Java methods really mean "either this or that" but the type system only says "here’s something…maybe," you’re flying blind. This post walks through using Result types, sealed hierarchies, and a bit of logic-thinking to make those hidden alternatives explicit, so the compiler – not your Javadoc – tells the truth about your code.]]></summary></entry><entry><title type="html">Revolutionizing Global Payments - A Comprehensive Analysis of Real-Time Payment Systems - UPI in India, FedNow in the US, and Similar Interfaces Worldwide</title><link href="https://systemhalted.in/2023/07/25/real-time-payments/" rel="alternate" type="text/html" title="Revolutionizing Global Payments - A Comprehensive Analysis of Real-Time Payment Systems - UPI in India, FedNow in the US, and Similar Interfaces Worldwide" /><published>2023-07-25T00:00:00+00:00</published><updated>2023-07-25T00:00:00+00:00</updated><id>https://systemhalted.in/2023/07/25/real-time-payments</id><content type="html" xml:base="https://systemhalted.in/2023/07/25/real-time-payments/"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Real-time payment systems have emerged as an essential pillar of the digital era, reshaping the financial landscape and providing individuals and businesses with efficient, seamless, and secure transaction capabilities. This comprehensive technical article delves into the evolution and functioning of real-time payment systems, focusing on two prominent examples - the Unified Payments Interface (UPI)<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> in India and the FedNow<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup> standard in the United States. Moreover, we will explore similar systems in other countries, such as the Faster Payments Service (FPS)<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> in the UK, SEPA Instant Credit Transfer (SCT Inst)<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup> in the Eurozone, and PIX<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">6</a></sup> in Brazil. By examining the intricate technical aspects, architecture, and global impact of these real-time payment solutions, this article aims to shed light on their pivotal role in revolutionizing global financial transactions.</p>

<h3 id="1-unified-payments-interface-upi-in-india">1. Unified Payments Interface (UPI) in India</h3>
<h4 id="11-genesis-and-evolution">1.1 Genesis and Evolution</h4>
<p>The Unified Payments Interface (UPI) was a pioneering initiative launched by the National Payments Corporation of India (NPCI) in 2016. Its genesis can be traced back to the Indian government’s vision of promoting a cashless economy and enhancing financial inclusion. Prior to UPI, digital payment systems in India were fragmented and lacked interoperability. UPI aimed to address these challenges by providing a seamless, real-time, and interbank payment solution.</p>

<p>The evolution of UPI has been remarkable. It started with a handful of banks and has now grown to include almost all major banks in the country. Its rapid adoption can be attributed to the convenience it offers to users, allowing them to link multiple bank accounts and perform transactions using a single mobile application.</p>

<h4 id="12-architecture-and-key-components">1.2 Architecture and Key Components</h4>
<p>The architecture of UPI is designed to be simple, scalable, and secure. At its core lies the NPCI’s payment switch, which acts as a central hub for routing transactions between participating banks. When a user initiates a UPI transaction through a mobile app, the payment switch ensures seamless communication between the user’s bank and the recipient’s bank.</p>

<p>Key components of the UPI system include the Virtual Payment Address (VPA), which acts as a unique identifier for users, eliminating the need for sharing sensitive bank details during transactions. Additionally, UPI leverages the Immediate Payment Service (IMPS)<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">7</a></sup> infrastructure for real-time fund transfers, further enhancing its efficiency.</p>

<h4 id="13-real-time-transaction-processing">1.3 Real-Time Transaction Processing</h4>
<p>One of the most significant advantages of UPI is its ability to process transactions in real-time. When a user initiates a payment, it is authorized and settled instantly, reflecting the amount in the recipient’s bank account within seconds. This real-time processing is instrumental in enabling quick and hassle-free payments between individuals and merchants.</p>

<p>The real-time transaction processing has fueled the adoption of UPI for various use cases, including bill payments, merchant transactions, peer-to-peer transfers, and online shopping. Additionally, its integration with other platforms like e-commerce apps and digital wallets has further contributed to its popularity.</p>

<h4 id="14-security-and-authentication">1.4 Security and Authentication</h4>
<p>Given the sensitive nature of financial transactions, UPI places a strong emphasis on security. Each UPI transaction requires two-factor authentication, usually involving a combination of a unique MPIN (Mobile Personal Identification Number) and biometric authentication (fingerprint or face recognition).</p>

<p>Moreover, UPI transactions are secured using end-to-end encryption, safeguarding the confidentiality of user data during transmission. The Virtual Payment Address (VPA)<sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">8</a></sup> acts as a shield, as users need not share their bank account details, reducing the risk of potential cyber frauds.</p>

<h3 id="2-fednow-standard-in-the-united-states">2. FedNow Standard in the United States</h3>
<h4 id="21-the-vision-for-fednow">2.1 The Vision for FedNow</h4>
<p>The Federal Reserve’s vision behind the development of the FedNow standard was to bridge the gap between existing payment systems and meet the growing demand for faster, more inclusive, and efficient payment options in the United States.</p>

<p>Recognizing the need for a ubiquitous real-time payment infrastructure, the Federal Reserve aims to provide businesses and consumers with instantaneous access to funds, enabling near-instantaneous transactions 24/7, including weekends and holidays.</p>

<h4 id="22-technical-architecture-and-infrastructure">2.2 Technical Architecture and Infrastructure</h4>
<p>The technical architecture of FedNow revolves around a secure, resilient, and high-speed payment network. The infrastructure is built to handle a massive volume of transactions securely, while adhering to industry standards and regulations.</p>

<p>The FedNow system operates on a central payment clearing mechanism, allowing participating banks to settle transactions instantly. The system will accommodate a wide range of payment types, including person-to-person (P2P), business-to-business (B2B), and business-to-consumer (B2C) transactions.</p>

<h4 id="23-real-time-settlement">2.3 Real-Time Settlement</h4>
<p>One of the key highlights of FedNow is its ability to provide real-time settlement, ensuring that funds are made available to the recipient’s account immediately after the transaction is initiated. This feature eliminates the need for delayed settlement periods, reducing risks and enhancing liquidity for businesses and individuals.</p>

<p>The real-time settlement capability is poised to revolutionize payment systems in the US, as it offers unprecedented speed and convenience, rivaling the efficiency of cash transactions.</p>

<h4 id="24-advancing-financial-inclusion">2.4 Advancing Financial Inclusion</h4>
<p>FedNow’s 24/7 availability is a significant step towards advancing financial inclusion in the United States. Unlike traditional payment systems, which often operate on limited schedules, FedNow will provide a level playing field for all users, irrespective of their location or economic status.</p>

<p>By offering real-time payment capabilities around the clock, FedNow will enable underserved communities to access financial services without barriers, empowering them with greater control over their finances.</p>

<h3 id="3-similar-interfaces-in-other-countries">3. Similar Interfaces in Other Countries</h3>
<h4 id="31-faster-payments-service-fps-in-the-uk">3.1 Faster Payments Service (FPS) in the UK</h4>
<p>The Faster Payments Service (FPS) in the UK is another noteworthy real-time payment system. Launched in 2008, FPS allows near-instantaneous electronic transfers between UK bank accounts. The system operates 24/7, providing users with the convenience of instant payments at any time.</p>

<p>FPS has played a vital role in transforming the UK’s payments landscape, facilitating faster and secure transactions for individuals and businesses. It has bolstered the growth of mobile banking and digital payments, further reducing the reliance on cash-based transactions.</p>

<h4 id="32-sepa-instant-credit-transfer-sct-inst-in-the-eurozone">3.2 SEPA Instant Credit Transfer (SCT Inst) in the Eurozone</h4>
<p>SEPA Instant Credit Transfer (SCT Inst) was introduced in the Eurozone in 2017, enabling individuals and businesses to transfer euros instantly between participating banks. SCT Inst operates on a pan-European level, fostering cross-border transactions with speed and efficiency.</p>

<p>The adoption of SCT Inst has been steadily growing, promoting seamless and borderless payments within the Eurozone. It has also opened up new opportunities for businesses to serve customers in different European countries without the constraints of delayed payments.</p>

<h4 id="33-pix-in-brazil">3.3 PIX in Brazil</h4>
<p>PIX, launched in Brazil in 2020, is a game-changer in the country’s payment landscape. This real-time payment system operates 24/7, allowing individuals and businesses to make instant transfers, payments, and purchases.</p>

<p>PIX has been widely embraced in Brazil, rapidly becoming the preferred method of payment for various transactions, including e-commerce, bill payments, and even peer-to-peer transfers. Its adoption has been accelerated by its integration into popular apps and digital platforms.</p>

<h3 id="4-global-impact-and-future-outlook">4. Global Impact and Future Outlook</h3>
<h4 id="41-financial-inclusion-and-economic-growth">4.1 Financial Inclusion and Economic Growth</h4>
<p>Real-time payment systems have had a profound impact on advancing financial inclusion. By providing instant and accessible financial services, these systems empower underserved populations to participate actively in the formal economy, stimulating economic growth and reducing income inequality.</p>

<p>The widespread adoption of real-time payment systems has also led to increased consumer spending and business efficiency, further fueling economic development.</p>

<h4 id="42-interoperability-and-cross-border-transactions">4.2 Interoperability and Cross-Border Transactions</h4>
<p>As real-time payment systems continue to gain traction worldwide, the potential for enhanced interoperability and seamless cross-border transactions becomes more apparent. With the establishment of common standards and protocols, international payments could be executed instantly, overcoming the complexities and delays associated with traditional cross-border transfers.</p>

<p>The interoperability of real-time payment systems is expected to facilitate smoother global commerce, benefiting businesses engaged in international trade and fostering economic cooperation between nations.</p>

<h4 id="43-technological-challenges-and-security-considerations">4.3 Technological Challenges and Security Considerations</h4>
<p>The development and implementation of real-time payment systems come with their own set of challenges. One of the key challenges is ensuring robust and secure infrastructures that can handle a massive volume of transactions without compromising on reliability.</p>

<p>Addressing these challenges requires continuous advancements in cybersecurity measures, fraud detection systems, and data encryption protocols. Additionally, collaboration between financial institutions, regulators, and technology providers is crucial in developing standardized security practices and frameworks to safeguard against cyber threats.</p>

<p>Looking ahead, real-time payment systems will continue to evolve, incorporating cutting-edge technologies like blockchain and artificial intelligence to enhance efficiency and security further. However, the collaborative effort to stay one step ahead of potential threats remains critical to maintaining the integrity of these systems.</p>

<h2 id="conclusion">Conclusion</h2>
<p>The world of real-time payment systems is witnessing an unprecedented revolution, reshaping the financial landscape and redefining the way individuals and businesses conduct transactions. Unified Payments Interface (UPI) in India and the emerging FedNow standard in the United States stand as testament to the power of technology in fostering a seamless and secure payment ecosystem.</p>

<p>Additionally, the global adoption of similar real-time payment interfaces, such as the Faster Payments Service (FPS) in the UK, SEPA Instant Credit Transfer (SCT Inst) in the Eurozone, and PIX in Brazil, exemplifies the growing demand for efficient and inclusive payment solutions worldwide.</p>

<p>As real-time payment systems continue to expand, their positive impact on financial inclusion, economic growth, and cross-border transactions is undeniable. Nevertheless, addressing technological challenges and ensuring robust security measures will be essential in maintaining the trust of users and further propelling the growth of these systems.</p>

<p>The future outlook for real-time payment systems is promising, with potential advancements in interoperability, global connectivity, and security protocols. As technology continues to evolve, these systems will play an increasingly pivotal role in shaping the future of global financial transactions, propelling us toward a cashless, interconnected, and inclusive world.</p>

<p><em>References</em></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>https://www.npci.org.in/what-we-do/upi/product-overview <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>https://en.wikipedia.org/wiki/Unified_Payments_Interface <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>https://www.frbservices.org/financial-services/fednow <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>https://en.wikipedia.org/wiki/Faster_Payments <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p>https://www.europeanpaymentscouncil.eu/what-we-do/sepa-instant-credit-transfer <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:6" role="doc-endnote">
      <p>https://www.bcb.gov.br/en/financialstability/pix_en <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:7" role="doc-endnote">
      <p>https://www.npci.org.in/what-we-do/imps/product-overview <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:8" role="doc-endnote">
      <p>https://paytm.com/blog/payments/upi/virtual-payment-address-know-how-to-create-vpa-benefits/ <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Society &amp; Economy&quot;, &quot;Technology&quot;, &quot;Politics &amp; Governance&quot;]" /><category term="society" /><category term="economy" /><category term="technology" /><category term="politics" /><category term="movie-review" /><category term="travel" /><category term="india" /><category term="united-states" /><summary type="html"><![CDATA[Real-time payment systems have become the backbone of modern economies, offering rapid and secure transactions for individuals and businesses alike. This in-depth technical article explores the transformative power of real-time payment systems, with a focus on two major players - Unified Payments Interface (UPI) in India and the emerging FedNow standard in the United States. Additionally, we analyze similar interfaces from around the world, including the Faster Payments Service (FPS) in the UK, SEPA Instant Credit Transfer (SCT Inst) in the Eurozone, and PIX in Brazil. Through an in-depth examination of each system’s development, architecture, features, and global impact, this article aims to provide readers with a comprehensive understanding of the rapidly evolving landscape of real-time payment solutions.]]></summary></entry><entry><title type="html">The Power of Transparency in Leadership - Lessons from Experience</title><link href="https://systemhalted.in/2023/07/24/transparency-in-leadership/" rel="alternate" type="text/html" title="The Power of Transparency in Leadership - Lessons from Experience" /><published>2023-07-24T00:00:00+00:00</published><updated>2023-07-24T00:00:00+00:00</updated><id>https://systemhalted.in/2023/07/24/transparency-in-leadership</id><content type="html" xml:base="https://systemhalted.in/2023/07/24/transparency-in-leadership/"><![CDATA[<p>As a manager, I’ve always believed in the fundamental importance of open and transparent communication with my team. I recognize that, as human beings, we all have our moments of forgetfulness, and I’m no exception. Therefore, I make it a point to be as forthcoming as professionally possible with my team, acknowledging that I might not remember to share everything with them, but I’m dedicated to improving this aspect continuously.</p>

<h2 id="embracing-transparency-as-a-core-value">Embracing Transparency as a Core Value</h2>

<p>Transparency is not just a buzzword for me; it’s a core value that I hold dearly. I firmly believe that creating a culture of openness and trust leads to greater collaboration and empowers the team to perform at their best. By being honest about successes and challenges, we can collectively find solutions and grow together.</p>

<p>In my years as a manager, I have witnessed firsthand the positive impact of transparency on team dynamics and overall productivity. When team members feel that their manager is transparent, they are more likely to reciprocate with their own openness, fostering an environment of mutual respect and understanding.</p>

<h2 id="expecting-transparency-from-above">Expecting Transparency from Above</h2>

<p>But this isn’t just a one-way street. In my journey as a manager, I’ve always expected the same level of transparency from my own superiors. When important news needs to be shared with the team, I strongly advocate for leaders to inform the team directly. Relying solely on other channels risks creating undercurrents and misunderstandings within the team which hampers the team dynamics. The power of face-to-face communication should never be underestimated.</p>

<p>As a manager, I see myself as a conduit between my team and upper management. It is my responsibility to ensure that vital information is conveyed transparently and effectively. This approach not only strengthens the bond of trust with my team but also sets an example for them to follow in their own interactions with colleagues.</p>

<h2 id="navigating-the-corporate-landscape-with-transparency">Navigating the Corporate Landscape with Transparency</h2>

<p>As we navigate the ever-changing landscape of the corporate world, it’s essential to remember that genuine transparency goes beyond mere lip service. It involves actively fostering an environment where open dialogue is encouraged, and every team member feels comfortable sharing their thoughts and ideas.</p>

<p>Transparency can be challenging, especially in high-stakes situations or when delivering unfavorable news. However, I’ve learned that being transparent about the reasoning behind decisions, even difficult ones, helps team members understand the bigger picture and adapt accordingly.</p>

<h2 id="the-benefits-of-embracing-transparency">The Benefits of Embracing Transparency</h2>

<p>Transparency isn’t always easy, and it requires vulnerability and courage, but the benefits far outweigh the challenges. It builds trust, strengthens relationships, and ultimately leads to a more engaged and motivated team.</p>

<p>When team members feel that their voices are heard and their concerns are taken seriously, they are more likely to take ownership of their work and strive for excellence. Transparency paves the way for constructive feedback, which is invaluable for individual and team growth.</p>

<p>Moreover, transparency can break down silos and foster cross-functional collaboration. When information is shared openly, teams can work together more effectively, leveraging each other’s expertise and talents to achieve common goals.</p>

<h2 id="embracing-transparency-in-personal-and-professional-life">Embracing Transparency in Personal and Professional Life</h2>

<p>Transparency should not be confined to the workplace; it’s a value that extends to all aspects of life. By practicing openness in our personal relationships, we can build deeper connections and foster understanding.</p>

<p>In our professional lives, transparency with clients and stakeholders can lead to stronger partnerships and lasting business relationships. Honest communication builds credibility and enhances the reputation of individuals and organizations alike.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Transparency is a powerful tool in leadership that fosters trust, collaboration, and growth. As a manager, I’ve experienced firsthand how embracing transparency positively impacts team dynamics and overall performance.</p>

<p>By expecting transparency from above and leading by example, I strive to create a culture of openness and mutual respect within my team. Together, we navigate the corporate landscape with transparency as our guiding principle, acknowledging challenges while valuing the numerous benefits it brings.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Personal Essays&quot;]" /><category term="personal" /><category term="opinion" /><category term="leadership" /><summary type="html"><![CDATA[Transparency is a powerful tool in leadership that fosters trust, collaboration, and growth. As a manager, I've experienced firsthand how embracing transparency positively impacts team dynamics and overall performance. By expecting transparency from above and leading by example, I strive to create a culture of openness and mutual respect within my team. Together, we navigate the corporate landscape with transparency as our guiding principle, acknowledging challenges while valuing the numerous benefits it brings.]]></summary></entry><entry><title type="html">Navigating Chaos - Reflecting on India’s Traffic Woes and Empowering Change on India’s Road with AI</title><link href="https://systemhalted.in/2023/06/12/navigating-chaos-indias-traffic-woes/" rel="alternate" type="text/html" title="Navigating Chaos - Reflecting on India’s Traffic Woes and Empowering Change on India’s Road with AI" /><published>2023-06-12T00:00:00+00:00</published><updated>2023-06-12T00:00:00+00:00</updated><id>https://systemhalted.in/2023/06/12/navigating-chaos-indias-traffic-woes</id><content type="html" xml:base="https://systemhalted.in/2023/06/12/navigating-chaos-indias-traffic-woes/"><![CDATA[<h2 id="introduction">Introduction:</h2>
<p>In the bustling streets of India, a chaotic symphony unfolds daily, as vehicles of all shapes and sizes jostle for space. For some, this spectacle is a source of amazement and curiosity, but for others, like myself, it evokes a profound sense of frustration and disappointment, which makes me persistently angry. The disregard for traffic laws, the lack of compassion for fellow travelers, and the pervasive “me-first” attitude have turned our roads into an ocean of malice. In this blog post, we delve into the realities of India’s traffic chaos and explore potential avenues for change.</p>

<h2 id="the-reality-of-chaos">The Reality of Chaos:</h2>
<p>India’s traffic woes are no secret. Roads that resemble a tangled web, lanes that are mere suggestions, and signals treated as inconsequential guidelines paint a vivid picture of disorder. The blatant violation of traffic rules, such as driving on the wrong side of the road without shame, is disheartening, to say the least. In this environment, the needs and safety of others fade into the background, as the individual’s interests take center stage.</p>

<h2 id="collective-karma">Collective Karma:</h2>
<p>While the concept of karma may be subjective and open to interpretation, it is worth contemplating its role in our society. If karma indeed operates, one could argue that our “collective karma” as a nation is submerged in an ocean of malice and contempt for one another. The continuous disregard for traffic laws and the lack of compassion on the roads might be seen as manifestations of this collective karma. However, it is crucial to recognize that not everyone shares this mindset. There are individuals who diligently adhere to traffic rules, embodying a sense of responsibility and consideration.</p>

<h2 id="understanding-the-complexity">Understanding the Complexity:</h2>
<p>To address India’s traffic challenges, we must acknowledge the multifaceted nature of the issue. Factors such as rapid urbanization, inadequate infrastructure, population density, and cultural attitudes towards driving all contribute to the current state of affairs. Changing these deep-rooted problems requires a collective effort from the government, law enforcement agencies, and society as a whole.</p>

<h2 id="embracing-constructive-solutions">Embracing Constructive Solutions:</h2>
<p>Rather than succumbing to despair, it is essential to channel our frustration into constructive actions that pave the way for positive change. Encouraging responsible behavior on the road, educating others about the importance of traffic rules, and supporting initiatives for better traffic management are all steps in the right direction. By focusing on solutions and fostering a sense of responsibility and compassion, we can gradually transform the chaotic landscape into a more orderly and safer environment.</p>

<h3 id="shifting-societal-attitudes">Shifting Societal Attitudes:</h3>
<p>To address India’s traffic problems, we must start by acknowledging that change begins at the societal level. It is imperative to foster a culture that values law and order, compassion, and respect for others. By promoting awareness and education about the importance of following traffic laws, we can sow the seeds of change. Initiatives such as road safety campaigns, community engagement, and school programs can play a pivotal role in instilling a sense of responsibility and accountability.</p>

<h3 id="improving-infrastructure-and-enforcement">Improving Infrastructure and Enforcement:</h3>
<p>Alongside changing attitudes, improvements in infrastructure and enforcement are vital. Adequate road infrastructure, well-designed traffic management systems, and clear signage can contribute to smoother traffic flow. Strengthening law enforcement agencies, ensuring stricter penalties for traffic violations, and implementing technology-driven solutions like AI-based traffic surveillance systems can help deter reckless behavior.</p>

<h3 id="ai-for-traffic-management">AI for Traffic Management:</h3>
<p>Artificial intelligence has the potential to revolutionize traffic management in India. AI-powered systems can analyze real-time data from cameras, sensors, and other sources to identify traffic patterns, congestion hotspots, and areas requiring attention. This data-driven approach enables authorities to make informed decisions about traffic flow optimization, signal timing, and road network improvements. Additionally, AI can help in predicting traffic incidents and suggesting alternative routes to reduce congestion.</p>

<h3 id="smart-traffic-control">Smart Traffic Control:</h3>
<p>AI can be leveraged to develop smart traffic control systems that dynamically adapt to traffic conditions. By using machine learning algorithms, these systems can optimize traffic signal timings based on real-time traffic data, improving the overall flow of vehicles and reducing congestion. AI-enabled traffic control can also enhance pedestrian safety by prioritizing pedestrian crossings during peak hours.</p>

<h3 id="intelligent-transportation-systems">Intelligent Transportation Systems:</h3>
<p>Intelligent Transportation Systems (ITS) powered by AI can enable better management of traffic across various modes of transportation. Integration of AI algorithms in public transportation systems can optimize routes, improve scheduling, and reduce waiting times, enhancing overall efficiency. AI can also facilitate the development of predictive models for traffic forecasting and adaptive traffic management strategies.</p>

<h3 id="collaborative-efforts">Collaborative Efforts:</h3>
<p>Addressing India’s traffic challenges requires collaboration between the government, law enforcement agencies, civil society organizations, and the public. Stakeholders must work together to develop comprehensive strategies that encompass infrastructure development, education, and enforcement. Engaging citizens through participatory initiatives and platforms for feedback can also foster a sense of ownership and collective responsibility. Working together, we can develop AI-driven solutions tailored to the unique needs of Indian roads and traffic conditions. Public participation, feedback mechanisms, and transparency in implementing AI-based systems are crucial to build trust and ensure responsible use of technology.</p>

<h3 id="education-and-empathy">Education and Empathy:</h3>
<p>Education plays a pivotal role in transforming societal attitudes. Incorporating traffic safety education in school curricula, driver training programs, and public awareness campaigns can empower individuals with knowledge and promote responsible behavior. Encouraging empathy and consideration for fellow travelers through public campaigns and initiatives can create a culture of compassion on the roads.</p>

<h2 id="conclusion">Conclusion:</h2>
<p>India’s traffic chaos is a complex challenge that demands our attention and collective effort. While it is disheartening to witness the disregard for traffic laws and the absence of compassion on the roads, it is crucial to recognize the individuals who embody responsible behavior. By reflecting on our individual actions and their potential consequences, we can contribute to positive change. Let us navigate through the chaos with a determination to promote a culture of respect, empathy, and adherence to traffic laws. India’s traffic chaos demands a comprehensive approach that embraces societal change and harnesses the power of AI. By shifting attitudes, improving infrastructure, strengthening enforcement, and leveraging AI for traffic management, we can pave the way for a safer, more efficient, and sustainable transportation system. Let us embrace AI as a tool to empower change, making India’s roads a symbol of order, safety, and harmony. Together, we can drive towards a safer and more harmonious future on India’s roads.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Society &amp; Economy&quot;, &quot;Politics &amp; Governance&quot;]" /><category term="society" /><category term="economy" /><category term="politics" /><category term="travel" /><category term="leadership" /><category term="india" /><summary type="html"><![CDATA[In the bustling streets of India, a chaotic symphony unfolds daily, as vehicles of all shapes and sizes jostle for space. For some, this spectacle is a source of amazement and curiosity, but for others, like myself, it evokes a profound sense of frustration and disappointment, which makes me persistently angry. The disregard for traffic laws, the lack of compassion for fellow travelers, and the pervasive "me-first" attitude have turned our roads into an ocean of malice. In this blog post, we delve into the realities of India's traffic chaos and explore potential avenues for change including use of Artificial Intelligence (AI).]]></summary></entry><entry><title type="html">The Advancements in Technology and Training Methods that have Improved the Performance of Athletes</title><link href="https://systemhalted.in/2023/01/17/technology-training-improved-performance/" rel="alternate" type="text/html" title="The Advancements in Technology and Training Methods that have Improved the Performance of Athletes" /><published>2023-01-17T00:00:00+00:00</published><updated>2023-01-17T00:00:00+00:00</updated><id>https://systemhalted.in/2023/01/17/technology-training-improved-performance</id><content type="html" xml:base="https://systemhalted.in/2023/01/17/technology-training-improved-performance/"><![CDATA[<p>Recently Virat Kohli<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup> scored his 46th ODI<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup> century. Sachin Tendulkar<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup> has scored 100 centuries in all formats with 49 centuries in ODI. Virat has always been compared to Sachin and his recent centuries have re-started the comparison. One contention is that Sachin took 463 ODI matches to score his 49 centuries, while Virat has scored his 46 centuries in just 268 matches.</p>

<p>In this debate, I stipulate that the world of sports has come a long way in the past decade. With advancements in technology and training methods, athletes are now able to push their bodies to new limits and break records that were once thought impossible. From professional athletes to weekend warriors, everyone is benefitting from these technological advancements. In this article, we will explore the ways in which technology and training methods have improved the performance of athletes and what we can expect to see in the future.</p>

<p>One of the biggest advancements in technology that has impacted the world of sports is the development of wearable technology. From fitness trackers to smart watches, athletes are now able to track their performance in real-time. This allows them to monitor their heart rate, distance, and pace while they are training and competing. This data can then be used to make adjustments to their training regimen and fine-tune their performance.</p>

<p>Another important aspect of sports performance that has been greatly impacted by technology is the clothing athletes wear. Breathable clothing has become increasingly popular in recent years, and for good reason. Breathable clothing can have a positive impact on sports performance by helping to regulate an athlete’s body temperature. When an athlete is participating in physical activity, their body generates heat, which can cause them to become overheated and fatigued. Breathable clothing allows sweat to evaporate through the fabric, helping to cool the body and keep the athlete comfortable. This can help to prolong endurance and improve overall performance.</p>

<p>Yet another way that technology is transforming the world of sports is through the use of video analysis. With the help of cameras and software, coaches and trainers are now able to analyze an athlete’s technique and identify areas for improvement. This allows them to make adjustments to the athlete’s training regimen in order to improve their performance. You can see the spider cameras all around. In cricket, the stump camera and technology like ball tracking and Ultra Edge <sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> to confirm if the ball hit the bat have changed the way the game is played. (That means the chances that the batter is given a out in a wrong decision have reduced. Sachin has been given out a lot of times due to bad on-field umpire decisions<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">5</a></sup>)</p>

<p>In addition to technology, training methods have also seen significant advancements in recent years. One of the biggest changes has been the shift towards functional training. Rather than focusing on isolated muscle groups, functional training focuses on the body as a whole and trains the muscles to work together. This type of training is more effective for athletes because it helps to improve their overall movement patterns, making them more efficient and less prone to injury.</p>

<p>Another training method that has become increasingly popular is high-intensity interval training (HIIT). This type of training involves short bursts of high-intensity activity followed by periods of rest or low-intensity activity. Research has shown that HIIT is an effective way to improve cardiovascular fitness and increase muscle mass. This makes it an ideal training method for athletes who need to be in top physical condition.</p>

<p>Nutrition and dietary supplements are also playing a bigger role in the performance of athletes. With the help of sports scientists and nutritionists, athletes are now able to tailor their diets to meet their specific needs. This includes things like consuming the right types of carbohydrates to fuel their bodies during training and competition, and taking supplements to support their recovery and overall health.</p>

<p>Finally, medical treatments and recovery techniques have also improved in recent years. Athletes are now able to access a wide range of treatments, from physical therapy to regenerative medicine. These treatments help to speed up the recovery process, allowing athletes to get back to training and competing more quickly.</p>

<p>In conclusion, the advancements in technology and training methods have had a significant impact on the performance of athletes. From wearable technology to functional training, these advancements have allowed athletes to push their bodies to new limits and break records that were once thought impossible. With technology continuing to evolve, we can expect to see even more improvements in the future. Athletes and coaches will continue to use data and analytics to track performance and make training and game-time decisions. As a result, we will see even more athletes achieving new heights of excellence in their respective sports.</p>

<p><strong>References</strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p><a href="https://en.wikipedia.org/wiki/Virat_Kohli">Virat Kohli</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p><a href="https://systemhalted.in/2023/01/16/cricket-beginners-guide/">ODI</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p><a href="https://en.wikipedia.org/wiki/Sachin_Tendulkar">Sachin Tendulkar</a> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>Bilal, Mohammad, <a href="https://www.dailyo.in/ground/what-is-ultra-edge-technology-how-does-it-work-in-cricket-37386">What is ultra-edge technology? How does it work in cricket?</a> <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5" role="doc-endnote">
      <p><a href="http://sachinandcritics.com/sachin_vs_ump.php">Wrong Decisions against Sachin Tendulkar</a> <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Sports &amp; Hobbies&quot;]" /><category term="sports" /><summary type="html"><![CDATA[The world of sports has come a long way in the past decade. With advancements in technology and training methods, athletes are now able to push their bodies to new limits and break records that were once thought impossible. From professional athletes to weekend warriors, everyone is benefitting from these technological advancements. In this post, we will explore the ways in which technology and training methods have improved the performance of athletes and what we can expect to see in the future.]]></summary></entry><entry><title type="html">American Football - Beginners Guide</title><link href="https://systemhalted.in/2023/01/16/american-football-rules/" rel="alternate" type="text/html" title="American Football - Beginners Guide" /><published>2023-01-16T00:00:00+00:00</published><updated>2023-01-16T00:00:00+00:00</updated><id>https://systemhalted.in/2023/01/16/american-football-rules</id><content type="html" xml:base="https://systemhalted.in/2023/01/16/american-football-rules/"><![CDATA[<p>As a newcomer to USA in 2013, American Football was really confusing at first. Here I summarize the rules at high level for the people who are new to the USA and want to understand and enjoy the game.</p>

<p>American football is a sport played by two teams, each consisting of eleven players. The objective of the game is to advance an oval-shaped ball down the field and score points by crossing the opposing team’s goal line or kicking the ball through a set of goalposts.</p>

<p>The game is divided into four quarters, each lasting 15 minutes, with a 2-minute break between the 1st and 2nd quarters and between the 3rd and 4th quarters, and a 15-minute halftime break between the 2nd and 3rd quarters.</p>

<p>Each team takes turns playing offense and defense. The team on offense, also known as the “offense,” attempts to advance the ball down the field by either running with the ball or throwing it to a teammate. The team on defense, also known as the “defense,” attempts to stop the offense and take control of the ball for themselves. Each team has four chances, known as downs, to advance the ball at least 10 yards. They can do this by running or throwing the ball. If the team successfully advances the ball 10 yards, they get a new set of downs and the yardage is reset. If they fail to make the yardage after 4 downs, the opposing team takes possession of the ball.</p>

<p>There are hundreds of different plays that can be run on any down, and they are often complex and chaotic. The head coach or quarterback calls the plays for the offensive team, while the defensive captain calls the plays for the defensive team.</p>

<p>The game starts with a coin toss to determine which team will receive the ball first and which side of the field they will start from. The team that wins the coin toss begins the game with a kick-off, where they punt the ball down the field for the other team to run back as far as possible.</p>

<p>On fourth down, the offensive team has the option to either try to make up the yards they are short or to kick the ball. If they decide to kick, they have two options: to punt or to try for a field goal. Depending on their position on the field, they will usually choose one over the other. If they are within 40 yards or so of the opposing team’s goalposts, they will likely attempt a field goal. If they are further back, they will likely choose to punt the ball.</p>

<p>Points can be scored in several ways:</p>

<ul>
  <li>Touchdown: 6 points, awarded when the offense carries the ball across the opponent’s goal line or catches a pass in the end zone.</li>
  <li>Field goal: 3 points, awarded when the offense successfully kicks the ball through the opponent’s goalposts.</li>
  <li>Safety: 2 points, awarded when the defense tackles the offensive player with the ball in their own end zone.</li>
  <li>Extra point: 1 point, awarded after a touchdown, the offense can choose to attempt to kick the ball through the opponent’s goalposts for one point or run/pass the ball into the end zone for 2 points.</li>
</ul>

<p>Go and enjoy the game!</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Sports &amp; Hobbies&quot;]" /><category term="sports" /><category term="leadership" /><category term="united-states" /><summary type="html"><![CDATA[As a newcomer to USA in 2013, American Football was really confusing at first. Here I summarize the rules at high level for the people who are new to the USA and want to understand and enjoy the game.]]></summary></entry><entry><title type="html">Cricket - Beginner’s Guide</title><link href="https://systemhalted.in/2023/01/16/cricket-beginners-guide/" rel="alternate" type="text/html" title="Cricket - Beginner’s Guide" /><published>2023-01-16T00:00:00+00:00</published><updated>2023-01-16T00:00:00+00:00</updated><id>https://systemhalted.in/2023/01/16/cricket-beginners-guide</id><content type="html" xml:base="https://systemhalted.in/2023/01/16/cricket-beginners-guide/"><![CDATA[<p>Cricket is a sport that is played between two teams of eleven players each. The objective of the game is for one team to score more runs than the other team. If you are new to the game, it can seem complex and difficult to understand. However, with a basic understanding of the rules and strategies, anyone can enjoy watching and playing cricket.</p>

<h3 id="the-field">The Field</h3>

<p>The game of cricket is played on a large oval-shaped field, with a rectangular 22-yard-long strip of grass called the pitch in the center. At each end of the pitch, there are three upright sticks called stumps, and on top of these stumps, two small horizontal sticks called bails are placed. These stumps and bails make up the wicket, which is the target that the fielding team tries to hit and the batting team tries to protect.</p>

<h3 id="the-coin-toss">The Coin Toss</h3>

<p>A coin toss is held at the beginning of the game to determine which team will bat first. The team that bats first tries to score as many runs as possible before they have ten players “out.” Once the first team has ten players out, the teams switch roles and the second team tries to score more runs than the first team.</p>

<h3 id="offense-and-defense">Offense and Defense</h3>

<p>In cricket, the team that is currently trying to score runs is said to be “batting,” while the team that is trying to prevent the opposing team from scoring runs is said to be “fielding.” Each team takes turns playing offense and defense, with the goal of outscoring the opposing team.</p>

<h3 id="getting-out">Getting Out</h3>

<p>When the team is on defense, they try to prevent the opposing team from scoring runs by getting the players “out.” There are several ways to get a player out:</p>

<ul>
  <li>A player can be “out” in several ways, including:</li>
  <li>Being caught by a fielder off a hit ball</li>
  <li>Being bowled (stumps hit by the ball on the wicket)</li>
  <li>Being run out (stumps hit by the ball while running between the wickets)</li>
  <li>Being stumped (the wicket-keeper puts down the wicket while the player is out of his crease)</li>
</ul>

<h3 id="scoring-runs">Scoring Runs</h3>

<p>When the team is on offense, they try to score runs by hitting the ball and running back and forth between the wickets. A run is scored each time the two batsmen successfully run from one end of the pitch to the other.</p>

<h3 id="end-of-the-game-and-winning-the-match">End of the Game and Winning the Match</h3>

<p>The game can end in one of several ways:</p>

<ul>
  <li>The second team may be out before scoring more runs than the first team, in which case the first team wins.</li>
  <li>The second team may score more runs than the first team before all their players are out, in which case the second team wins.</li>
  <li>The game may end in a tie if both teams have the same score.</li>
</ul>

<h3 id="match-formats">Match Formats</h3>

<h4 id="test-match">Test Match</h4>

<p>A test match is the traditional format of cricket and is considered to be the pinnacle of the sport. It is the longest format of the game, usually played over five days, with each team having two innings. In test matches, there is no limit to the number of overs that each team can play, and a draw is a possible outcome. This means that if both teams are unable to bowl out the other team, or if the game ends in a tie, the match is considered to be a draw.</p>

<p>Also, the test matches tend to have a more strategic and tactical approach, as the teams have more time to plan and execute their strategies. The players also have to be more patient and disciplined in this format as the game can last up to five days.</p>

<p>The test match format is considered to be the most challenging and demanding format of the game and is often considered to be a true test of a team’s skill and ability. It is a format that is played between national teams and considered as the traditional format of cricket.</p>

<h4 id="limited-overs-match">Limited Overs Match</h4>

<p>These formats are designed to be completed in a shorter amount of time and are often considered to be more fast-paced and exciting. The two most popular limited-overs formats are One Day and T20.
    * One Day - In One Day format, each team has a set number of overs, usually 50, to score as many runs as possible. The team that scores the most runs wins the match. This format is considered to be a balance between the longer test format and the shorter T20 format, and it is popular for international matches.
    * T20 - T20 format is the shortest and most exciting format of cricket, where each team has 20 overs to score as many runs as possible. The team that scores the most runs wins the match. This format is popular for domestic and international matches, and it is known for its fast-paced action and high-scoring matches.</p>

<p>Cricket is a sport with many rules and strategies, and can take some time to fully understand. However, with a basic understanding of the game and its rules, anyone can enjoy watching and playing cricket. The game is known for its rich history and traditions, as well as its unique terminology and strategies. It is especially popular in countries such as England, Australia, India, and South Africa. Give it a try, you might find it to be a fascinating sport!</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Sports &amp; Hobbies&quot;]" /><category term="sports" /><category term="travel" /><category term="leadership" /><category term="india" /><summary type="html"><![CDATA[This post summarizes sport of cricket for people who are interested in the game.]]></summary></entry><entry><title type="html">How to keep kids safe playing Roblox?</title><link href="https://systemhalted.in/2023/01/16/safety-tips-roblox/" rel="alternate" type="text/html" title="How to keep kids safe playing Roblox?" /><published>2023-01-16T00:00:00+00:00</published><updated>2023-01-16T00:00:00+00:00</updated><id>https://systemhalted.in/2023/01/16/safety-tips-roblox</id><content type="html" xml:base="https://systemhalted.in/2023/01/16/safety-tips-roblox/"><![CDATA[<p>I am constantly worried about my kids’ safety when they are playing Roblox or any game online. As a parent, it’s important to be aware of the digital world that our children are exploring. One of the most popular online gaming platforms among kids today is Roblox, a massively multiplayer game that allows players to create and share their own virtual worlds. While Roblox can be a fun and educational experience for kids, it’s important to take steps to ensure their safety while they’re playing.</p>

<p>Here are some tips to help keep your child safe while playing Roblox:</p>

<ol>
  <li>Set up parental controls: Roblox offers a variety of parental control options that allow you to limit the amount of time your child can spend on the platform, as well as restrict access to certain features. You can also set up a PIN code to prevent your child from making in-game purchases without your permission.</li>
  <li>Monitor your child’s chat: Roblox allows players to communicate with each other through in-game chat, which can be a great way for kids to make friends and collaborate on projects. However, it’s important to keep an eye on the chat to make sure that your child isn’t being bullied or exposed to inappropriate content.</li>
  <li>Check the game’s rating: Roblox games are rated by other players, so it’s important to check the rating of a game before your child starts playing it. Games with a high rating are generally considered to be safe, while games with a low rating may contain inappropriate content.</li>
  <li>Educate your child about online safety: It’s important to teach your child about online safety and the importance of being mindful of the information they share online. Remind them not to share personal information, such as their name, address, or phone number, with strangers.</li>
  <li>Be involved in their gaming: Be aware of your child’s gaming habits and interests. Play with them and observe the games they are playing, the people they are interacting with and the kind of content they are exposed to.</li>
  <li>Be aware of the potential risks of virtual currency: Roblox has virtual currency called “Robux” that can be used to purchase in-game items. Be aware that some children may be tempted to buy Robux with real money, so make sure you discuss the potential risks of virtual currency with your child.</li>
  <li>Keep an open communication with your child: Encourage your child to talk to you if they ever feel uncomfortable or unsafe while playing Roblox or online. This will help them feel more comfortable coming to you if they ever need help.</li>
  <li>Keep the computer in a common area: If possible, place the computer in a common area of the house so you can keep an eye on your child’s online activities.</li>
  <li>Limit the time they can play: It is important that your kids are not spending their entire time online playing games. Other aspects are important. Encourage them to read and go out and play.</li>
  <li>Keep an eye on your child’s friends list: Roblox allows players to add friends, so it’s important to monitor your child’s friends list to ensure that they are only interacting with people you trust. 
11.Use the “Report Abuse” feature: Roblox has a “Report Abuse” feature that allows players to report any inappropriate behavior or content they encounter. Encourage your child to use this feature if they ever come across anything that makes them feel uncomfortable or unsafe.</li>
  <li>Discuss online behavior with your child: Talk to your child about appropriate online behavior and explain to them the importance of being respectful and kind to others while playing games online.</li>
  <li>Stay informed: Stay informed and educated on the latest features and updates of Roblox platform. This will help you to keep your child safe and aware of any new risks or concerns. Also, be aware of the latest trends and games that your child may be interested in.</li>
  <li>Monitor your child’s online activities: Regularly check your child’s account to see what games they’re playing, who they’re interacting with, and what kind of content they’re viewing. This will give you a better understanding of your child’s online activities and will help you to address any concerns or issues that may arise.</li>
  <li>Be a role model: Be a role model for your child by showing them how to use the internet and online games in a safe and responsible manner.</li>
</ol>

<p>I hope by taking these steps, you and I can help keep our child safe while they’re playing Roblox and enjoy the fun and educational benefits that the platform has to offer. It’s important to remember that no system or method can provide a 100% guarantee of safety so it’s important to keep an open line of communication with your child and stay informed about the latest updates and trends of the platform.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Technology&quot;]" /><category term="video games" /><category term="Security" /><summary type="html"><![CDATA[This post will discuss some tips for parents to keep the kids safe while playing Roblox.]]></summary></entry><entry><title type="html">Git Bisect - Finding the Source of a Bug in Your Codebase</title><link href="https://systemhalted.in/2023/01/12/git-bisect/" rel="alternate" type="text/html" title="Git Bisect - Finding the Source of a Bug in Your Codebase" /><published>2023-01-12T00:00:00+00:00</published><updated>2023-01-12T00:00:00+00:00</updated><id>https://systemhalted.in/2023/01/12/git-bisect</id><content type="html" xml:base="https://systemhalted.in/2023/01/12/git-bisect/"><![CDATA[<p>As a software developer, it’s inevitable that bugs will appear in your codebase. When this happens, it can be a time-consuming and frustrating process to track down the source of the problem. However, there is a powerful tool built into Git that can help: bisect.</p>

<p>Git bisect allows you to quickly and easily identify the commit that introduced a bug by using a binary search algorithm. The process works by narrowing down the possible commits that could have introduced the bug by repeatedly selecting a “good” and “bad” commit and checking the ones in between.</p>

<p>To use Git bisect, first make sure that you have the latest version of your codebase on a clean branch. Then, run the command <code class="language-plaintext highlighter-rouge">git bisect start</code> to begin the bisect process. Next, you’ll need to mark the current commit as “bad” using the command <code class="language-plaintext highlighter-rouge">git bisect bad</code>. This will tell Git that the bug is present in the current version of the code.</p>

<p>Next, you’ll need to find a commit that you know is “good”, meaning that the bug is not present. This could be a commit from before the bug was introduced, or a release version of your code that you know is working correctly. Once you have identified a “good” commit, run the command <code class="language-plaintext highlighter-rouge">git bisect good &lt;commit&gt;</code> to mark it as such.</p>

<p>Git will now begin the bisect process by checking out a commit in between the “good” and “bad” commits. You’ll need to test the code at this point to determine if the bug is present or not. If the bug is present, run the command git bisect bad to mark the current commit as bad. If the bug is not present, run the command git bisect good to mark it as good.</p>

<p>Git will continue to bisect the codebase in this way until it has identified the specific commit that introduced the bug. Once the commit has been found, run the command git bisect reset to exit the bisect process and return to the latest version of the code.</p>

<p>It’s important to note that bisecting a codebase can take some time, especially for large codebases with many commits. However, the process is automated and can save a significant amount of time compared to manually searching through the codebase for the source of the bug.</p>

<p>In conclusion, Git bisect is a powerful tool that can help you quickly and efficiently identify the source of a bug in your codebase. By using a binary search algorithm, bisect can narrow down the possible commits that could have introduced the bug, saving you time and frustration. Give it a try the next time you run into a tricky bug in your code!”</p>

<p>Note: the commands above are just examples and the exact commands may vary depending on the version of git and the operating system you are using.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Software Engineering&quot;]" /><category term="software" /><summary type="html"><![CDATA[Git bisect allows you to quickly and easily identify the commit that introduced a bug by using a binary search algorithm. The process works by narrowing down the possible commits that could have introduced the bug by repeatedly selecting a "good" and "bad" commit and checking the ones in between.]]></summary></entry><entry><title type="html">Language Part 6 - Non-Verbal Communication, Tone, and Body language</title><link href="https://systemhalted.in/2022/12/26/language-part-6-tone-body-lang-nvc/" rel="alternate" type="text/html" title="Language Part 6 - Non-Verbal Communication, Tone, and Body language" /><published>2022-12-26T00:00:00+00:00</published><updated>2022-12-26T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/26/language-part-6-tone-body-lang-nvc</id><content type="html" xml:base="https://systemhalted.in/2022/12/26/language-part-6-tone-body-lang-nvc/"><![CDATA[<p><strong><em>Disclaimer</em></strong>
I am not a linquist and have no knowledge about languages. Even though I am filing this under <code class="language-plaintext highlighter-rouge">Linguistic</code> category, it is more of my <code class="language-plaintext highlighter-rouge">Insane Thoughts</code> and thus is twin filed under that category as well.</p>

<p>Language is a complex system of communication that involves not only words and grammar, but also other elements such as nonverbal communication, tone, and body language. These elements can play a significant role in conveying meaning and understanding in language, and they are important to consider when communicating with others.</p>

<p>Non-verbal communication is a type of communication that does not involve words or language. It can include body language, gestures, facial expressions, eye movements, posture, and other physical cues. Non-verbal communication can convey a wide range of emotions and meanings, and it can be an important aspect of language in different cultural contexts.</p>

<p>For example, gestures are a common form of nonverbal communication that can convey meaning and emotion. Different cultures and societies may use different gestures to convey the same meaning, so it is important to be aware of these differences when communicating with others. Facial expressions are another common form of nonverbal communication that can convey a wide range of emotions, such as happiness, sadness, anger, or surprise. Eye movements and gaze patterns can also convey meaning and emotion, and they can be an important aspect of nonverbal communication in some cultural contexts.</p>

<p>Posture is another aspect of nonverbal communication that can convey meaning and emotion. For example, a person who is standing with their arms crossed and their body turned away may be conveying a sense of discomfort or disinterest. On the other hand, a person who is standing with their body turned towards the speaker and their arms uncrossed may be conveying a sense of interest and engagement.</p>

<p>Tone is another important aspect of language that can convey meaning and emotion. Tone is the way that words are spoken, and it can be affected by the pitch, volume, and rhythm of speech. Tone can convey a wide range of emotions, such as anger, happiness, or sadness. For example, a person speaking in a high-pitched, excited tone may be conveying happiness or enthusiasm, while a person speaking in a low, monotone voice may be conveying boredom or disinterest.</p>

<p>It is important to be aware of the tone that is being used when speaking, as it can have a significant impact on the meaning and interpretation of words and sentences. For example, a statement spoken in a sarcastic tone may be interpreted differently than the same statement spoken in a sincere tone. Tone can also be used to convey emphasis and to signal the end of a sentence or thought. For example, a rising pitch at the end of a sentence can indicate a question, while a falling pitch can indicate a statement.</p>

<p>Overall, nonverbal communication is a complex and important aspect of language that can convey a wide range of meanings and emotions. It is important to be aware of the role that nonverbal communication plays in language and to consider it when communicating with others.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Languages &amp; Linguistics&quot;, &quot;Series 1 - Language and Linguistics&quot;]" /><summary type="html"><![CDATA[This is Part 6 of Language series where we will talk about non-verbal communication.]]></summary></entry><entry><title type="html">Language Part 5 - Script</title><link href="https://systemhalted.in/2022/12/25/language-part-5-script/" rel="alternate" type="text/html" title="Language Part 5 - Script" /><published>2022-12-25T00:00:00+00:00</published><updated>2022-12-25T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/25/language-part-5-script</id><content type="html" xml:base="https://systemhalted.in/2022/12/25/language-part-5-script/"><![CDATA[<p><strong><em>Disclaimer</em></strong>
I am not a linquist and have no knowledge about languages. Even though I am filing this under <code class="language-plaintext highlighter-rouge">Linguistic</code> category, it is more of my <code class="language-plaintext highlighter-rouge">Insane Thoughts</code> and thus is twin filed under that category as well.</p>

<p>Script is an important aspect of language that refers to the written form of a language. It is a system of symbols, letters, or characters that represent the sounds and words of a language, and it is a key aspect of written communication.</p>

<p>Script is the written form of a language, and it is a system of symbols, letters, or characters that represent the sounds and words of a language. Different languages have their own scripts, and these scripts can vary greatly in terms of their complexity and the number of symbols or characters that they use. For example, the English alphabet uses 26 letters to represent the sounds of the language, while the Chinese script uses thousands of characters to represent the sounds and words of the language.</p>

<p>It is important to note that a language can be written in multiple scripts. For example, the Hindi language is written in the Devanagari script, but it can also be written in the Roman script, which is more familiar to speakers of English. Similarly, the Arabic language is written in the Arabic script, but it can also be written in the Roman script or other scripts. This can be useful for speakers of a language who are not familiar with the native script, or for people who are learning a language as a second or foreign language.</p>

<p>The choice of script for a language can be influenced by a variety of factors, such as the history of the language, the cultural context in which it is used, and the needs and preferences of the speakers of the language. Some languages may have multiple scripts that are used interchangeably, while others may have a preferred or official script that is used more widely.</p>

<p>The use of script can also have broader cultural and political implications. In some cases, the use of a particular script may be seen as a symbol of cultural identity or political independence. For example, the adoption of the Latin script for the Kurdish language has been seen as a way to assert Kurdish cultural identity and independence from the dominant Arab and Persian cultures in the region.</p>

<p>At the same time, the use of script can also be a source of controversy and conflict. In some cases, the use of a particular script may be seen as a threat to the dominant culture or as an attempt to divide the population. For example, the use of the Cyrillic script for the Bosnian language has been a source of tension between Bosnian Serbs and Croats, who have historically used the Latin script.</p>

<p>However, it is important to note that script is not essential for a language. Language can also be communicated through speech, gestures, or other forms of expression, and a language can still function and be understood even if it is not written down. Many languages have been spoken for centuries or even millennia without a written form, and they have been passed down through oral tradition.</p>

<p>In conclusion, though without a script, it would be difficult to convey written messages or to record and preserve written language, it is not necessary to have a script for communication. Also, it is important to note that choice of script can have cultural, political, and social implications much like the choice of language itself.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Languages &amp; Linguistics&quot;, &quot;Series 1 - Language and Linguistics&quot;]" /><summary type="html"><![CDATA[This is Part 5 of Language series where we will talk about script.]]></summary></entry><entry><title type="html">Language Part 4 - Pronunciation</title><link href="https://systemhalted.in/2022/12/24/language-part-4-pronunciation/" rel="alternate" type="text/html" title="Language Part 4 - Pronunciation" /><published>2022-12-24T00:00:00+00:00</published><updated>2022-12-24T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/24/language-part-4-pronunciation</id><content type="html" xml:base="https://systemhalted.in/2022/12/24/language-part-4-pronunciation/"><![CDATA[<p><strong><em>Disclaimer</em></strong>
I am not a linquist and have no knowledge about languages. Even though I am filing this under <code class="language-plaintext highlighter-rouge">Linguistic</code> category, it is more of my <code class="language-plaintext highlighter-rouge">Insane Thoughts</code> and thus is twin filed under that category as well.</p>

<p>Pronunciation to the way that words are spoken and how they sound. It plays a vital role in effective communication, as it helps us to convey meaning and be understood by others. It refers to the way that words are spoken and how they sound. It is an important aspect of language because it helps to convey meaning and ensure that we are understood by others.</p>

<p>Pronunciation can vary depending on the language and dialect being spoken, and it is important to be aware of these differences in order to communicate effectively. There are many factors that can affect pronunciation, including the sounds of the language, the stress patterns of words, and the intonation and rhythm of speech.</p>

<p>One of the ways that pronunciation helps us to convey meaning is through the sounds of the language. Different languages have their own set of sounds, and it is important to be able to produce these sounds accurately in order to be understood. For example, Hindi has a retroflex sound, which is produced by curling the tip of the tongue back towards the roof of the mouth. This sound does not exist in English, and it can be challenging for English speakers to produce accurately.</p>

<p>Pronunciation also plays a role in the stress patterns of words. In many languages, certain syllables in a word are stressed or pronounced more strongly than others. This can affect the meaning of a word, and it is important to pronounce words with the correct stress pattern in order to convey the intended meaning. In addition to this, pronunciation also involves the intonation and rhythm of speech. Intonation refers to the rise and fall of the voice, and it can convey meaning and emphasis. Rhythm refers to the pattern of stressed and unstressed syllables in speech, and it can affect the flow and clarity of communication.</p>

<p>For example, while English and Hindi do have some similarities in their stress patterns, there are also some important differences between the two languages. In both English and Hindi, stress patterns can affect the meaning of words and the way that they are pronounced. In English, stress is typically placed on the first syllable of a word, although there are many exceptions to this rule. For example, the word “produce” is stressed on the second syllable when it is a verb, but it is stressed on the first syllable when it is a noun.</p>

<p>In Hindi, stress patterns are generally more predictable than in English, and they are typically based on the length of the syllables in a word. In Hindi, stressed syllables are generally longer and louder than unstressed syllables, and they are often pronounced with a higher pitch.</p>

<p>In conclusion, pronunciation is an important aspect of language that helps us to convey meaning and be understood by others. It involves the sounds of the language, the stress patterns of words, and the intonation and rhythm of speech, and it requires practice and effort to master. By understanding and mastering pronunciation, we can more effectively communicate with others and express our thoughts and ideas.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Languages &amp; Linguistics&quot;, &quot;Series 1 - Language and Linguistics&quot;]" /><summary type="html"><![CDATA[This is Part 4 of Language series where we will talk about pronunciation.]]></summary></entry><entry><title type="html">Language Part 3 - Vocabulary</title><link href="https://systemhalted.in/2022/12/23/language-part-3-vocabulary/" rel="alternate" type="text/html" title="Language Part 3 - Vocabulary" /><published>2022-12-23T00:00:00+00:00</published><updated>2022-12-23T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/23/language-part-3-vocabulary</id><content type="html" xml:base="https://systemhalted.in/2022/12/23/language-part-3-vocabulary/"><![CDATA[<p><strong><em>Disclaimer</em></strong>
I am not a linquist and have no knowledge about languages. Even though I am filing this under <code class="language-plaintext highlighter-rouge">Linguistic</code> category, it is more of my <code class="language-plaintext highlighter-rouge">Insane Thoughts</code> and thus is twin filed under that category as well.</p>

<p>Vocabulary is an essential part of language that refers to the set of words that we use to express our thoughts, feelings, and ideas. It is a key aspect of effective communication, as it allows us to express a wide range of concepts and ideas in a clear and concise manner.</p>

<p>Vocabulary can be defined as the words of a language, including single items and phrases or chunks of several words which convey a particular meaning, the way individual words do. <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>But why is vocabulary so important in language, and how does it work? Let’s take a closer look at this important aspect of communication.</p>

<p>One of the main reasons that vocabulary is important in language is that it allows us to express a wide range of concepts and ideas. A rich vocabulary enables us to describe and explain complex concepts, convey abstract ideas, and express our thoughts and feelings in a precise and nuanced way. It also allows us to understand and interpret the words and ideas of others, as a larger vocabulary enables us to better grasp the meaning of new or unfamiliar words.</p>

<p>Vocabulary is also important in language because it allows us to communicate more effectively with others. By using a wide range of words and phrases, we can convey our thoughts and ideas in a clear and concise manner, and we can better understand the words and ideas of others. This is especially important in professional settings, where effective communication is crucial for success.</p>

<p>Building and expanding your vocabulary is an ongoing process that requires practice and effort. There are many ways to improve your vocabulary, including reading widely, learning new words and phrases, and using a dictionary or thesaurus to look up unfamiliar words. By making an effort to expand your vocabulary, you can become a more effective communicator and improve your understanding of language.</p>

<p>Like discussed in the last post, the grammar gives identity to the language and vocabulary gives substance to it. Let’s take the same example as in last post about grammar, <code class="language-plaintext highlighter-rouge">"इस पार्क (park) में बहुत सारे स्लाइड्स (slides) हैं|"</code> This is ofcourse Hindi but notice that the two most important words, the subject of the sentence - <code class="language-plaintext highlighter-rouge">park</code> and <code class="language-plaintext highlighter-rouge">slides</code> - are both English words but somehow we ended up writing a Hindi sentence. This is because though we are using foreign words, the structure of the sentence follows Hindi grammar. Notice that the other words - in Hindi - are not as important as the two English words. Thus, vocabulary used enhances the quality of the sentence, and thus the quality of the language.</p>

<p>When native speakers of a language come into contact with a language used by others, they try to incorporate some of the terminology into their regular use, so increasing their vocabulary. Oxford dictionary adds 4000 new words to its repertoire every year. That means we will see increasing number of foreign language influence on English vocabulary, which is a good thing.</p>

<p>Maintaining a purity of language does no good and people who are puritan in their perspective do more disservice than service to the language.</p>

<p>In conclusion, vocabulary is an essential part of language that allows us to express a wide range of concepts and ideas. It is a key aspect of effective communication, and it is something that can be improved and expanded through practice and effort. By building a rich vocabulary, we can more effectively express ourselves and understand the words and ideas of others.</p>

<p><strong><em>References</em></strong></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>https://www.tesol.org/docs/books/bk_ELTD_Vocabulary_974 <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Languages &amp; Linguistics&quot;, &quot;Series 1 - Language and Linguistics&quot;]" /><category term="sports" /><summary type="html"><![CDATA[This is Part 3 of Language series where we will talk about vocabulary.]]></summary></entry><entry><title type="html">Language Part 2 - Grammar</title><link href="https://systemhalted.in/2022/12/22/language-part-2-grammar/" rel="alternate" type="text/html" title="Language Part 2 - Grammar" /><published>2022-12-22T00:00:00+00:00</published><updated>2022-12-22T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/22/language-part-2-grammar</id><content type="html" xml:base="https://systemhalted.in/2022/12/22/language-part-2-grammar/"><![CDATA[<p><strong><em>Disclaimer</em></strong>
I am not a linquist and have no knowledge about languages. Even though I am filing this under <code class="language-plaintext highlighter-rouge">Linguistic</code> category, it is more of my <code class="language-plaintext highlighter-rouge">Insane Thoughts</code> and thus is twin filed under that category as well.</p>

<p>Grammar is a fundamental aspect of language that refers to the set of rules that govern the structure and organization of words and phrases in a sentence. It is a complex and multifaceted system that plays a vital role in effective communication.
But what exactly is grammar, and how does it work? Let’s take a closer look at this important aspect of language.</p>

<p>Grammar is the set of rules that govern the structure and organization of words and phrases in a sentence. It helps to convey meaning and create coherent and well-formed sentences. Grammar includes elements such as nouns, verbs, adjectives, adverbs, and other parts of speech, as well as the rules for how these words and phrases can be combined to form sentences.</p>

<p>Grammar also includes the rules for punctuation, which helps to clarify the meaning of a sentence and make it easier to understand. For example, a comma can be used to indicate a pause or to separate clauses in a sentence, while a period indicates the end of a sentence.</p>

<p>In addition to these basic elements, grammar also includes more complex rules for verb tenses, word order, and other aspects of sentence structure. These rules vary from one language to another, and they are an essential part of understanding and using a language effectively.</p>

<p>When talking about language, grammar is without a doubt the most important factor, with vocabulary coming in second (we will discuss about vocabulary in the next post). The grammar gives identity to the language. Take for an example, this sentence supposedly in Hindi, <code class="language-plaintext highlighter-rouge">"इस पार्क (park) में बहुत सारे स्लाइड्स (slides) हैं|"</code> This is ofcourse Hindi but notice that the two most important words, the subject of the sentence - <code class="language-plaintext highlighter-rouge">park</code> and <code class="language-plaintext highlighter-rouge">slides</code> - are both English words but somehow we ended up writing a Hindi sentence. This is because though we are using foreign words, the structure of the sentence follows Hindi grammar.</p>

<p>Thus, Grammar is an important aspect of language because it helps to convey meaning and create coherent and well-formed sentences despite use of foreign words. It is a key aspect of effective communication, and it is something that is learned and developed over time. While grammar can be a challenging aspect of language to master, it is a vital skill to have in order to effectively convey your thoughts and ideas to others.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Languages &amp; Linguistics&quot;, &quot;Series 1 - Language and Linguistics&quot;]" /><summary type="html"><![CDATA[This is Part 2 of Language series where we will talk about grammar.]]></summary></entry><entry><title type="html">Language Part 1 - Introduction</title><link href="https://systemhalted.in/2022/12/21/language-part-1-introduction/" rel="alternate" type="text/html" title="Language Part 1 - Introduction" /><published>2022-12-21T00:00:00+00:00</published><updated>2022-12-21T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/21/language-part-1-introduction</id><content type="html" xml:base="https://systemhalted.in/2022/12/21/language-part-1-introduction/"><![CDATA[<p>Yesterday, my son Rayirth asked why his teacher says that English is the toughest language. While discussing it dawned to me that English is not difficult due to how the language is designed but due to the very nature of the script it uses. For example, cut and put are pronounced differently but written similarly. Thus, one thing is clear that language is not same as the script. Then what is language? How do we define language? In this series of post, I am going to tackle this question and discuss various aspects or components of language. This is the first post in the series where I will try to understand what is a language and how is it useful for human communication.</p>

<p><strong><em>Disclaimer</em></strong> 
I am not a linquist and have no knowledge about languages. Even though I am filing this under <code class="language-plaintext highlighter-rouge">Linguistic</code> category, it is more of my <code class="language-plaintext highlighter-rouge">Insane Thoughts</code> and thus is twin filed under that category as well.</p>

<p>Language is a fundamental aspect of human communication. It is a system of symbols, sounds, and gestures that we use to express our thoughts, feelings, and ideas to others. Language allows us to convey complex information, share our knowledge and experiences, and connect with others on a deeper level.</p>

<p>But what exactly is language? It can be difficult to define, as it is a complex and multifaceted system that includes many different elements. Some definitions of language include the following:</p>

<ul>
  <li>
    <p>“A system of communication by speech, either spoken or written, consisting of the use of words in a structured and conventional way.” (Oxford English Dictionary)</p>
  </li>
  <li>
    <p>“A system of communication through speech, consisting of sounds, words, and grammar, or the system of communication used by a particular country or group of people.” (Merriam-Webster)</p>
  </li>
  <li>
    <p>“A system of communication through speech or writing, that is used by humans in a particular country or community.” (Cambridge Dictionary)</p>
  </li>
</ul>

<p>These definitions highlight the various components of language, including the use of words and grammar to convey meaning, and the role of speech or writing in communication. Language is a highly organized and structured system, with rules and conventions that vary from one language to another.</p>

<p>The role of language in human communication is essential. It allows us to express our thoughts, ideas, and emotions in a way that can be understood by others. Without language, we would be unable to share our knowledge and experiences, or to connect with others in a meaningful way. Language is also a key aspect of culture, as it reflects the values, beliefs, and traditions of a particular group of people.</p>

<p>As we can see from these definitions, language is a complex and multifaceted system of communication that plays a vital role in human interaction. It allows us to express ourselves and understand others, and it is an essential part of who we are as human beings.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Languages &amp; Linguistics&quot;, &quot;Series 1 - Language and Linguistics&quot;]" /><summary type="html"><![CDATA[This is part 1 of Language series where we will define Language and why it is important.]]></summary></entry><entry><title type="html">Mastodon - What is it? Why should I join? How to join?</title><link href="https://systemhalted.in/2022/12/20/mastodon/" rel="alternate" type="text/html" title="Mastodon - What is it? Why should I join? How to join?" /><published>2022-12-20T00:00:00+00:00</published><updated>2022-12-20T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/20/mastodon</id><content type="html" xml:base="https://systemhalted.in/2022/12/20/mastodon/"><![CDATA[<h2 id="what-is-mastodon">What is Mastodon?</h2>

<p>Mastodon is a decentralized, open-source social media platform that allows users to create and join communities called “instances.” Each instance is run by a different administrator and has its own rules and moderation policies. Mastodon is based on the same technology as Twitter, but it is not owned by a single company and is not subject to the same centralized control.</p>

<h2 id="why-join-mastodon">Why Join Mastodon?</h2>

<p>There are several reasons why you might want to join Mastodon:</p>

<ol>
  <li>
    <p>Decentralization: As mentioned earlier, Mastodon is decentralized, which means that it is not owned or controlled by any one company or organization. This gives users more control over their content and privacy, as well as the ability to choose which communities they want to be a part of.</p>
  </li>
  <li>
    <p>Inclusivity: Many Mastodon instances have a focus on inclusivity and diversity, and strive to create safe and welcoming communities for all users. This can be especially appealing for those who have felt marginalized or excluded on other social media platforms.</p>
  </li>
  <li>
    <p>Customization: Each Mastodon instance is unique and can be customized to meet the needs and interests of its community. This allows for a wide range of communities to form and thrive on the platform.</p>
  </li>
</ol>

<h2 id="how-to-join-mastodon">How to Join Mastodon?</h2>

<ol>
  <li>
    <p>Choose an instance: The first step to joining Mastodon is to choose an instance to join. There are many different instances to choose from, each with its own focus and community. Here are a couple of examples of specific Mastodon instances that you might be interested in checking out:</p>

    <ul>
      <li>eMacs.ch: This is a Mastodon instance that is focused on the Emacs text editor and related topics. It is a great place for Emacs users to connect and discuss their experiences with the software.</li>
      <li>fosstodon.org: This is an instance that is focused on free and open-source software (FOSS). It is a great place for FOSS enthusiasts to connect and discuss their favorite projects and technologies.</li>
    </ul>
  </li>
  <li>
    <p>Create an account: Once you’ve chosen an instance, you can create an account by visiting the instance’s website and following the prompts. You will need to choose a username and set a password.</p>
  </li>
  <li>
    <p>Customize your profile: After you’ve created your account, you can customize your profile by adding a profile picture, bio, and other information.</p>
  </li>
  <li>
    <p>Explore and interact: Once you’ve set up your account, you can start exploring Mastodon and interacting with other users. You can follow other users, create and join communities, and post updates (called “toots”).</p>
  </li>
</ol>

<p>Mastodon is a dynamic and diverse platform that offers users a lot of flexibility and control. Whether you’re looking for a more privacy-conscious alternative to traditional social media platforms, or you want to join a community of like-minded individuals, Mastodon has something to offer.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Society &amp; Economy&quot;]" /><category term="society" /><category term="economy" /><summary type="html"><![CDATA[Mastodon is a dynamic and diverse platform that offers users a lot of flexibility and control. Whether you're looking for a more privacy-conscious alternative to traditional social media platforms, or you want to join a community of like-minded individuals, Mastodon has something to offer.]]></summary></entry><entry><title type="html">On Agile - Part 2</title><link href="https://systemhalted.in/2022/12/20/on-agile-2/" rel="alternate" type="text/html" title="On Agile - Part 2" /><published>2022-12-20T00:00:00+00:00</published><updated>2022-12-20T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/20/on-agile-2</id><content type="html" xml:base="https://systemhalted.in/2022/12/20/on-agile-2/"><![CDATA[<p>This is continuation of <a href="https://systemhalted.in/2021/09/10/on-agile/">On Agile - Part 1</a></p>

<p>Agile methodologies are approaches to software development that prioritize flexibility, collaboration, and continuous improvement. The Agile Manifesto, a set of guiding principles for Agile development, emphasizes individual interactions, working solutions, and customer collaboration over processes and tools.</p>

<p>Scrum is a popular Agile framework that involves regular, short sprints of work, during which small cross-functional teams work together to complete a set of defined goals. Scrum teams have a designated Scrum Master, who is responsible for facilitating the process and ensuring that the team is following the Scrum framework.</p>

<p>Kanban is another Agile framework that involves visualizing work as it moves through a workflow. Teams using Kanban pull work from a “to-do” column into a “doing” column, and then into a “done” column as it is completed. Kanban is often used in conjunction with Scrum, with the Kanban board serving as a visual representation of the work being done during a Scrum sprint.</p>

<p>Extreme Programming (XP) is an Agile methodology that emphasizes the values of simplicity, communication, feedback, and courage. XP involves frequent releases, ongoing testing and refactoring, and close collaboration between developers, customers, and users.</p>

<p>SAFe (Scaled Agile Framework) is a framework for scaling Agile practices to large organizations. SAFe is based on the principles of Lean and Agile, and involves the use of Lean-Agile leaders and teams, Lean-Agile portfolio management, and Lean-Agile governance.</p>

<p>While Agile methodologies, Scrum, Kanban, Extreme Programming, and SAFe can be effective approaches to software development, they are not without their pitfalls. Some common challenges with these approaches include:</p>

<ul>
  <li>
    <p>Misunderstanding or misapplying the values and principles of Agile: It’s important for development teams to understand and align on the values and principles underlying Agile methodologies, and to apply them appropriately in their work.</p>
  </li>
  <li>
    <p>Lack of buy-in or commitment from stakeholders: Agile requires the participation and commitment of all stakeholders, including customers, developers, and management. Without buy-in from these groups, it can be difficult to effectively implement Agile practices.</p>
  </li>
  <li>
    <p>Overly rigid or prescriptive application of frameworks: While frameworks like Scrum and SAFe can provide guidance and structure, it’s important to remember that Agile is about adaptability and continuous improvement. Overly rigid application of frameworks can stifle innovation and hinder progress.</p>
  </li>
  <li>
    <p>Difficulty with team communication and collaboration: Agile relies on frequent and open communication and collaboration among team members. If teams are not accustomed to this level of transparency and interaction, it can be a challenge to effectively implement Agile practices.</p>
  </li>
</ul>

<p>Here are a few strategies for addressing the pitfalls of Agile methodologies, Scrum, Kanban, Extreme Programming, and SAFe:</p>

<ul>
  <li>
    <p>Educate and align stakeholders on the values and principles of Agile: Ensuring that all stakeholders understand and align on the values and principles of Agile can help to overcome misunderstandings and misapplications of these approaches. This may involve providing training or educational resources to stakeholders, and engaging in ongoing communication and collaboration to ensure that everyone is on the same page.</p>
  </li>
  <li>
    <p>Foster a culture of transparency and collaboration: Agile relies on frequent and open communication and collaboration among team members. Creating a culture that values and encourages transparency and collaboration can help to overcome challenges with team communication and collaboration. This may involve providing resources and support for team members to collaborate effectively, and encouraging a culture of open and honest communication.</p>
  </li>
  <li>
    <p>Be flexible and adaptable: Remember that Agile is about adaptability and continuous improvement. Don’t be too rigid in your application of frameworks or practices, and be willing to adjust and adapt as needed based on the needs of your team and your customers.</p>
  </li>
  <li>
    <p>Monitor and track progress regularly: Regular monitoring and tracking of progress can help to identify potential challenges or roadblocks early on, and allow teams to adjust their approach as needed. This may involve using tools like Scrum burndown charts or Kanban boards to visualize work and progress, and holding regular meetings or reviews to assess progress and identify areas for improvement.</p>
  </li>
  <li>
    <p>Seek outside support or guidance: If you’re having trouble implementing Agile practices or overcoming challenges with your approach, don’t be afraid to seek outside support or guidance. This may involve hiring an Agile coach or consultant, or joining a community of Agile practitioners to share best practices and lessons learned.
Thus, Agile methodologies like Scrum, Kanban, Extreme Programming, and SAFe can be powerful approaches to software development, but they require careful consideration and a commitment to the values and principles underlying these approaches. By understanding and addressing the potential pitfalls of these approaches, development teams can increase their chances of success with Agile.</p>
  </li>
</ul>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Software Engineering&quot;]" /><category term="software" /><category term="leadership" /><summary type="html"><![CDATA[In this post I do a quick glance of Agile frameworks, their pitfalls and some high level strategies to avoid those pitfalls.]]></summary></entry><entry><title type="html">Graduated from Georgia Tech</title><link href="https://systemhalted.in/2022/12/12/graduated-gatech/" rel="alternate" type="text/html" title="Graduated from Georgia Tech" /><published>2022-12-12T00:00:00+00:00</published><updated>2022-12-12T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/12/graduated-gatech</id><content type="html" xml:base="https://systemhalted.in/2022/12/12/graduated-gatech/"><![CDATA[<p>#Copied from LinkedIn
I’m excited to announce that I recently completed my MS in Computer Science from Georgia Institute of Technology or Georgia Tech, with a specialization in Computing Systems.</p>

<p>Some of my favorite courses during the course of my studies were Gradute Introduction to Operating Systems (GIOS), Software Analysis and Test (SAT), Network Science (NS), High Performance Computing Architecture (HPCA), Knowledge Based Artificial Intelligence (KBAI), and Introduction to Graduate Algorithms (GA).</p>

<p>It wasn’t always easy balancing work, family, and school, especially during the pandemic, but I’m proud to have made it through and achieved this important milestone. I’m looking forward to seeing where this degree takes me and am grateful for all the support I received along the way. Special thanks to my wife, Priti for sticking with me. This degree certainly tested our relationship at times.  #humblebrag #newlymintedMS #computerscience #computingsystems</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Life Events&quot;]" /><category term="personal" /><summary type="html"><![CDATA[Finally, I completed my MS in Computer Science from Georgia Institute of Technology]]></summary></entry><entry><title type="html">The Role of Management Philosophy for New Managers</title><link href="https://systemhalted.in/2022/12/12/management-philosophy/" rel="alternate" type="text/html" title="The Role of Management Philosophy for New Managers" /><published>2022-12-12T00:00:00+00:00</published><updated>2022-12-12T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/12/management-philosophy</id><content type="html" xml:base="https://systemhalted.in/2022/12/12/management-philosophy/"><![CDATA[<p>As a manager, your philosophy shapes how you approach your work and interact with your team. It influences your decision-making, your communication style, and your overall leadership approach. In short, your management philosophy is an essential component of your effectiveness as a leader.</p>

<p>But what exactly is a management philosophy? In its simplest form, a management philosophy is a set of guiding principles that inform how a manager approaches their role. It can be influenced by a wide range of factors, including personal beliefs, company values, and industry norms.</p>

<p>One of the key benefits of having a well-defined management philosophy is that it provides a clear framework for decision-making. When faced with a challenging situation, a manager can refer to their philosophy to help guide their response. This can help to ensure that decisions are made consistently and in line with the manager’s values and goals.</p>

<p>Another benefit of having a strong management philosophy is that it can help to build trust and credibility with your team. When team members understand your philosophy and know what to expect from you as a manager, they are more likely to trust and respect you. This, in turn, can foster a positive and productive working environment.</p>

<p>But a management philosophy is not just about personal principles – it should also align with the overall goals and values of the organization. A manager who is out of step with their company’s culture and goals is unlikely to be effective in their role. Therefore, it’s important for managers to take the time to understand the organization’s mission, vision, and values, and to ensure that their philosophy aligns with these.</p>

<p>So, how can you develop your own management philosophy? Here are a few steps to get you started:</p>

<ol>
  <li>Reflect on your personal beliefs and values. What do you believe in and what is important to you?</li>
  <li>Consider the goals and values of your organization. How do these align with your own beliefs and values?</li>
  <li>Define your management approach. What is your leadership style and how do you like to work with your team?</li>
  <li>Communicate your philosophy to your team. Let them know what they can expect from you as a manager, and how you will approach your role.</li>
</ol>

<p>To summarize, having a well-defined management philosophy is an essential component of effective leadership. It provides a clear framework for decision-making, helps to build trust and credibility with your team, and ensures that your approach aligns with the goals and values of your organization. By taking the time to develop your own philosophy, you can become a more effective and confident manager.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Personal Essays&quot;]" /><category term="personal" /><category term="opinion" /><category term="sports" /><category term="leadership" /><category term="management" /><summary type="html"><![CDATA[As a manager and specially as a new manager, your philosophy and approach to leadership can have a significant impact on your team and the overall success of your organization. Whether you're new to management or an experienced leader, it's important to have a clear and well-defined management philosophy that guides your actions and decisions.]]></summary></entry><entry><title type="html">Nazeer Akbarabadi - Mahadevji ka byah</title><link href="https://systemhalted.in/2022/12/11/nazeer-akbarabadi-mahadevji-ka-byah/" rel="alternate" type="text/html" title="Nazeer Akbarabadi - Mahadevji ka byah" /><published>2022-12-11T00:00:00+00:00</published><updated>2022-12-11T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/11/nazeer-akbarabadi-mahadevji-ka-byah</id><content type="html" xml:base="https://systemhalted.in/2022/12/11/nazeer-akbarabadi-mahadevji-ka-byah/"><![CDATA[<p>Nazeer Akbarabadi, a contemporary poet of Mir Taqi Mir, was born in Delhi. He moved to Agra when he was around 21-22 years old as Mughal Empire started declining during the the reign of Mohammad Shah and Alamgir II.</p>

<p>Nazeer Akbarabadi loved Agra so much that though he was born in Delhi and moved to Agra as a grown men, he took Akbarabadi as his Taqallus or pen name. Agra was also known as Akbarabad as it was re-founded by Akbar.</p>

<p>He wrote beautiful poetry on Indian, specially Hindu festivals. 
His poetry is a great example Ganga-Jamuni Tehzeeb (culture), showcasing the syncretic Indian and Muslim thought.
Here I am presenting one of his Nazms, “Mahadevji ka Byah”</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    पहले नाँव गणेश का, लीजिए सीस नवाए 
    जा से कारज सिद्ध हों, सदा महूरत लाए 
    pahle naañv ganesh kaa, lījiye siis navā.e 
    jā se kāraj sidh hoñ, sadā mahūrat laa.e 

    बोल बचन आनंद के, प्रेम, पीत और चाह 
    सुन लो यारो, ध्यान धर, महादेव का ब्याह 
    bol bachan ānand ke, prem, piit aur chaah 
    sun lo yāro, dhyān dhar, mahādev kā byaah 

    जोगी जंगम से सुना, वो भी किया बयान 
    और कथा में जो सुना, उस का भी परमाण 
    jogī jañgam se sunā, vo bhī kiyā bayān 
    aur kathā meñ jo sunā, us kā bhī parmān 

    सुनने वाले भी रहें हँसी ख़ुशी दिन रैन 
    और पढ़ें जो याद कर, उन को भी सुख चैन 
    sunñe vaale bhī raheñ hañsī ḳhushī din rain 
    aur paḌheñ jo yaad kar, un ko bhī sukh chain 

    और जिस ने इस ब्याह की, महिमा कही बनाए 
    उस के भी हर हाल में, शिव-जी रहें सुहाए 
    aur jis ne is byaah kii, mahimā kahī banā.e 
    us ke bhī har haal meñ, shiv-jī raheñ suhā.e 

    ख़ुशी रहे दिन रात वो, कभी न हो दिल-गीर 
    महिमा उस की भी रहे जिस का नाम 'नज़ीर'  
    ḳhushī rahe din raat vo, kabhī na ho dil-gīr 
    mahimā us kī bhī rahe jis kā naam 'nazīr'
</code></pre></div></div>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Politics &amp; Governance&quot;, &quot;Poetry &amp; Literature&quot;]" /><category term="politics" /><category term="poetry" /><category term="travel" /><category term="india" /><category term="agra" /><category term="hindi" /><summary type="html"><![CDATA[This post is about Nazeer Akbarabadi (1735-1830), a poet who wrote beautiful poetry on Indian festivals.]]></summary></entry><entry><title type="html">Problem with Delivery Apps</title><link href="https://systemhalted.in/2022/12/08/delivery-apps/" rel="alternate" type="text/html" title="Problem with Delivery Apps" /><published>2022-12-08T00:00:00+00:00</published><updated>2022-12-08T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/08/delivery-apps</id><content type="html" xml:base="https://systemhalted.in/2022/12/08/delivery-apps/"><![CDATA[<p>The problem with delivery apps like Grubhub, DoorDash, Instacart, etc. is :</p>

<ol>
  <li>Marked up price</li>
  <li>Service Fee</li>
  <li>Delivery Fee</li>
  <li>Tips</li>
</ol>

<p>Adding 2, 3 and 4, the cost is almost equal to 1. Means you are paying double.
I am not sure why the onus of providing a reasonable living to the delivery driver is on the customer through tips when the customer is already paying Delivery Fee and Service Fee. ￼</p>

<p>I know it is a controversial topic to touch in USA but that is mind boggling that a company has its entire revenue model where it can push the onus of their “employee” paychecks on the end customer in addition to charging the cost of providing the service to the customer.</p>

<p>Basically, they are screwing both the customer and their “employees”.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Personal Essays&quot;, &quot;Society &amp; Economy&quot;]" /><category term="personal" /><category term="opinion" /><category term="society" /><category term="economy" /><category term="united-states" /><summary type="html"><![CDATA[There are certainly problems with Delivery Apps when it comes down to employee and customer satisfaction. A quick take.]]></summary></entry><entry><title type="html">What is Advaita Vedanta?</title><link href="https://systemhalted.in/2022/12/04/advaita-vedanta/" rel="alternate" type="text/html" title="What is Advaita Vedanta?" /><published>2022-12-04T00:00:00+00:00</published><updated>2022-12-04T00:00:00+00:00</updated><id>https://systemhalted.in/2022/12/04/advaita-vedanta</id><content type="html" xml:base="https://systemhalted.in/2022/12/04/advaita-vedanta/"><![CDATA[<p>In few of my past posts on AI, I used Advaita Vedanta to come up with a test of intelligence. But did not discuss Advaita Vedanta. This post is to fill that gap.</p>

<p>Advaita Vedanta is a school of Hindu philosophy that teaches the concept of non-dualism, or the idea that the individual self and the universal self are one and the same. This philosophy is based on the teachings of the Upanishads, which are part of the Vedas, the oldest sacred texts of Hinduism.</p>

<p>The main proponent of Advaita Vedanta was the 8th century philosopher Adi Shankara, who is considered to be one of the greatest Hindu philosophers of all time. Shankara’s interpretation of the Upanishads emphasized the concept of non-dualism, which he believed was the ultimate goal of spiritual practice.</p>

<p>According to Advaita Vedanta, the individual self and the universal self are not separate entities, but rather two aspects of the same reality. This means that the ultimate goal of spiritual practice is not just to attain happiness or enlightenment, but rather to realize the oneness of the individual self and the universal self.</p>

<p>This realization is known as moksha, or liberation from the cycle of reincarnation. It is believed that once an individual realizes their oneness with the universal self, they are freed from the endless cycle of birth, death, and rebirth.</p>

<p>In order to achieve this realization, Advaita Vedanta recommends a number of spiritual practices, such as meditation, yoga, and study of the Vedas. These practices are designed to help an individual cultivate a deeper understanding of the non-dual nature of reality, and to gradually let go of the false belief in a separate self.</p>

<p>One of the key concepts in Advaita Vedanta is the idea of Maya, or illusion. This refers to the idea that the world we perceive with our senses is not real, but rather a manifestation of the universal self. In other words, the world we see is not the true reality, but rather a projection of our own consciousness.</p>

<p>This idea may seem difficult to understand at first, but it is actually a very profound and powerful concept. By recognizing the illusory nature of the world, we can begin to let go of our attachment to it, and instead focus on the ultimate reality of the non-dual self.</p>

<p>In conclusion, Advaita Vedanta is a powerful and transformative philosophy that teaches the concept of non-dualism. Through the realization of the oneness of the individual self and the universal self, we can attain liberation (from the cycle of reincarnation) and experience true freedom and peace.</p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Spirituality &amp; Philosophy&quot;]" /><category term="leadership" /><summary type="html"><![CDATA[Advaita Vedanta is a powerful and transformative philosophy that teaches the concept of non-dualism. Through the realization of the oneness of the individual self and the universal self, we can attain liberation from the cycle of reincarnation and experience true freedom and peace.]]></summary></entry><entry><title type="html">दूर आगरा से</title><link href="https://systemhalted.in/2022/11/27/door-agra-se/" rel="alternate" type="text/html" title="दूर आगरा से" /><published>2022-11-27T00:00:00+00:00</published><updated>2022-11-27T00:00:00+00:00</updated><id>https://systemhalted.in/2022/11/27/door-agra-se</id><content type="html" xml:base="https://systemhalted.in/2022/11/27/door-agra-se/"><![CDATA[<p>This probably is my first Ghazal.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>दूर आगरा से (door Agra se)
==================
घर से निकले, निकल आये दूर आगरा से,
रात सोते में सपने आये दूर आगरा से
Ghar se nikle, nikal aaye door Agra se,
Raat sote mein, sapne aaye door Agra se

कब जाएँगे, इसका इल्म नहीं है मुझको,
कैसे रह पायेंगे हमसाये दूर आगरा से
Kab jayenge, iska ilm nahin hai mujhko,
Kaise reh payenge, humsaaye door Agra se

तड़प है दिल में, छटपटा रहा हूँ मैं,
कब तक बेबस, जिया जाए दूर आगरा से
Tadap hai dil mein, chatapata raha hoon main,
Kab tak bebas, jiya jaye door Agra se

‘पलक’ आंसुओं से है भीगी हुई मेरी,
क्यूँकर गुमसुम यह रह पाये दूर आगरा से
‘Palak’ aansuon se hai bheegi hui meri,
Kyun kar gumsum yeh reh paaye door Agra se

~पलक (Palak)
</code></pre></div></div>

<p><img src="/assets/images/taj-lego.jpeg" alt="" /></p>]]></content><author><name>systemhalted</name><email>insanethoughts@live.com</email></author><category term="[&quot;Poetry &amp; Literature&quot;]" /><category term="poetry" /><category term="travel" /><category term="agra" /><category term="hindi" /><summary type="html"><![CDATA[Here I try to express my life, H1B and GC travails using Mir's couplets.]]></summary></entry></feed>