<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://karei.codeberg.page/</id>
    <title>Karei's Blog Blog</title>
    <updated>2026-05-24T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://karei.codeberg.page/"/>
    <subtitle>Karei's Blog Blog</subtitle>
    <icon>https://karei.codeberg.page/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[C Chose the Wrong Origin: Why 1-Based Indexing Is Better Language Design]]></title>
        <id>https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/</id>
        <link href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/"/>
        <updated>2026-05-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[The first element is the first element, not the zeroth element.]]></summary>
        <content type="html"><![CDATA[<p><em>The first element is the first element, not the zeroth element.</em></p>
<p>For decades, we have been told by systems programmers that counting from zero is "closer to the metal," "mathematically purer," and the definitive mark of a "real programmer." Languages that use 1-based indexing—like Julia, R, MATLAB, and Fortran—are often patronized as quirky tools for mathematicians who just "don't understand computer science."</p>
<p>I call bullshit.</p>
<!-- -->
<p>0-based indexing is not a fundamental law of computing. It is an implementation leak. The first item in a sequence becomes the "zeroth" element only when you choose to describe it by its displacement from a memory address. While that perspective is perfectly valid for pointer arithmetic, buffers, and low-level boundaries, it is fundamentally the wrong way to name human-facing objects.</p>
<p>What started as a bare-metal address-offset convention in C was wrongfully elevated into a universal philosophy of language design. By forcing humans to adopt this machine-centric view for high-level mathematical modeling, the software industry has condemned generations of developers to a permanent, exhausting cognitive friction.</p>
<p>It is time to tear down this illusion. Let's start from the very beginning: how human beings actually perceive the world.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-elementary-school-reality-check">The Elementary School Reality Check<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-elementary-school-reality-check" class="hash-link" aria-label="Direct link to The Elementary School Reality Check" title="Direct link to The Elementary School Reality Check" translate="no">​</a></h3>
<p>Before we even touch a keyboard, every single human being learns to count objects starting from 1. This isn't just an arbitrary childhood habit; it is the fundamental reality of discrete mathematics.</p>
<p>Let's look at a classic elementary school math problem—the "Tree-Planting Problem." Imagine a row of trees:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">O  O  O  O  O  O  O  O</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">1  2  3  4  5  6  7  8</span><br></div></code></pre></div></div>
<p><em>Question: How many trees are there from the 3rd tree to the 7th tree, inclusive?</em></p>
<p>Any second-grader will tell you the answer: <code>7 - 3 + 1 = 5</code>.</p>
<p>The formula for the number of elements in a closed interval <code>[i, j]</code> is <code>j - i + 1</code>. This formula is hardwired into human intuition because it accurately describes the physical reality of discrete objects.</p>
<p>Yet, the 0-based zealots will look at this and complain: <em>"Ugh, that <code>+1</code> is so ugly and error-prone! We should use half-open intervals <code>[i, j)</code> and 0-based indexing so the length is just <code>j - i</code>!"</em></p>
<p>This is where the delusion begins. To avoid typing a simple <code>+1</code>—a mathematical truth of closed intervals—0-based languages force you to shift your entire cognitive model of the universe. They demand that the first tree be called the "zeroth tree." They sacrifice the natural naming of physical entities just to make the arithmetic of interval boundaries look marginally cleaner.</p>
<p>Trading a massive, global cognitive distortion for a microscopic local algebraic convenience is not good engineering. It is anti-human.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="objects-are-not-offsets">Objects are Not Offsets<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#objects-are-not-offsets" class="hash-link" aria-label="Direct link to Objects are Not Offsets" title="Direct link to Objects are Not Offsets" translate="no">​</a></h2>
<p>The central distinction that the 0-based camp refuses to acknowledge is this:</p>
<p><strong>1-based indexing names objects.</strong>
<strong>0-based indexing names displacements.</strong></p>
<p>When humans refer to physical or mathematical entities, we use ordinal positions: the first child, the first employee, the first row of a matrix, the first equation in a dynamic system. Nobody naturally says "the zeroth apple" or "the zeroth physical unit."</p>
<p>Of course, a programming language can redefine reality. A language can dictate anything. But forcing a definition that violently conflicts with human cognition is the hallmark of poor language design.</p>
<p>Consider a simple sequence:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Elements:      A   B   C</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Object Index:  1   2   3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Offset:        0   1   2</span><br></div></code></pre></div></div>
<p>Both integer rows describe something real, but they answer entirely different questions.
The object index answers: <em>"Which object is this?"</em>
The offset answers: <em>"How far is this object from the chosen origin?"</em></p>
<p>A good language design should not pretend they are the same thing. The first element has a displacement of 0 from the beginning. That is a physical truth of memory layout. But it is still the <em>first</em> element. Confusing these two facts is the original sin of 0-based indexing.</p>
<blockquote>
<p>The first object is not an offset. It is an object.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-semantic-theft-offset-is-not-identity">The Semantic Theft: Offset is NOT Identity<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-semantic-theft-offset-is-not-identity" class="hash-link" aria-label="Direct link to The Semantic Theft: Offset is NOT Identity" title="Direct link to The Semantic Theft: Offset is NOT Identity" translate="no">​</a></h2>
<p>The root of this madness lies in the C programming language and its pointer arithmetic:</p>
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">a</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">i</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">*</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">a </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> i</span><span class="token punctuation" style="color:#393A34">)</span><br></div></code></pre></div></div>
<p>In C, <code>i</code> is not an "index" in the mathematical sense. It is an <em>offset</em> (displacement). It answers the question: <em>"How many memory strides away are we from the base address?"</em> The first element is 0 strides away, hence <code>a[0]</code>.</p>
<p>As a low-level machine implementation, this is completely logical. But here is the critical distinction:</p>
<p><strong>Offset is an implementation perspective. Ordinal (1st, 2nd, 3rd) is a user-facing identity.</strong></p>
<p>When you write a mathematical formula like <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>∑</mo><mo stretchy="false">{</mo></msub><mi>i</mi><mo>=</mo><mn>1</mn><msup><mo stretchy="false">}</mo><mo stretchy="false">{</mo></msup><mi>N</mi><mo stretchy="false">}</mo><msub><mi>x</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">\sum_\{i=1\}^\{N\} x_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mopen mtight">{</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:1.138em;vertical-align:-0.25em"></span><span class="mord">1</span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mopen mtight">{</span></span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.109em">N</span><span class="mclose">}</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em"><span></span></span></span></span></span></span></span></span></span>, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em"></span><span class="mord mathnormal">i</span></span></span></span> represents the <em>identity</em> of the variable. It answers the question: <em>"Which specific object is this?"</em></p>
<p>0-based languages commit the ultimate semantic theft: they take a machine-level offset coordinate and violently force it onto the user as an object identity. They force you to run a permanent, non-stop "translation daemon" in the back of your mind. Every time you want the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em"></span><span class="mord mathnormal" style="margin-right:0.0315em">k</span></span></span></span>-th element, you must subconsciously calculate <code>k - 1</code>.</p>
<p>This is not a "frictionless" programming experience. This is cognitive labor. You are manually doing the translation that the compiler was invented to do for you.</p>
<blockquote>
<p>Machines are built to serve humans, not the other way around. If my mathematical model starts at 1, the language should start at 1.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-dijkstra-fallacy-counting-gaps-vs-counting-objects">The Dijkstra Fallacy: Counting Gaps vs. Counting Objects<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-dijkstra-fallacy-counting-gaps-vs-counting-objects" class="hash-link" aria-label="Direct link to The Dijkstra Fallacy: Counting Gaps vs. Counting Objects" title="Direct link to The Dijkstra Fallacy: Counting Gaps vs. Counting Objects" translate="no">​</a></h2>
<p>So, how did this semantic theft become a religious dogma? Whenever you attack 0-based indexing, someone will inevitably quote Edsger W. Dijkstra's famous manuscript, <em>Why numbering should start at zero (EWD831)</em>.</p>
<p>Dijkstra argued that using half-open intervals <code>0 &lt;= i &lt; N</code> is the cleanest way to represent sequences, as the length is simply <code>N - 0 = N</code>, and adjacent sequences share a clean boundary.</p>
<p>Let's dismantle this sacred cow. Dijkstra was an absolute genius, but in this specific argument, he committed a massive semantic theft: <strong>he conflated objects with boundaries.</strong></p>
<p>Look at a sequence of elements:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Elements:      A   B   C   D   E</span><br></div></code></pre></div></div>
<p>If you are slicing an array, inserting an element, or calculating a prefix sum, you are dealing with boundaries, or gaps:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Boundaries:  0   1   2   3   4   5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">             | A | B | C | D | E |</span><br></div></code></pre></div></div>
<p>Yes, boundaries start at 0. The gap <em>before</em> the first element is gap 0. Prefix lengths start at 0. Displacements start at 0. Dijkstra perfectly optimized the algebra of boundaries.</p>
<p>But a programming array is primarily a collection of elements, not just boundaries. Element <code>A</code> is the <em>1st</em> object. Element <code>B</code> is the <em>2nd</em> object.</p>
<blockquote>
<p>The fact that an algorithm has a zero state does not mean the data objects inside that algorithm should be zero-indexed.</p>
</blockquote>
<p>Dijkstra's fatal flaw was forcing the numbering system of <em>boundaries</em> onto the <em>objects</em> themselves. Just because the boundary before <code>A</code> is 0, it does not mean the object <code>A</code> itself should be named 0. You cannot rename a discrete physical object just because it makes your slicing syntax slightly prettier.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-0-0-grid-machine-thinking-in-disguise">The (0, 0) Grid: Machine Thinking in Disguise<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-0-0-grid-machine-thinking-in-disguise" class="hash-link" aria-label="Direct link to The (0, 0) Grid: Machine Thinking in Disguise" title="Direct link to The (0, 0) Grid: Machine Thinking in Disguise" translate="no">​</a></h2>
<p>The desire to unify everything under 0-based coordinates leads to the modern nightmare of LeetCode grid problems. When you do that, you get the modern nightmare of LeetCode grid problems: forcing developers to map a 2D physical grid starting from <code>(0,0)</code>. A matrix cell is an object, not a displacement vector. Calling the upper-left cell <code>(0,0)</code> is not mathematics; it is storage layout leaking into the problem statement, violently bullying human intuition.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-false-unity-of-0-based-coordinates">The false unity of 0-based coordinates<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-false-unity-of-0-based-coordinates" class="hash-link" aria-label="Direct link to The false unity of 0-based coordinates" title="Direct link to The false unity of 0-based coordinates" translate="no">​</a></h2>
<p>Another defense of 0-based indexing is that it creates one unified coordinate system:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">element index</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">boundary index</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">prefix length</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">storage offset</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">slice endpoint</span><br></div></code></pre></div></div>
<p>can all be represented with the same integers if indexing starts from 0. This supposedly reduces conversions and therefore reduces mistakes.</p>
<p>This sounds plausible only if one has already accepted the offset worldview. From the perspective of object-centered programming, it is not simplification. It is semantic compression with hidden costs.</p>
<p>But this is not true semantic unity. It is flattening different meanings into one number system.</p>
<p>The price of this flattening is that object identity gets distorted. The first element becomes <code>0</code> so that boundaries, offsets, and prefix lengths can look cleaner.</p>
<p>Even in low-level buffer manipulation, this should be understood as an implementation convention, not as a superior human-facing indexing model. It is certainly not a universal language design principle.</p>
<p>0-based indexing does not eliminate off-by-one reasoning. It relocates it. It reduces some boundary errors by creating object-identity errors.</p>
<p>In a 1-based model, we may still write transformations such as:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">physical_offset = object_index - 1</span><br></div></code></pre></div></div>
<p>That is fine. The point is not to make <code>-1</code> disappear from the universe. The point is to put the cognitive burden in the right place.</p>
<p>If we are dealing with implementation offsets, let offset conversion happen there. If we are dealing with human-facing object indices, the first object should be 1.</p>
<blockquote>
<p>A notation that is locally elegant for slicing but globally hostile to object naming is not good language design.</p>
</blockquote>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-myth-of-the-extra-subtraction">The Myth of the "Extra Subtraction"<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-myth-of-the-extra-subtraction" class="hash-link" aria-label="Direct link to The Myth of the &quot;Extra Subtraction&quot;" title="Direct link to The Myth of the &quot;Extra Subtraction&quot;" translate="no">​</a></h2>
<p>When defenders of 0-based indexing are backed into a corner, they almost always resort to the classic performance argument:
<em>"1-based indexing is inefficient. If you start at 1, the compiler has to waste CPU cycles doing <code>*(base + i - 1)</code> for every array access!"</em></p>
<p>This argument is incredibly persistent, but it is fundamentally flawed. It exposes a profound lack of imagination regarding how programming language compilers and object models actually work.</p>
<p>The critique <code>*(base + i - 1)</code> assumes that the logical origin of an array <em>must</em> be the physical address of its very first element. Yes, if you blindly force a 1-based index into a 0-based origin model, you get a <code>-1</code> penalty.</p>
<p>But why should we accept the 0-based origin model as absolute truth?</p>
<p>Enter the <em>Virtual Origin Shift</em>.</p>
<p>A modern, intelligently designed 1-based language does not patch a 0-based system; it redefines the origin. Instead of anchoring the array to the first physical element, the compiler can simply set the logical origin (the base pointer) to the position of a <em>one-before-begin sentinel</em>.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Physical memory:  [ element_1 ] [ element_2 ] [ element_3 ]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                  ^</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                  physical_base</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Logical origin:   virtual_base = physical_base - sizeof(element)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Memory access:    A[i] = *(virtual_base + i)   for i = 1, 2, ...</span><br></div></code></pre></div></div>
<p>Look at that. There is no <code>i - 1</code>. There is no performance penalty. There is no extra subtraction at runtime. The memory offset calculation for 1-based indexing (<code>origin + i</code>) is exactly as elegant and direct as it is for 0-based indexing.</p>
<p>C standardizes the "one-past-end" sentinel to make 0-based slicing neat. A 1-based language simply leverages a "one-before-begin" virtual origin. Both models are perfectly coherent at the hardware level. The difference is that the 1-based model hides the offset translation inside the compiler, leaving the human user with a clean, mathematically accurate interface.</p>
<p>0-based indexing is not the "natural consequence of memory." It is the natural consequence of choosing the wrong origin and forcing the human to do the compiler's job.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-illusion-of-off-by-one-prevention">The Illusion of "Off-by-One" Prevention<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#the-illusion-of-off-by-one-prevention" class="hash-link" aria-label="Direct link to The Illusion of &quot;Off-by-One&quot; Prevention" title="Direct link to The Illusion of &quot;Off-by-One&quot; Prevention" translate="no">​</a></h2>
<p>Another desperate defense is that 0-based indexing prevents "off-by-one" errors (OBOEs). The claim is that half-open intervals <code>[0, N)</code> magically solve boundary mistakes.</p>
<p>Let's be brutally honest: 0-based indexing does not eliminate off-by-one errors. <strong>It merely relocates them.</strong></p>
<p>It reduces some errors when slicing buffers, but it creates a massive, permanent source of errors in object identity and algorithm design. When you are writing a complex Dynamic Programming (DP) algorithm, or implementing a mathematical formula from a research paper, you are inherently dealing with <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em"></span><span class="mord mathnormal">i</span></span></span></span>-th states and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>j</mi></mrow><annotation encoding="application/x-tex">j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em"></span><span class="mord mathnormal" style="margin-right:0.0572em">j</span></span></span></span>-th characters.</p>
<p>In a 0-based language, if state <code>i</code> represents the first <code>i</code> characters, but the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em"></span><span class="mord mathnormal">i</span></span></span></span>-th character itself is at <code>string[i-1]</code>, you have engineered a cognitive nightmare. The code becomes littered with <code>s[i-1]</code> patches. This isn't just "writing a few more characters"; this is severe semantic misalignment.</p>
<p>When a language design forces you to constantly doubt whether <code>i</code> means "the <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em"></span><span class="mord mathnormal">i</span></span></span></span>-th object" or "an offset of <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em"></span><span class="mord mathnormal">i</span></span></span></span>", it breeds paranoia. In 1-based languages, if the math says <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mo stretchy="false">{</mo></msub><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">A_\{i, j\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mopen mtight">{</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em"><span></span></span></span></span></span></span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord mathnormal" style="margin-right:0.0572em">j</span><span class="mclose">}</span></span></span></span>, the code says <code>A[i, j]</code>. The boundary of the physical entity perfectly aligns with the logical boundary.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion-reclaiming-human-intuition">Conclusion: Reclaiming Human Intuition<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#conclusion-reclaiming-human-intuition" class="hash-link" aria-label="Direct link to Conclusion: Reclaiming Human Intuition" title="Direct link to Conclusion: Reclaiming Human Intuition" translate="no">​</a></h2>
<p>The debate between 0-based and 1-based indexing is not just about syntax. It is about who yields to whom in the software engineering hierarchy.</p>
<p>The 0-based paradigm demands that the human mind bends to accommodate the machine's memory layout. It wraps this compromise in the guise of "elegance" and "professionalism," punishing those who rely on natural human counting.</p>
<p>1-based indexing, when implemented with modern compiler architecture, proves that we do not have to compromise. We can have bare-metal, C-level performance without sacrificing the purity of mathematical modeling.</p>
<p>It is time to stop pretending that <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em"></span><span class="mord">0</span></span></span></span> is the start of a sequence of objects. Zero is a count. Zero is an offset. Zero is empty.</p>
<p>But the first element? The first element is exactly that: <em>1</em>.</p>
<p>If we truly want to reduce cognitive load and rediscover the pure joy of programming, it begins with choosing the right origin. It begins by counting from 1.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="epilogue-the-psychology-of-the-0-based-programmers">Epilogue: The Psychology of the 0-Based Programmers<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#epilogue-the-psychology-of-the-0-based-programmers" class="hash-link" aria-label="Direct link to Epilogue: The Psychology of the 0-Based Programmers" title="Direct link to Epilogue: The Psychology of the 0-Based Programmers" translate="no">​</a></h2>
<p>If the mathematical and architectural arguments for 1-based indexing are so robust, why does the mainstream programming community defend 0-based indexing with such religious fervor?</p>
<p>The answer does not lie in computer science. It lies in social psychology. The relentless defense of 0-based indexing is a textbook manifestation of two well-documented psychological phenomena: <em>Cognitive Dissonance</em> and the <em>Sweet Lemon Effect</em>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-cognitive-dissonance-the-sunk-cost-of-brain-rewiring">1. Cognitive Dissonance: The Sunk Cost of Brain Rewiring<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#1-cognitive-dissonance-the-sunk-cost-of-brain-rewiring" class="hash-link" aria-label="Direct link to 1. Cognitive Dissonance: The Sunk Cost of Brain Rewiring" title="Direct link to 1. Cognitive Dissonance: The Sunk Cost of Brain Rewiring" translate="no">​</a></h3>
<p>Every Computer Science student and IT professional has gone through the painful, counter-intuitive process of rewiring their natural human cognition to adapt to the machine's 0-based memory layout. It took years of debugging <code>Index Out of Bounds</code> errors and mentally calculating <code>i - 1</code> to finally make this unnatural habit feel "automatic."</p>
<p>When you present these developers with the fact that 1-based indexing is a superior, zero-friction design for object modeling, it triggers massive <em>Cognitive Dissonance</em>.</p>
<p>To accept that 1-based indexing is better is to accept a devastating truth: <em>The immense mental effort they spent over the last decade adapting to the machine was largely unnecessary.</em> It means admitting that their "hard-earned programming intuition" is not a mark of high intelligence, but merely a scar left by a 1970s hardware compromise.</p>
<p>Human ego inherently rejects this. To protect their self-worth and justify their sunk costs, they instinctively lash out. They must fiercely defend 0-based indexing, not because it is mathematically correct, but to convince themselves that their suffering had meaning.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-the-sweet-lemon-effect-rationalizing-the-matrix">2. The Sweet Lemon Effect: Rationalizing the Matrix<a href="https://karei.codeberg.page/c-wrong-origin-1-based-indexing-language-design/#2-the-sweet-lemon-effect-rationalizing-the-matrix" class="hash-link" aria-label="Direct link to 2. The Sweet Lemon Effect: Rationalizing the Matrix" title="Direct link to 2. The Sweet Lemon Effect: Rationalizing the Matrix" translate="no">​</a></h3>
<p>The second psychological barrier is the brutal reality of the job market.</p>
<p>Deep down, many smart engineers know that 1-based languages (like Julia) offer a far more elegant and mathematically pure experience. But they also know they are trapped. The corporate world, the tech giants, and the global job market are completely dominated by C, Java, Python, and JavaScript. They are chained to the 0-based monolith to pay their bills and advance their careers.</p>
<p>When you cannot have what is good, the mind protects itself by deciding that what you <em>do</em> have is actually exactly what you wanted all along. This is the <em>Sweet Lemon Effect</em> (the inverse of sour grapes).</p>
<p>Instead of facing the depressing reality that they are just digital laborers forced to use suboptimal, legacy tools dictated by corporate momentum, they deceive themselves. They hallucinate non-existent mathematical elegance in 0-based slicing. They convince themselves the "lemon" is sweet. They chant <em>"0-based is closer to the metal"</em> to mask the bitter taste of having no choice in the matter.</p>
<p>The defense of 0-based indexing is rarely about logic anymore. It is an industry-wide coping mechanism.</p>
<p>Whether you are building a high-level mathematical model, a web backend, or a low-level memory buffer, demanding 1-based indexing is not just a syntactic preference. You are rejecting the cognitive labor imposed by a 1970s hardware constraint. You are demanding that the language design enforces a fundamental separation of concerns: the compiler handles the offsets, and the human handles the objects.</p>
<p>And objects start at 1.</p>]]></content>
        <category label="Language Design" term="Language Design"/>
        <category label="Arrays" term="Arrays"/>
        <category label="Indexing" term="Indexing"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Putting User Assets Back in the Hands of Users: LLMs, Open Formats, and Controllable Toolchains]]></title>
        <id>https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/</id>
        <link href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/"/>
        <updated>2026-05-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A small observation about AI poster and slides generators led me to a much larger question: who actually controls the assets we create?]]></summary>
        <content type="html"><![CDATA[<p>A small observation about AI poster and slides generators led me to a much larger question: who actually controls the assets we create?</p>
<!-- -->
<p>At first glance, the market looks full of convenient tools. There are AI poster generators, AI slide makers, AI document editors, AI diagram tools, AI writing platforms, and many polished Software as a Service (SaaS) products that promise to turn a prompt into a beautiful output. For many users, this is attractive. You type a sentence, pick a template, drag a few objects, and export a PDF.</p>
<p>But once I looked at the problem from the perspective of a geek, the surface convenience became less interesting than the underlying structure.</p>
<p>A poster is not just a picture. A technical diagram is not just decoration. A paper is not just formatted text. These are user assets. They encode ideas, methods, assumptions, structures, relationships, workflows, evidence, and arguments. If these assets are created inside a black-box platform, then the user may be able to edit them visually, but does not fully own the logic by which they are represented, rendered, transformed, and preserved.</p>
<p>That distinction matters.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-problem-is-not-whether-ai-can-generate-a-poster">The problem is not whether AI can generate a poster<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#the-problem-is-not-whether-ai-can-generate-a-poster" class="hash-link" aria-label="Direct link to The problem is not whether AI can generate a poster" title="Direct link to The problem is not whether AI can generate a poster" translate="no">​</a></h2>
<p>Many AI poster tools probably do not rely purely on image generation. Behind the scenes, they likely use some internal object model: text boxes, shapes, panels, coordinates, fonts, colors, and layout constraints. The final poster may be editable in a web GUI. In that narrow sense, they are not merely producing a dead image.</p>
<p>But that does not solve the real problem.</p>
<p>The issue is not whether a poster consists of editable objects. The issue is whether the user has access to the object model, the file format, the rendering logic, and the toolchain that turns source representation into visual output.</p>
<p>A closed SaaS platform may give me objects to drag. But those objects live inside someone else's system. The platform controls the schema, the renderer, the export logic, the templates, the pricing, and the future compatibility of my work. I can edit what the platform allows me to edit. I can export what the platform allows me to export. I can preserve what the platform allows me to preserve.</p>
<p>That is not the same as owning the asset.</p>
<p>This is why I became interested in a very different workflow:</p>
<p>Natural language intention -&gt; LLM-assisted source editing -&gt; open structured file -&gt; open renderer/editor -&gt; human visual refinement -&gt; portable output.</p>
<p>In practice, one concrete version of this is:</p>
<p>LLM -&gt; draw.io XML -&gt; diagrams.net/draw.io GUI -&gt; SVG/PDF/PNG export.</p>
<p>At first, this sounds like a cheap trick: instead of paying for an AI poster SaaS, ask an LLM to edit a draw.io XML file directly.</p>
<p>But the deeper point is not cost. The deeper point is control.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="xml-alone-is-not-enough">XML alone is not enough<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#xml-alone-is-not-enough" class="hash-link" aria-label="Direct link to XML alone is not enough" title="Direct link to XML alone is not enough" translate="no">​</a></h2>
<p>It is tempting to say that draw.io works well with LLMs because its file format is XML. XML is text. LLMs can read text, modify text, and produce text. Therefore, LLMs can edit draw.io files.</p>
<p>That explanation is only half correct.</p>
<p>Many commercial formats are also structured. A <code>.docx</code> file, for example, is essentially a package containing XML files. It is not a mysterious binary blob in the old sense. In principle, one can inspect it, modify it, and generate it.</p>
<p>But anyone who has dealt seriously with Word documents knows the problem: readable does not mean predictable.</p>
<p>Word processing formats carry decades of historical compatibility. The specification may contain behaviors inherited from old versions, compatibility modes, layout conventions, default settings, and implementation-dependent interpretations. You may edit the XML, but the GUI may not behave as expected. You may change a paragraph style, only to discover that numbering, spacing, table layout, floating objects, fonts, or pagination are affected by rules hidden somewhere else.</p>
<p>The file is structured, but the system is not fully transparent.</p>
<p>This is the critical distinction:</p>
<p><em>Structured format is not the same as controllable toolchain.</em></p>
<p>For LLM collaboration, the problem is not simply whether the file can be read. The problem is whether the LLM can reason about how the file will be interpreted.</p>
<p>In the case of draw.io, the advantage is not merely that the <code>.drawio</code> file is XML. The important point is that the editor and renderer are open enough for the behavior of the file to be studied, debugged, and understood. If something goes wrong in the XML, one can inspect not only the file, but also the logic that interprets the file.</p>
<p>That changes the nature of LLM assistance.</p>
<p>Without access to the rendering logic, the LLM is guessing. With access to the source format and the implementation, the LLM can work within an intelligible graphical language.</p>
<p>XML provides editability. Open implementation provides explainability. The GUI provides human correction. The export formats provide portability.</p>
<p>The power comes from the combination.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-latex-still-matters">Why LaTeX still matters<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#why-latex-still-matters" class="hash-link" aria-label="Direct link to Why LaTeX still matters" title="Direct link to Why LaTeX still matters" translate="no">​</a></h2>
<p>The same idea also applies to documents. This is why LaTeX has remained important for serious technical writing.</p>
<p>LaTeX is not valuable simply because it produces beautiful PDFs. Its deeper value is that it turns documents into source files. A paper becomes something that can be edited as text, version-controlled, searched, diffed, compiled, debugged, and reproduced.</p>
<p>The workflow is transparent in a way that GUI-based document editing often is not. There may still be complexity. LaTeX templates can be painful. Packages can interact in obscure ways. Compilation errors can be ugly. But the document is fundamentally source-driven.</p>
<p>That makes it a natural partner for LLMs.</p>
<p>LLMs are much better at modifying source representations than manipulating opaque GUIs. They can revise Markdown, LaTeX, XML, SVG, YAML, Julia code, configuration files, and structured documents. They can explain diffs, trace errors, update repeated patterns, and refactor text. They can operate where the work is represented as explicit structure.</p>
<p>This is why I currently prefer Quarto for many documents.</p>
<p>Pure LaTeX is powerful, but it can be unnecessarily heavy for everyday writing. Quarto provides a practical front end: Markdown for readable writing, YAML for metadata, Pandoc for conversion, and LaTeX or other backends when needed. It preserves the source-file philosophy while reducing the friction.</p>
<p>In that sense, Quarto is not a rejection of LaTeX. It is a more ergonomic layer over the same general principle:</p>
<p>Keep the core asset as an open, text-based, version-controllable source file.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="llms-should-edit-source-files-not-trap-us-inside-guis">LLMs should edit source files, not trap us inside GUIs<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#llms-should-edit-source-files-not-trap-us-inside-guis" class="hash-link" aria-label="Direct link to LLMs should edit source files, not trap us inside GUIs" title="Direct link to LLMs should edit source files, not trap us inside GUIs" translate="no">​</a></h2>
<p>The strongest form of LLM-assisted work is not "click a magic button in a platform."</p>
<p>It is this:</p>
<p>The user expresses intent.
The LLM translates that intent into modifications of open source files.
The open toolchain renders or compiles those files.
The user inspects and corrects the result.
The final asset remains portable and maintainable.</p>
<p>This is fundamentally different from using an AI feature inside a closed SaaS editor.</p>
<p>In a closed platform, the AI is embedded inside the vendor's environment. The output is often a platform object. The history, schema, rendering, and future compatibility are controlled externally.</p>
<p>In an open-source-file workflow, the LLM is a replaceable assistant. It does not own the document. It does not own the diagram. It does not own the project. It only helps transform an asset that remains under the user's control.</p>
<p>That is the key architectural difference.</p>
<ul>
<li class="">
<p>For posters, this means LLMs should generate or modify draw.io XML, SVG, Mermaid, Graphviz, Typst, or other open representations, rather than only producing flat images or platform-locked designs.</p>
</li>
<li class="">
<p>For documents, this means LLMs should work on Markdown, Quarto, LaTeX, BibTeX, CSL, YAML, and related source files, rather than only operating inside Word or a proprietary cloud editor.</p>
</li>
<li class="">
<p>For software, this means LLMs should work with code, tests, documentation, CI, and reproducible environments, rather than only producing isolated snippets.</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="output-should-be-source-like-not-screenshot-like">Output should be source-like, not screenshot-like<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#output-should-be-source-like-not-screenshot-like" class="hash-link" aria-label="Direct link to Output should be source-like, not screenshot-like" title="Direct link to Output should be source-like, not screenshot-like" translate="no">​</a></h2>
<p>A screenshot is dead. A source file is alive.</p>
<p>A screenshot can be viewed, but not meaningfully edited. A source file can be modified, regenerated, reviewed, and reused. A screenshot captures a moment. A source file captures a process.</p>
<p>This matters especially for technical work, because communication is iterative. Figures change. Terminology changes. Models change. Equations change. Experimental results change. Reviewers ask for revisions. Collaborators ask for different layouts. Posters need new dimensions. A method diagram becomes a figure in a paper, then a slide in a talk, then documentation for software.</p>
<p>If the asset is a flat image or trapped inside a SaaS platform, every revision becomes manual repair.</p>
<p>If the asset is source-like, revisions become engineering operations.</p>
<p>This is why "Poster-as-Code" is not just a slogan. It means treating visual communication as something closer to software or LaTeX: structured, inspectable, editable, and reproducible.</p>
<p>A poster should not be a one-time visual artifact. It should be a maintained representation of an argument.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="open-source-is-not-just-ideology">Open source is not just ideology<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#open-source-is-not-just-ideology" class="hash-link" aria-label="Direct link to Open source is not just ideology" title="Direct link to Open source is not just ideology" translate="no">​</a></h2>
<p>It is easy to frame this as an open-source preference, but that is too shallow.</p>
<p>The real issue is not moral purity. The issue is whether the toolchain allows understanding, debugging, migration, and long-term maintenance.</p>
<p>Open source matters because it makes the interpreter visible.</p>
<p>For a document, the interpreter may be a LaTeX engine, Pandoc, or a rendering pipeline.
For a diagram, the interpreter may be the draw.io/diagrams.net editor and renderer.
For software, the interpreter may be a compiler, package ecosystem, test runner, or CI system.</p>
<p>If the source file is visible but the interpreter is hidden, the workflow remains partially black-boxed. The LLM can edit inputs, but it cannot fully understand why outputs behave as they do.</p>
<p>This is the lesson from Word-like systems. A document format may be technically inspectable, but if the actual rendering behavior depends on a closed, historically layered GUI engine, the result is difficult to predict.</p>
<p>By contrast, when both the source representation and the interpreting toolchain are open, LLM collaboration becomes much more powerful. Errors become traceable. Behavior becomes explainable. Outputs become reproducible. The user can intervene at every layer.</p>
<p>Open source is therefore not merely about avoiding license fees. It is about reducing epistemic dependence on tools whose behavior cannot be fully inspected.</p>
<p>For serious work, that is not a small issue.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cost-is-only-one-part-of-the-story">Cost is only one part of the story<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#cost-is-only-one-part-of-the-story" class="hash-link" aria-label="Direct link to Cost is only one part of the story" title="Direct link to Cost is only one part of the story" translate="no">​</a></h2>
<p>Of course, cost matters. Many students, independent creators, and small teams cannot casually pay for every commercial SaaS tool, design platform, document service, or specialized editor. The financial burden of modern tooling is real.</p>
<p><em>But the deeper cost is lock-in</em>.</p>
<p>A cheap SaaS tool can become expensive if it captures your assets. A convenient platform can become costly if leaving it means losing editability, structure, metadata, or reproducibility. A polished editor can become a liability if its internal format changes, export quality degrades, or pricing model shifts.</p>
<p>This is why I do not think the goal is simply "never spend money."</p>
<p>A better principle is:</p>
<p>Spend money on replaceable resources, not on locking up irreplaceable user assets.</p>
<p>Compute is replaceable. API providers are replaceable. Models are replaceable. Hardware can be upgraded. Even a commercial LLM API can be acceptable if it is only used as a temporary intelligence layer.</p>
<p>But the core assets should remain portable: source files, open formats, version history, reproducible builds, editable diagrams, and local copies.</p>
<p>In my current workflow, an OpenAI API call may help modify a document or diagram. But the resulting asset is not stored inside OpenAI. It is not a proprietary AI-platform object. It is a Quarto file, a Markdown file, a draw.io XML file, a Julia source file, an SVG, or a PDF.</p>
<p>The LLM service can be replaced later by another API or by a local LLM running on my own GPU. The core workflow remains intact.</p>
<p>That is the difference between using a commercial service and being owned by one.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-personal-workstation-not-a-saas-dependency-chain">A personal workstation, not a SaaS dependency chain<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#a-personal-workstation-not-a-saas-dependency-chain" class="hash-link" aria-label="Direct link to A personal workstation, not a SaaS dependency chain" title="Direct link to A personal workstation, not a SaaS dependency chain" translate="no">​</a></h2>
<p>The long-term direction is clear to me: a personal workstation built around open tools.</p>
<p>Today, the LLM layer may depend on a cloud API. Tomorrow, with local hardware, it may run locally. That transition should not require changing the structure of the core assets.</p>
<p>This is the architecture I care about.</p>
<p>Not "AI replaces tools."
Not "LLMs generate everything."
Not "LLMs make design automatic."</p>
<p>Rather:</p>
<p>LLMs become source-level collaborators inside an open, inspectable, user-controlled toolchain.</p>
<p>That is a much more durable vision.</p>
<p>Modern SaaS tools often sell convenience. Convenience is not bad. But convenience can hide a transfer of control.</p>
<p>The user gives the platform intention, content, structure, and data. The platform returns a polished output. In the short term, this feels efficient. In the long term, the user may discover that the real asset has never fully belonged to them.</p>
<p>Serious work should not work that way.</p>
<p>A user should be able to inspect the document source, understand the diagram representation, reproduce the figure, migrate the project, regenerate the output, and continue editing years later without depending on a vendor's web interface.</p>
<p>That is not nostalgia for old tools. It is a practical requirement for serious intellectual work.</p>
<p>AI makes this even more important. As AI systems become more capable, the temptation to work entirely inside closed AI platforms will increase. But the more powerful AI becomes, the more important it is to decide where its outputs land.</p>
<p>If AI produces platform-locked artifacts, then AI accelerates dependence.
If AI produces open source assets, then AI strengthens independence.</p>
<p>That choice is architectural.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion-put-the-asset-first">Conclusion: put the asset first<a href="https://karei.codeberg.page/user-assets-llms-open-formats-toolchains/#conclusion-put-the-asset-first" class="hash-link" aria-label="Direct link to Conclusion: put the asset first" title="Direct link to Conclusion: put the asset first" translate="no">​</a></h2>
<p>The central question is not "Which AI tool can generate the best poster?"</p>
<p>The central question is:</p>
<p>Where does the asset live, and who controls it?</p>
<p>If the asset lives inside a closed platform, the user is renting convenience.
If the asset lives in an open, inspectable, version-controllable source format, the user owns a durable piece of intellectual infrastructure.</p>
<p>This is why I care about workflows such as Quarto for documents and draw.io XML for diagrams. They allow LLMs to collaborate without taking control away from the user. They turn communication into something closer to engineering: transparent, reproducible, editable, and portable.</p>
<p>The goal is not merely to save money. The goal is to make money less relevant to the ability to create, express, revise, and preserve work.</p>
<p>Money can be spent on compute. Money can be spent on hardware. Money can be spent on replaceable services.</p>
<p>But money should not have to be spent to keep one's own assets editable, understandable, and alive.</p>
<p>That is the real promise of LLMs combined with open formats and open toolchains:</p>
<p>not automatic content generation, but the return of control.</p>
<p><em>User assets should belong to users.</em></p>]]></content>
        <category label="LLM" term="LLM"/>
        <category label="Open Science" term="Open Science"/>
        <category label="Open Formats" term="Open Formats"/>
        <category label="Toolchains" term="Toolchains"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Jacobian-Free Newton-Krylov]]></title>
        <id>https://karei.codeberg.page/jfnk/</id>
        <link href="https://karei.codeberg.page/jfnk/"/>
        <updated>2025-04-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Introduction]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="introduction">Introduction<a href="https://karei.codeberg.page/jfnk/#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction" translate="no">​</a></h2>
<p>The <em>Jacobian-Free Newton–Krylov</em> (JFNK) method is a nonlinear solver that combines Newton’s method with Krylov-subspace linear solvers <em>without</em> ever forming the Jacobian matrix explicitly.</p>
<!-- -->
<p>At each Newton iteration we solve the linear system</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>J</mi><mo stretchy="false">(</mo><msup><mi>x</mi><mi>k</mi></msup><mo stretchy="false">)</mo><mtext> </mtext><mi>δ</mi><mi>x</mi><mo>=</mo><mo>−</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>x</mi><mi>k</mi></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">J(x^k)\,\delta x = -F(x^k)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1491em;vertical-align:-0.25em"></span><span class="mord mathnormal" style="margin-right:0.0962em">J</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em"><span style="top:-3.113em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0315em">k</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord mathnormal" style="margin-right:0.0379em">δ</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:1.1491em;vertical-align:-0.25em"></span><span class="mord">−</span><span class="mord mathnormal" style="margin-right:0.1389em">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em"><span style="top:-3.113em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0315em">k</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span>
<p>using a Krylov method (e.g. GMRES). Rather than assembling <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.0962em">J</span></span></span></span>, JFNK approximates Jacobian–vector products <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi>v</mi></mrow><annotation encoding="application/x-tex">J(x)v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathnormal" style="margin-right:0.0962em">J</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.0359em">v</span></span></span></span> via finite differences:</p>
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>J</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mtext> </mtext><mi>v</mi><mo>≈</mo><mfrac><mrow><mi>F</mi><mo stretchy="false">(</mo><mi>x</mi><mo>+</mo><mi>ε</mi><mtext> </mtext><mi>v</mi><mo stretchy="false">)</mo><mo>−</mo><mi>F</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><mi>ε</mi></mfrac><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">J(x)\,v \approx \frac{F(x + \varepsilon\,v) - F(x)}{\varepsilon},</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathnormal" style="margin-right:0.0962em">J</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord mathnormal" style="margin-right:0.0359em">v</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em"><span style="top:-2.314em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord mathnormal">ε</span></span></span><span style="top:-3.23em"><span class="pstrut" style="height:3em"></span><span class="frac-line" style="border-bottom-width:0.04em"></span></span><span style="top:-3.677em"><span class="pstrut" style="height:3em"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1389em">F</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mord mathnormal">ε</span><span class="mspace" style="margin-right:0.1667em"></span><span class="mord mathnormal" style="margin-right:0.0359em">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em"></span><span class="mord mathnormal" style="margin-right:0.1389em">F</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mpunct">,</span></span></span></span></span>
<p>with a small <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ε</mi></mrow><annotation encoding="application/x-tex">ε</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">ε</span></span></span></span>. This “matrix-free” approach reduces memory and computational cost when <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.0962em">J</span></span></span></span> is large or expensive to form, and allows reuse of existing residual-evaluation code. Preconditioning can still be applied by approximating <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>J</mi></mrow><annotation encoding="application/x-tex">J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.0962em">J</span></span></span></span> or its inverse action. JFNK is widely used in large-scale simulations (e.g., fluid dynamics, reactive flows) where explicit Jacobian assembly would be prohibitive.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="julia-implementation">Julia implementation<a href="https://karei.codeberg.page/jfnk/#julia-implementation" class="hash-link" aria-label="Direct link to Julia implementation" title="Direct link to Julia implementation" translate="no">​</a></h2>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using LinearAlgebra, LinearMaps, Krylov, Printf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">F(x) = [x[1] + x[2]^2, x[1] + 2x[2] + x[1] * x[2]]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function JFNK(F, x0; tol=1e-10, k_max=20, verbose=true)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    n = length(x0)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    x = copy(x0)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    r = copy(F(x))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # *using `LinearMaps` create a matrix-free operator for Jacobian-vector product J*v ≈ (F(x+δ*v) - F(x)) / δ</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    Jop = LinearMap(v -&gt; Jv_product(v, F, x, r), n, n)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    k = 0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    solved = false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    while !solved &amp;&amp; k &lt; k_max</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        k += 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        v, stats = Krylov.gmres(Jop, -r)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        x .+= v</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        r .= F(x)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        normr = norm(r)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        verbose &amp;&amp; @printf(" %2d: x = [%.2e %.2e], ||r|| = %.2e\n", k, x[1], x[2], normr)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        if normr &lt; tol</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            if verbose</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                printstyled("Equation solved.\n"; color=:green)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                println("Because the residual norm is less than specified tolerance.\n")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            solved = true</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        if k == k_max</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            if verbose</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                printstyled("Failed to solve the equation.\n"; color=9)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">                println("JFNK not converge in $k_max iterations.\n")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    return x</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function Jv_product(v, F, x, r)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # Finite-difference parameter</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    δ = sqrt(eps()) * max(norm(x), 1.0)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    return (F(x .+ δ .* v) .- r) ./ δ</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">x0 = [1.5, 0.1]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">x = JFNK(F, x0)</span><br></div></code></pre></div></div>
<p><strong>Inputs</strong></p>
<ul>
<li class="">
<p><strong><code>F</code></strong> (<code>Function</code>):
The nonlinear residual function <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><msup><mi mathvariant="double-struck">R</mi><mi>n</mi></msup><mo>→</mo><msup><mi mathvariant="double-struck">R</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">F: \mathbb{R}^n \to \mathbb{R}^n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em"></span><span class="mord mathnormal" style="margin-right:0.1389em">F</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6889em"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6889em"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em"><span style="top:-3.063em;margin-right:0.05em"><span class="pstrut" style="height:2.7em"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span>. Each call <code>F(x)</code> returns an <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">n</span></span></span></span>-element vector.</p>
</li>
<li class="">
<p><strong><code>x0</code></strong> (<code>AbstractVector{&lt;:Real}</code>):
The initial guess for the solution, of length <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal">n</span></span></span></span>. The algorithm will refine this vector.</p>
</li>
<li class="">
<p><strong><code>tol</code></strong> (<code>Real</code>, keyword; default <code>1e-10</code>):
The stopping tolerance on the residual norm. Once <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∥</mi><mi>F</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∥</mi><mo>&lt;</mo><mtext>tol</mtext></mrow><annotation encoding="application/x-tex">\|F(x)\| &lt; \text{tol}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord">∥</span><span class="mord mathnormal" style="margin-right:0.1389em">F</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord">∥</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:0.6944em"></span><span class="mord text"><span class="mord">tol</span></span></span></span></span>, iteration stops.</p>
</li>
<li class="">
<p><strong><code>k_max</code></strong> (<code>Integer</code>, keyword; default <code>20</code>):
The maximum number of Newton–Krylov (outer) iterations allowed before giving up.</p>
</li>
<li class="">
<p><strong><code>verbose</code></strong> (<code>Bool</code>, keyword; default <code>true</code>):
If <code>true</code>, print progress each iteration (values of <code>x</code> and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∥</mi><mi>r</mi><mi mathvariant="normal">∥</mi></mrow><annotation encoding="application/x-tex">\|r\|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord">∥</span><span class="mord mathnormal" style="margin-right:0.0278em">r</span><span class="mord">∥</span></span></span></span>) and a final success/failure message with colored output.</p>
</li>
</ul>
<p><strong>Internal Variables</strong></p>
<ul>
<li class="">
<p><strong><code>n</code></strong>: problem size (length of <code>x0</code>).</p>
</li>
<li class="">
<p><strong><code>x</code></strong>: current iterate (updated each iteration).</p>
</li>
<li class="">
<p><strong><code>r</code></strong>: current residual, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>r</mi><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">r = F(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em"></span><span class="mord mathnormal" style="margin-right:0.0278em">r</span><span class="mspace" style="margin-right:0.2778em"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord mathnormal" style="margin-right:0.1389em">F</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span>.</p>
</li>
</ul>]]></content>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
        <category label="Algorithm" term="Algorithm"/>
        <category label="Nonlinear System" term="Nonlinear System"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Guidance for Solving Linear Equations]]></title>
        <id>https://karei.codeberg.page/solving-linear-equations/</id>
        <link href="https://karei.codeberg.page/solving-linear-equations/"/>
        <updated>2025-04-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[{/ truncate /}]]></summary>
        <content type="html"><![CDATA[
<p><img decoding="async" loading="lazy" alt="Desktop View" src="https://karei.codeberg.page/assets/images/Solving%20linear%20systems-84edb881d138d4ee804193dd517639f7.png" width="2001" height="1171" class="img_ev3q"></p>]]></content>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
        <category label="Algorithm" term="Algorithm"/>
        <category label="Nonlinear System" term="Nonlinear System"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Create new package via PkgTemplates.jl]]></title>
        <id>https://karei.codeberg.page/pkg-templates/</id>
        <link href="https://karei.codeberg.page/pkg-templates/"/>
        <updated>2025-02-07T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Create new package via PkgTemplates.jl]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="create-new-package-via-pkgtemplatesjl">Create new package via PkgTemplates.jl<a href="https://karei.codeberg.page/pkg-templates/#create-new-package-via-pkgtemplatesjl" class="hash-link" aria-label="Direct link to Create new package via PkgTemplates.jl" title="Direct link to Create new package via PkgTemplates.jl" translate="no">​</a></h2>
<!-- -->
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using PkgTemplates</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">t = Template(</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    user    = "Your_GitHub_username",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    authors = ["name &lt;your_email@example.com&gt;"],</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # Specify the directory where the generated package is stored</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    dir     = "D:\\packages",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # Specify the minimum Julia version required by the package</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    julia   = v"1.10",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # Configure multiple plugins to customize various aspects of the package</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    plugins = [</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ProjectFile(version=v"0.1.0-DEV"), # Creates a Project.toml.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # version::VersionNumber: The initial version of created packages.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Tests(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Readme(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        License(name="ASL"),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        GitHubActions(extra_versions=["1", "lts"]),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        TagBot(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # Automatically check for dependent updates and generate PRs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        CompatHelper(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # Add GitHub Actions-based online documentation build support for packages</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Documenter{GitHubActions}(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # Logo information for documentation.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Logo(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        BlueStyleBadge(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ColPracBadge(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        PkgEvalBadge(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # Create a .JuliaFormatter.toml file</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        Formatter(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # Sets up a PkgBenchmark.jl benchmark suite.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        PkgBenchmark(),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # To ensure benchmark reproducibility, you will need to manually create an environment in the benchmark subfolder (for which the Manifest.toml is committed to version control). In this environment, you should at the very least:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # pkg&gt; add BenchmarkTools  pkg&gt; dev your new package</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ]</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">)</span><br></div></code></pre></div></div>
<p>Use the template to generate a new package, and name the package "MyNewPackage".</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">generate(t, "MyNewPackage")</span><br></div></code></pre></div></div>]]></content>
        <category label="Tutorial" term="Tutorial"/>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Difference between get(), getproperty(), and getfield()]]></title>
        <id>https://karei.codeberg.page/get-et-al/</id>
        <link href="https://karei.codeberg.page/get-et-al/"/>
        <updated>2025-01-24T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[1. get]]></summary>
        <content type="html"><![CDATA[<ol>
<li class=""><strong><code>get</code></strong>
<ul>
<li class=""><strong>Scope</strong>：Generally used to retrieve values from indexable data structures (such as <code>Dict</code>, <code>Array</code>) or other containers with customizable interfaces.</li>
<li class=""><strong>Function</strong>：<code>get(collection, key, default)</code> will attempt to retrieve the value for <code>key</code> from <code>collection</code>. If the value is not found, <code>default</code> will be returned.</li>
<li class=""><strong>Example</strong>：<!-- -->
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">d = Dict(:a =&gt; 1, :b =&gt; 2)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println(get(d, :a, 0))  # 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println(get(d, :c, 0))  # 0 (Due to :c not existing)</span><br></div></code></pre></div></div>
</li>
<li class=""><strong>Application</strong>：When there is no guarantee that a key will always exist, you can gracefully provide a default value and avoid throwing an error.</li>
</ul>
</li>
</ol>
<!-- -->
<ol start="2">
<li class="">
<p><strong><code>getproperty</code></strong></p>
<ul>
<li class=""><strong>Scope</strong>：This is the underlying mechanism for attribute access* in Julia, which is mainly related to <strong>dot notation syntax (<code>.</code>)</strong>.</li>
<li class=""><strong>Function</strong>：When we use the <code>obj.someproperty</code> syntax on an object <code>obj</code>, Julia will call <code>getproperty(obj, :someproperty)</code> to get the property. You can also define/override the <code>Base.getproperty</code> method in your custom types to execute some custom logic when accessing properties (such as lazy loading, redirecting to other fields, calculating virtual properties, etc.).</li>
<li class=""><strong>Example</strong>：<!-- -->
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">struct MyType</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    x::Int</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function Base.getproperty(m::MyType, sym::Symbol)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    if sym === :y</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        return m.x + 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    else</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        return getfield(m, sym)  # fallback to default field access</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">m = MyType(10)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println(m.x)  # Actual call getproperty(m, :x) -&gt; getfield(m, :x)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println(m.y)  # Actual call getproperty(m, :y) -&gt; Custom logic returns 11</span><br></div></code></pre></div></div>
</li>
<li class=""><strong>Application</strong>：Intercept and dynamically handle access to the properties of structures/objects. For example, properties that are “calculated” rather than actually stored can be made to be accessed like normal fields by overriding <code>getproperty</code>.</li>
</ul>
</li>
<li class="">
<p><strong><code>getfield</code></strong></p>
<ul>
<li class=""><strong>Scope</strong>：This is the function for <em>directly accessing the fields of a structure</em> in Julia.</li>
<li class=""><strong>Function</strong>：<code>getfield(obj, :fieldname)</code> is <strong>low-level</strong> access to a field of a structure and does not trigger the overriding logic of <code>getproperty</code>. In other words, it just “gets the actual field in the object” and does not execute additional custom methods.</li>
<li class=""><strong>Example</strong>：<!-- -->
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">struct MyType</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    x::Int</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">m = MyType(10)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println(getfield(m, :x))  # 10</span><br></div></code></pre></div></div>
</li>
<li class=""><strong>Application</strong>：Use <code>getfield</code> when you need to bypass any possible <code>getproperty</code> overloads or when you explicitly want to access the fields of the underlying structure directly. For example, in a custom implementation of <code>getproperty</code>, <code>getfield</code> is often used to get the actual field value.</li>
</ul>
</li>
</ol>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary">Summary<a href="https://karei.codeberg.page/get-et-al/#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary" translate="no">​</a></h3>
<ul>
<li class=""><strong><code>get</code></strong> is a high-level "safe" getter function for data structures that provides default values to handle missing keys.</li>
<li class=""><strong><code>getproperty</code></strong> is the mechanism behind the dot syntax (<code>.</code>), allowing users to customize property access behavior through overloading.</li>
<li class=""><strong><code>getfield</code></strong> is the lowest-level function that directly accesses the fields of a structure without any overloading. It is generally only explicitly called when writing low-level code or customizing <code>getproperty</code>.</li>
</ul>]]></content>
        <category label="Tutorial" term="Tutorial"/>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Control Flow]]></title>
        <id>https://karei.codeberg.page/control-flow/</id>
        <link href="https://karei.codeberg.page/control-flow/"/>
        <updated>2025-01-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Different ways to write for loop in Julia lang.]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-for-loop">The for loop<a href="https://karei.codeberg.page/control-flow/#the-for-loop" class="hash-link" aria-label="Direct link to The for loop" title="Direct link to The for loop" translate="no">​</a></h2>
<p>To iterate over the elements within an array, there are several different ways to write the code. Now suppose we have such an array: <code>a = copy(reshape(1:16, 4, 4))</code></p>
<!-- -->
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">4×4 Matrix{Int64}:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 1  5   9  13</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 2  6  10  14</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 3  7  11  15</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 4  8  12  16</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-eachindexa">1. eachindex(a)<a href="https://karei.codeberg.page/control-flow/#1-eachindexa" class="hash-link" aria-label="Direct link to 1. eachindex(a)" title="Direct link to 1. eachindex(a)" translate="no">​</a></h3>
<p>In Julia, matrices are stored column-first. Hence, <code>eachindex()</code> iterates over matrix a in column order.</p>
<ul>
<li class=""><code>eachindex()</code> returns the index of each element of a matrix, of type <code>Int</code></li>
</ul>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">for i in eachindex(a)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    println("Index: $i, Element: $(a[i])")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Index: 1, Element: 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 2, Element: 2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 3, Element: 3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 4, Element: 4</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 5, Element: 5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 6, Element: 6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-a">2. a<a href="https://karei.codeberg.page/control-flow/#2-a" class="hash-link" aria-label="Direct link to 2. a" title="Direct link to 2. a" translate="no">​</a></h3>
<ul>
<li class=""><code>in a</code> returns each element of a matrix, of type <code>eltype(a)</code></li>
</ul>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">for element in a</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    println("Element: $element")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-pairsa">3. pairs(a)<a href="https://karei.codeberg.page/control-flow/#3-pairsa" class="hash-link" aria-label="Direct link to 3. pairs(a)" title="Direct link to 3. pairs(a)" translate="no">​</a></h3>
<p>The <code>pairs()</code> function, when used as an iterator, can iterate not only over arrays, but also over Pairs and dictionaries.</p>
<ul>
<li class=""><code>pairs(a::Vector)</code> returns a pair of index and value, of type <code>Tuple{Int,eltype(a)}</code></li>
<li class=""><code>pairs(a::Matrix)</code> returns a pair of index and value, of type <code>Tuple{CartesianIndex{2},eltype(a)}</code></li>
</ul>
<!-- -->
<ul>
<li class=""><code>pairs(::Dict)</code> returns a pair of key and value, of type <code>Tuple{eltype(a.keys),eltype(a.vals)}</code></li>
</ul>
<p>A <code>[println("Index: $i, Element: $element") for (i, element) in pairs(a)]</code> gives:</p>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Index: CartesianIndex(1, 1), Element: 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: CartesianIndex(2, 1), Element: 2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: CartesianIndex(3, 1), Element: 3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: CartesianIndex(4, 1), Element: 4</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: CartesianIndex(1, 2), Element: 5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: CartesianIndex(2, 2), Element: 6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-enumeratea">4. enumerate(a)<a href="https://karei.codeberg.page/control-flow/#4-enumeratea" class="hash-link" aria-label="Direct link to 4. enumerate(a)" title="Direct link to 4. enumerate(a)" translate="no">​</a></h3>
<p>The first parameter <em>i</em> produced by <code>enumerate</code> is the index of natural number starting from 1.</p>
<p>A <code>[println("Index: $i, Element: $element") for (i, element) in enumerate(a)]</code> gives:</p>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Index: 1, Element: 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 2, Element: 2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 3, Element: 3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 4, Element: 4</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 5, Element: 5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Index: 6, Element: 6</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-axesan">5. axes(a,n)<a href="https://karei.codeberg.page/control-flow/#5-axesan" class="hash-link" aria-label="Direct link to 5. axes(a,n)" title="Direct link to 5. axes(a,n)" translate="no">​</a></h3>
<p>This function iterates over the <em>n</em>th axis of array <code>a</code>.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">for element in axes(a, 1)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    println("Element: $element")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Element: 1</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Element: 2</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Element: 3</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Element: 4</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="creating-iterators">Creating Iterators<a href="https://karei.codeberg.page/control-flow/#creating-iterators" class="hash-link" aria-label="Direct link to Creating Iterators" title="Direct link to Creating Iterators" translate="no">​</a></h3>
<p>An iterator can be created using parentheses wrapped around an array and a for loop -&gt; <code>(a[i] for i in a)</code></p>
<p>For example, we can create a row index iterator for matrix x:</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">x = rand(1000, 4);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">eachrow_x = (x[i:i, :] for i in axes(x, 1));</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">eachrow_x = (view(x, i:i, :) for i in axes(x, 1));</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">eachrow_x = eachrow(x);</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">for (i, xi) in enumerate(eachrow_x)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    println("Index: $i, Element: $element")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    xi[1] = 0.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<ul>
<li class="">
<p>Line 2 let the for loop performs a slicing operation on the matrix x at each iteration, producing a new vector for which a memory allocation occurs.</p>
</li>
<li class="">
<p>Lines 3 and 4 are equivalent iterators that let the for loop produce a row view of the matrix x per iteration. No memory allocation.</p>
</li>
</ul>]]></content>
        <category label="Tutorial" term="Tutorial"/>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Inputs and Outputs]]></title>
        <id>https://karei.codeberg.page/inputs-outputs/</id>
        <link href="https://karei.codeberg.page/inputs-outputs/"/>
        <updated>2025-01-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Basic input and output of the Julia language.]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="clear-screen">Clear screen<a href="https://karei.codeberg.page/inputs-outputs/#clear-screen" class="hash-link" aria-label="Direct link to Clear screen" title="Direct link to Clear screen" translate="no">​</a></h2>
<!-- -->
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">print("\033c")</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="suspension">Suspension<a href="https://karei.codeberg.page/inputs-outputs/#suspension" class="hash-link" aria-label="Direct link to Suspension" title="Direct link to Suspension" translate="no">​</a></h2>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">println("Press any key to continue...")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">readline()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println("Continuing execution...")</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="reading-input-from-a-terminal">Reading input from a terminal<a href="https://karei.codeberg.page/inputs-outputs/#reading-input-from-a-terminal" class="hash-link" aria-label="Direct link to Reading input from a terminal" title="Direct link to Reading input from a terminal" translate="no">​</a></h2>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">input = stdin |&gt; readline |&gt; split |&gt; x -&gt; parse.(Int, x)</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="output-data-to-terminal">Output data to terminal<a href="https://karei.codeberg.page/inputs-outputs/#output-data-to-terminal" class="hash-link" aria-label="Direct link to Output data to terminal" title="Direct link to Output data to terminal" translate="no">​</a></h2>
<p>There are many ways to print a matrix, and I'm going to cover all the ones I know of.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">matrix = [0.0 2.3456 20.0;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    4.5678 5.0 123456.7890;</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    0.001234 123.456 0.0000078901]</span><br></div></code></pre></div></div>
<p>The most straightforward way is to enter the variable name <code>matrix</code> into the REPL, which is equivalent to <code>display(matrix)</code> and <code>@info "Message" matrix</code>, they all call <code>Base.show(stdout, "text/plain", matrix)</code>.</p>
<p>We will get the following output:</p>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">3×3 Matrix{Float64}:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 0.0         2.3456  20.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 4.5678      5.0      1.23457e5</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 0.001234  123.456    7.8901e-6</span><br></div></code></pre></div></div>
<blockquote>
<p><code>"text/plain"</code> or <code>MIME("text/plain)</code> as the second argument indicates a human-readable log format.</p>
</blockquote>
<p>Another set of output functions are <code>print(matrix)</code>, <code>println(matrix)</code>, and <code>show(matrix)</code>, they all call <code>Base.show(stdout, matrix)</code>. Their output is more concise and easy to use as input/output for program data streams:</p>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">[0.0 2.3456 20.0; 4.5678 5.0 123456.789; 0.001234 123.456 7.8901e-6]</span><br></div></code></pre></div></div>
<p>To print all decimals, use <code>Base.print_matrix(stdout, matrix)</code></p>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain"> 0.0         2.3456      20.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 4.5678      5.0     123456.789</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"> 0.001234  123.456        7.8901e-6</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="formatted-output">Formatted output<a href="https://karei.codeberg.page/inputs-outputs/#formatted-output" class="hash-link" aria-label="Direct link to Formatted output" title="Direct link to Formatted output" translate="no">​</a></h2>
<p>If the numbers in the array are not on the same order of magnitude, or if some of the numbers are integers but the whole array is <code>Float64</code>, these integers are forced to be appended with a ".0", which makes it hard to read, such as the above variable <code>matrix</code>. The following line of code allows you to pretty print the matrix in <code>"%7.3g  "</code> format.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using Printf</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># for a matrix, one can use</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">foreach(row -&gt; (foreach(x -&gt; @printf("%7.3g ", x), row); println()), eachrow(matrix))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># for a vector, use</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println("matrix=[" * join(map(x -&gt; @sprintf("%.4f", x), matrix), "  ") * "]")</span><br></div></code></pre></div></div>
<p>In this way, the integers in the matrix are not accompanied by “.0” and the length of each number is controlled.</p>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">      0    2.35      20</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">   4.57       5 1.23e+05</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">0.00123     123 7.89e-06</span><br></div></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-prettytablesjl">Using PrettyTables.jl<a href="https://karei.codeberg.page/inputs-outputs/#using-prettytablesjl" class="hash-link" aria-label="Direct link to Using PrettyTables.jl" title="Direct link to Using PrettyTables.jl" translate="no">​</a></h3>
<p>PrettyTables.jl provides a format for printing matrices specifically, and the same can be done with <code>"%.3g  "</code> for pretty printing.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using PrettyTables</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">pretty_table(matrix; </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    tf=tf_matrix, </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    show_header=false, </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    formatters=ft_printf("%.3g"), </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    isplay_size=(-1, -1)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">)</span><br></div></code></pre></div></div>
<div class="language-2 codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-2 codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">┌                         ┐</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│       0  2.35        20 │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│    4.57     5  1.23e+05 │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">│ 0.00123   123  7.89e-06 │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">└                         ┘</span><br></div></code></pre></div></div>
<blockquote>
<p>The <code>display_size=(-1, -1)</code> statement allows you to print the entire matrix, whether the terminal is large enough or not. However, when the terminal is not large enough to print the matrix using the built-in function above, part of the matrix will be omitted.</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-formatjl">Using Format.jl<a href="https://karei.codeberg.page/inputs-outputs/#using-formatjl" class="hash-link" aria-label="Direct link to Using Format.jl" title="Direct link to Using Format.jl" translate="no">​</a></h3>
<p>To put a comma between every third number, use the following method:</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using Format</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">s = cfmt("%'d", 123456789) # fast</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">s = format(123456789, commas=true) # medium</span><br></div></code></pre></div></div>
<p>Output is a string:<code>"123,456,789"</code></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="output-to-vs-codes-table-window">Output to VS code's table window<a href="https://karei.codeberg.page/inputs-outputs/#output-to-vs-codes-table-window" class="hash-link" aria-label="Direct link to Output to VS code's table window" title="Direct link to Output to VS code's table window" translate="no">​</a></h2>
<p><code>vscodedisplay(matrix)</code> opens a new window in VS code that displays the variables in a tabular form.</p>
<p><img decoding="async" loading="lazy" alt="Desktop View" src="data:image/png;base64,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" width="516" height="209" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="output-to-ms-excel">Output to MS excel<a href="https://karei.codeberg.page/inputs-outputs/#output-to-ms-excel" class="hash-link" aria-label="Direct link to Output to MS excel" title="Direct link to Output to MS excel" translate="no">​</a></h2>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using DataFrames, XLSX</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">fname = "report.xlsx"</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">isfile(fname) &amp;&amp; rm(fname)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">writetable(fname, "Report A" =&gt; DataFrame(matrix, :auto))</span><br></div></code></pre></div></div>]]></content>
        <category label="Tutorial" term="Tutorial"/>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Plot]]></title>
        <id>https://karei.codeberg.page/plot/</id>
        <link href="https://karei.codeberg.page/plot/"/>
        <updated>2025-01-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Plotting in the Julia language.]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="plotlylightjl">PlotlyLight.jl<a href="https://karei.codeberg.page/plot/#plotlylightjl" class="hash-link" aria-label="Direct link to PlotlyLight.jl" title="Direct link to PlotlyLight.jl" translate="no">​</a></h2>
<p>I really had to write about the PlotlyLight package because it starts up much faster than other plotting packages, both in terms of first run time and first plot time. So how fast is it?</p>
<!-- -->
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">@time import Plots # 1.757127 seconds </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@time Plots.plotlyjs() # 17.849170 seconds</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@time Plots.plot(1:20, 1:20, type="scatter") # 3.281065 seconds </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@time import PlotlyJS # 1.746334 seconds</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@time trace1 = PlotlyJS.Plot(PlotlyJS.scatter(x=1:20, y=1:20, mode="markers")) # 1.760041 seconds</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@time using PlotlyLight # 0.114527</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@time p1 = plot.scatter(x=1:10, y=rand(10), mode="lines+markers"); # 0.101052 seconds</span><br></div></code></pre></div></div>
<p>To get started, You can directly copy and modify the template below, which already includes most of the commonly used options.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">function set_PlotlyLight_template(; theme::Symbol=:light)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    template = Config(</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        font=Config(family="Arial", size=16, color=theme == :light ? "black" : "#dbdbdb"),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        plot_bgcolor=theme == :light ? "white" : "rgba(0,0,0,0)",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        paper_bgcolor=theme == :light ? "white" : "rgba(0,0,0,0)",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        margin=(l=60, r=15, t=10, b=60, pad=0),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        xaxis=Config(</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            showline  = true,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            linecolor = theme == :light ? "black" : "#dbdbdb",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            linewidth = 1.5,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            mirror    = true, # Mirror image has axes on all four sides</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            ticks     = "inside", # Orientation of the ticks</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            title     = Config(standoff=1),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            gridcolor = theme == :light ? "rgba(0,0,0,0.1)" : "rgba(255,255,255,0.2)",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            zeroline  = false</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            # titlefont  = template.font,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            # domain    = (0, 0.6), # 60% of width in x-direction</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        legend=Config(</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            bgcolor = theme == :light ? "white" : "rgba(0,0,0,0.5)",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            x       = 0.01, # Relative position of the horizontal to the anchor point</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            y       = 0.99 # Relative position of the vertical pair of anchors</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            # xanchor     = "right", # Anchor x-axis alignment datum ("left", "center", "right")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            # yanchor     = "top",   # Anchor y-axis alignment datum ("top", "middle", "bottom")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            # borderwidth = 0,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        )</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    )</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    template.yaxis = template.xaxis</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    return template</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">PlotlyLight.settings.layout.template.layout = set_PlotlyLight_template()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># equivalent to `PlotlyLight.settings.layout.template = Config(layout=my_template)`</span><br></div></code></pre></div></div>
<p>Let's plot a figure to see this.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using PlotlyLight</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">p1 = plot.scatter(x=1:10, y=rand(10), mode="lines+markers", layout=set_PlotlyLight_template())</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># The above can be simplified as</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">p1 = plot(x=1:10, y=rand(10))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Now we save it</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">using PlotlyKaleido</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">PlotlyKaleido.start()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">savefig(p1, "myplot.png") # .svg</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="plotsjl">Plots.jl<a href="https://karei.codeberg.page/plot/#plotsjl" class="hash-link" aria-label="Direct link to Plots.jl" title="Direct link to Plots.jl" translate="no">​</a></h2>
<p><a href="https://docs.juliaplots.org/stable/" target="_blank" rel="noopener noreferrer" class="">Plots</a> is a visualization interface and toolset. It sits above other backends, like GR, PythonPlot, PGFPlotsX, or Plotly, connecting commands with implementation. If one backend does not support your desired features or make the right trade-offs, you can just switch to another backend with one command. No need to change your code. No need to learn a new syntax. Plots might be the last plotting package you ever learn.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">fig = plot(-10:0.1:10, sin.(-10:0.1:10),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    bg_color=RGB(0.12),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    label="sin(x)",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    linewidth=1.5,           </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    linecolor=:yellow3,     </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    marker=:circle,        </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    markersize=3,      </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    markercolor=:yellow3,    </span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    markerstrokewidth=0,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    title="Plot of sin(x)",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    xlabel="x",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ylabel="y")</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">savefig(fig, "sin.png")</span><br></div></code></pre></div></div>
<p><img decoding="async" loading="lazy" alt="Desktop View" src="https://karei.codeberg.page/assets/images/03-50ab28115a52b4f9aedd443ddb7dadd2.png" width="600" height="400" class="img_ev3q"></p>
<p>It can be very annoying to enter so many parameters every time you plot, so Plots provides a default parameter function. You can set the global default parameters via <code>default()</code>.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">default(fontfamily="arial",</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    bg_color=:transparent,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    framestyle=:box,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    tick_direction=:none,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    linewidth=1.5,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    tickfont=(12, RGB(0)), # RGB(0)=:black</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    guidefont=(12, RGB(0)),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    fg_color_axis=RGB(0),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    fg_color_border=RGB(0),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    fg_color_grid=RGB(0.82),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    markersize=3,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    markerstrokewidth=0,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    legendfontsize=11,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    legendfontcolor=RGB(0),</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    legend_foreground_color=RGB(0))</span><br></div></code></pre></div></div>
<p>To add a plot to the current figure, use the ! version of the function, e.g. <code>plot!()</code>. To draw on a specified figure, use <code>fig</code> as the first argument: <code>plot(fig, ...)</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="cairomakiejl">CairoMakie.jl<a href="https://karei.codeberg.page/plot/#cairomakiejl" class="hash-link" aria-label="Direct link to CairoMakie.jl" title="Direct link to CairoMakie.jl" translate="no">​</a></h2>
<p><a href="https://docs.makie.org/v0.22/explanations/backends/cairomakie" target="_blank" rel="noopener noreferrer" class="">CairoMakie</a> is suitable for drawing two-dimensional, static images. It offers many parameters for detailed  customization. We can write a function to wrap commonly used settings.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">"""</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    cairomakie_plot(x, y; lable=nothing, yscale0=identity)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">`yscale0`: identity, log10</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">"""</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function cairomakie_plot(x, y; lable=nothing, yscale0=identity)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    with_theme(theme_dark()) do</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        fig = Figure(fontsize=14, size=(700, 400))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        xrange = (minimum(x), maximum(x))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ax = Axis(fig[1, 1],</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            xlabel="x", xtickalign=1, xgridvisible=false, # xticklabelsize=14</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            ylabel="y", ytickalign=1, yscale=yscale0,</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">            limits=(xrange, nothing))</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        lines!(ax, x, y, linewidth=2, linestyle=:solid, color=:tomato, label=lable)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        scatter!(ax, x, y, marker=:circle, color=:tomato)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        axislegend(ax, labelsize=15) # position=:lb</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        display(fig)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        # save("my_first_figure.svg", fig)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<p>The syntax of <code>with_theme() do ...</code> allows a one-time application of theme styles. The default style is restored on the next plotting.</p>
<p>To permanently change the drawing theme, one can use <code>set_theme!(merge(theme_dark(), theme_latexfonts()))</code>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="example">Example<a href="https://karei.codeberg.page/plot/#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no">​</a></h3>
<p>Let's draw a sine function and save it as a vector graph:</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using CairoMakie</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">f(x) = sin(x)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">x = -10:0.1:10</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">y = f.(x)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">cairomakie_plot(x, y)</span><br></div></code></pre></div></div>
<p><img decoding="async" loading="lazy" alt="Desktop View" src="https://karei.codeberg.page/assets/images/02-aa76ab0370dc72775e1d902000d24642.svg" width="600" height="450" class="img_ev3q"></p>]]></content>
        <category label="Tutorial" term="Tutorial"/>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Timing and Benchmarking]]></title>
        <id>https://karei.codeberg.page/timing-and-benchmarking/</id>
        <link href="https://karei.codeberg.page/timing-and-benchmarking/"/>
        <updated>2025-01-17T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Timing and benchmarking of the Julia language.]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="timing">Timing<a href="https://karei.codeberg.page/timing-and-benchmarking/#timing" class="hash-link" aria-label="Direct link to Timing" title="Direct link to Timing" translate="no">​</a></h2>
<p><strong>time()</strong></p>
<!-- -->
<p><code>time()</code> function gets the system time in seconds since the epoch, with fairly high (typically, microsecond) resolution.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">start_time = time()</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># ...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">elapsed_time = time() - start_time</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println("Elapsed time: $elapsed_time seconds")</span><br></div></code></pre></div></div>
<p><strong>@elapsed</strong></p>
<p><code>@elapsed</code> is a macro to evaluate an expression, discarding the resulting value, instead returning the number of seconds it took to execute as a floating-point number.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">elapsed_time = @elapsed begin</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    # ...</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">println("Elapsed time: $elapsed_time seconds")</span><br></div></code></pre></div></div>
<p><strong>TimerOutputs.jl</strong></p>
<p><a href="https://github.com/KristofferC/TimerOutputs.jl" target="_blank" rel="noopener noreferrer" class="">TimerOutputs</a> is a small Julia package that is used to generate formatted output from timings made in different sections of a program.</p>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using TimerOutputs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">const to = TimerOutput() # create a timer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"># Define a function that needs to be timed</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">function compute_sum(n)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    sum = 0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    @timeit to "Loop over elements" for i in 1:n</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        sum += i</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    return sum</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@timeit to "Total computation" begin</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    result1 = compute_sum(100_000)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    result2 = compute_sum(200_000)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    println("Result 1: ", result1)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    println("Result 2: ", result2)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    show(to)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="benchmarking">Benchmarking<a href="https://karei.codeberg.page/timing-and-benchmarking/#benchmarking" class="hash-link" aria-label="Direct link to Benchmarking" title="Direct link to Benchmarking" translate="no">​</a></h2>
<div class="language-julia codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-julia codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">using BenchmarkTools</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">a = rand(100,100)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">b = rand(100,100)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">@btime begin</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    c = $a + $b</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">end</span><br></div></code></pre></div></div>
<p>A description of “$” can be found at <a href="https://stackoverflow.com/questions/68261871/what-is-the-dollar-sign-prefix-in-function-arguments-used-for-in-julia" target="_blank" rel="noopener noreferrer" class="">stackoverflow</a>.</p>]]></content>
        <category label="Tutorial" term="Tutorial"/>
        <category label="Programming" term="Programming"/>
        <category label="Julia" term="Julia"/>
    </entry>
</feed>