diff options
Diffstat (limited to 'gemfeed/atom.xml')
| -rw-r--r-- | gemfeed/atom.xml | 677 |
1 files changed, 521 insertions, 156 deletions
diff --git a/gemfeed/atom.xml b/gemfeed/atom.xml index 3a48e534..25bf4cf1 100644 --- a/gemfeed/atom.xml +++ b/gemfeed/atom.xml @@ -1,12 +1,532 @@ <?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> - <updated>2026-05-16T09:16:19+03:00</updated> + <updated>2026-05-31T14:27:21+03:00</updated> <title>foo.zone feed</title> <subtitle>To be in the .zone!</subtitle> <link href="https://foo.zone/gemfeed/atom.xml" rel="self" /> <link href="https://foo.zone/" /> <id>https://foo.zone/</id> <entry> + <title>gt a calculator - a calculator built with local LLMs</title> + <link href="https://foo.zone/gemfeed/2026-06-01-gt-calculator.html" /> + <id>https://foo.zone/gemfeed/2026-06-01-gt-calculator.html</id> + <updated>2026-05-31T14:24:10+03:00</updated> + <author> + <name>Paul Buetow aka snonux</name> + <email>paul@dev.buetow.org</email> + </author> + <summary>I created a calculator. Not because the world needed another one, but because I wanted to test something: how well do local LLMs hold up as pair programmers on a real project?</summary> + <content type="xhtml"> + <div xmlns="http://www.w3.org/1999/xhtml"> + <h1 style='display: inline' id='gt-a-calculator---a-calculator-built-with-local-llms'>gt a calculator - a calculator built with local LLMs</h1><br /> +<br /> +<span class='quote'>Published at 2026-05-31T14:24:10+03:00</span><br /> +<br /> +<span>I created a calculator. Not because the world needed another one, but because I wanted to test something: how well do local LLMs hold up as pair programmers on a real project?</span><br /> +<br /> +<span>The answer is: well enough.</span><br /> +<br /> +<span><span class='inlinecode'>gt</span> is a command-line calculator written in Go that does RPN (Reverse Polish Notation), percentage calculations, unit conversion, and a fair bit more. The name stands for "greater than" — <span class='inlinecode'>gt</span> is a comparison operator the calculator supports. Plus it was free in my terminal and I liked the short name.</span><br /> +<br /> +<span>If you want the full feature guide, the README links to a detailed doc for every feature covered here and more:</span><br /> +<br /> +<a class='textlink' href='https://codeberg.org/snonux/gt'>gt on Codeberg</a><br /> +<a href='./gt-calculator/logo.svg'><img alt='gt logo' title='gt logo' src='./gt-calculator/logo.svg' /></a><br /> +<br /> +<span>The whole thing — code, tests, documentation, even the logo — was built using only LLMs that can run locally on reasonable hardware: Qwen, Gemma, Nemotron, GPT-OSS. To be honest, I didn't run them locally either — I rented a Hyperstack GPU just to get a feel for the quality before investing in hardware. The point was to test models that don't require a cloud API and could realistically run on your own box.</span><br /> +<br /> +<a class='textlink' href='https://www.hyperstack.cloud/'>https://www.hyperstack.cloud/</a><br /> +<br /> +<span>This post is about the calculator and what it does. My experience running those LLMs as pair programmers will be a separate post later.</span><br /> +<br /> +<span>And no, this wasn't vibe-coded. I used a specific technique and a set of AI skills to drive the LLMs. The codebase came out well-structured and maintainable — not the "prompt it and pray" mess. </span><br /> +<br /> +<h2 style='display: inline' id='table-of-contents'>Table of Contents</h2><br /> +<br /> +<ul> +<li><a href='#gt-a-calculator---a-calculator-built-with-local-llms'>gt a calculator - a calculator built with local LLMs</a></li> +<li>⇢ <a href='#the-motivation'>The motivation</a></li> +<li>⇢ <a href='#what-it-does'>What it does</a></li> +<li>⇢ <a href='#percentage-calculations'>Percentage calculations</a></li> +<li>⇢ <a href='#rpn-arithmetic'>RPN arithmetic</a></li> +<li>⇢ ⇢ <a href='#logarithms'>Logarithms</a></li> +<li>⇢ ⇢ <a href='#hyper-operators-n-ary'>Hyper operators (n-ary)</a></li> +<li>⇢ ⇢ <a href='#comparisons-and-booleans'>Comparisons and booleans</a></li> +<li>⇢ <a href='#variables-and-symbols'>Variables and symbols</a></li> +<li>⇢ <a href='#built-in-constants'>Built-in constants</a></li> +<li>⇢ <a href='#the-metrics-system'>The metrics system</a></li> +<li>⇢ ⇢ <a href='#suffix-notation'>Suffix notation</a></li> +<li>⇢ ⇢ <a href='#unit-conversion'>Unit conversion</a></li> +<li>⇢ ⇢ <a href='#metric-aware-arithmetic'>Metric-aware arithmetic</a></li> +<li>⇢ ⇢ <a href='#custom-metrics'>Custom metrics</a></li> +<li>⇢ ⇢ <a href='#si-vs-iec-modes'>SI vs IEC modes</a></li> +<li>⇢ <a href='#stack-manipulation'>Stack manipulation</a></li> +<li>⇢ <a href='#rational-number-mode'>Rational number mode</a></li> +<li>⇢ <a href='#the-repl'>The REPL</a></li> +<li>⇢ <a href='#some-more-usage-examples'>Some more usage examples</a></li> +<li>⇢ <a href='#fish-shell-completions'>Fish shell completions</a></li> +<li>⇢ <a href='#installation'>Installation</a></li> +<li>⇢ <a href='#wrapping-up'>Wrapping up</a></li> +</ul><br /> +<h2 style='display: inline' id='the-motivation'>The motivation</h2><br /> +<br /> +<span>Four things drove this.</span><br /> +<br /> +<span>First, I wanted to test local LLMs as coding partners. Not the cloud-hosted ones with infinite context and billions of parameters — the ones you can actually run yourself. I figured a calculator project is big enough to be interesting but small enough to finish.</span><br /> +<br /> +<span>Second, cloud independence is a thing I care about. I build tools that don't need a network connection to function. Writing software that talks to OpenAI or Anthropic APIs doesn't count as "running locally." Everything here runs offline.</span><br /> +<br /> +<span>Third, I wanted to learn more about how these models actually work in practice. Not benchmarks or leaderboard scores — the day-to-day experience. How do you operate them? How do you structure prompts? When do they produce clean code versus garbage? Where do they struggle?</span><br /> +<br /> +<span>Finally, the tool needed to be genuinely useful. A toy that calculates <span class='inlinecode'>2 + 2</span> isn't worth the disk space. I aimed for a calculator I'd actually reach for.</span><br /> +<br /> +<h2 style='display: inline' id='what-it-does'>What it does</h2><br /> +<br /> +<span>At its core, <span class='inlinecode'>gt</span> is a stack-based RPN calculator with percentage support and a full metrics system. It runs as a single binary, has no dependencies, and works three ways:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'3 4 +'</font> <i><font color="silver"># one-liner: RPN</font></i> +gt <font color="#808080">'20% of 150'</font> <i><font color="silver"># one-liner: percentage</font></i> +gt <i><font color="silver"># interactive REPL</font></i> +</pre> +<br /> +<span>You can also pipe into it: <span class='inlinecode'>echo '1000Mbps @Gbps convert' | gt</span> → <span class='inlinecode'>1</span>.</span><br /> +<br /> +<h2 style='display: inline' id='percentage-calculations'>Percentage calculations</h2><br /> +<br /> +<span>This is the simplest entry point. Three forms, all case-insensitive, all with step-by-step output:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'20% of 150'</font> <i><font color="silver"># → 30.00</font></i> +gt <font color="#808080">'30 is what % of 150'</font> <i><font color="silver"># → 20.00%</font></i> +gt <font color="#808080">'30 is 20% of what'</font> <i><font color="silver"># → 150.00</font></i> +</pre> +<br /> +<span>Every percentage result shows the formula and intermediate values, so you can verify the math. Useful for tips, discounts, tax, and any "what's the actual number?" moment.</span><br /> +<br /> +<h2 style='display: inline' id='rpn-arithmetic'>RPN arithmetic</h2><br /> +<br /> +<span>The main engine uses Reverse Polish Notation. No parentheses needed — the order of tokens determines the order of operations.</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'3 4 +'</font> <i><font color="silver"># 7</font></i> +gt <font color="#808080">'2 10 ^'</font> <i><font color="silver"># 1024</font></i> +gt <font color="#808080">'100 10 / 5 +'</font> <i><font color="silver"># 15</font></i> +gt <font color="#808080">'3 4 + 5 6 + *'</font> <i><font color="silver"># (3+4) × (5+6) = 77</font></i> +</pre> +<br /> +<span>Six basic operators: <span class='inlinecode'>+</span>, <span class='inlinecode'>-</span>, <span class='inlinecode'>*</span>, <span class='inlinecode'>/</span>, <span class='inlinecode'>^</span>, <span class='inlinecode'>%</span>. All work on the stack, popping operands and pushing the result.</span><br /> +<br /> +<span>The fast integer power operator <span class='inlinecode'>**</span> uses binary exponentiation (O(log n) instead of O(n)). So <span class='inlinecode'>2 100 **</span> does about 7 multiplications instead of 99. It only accepts integer exponents — use <span class='inlinecode'>^</span> for fractional powers.</span><br /> +<br /> +<h3 style='display: inline' id='logarithms'>Logarithms</h3><br /> +<br /> +<span>Three unary operators for when you need them:</span><br /> +<br /> +<span>- <span class='inlinecode'>lg</span> — base 2 (information theory, algorithm complexity)</span><br /> +<span>- <span class='inlinecode'>log</span> — base 10 (decibels, pH, order of magnitude)</span><br /> +<span>- <span class='inlinecode'>ln</span> — natural log (continuous growth, statistics)</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'1024 lg'</font> <i><font color="silver"># → 10</font></i> +gt <font color="#808080">'1000 log'</font> <i><font color="silver"># → 3</font></i> +gt <font color="#808080">'e ln'</font> <i><font color="silver"># → 1.0000000000</font></i> +</pre> +<br /> +<h3 style='display: inline' id='hyper-operators-n-ary'>Hyper operators (n-ary)</h3><br /> +<br /> +<span>Want to add everything on the stack at once? Square-bracket operators pop the entire stack and reduce left-associatively:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'1 2 3 4 5 [+]'</font> <i><font color="silver"># → 15 (sum of all)</font></i> +gt <font color="#808080">'100 10 20 30 5 [-]'</font> <i><font color="silver"># → 35 (100-10-20-30-5)</font></i> +gt <font color="#808080">'2 5 10 [*]'</font> <i><font color="silver"># → 100 (product)</font></i> +gt <font color="#808080">'1000 2 2 2 2 [/]'</font> <i><font color="silver"># → 62.5</font></i> +</pre> +<br /> +<span>Full set: <span class='inlinecode'>[+]</span>, <span class='inlinecode'>[-]</span>, <span class='inlinecode'>[*]</span>, <span class='inlinecode'>[/]</span>, <span class='inlinecode'>[^]</span>, <span class='inlinecode'>[%]</span> for arithmetic, plus <span class='inlinecode'>[lg]</span>, <span class='inlinecode'>[log]</span>, <span class='inlinecode'>[ln]</span> for logarithms. The log hyper operators work differently from the arithmetic ones — they compute the sum of the log function applied to each value, not a left-associative reduction. The square-bracket syntax is inspired by Raku's hyper operators.</span><br /> +<br /> +<a class='textlink' href='https://raku.org'>https://raku.org</a><br /> +<br /> +<h3 style='display: inline' id='comparisons-and-booleans'>Comparisons and booleans</h3><br /> +<br /> +<span>Six comparison operators, each with a symbolic alias:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'5 3 gt'</font> <i><font color="silver"># → true</font></i> +gt <font color="#808080">'3 5 <'</font> <i><font color="silver"># → true</font></i> +gt <font color="#808080">'5 5 =='</font> <i><font color="silver"># → true</font></i> +</pre> +<br /> +<span>Results are <span class='inlinecode'>true</span> or <span class='inlinecode'>false</span>, which coerce into arithmetic (true = 1, false = 0). That means you can do inline conditionals:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'85 80 gt 10 *'</font> <i><font color="silver"># → 10 (85 > 80, so 1 × 10)</font></i> +gt <font color="#808080">'50 80 gt 10 *'</font> <i><font color="silver"># → 0 (50 < 80, so 0 × 10)</font></i> +</pre> +<br /> +<span>Range validation works by summing boolean results:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'72 68 gte 100 lte +'</font> <i><font color="silver"># → 2 (both checks pass, temp is in range)</font></i> +gt <font color="#808080">'105 68 gte 100 lte +'</font> <i><font color="silver"># → 1 (out of range)</font></i> +</pre> +<br /> +<h2 style='display: inline' id='variables-and-symbols'>Variables and symbols</h2><br /> +<br /> +<span>Store values with three assignment styles:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'x 10 :='</font> <i><font color="silver"># right assignment</font></i> +gt <font color="#808080">'20 y =:'</font> <i><font color="silver"># left assignment</font></i> +gt <font color="#808080">'rate 100Mbps ='</font> <i><font color="silver"># standard (or rate = 100Mbps)</font></i> +</pre> +<br /> +<span><span class='inlinecode'>vars</span> lists them, <span class='inlinecode'>clear</span> wipes all variables and constants, <span class='inlinecode'>:name d</span> deletes one. In REPL mode, variables persist to disk between sessions.</span><br /> +<br /> +<span>Symbols (the <span class='inlinecode'>:x</span> syntax) are named placeholders on the stack. They're how you do explicit variable assignment and deletion without ambiguity. Bare identifiers that don't match any variable or constant also push as symbols.</span><br /> +<br /> +<h2 style='display: inline' id='built-in-constants'>Built-in constants</h2><br /> +<br /> +<span>Thirty-six of them. Use them directly as tokens:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'pi 2 *'</font> <i><font color="silver"># → 6.283185307</font></i> +gt <font color="#808080">'euler'</font> <i><font color="silver"># → 2.718281828</font></i> +gt <font color="#808080">'phi 10 *'</font> <i><font color="silver"># → 16.18 (golden rectangle)</font></i> +gt <font color="#808080">'sqrt2 sqrt3 *'</font> <i><font color="silver"># → 2.449 (√6)</font></i> +</pre> +<br /> +<span>Greek letter aliases work too: <span class='inlinecode'>π</span>, <span class='inlinecode'>τ</span>, <span class='inlinecode'>φ</span>, <span class='inlinecode'>√2</span>, <span class='inlinecode'>√3</span>, <span class='inlinecode'>√5</span>.</span><br /> +<br /> +<h2 style='display: inline' id='the-metrics-system'>The metrics system</h2><br /> +<br /> +<span>This is where <span class='inlinecode'>gt</span> earns its swiss army knife title. Every number carries a unit of measurement, and arithmetic understands those units.</span><br /> +<br /> +<span>Six built-in categories, plus <span class='inlinecode'>Cool</span> — the default unitless metric for plain numbers. The name comes from Raku's <span class='inlinecode'>Cool</span> role, which represents things that are "cool enough" to do basic operations (strings, numbers, etc.). In <span class='inlinecode'>gt</span>, Cool values absorb into any metric category during arithmetic, so <span class='inlinecode'>5 100Mbps +</span> treats the <span class='inlinecode'>5</span> as <span class='inlinecode'>5Mbps</span>.</span><br /> +<br /> +<span>- *DataRate*: bps, Kbps, Mbps, Gbps, Tbps</span><br /> +<span>- *DataSize*: bits, bytes, KB/MB/GB/TB/PB (SI), KiB/MiB/GiB/TiB/PiB (IEC)</span><br /> +<span>- *Time*: ms, s, min, hr, day</span><br /> +<span>- *Weight*: mg, g, kg, lb, oz, ton</span><br /> +<span>- *Speed*: mps, kmh, mph, knots</span><br /> +<span>- *Distance*: m, km, mi, ft, in, nm (nautical miles)</span><br /> +<br /> +<h3 style='display: inline' id='suffix-notation'>Suffix notation</h3><br /> +<br /> +<span>Attach units directly to numbers:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'100Mbps'</font> <i><font color="silver"># 100 megabits per second</font></i> +gt <font color="#808080">'5GB'</font> <i><font color="silver"># 5 gigabytes</font></i> +gt <font color="#808080">'1hr'</font> <i><font color="silver"># 1 hour</font></i> +gt <font color="#808080">'70kg'</font> <i><font color="silver"># 70 kilograms</font></i> +</pre> +<br /> +<h3 style='display: inline' id='unit-conversion'>Unit conversion</h3><br /> +<br /> +<span>Use <span class='inlinecode'>@<target> convert</span>:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'1000Mbps @Gbps convert'</font> <i><font color="silver"># → 1</font></i> +gt <font color="#808080">'1km @mi convert'</font> <i><font color="silver"># → 0.6213711922</font></i> +gt <font color="#808080">'60mph @kmh convert'</font> <i><font color="silver"># → 96.56</font></i> +gt <font color="#808080">'3day @s convert'</font> <i><font color="silver"># → 259200</font></i> +</pre> +<br /> +<h3 style='display: inline' id='metric-aware-arithmetic'>Metric-aware arithmetic</h3><br /> +<br /> +<span>Addition and subtraction auto-convert within categories:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'1km 500m +'</font> <i><font color="silver"># → 1.5 (converted to km)</font></i> +gt <font color="#808080">'1Gbps 500Mbps -'</font> <i><font color="silver"># → 500 (in Mbps)</font></i> +</pre> +<br /> +<span>Multiplication and division do cross-category inference:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'100Mbps 1hr *'</font> <i><font color="silver"># rate × time = data transferred</font></i> +gt <font color="#808080">'10GB 2hr /'</font> <i><font color="silver"># data / time = rate</font></i> +gt <font color="#808080">'100kmh 1hr * @mi convert'</font> <i><font color="silver"># → 62.14 miles traveled</font></i> +</pre> +<br /> +<span>Comparison operators are metric-aware too:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>gt <font color="#808080">'1km 1000m eq'</font> <i><font color="silver"># → true</font></i> +gt <font color="#808080">'1GB 1024MB eq'</font> <i><font color="silver"># → false (SI: 1GB = 1000MB)</font></i> +</pre> +<br /> +<h3 style='display: inline' id='custom-metrics'>Custom metrics</h3><br /> +<br /> +<span>Define your own units:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>custom define reel <font color="#000000">304.8</font> Distance <i><font color="silver"># surveyor's reel</font></i> +custom define fortnight <font color="#000000">1209600</font> Time +</pre> +<br /> +<span>Then use them like built-ins: <span class='inlinecode'>5reel @m convert</span> → 1524.</span><br /> +<br /> +<h3 style='display: inline' id='si-vs-iec-modes'>SI vs IEC modes</h3><br /> +<br /> +<span>Data size units have two modes. SI (default) uses powers of 1000. IEC uses powers of 1024. Switch with <span class='inlinecode'>metric decimal set</span> / <span class='inlinecode'>metric binary set</span>. The dedicated IEC units (KiB, MiB, GiB) are always unambiguous.</span><br /> +<br /> +<h2 style='display: inline' id='stack-manipulation'>Stack manipulation</h2><br /> +<br /> +<span>Five operators for managing the RPN stack:</span><br /> +<br /> +<span>- <span class='inlinecode'>dup</span> — duplicate the top value</span><br /> +<span>- <span class='inlinecode'>swap</span> — swap top two values</span><br /> +<span>- <span class='inlinecode'>pop</span> — discard the top value</span><br /> +<span>- <span class='inlinecode'>show</span> / <span class='inlinecode'>showstack</span> / <span class='inlinecode'>print</span> — display the stack without modifying it</span><br /> +<span>- <span class='inlinecode'>clear</span> — clear all variables and constants</span><br /> +<br /> +<span><span class='inlinecode'>dup</span> and <span class='inlinecode'>swap</span> come up a lot. Square a number: <span class='inlinecode'>7 dup *</span> → 49. Reverse operand order: <span class='inlinecode'>2 10 swap /</span> → 5 (instead of 0.2).</span><br /> +<br /> +<h2 style='display: inline' id='rational-number-mode'>Rational number mode</h2><br /> +<br /> +<span>"Rational" refers to rational numbers — numbers that can be expressed as an exact fraction of two integers (numerator/denominator). The name "rat" is just the shorthand command.</span><br /> +<br /> +<span>In the default float64 mode, numbers are stored as binary floating-point approximations. <span class='inlinecode'>0.1</span> cannot be represented exactly in binary, so it becomes something like <span class='inlinecode'>0.1000000000000000055511151231257827...</span>. This causes the classic problem:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>> rat off +Rational mode disabled (using float64) +> <font color="#000000">0.3</font> <font color="#000000">0.1</font> - <font color="#000000">0.2</font> - +-<font color="#000000">2.775557562e-17</font> +</pre> +<br /> +<span>The result should be <span class='inlinecode'>0</span>, but floating-point rounding errors accumulated. Silent wrong answer.</span><br /> +<br /> +<span>Rational mode stores numbers as exact fractions using Go's <span class='inlinecode'>math/big.Rat</span>. <span class='inlinecode'>0.1</span> is stored as <span class='inlinecode'>1/10</span>, <span class='inlinecode'>0.2</span> as <span class='inlinecode'>2/10</span> (simplified to <span class='inlinecode'>1/5</span>), and all arithmetic operates on those exact values. No binary approximation, no silent drift.</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>> rat on +Rational mode enabled +> <font color="#000000">0.1</font> <font color="#000000">0.2</font> + +<font color="#000000">0.3000000000</font> +</pre> +<br /> +<span>Internally, <span class='inlinecode'>1/3</span> stays as the exact fraction <span class='inlinecode'>1/3</span>, and <span class='inlinecode'>1/3 * 3</span> computes to exactly <span class='inlinecode'>3/3 = 1</span>. No binary conversion, no rounding.</span><br /> +<br /> +<span>REPL-only. Has a known limitation with non-dyadic decimals and metric operations — the docs explain the why.</span><br /> +<br /> +<h2 style='display: inline' id='the-repl'>The REPL</h2><br /> +<br /> +<span>Run <span class='inlinecode'>gt</span> with no arguments when attached to a terminal and you get the interactive session. Command history (1000 entries, persisted to <span class='inlinecode'>~/.gt_history</span>), tab completion, Emacs-style line editing, Ctrl+R reverse search.</span><br /> +<br /> +<span>Variables save to disk between sessions. Session logging with <span class='inlinecode'>--log session.log</span>. Session state lives in <span class='inlinecode'>~/.local/state/gt/vars</span>.</span><br /> +<br /> +<span>Built-in REPL commands: <span class='inlinecode'>help</span>, <span class='inlinecode'>clear</span>, <span class='inlinecode'>quit</span>/<span class='inlinecode'>exit</span>, <span class='inlinecode'>rpn</span>/<span class='inlinecode'>calc</span>, <span class='inlinecode'>rat</span>, <span class='inlinecode'>stack</span>. Tab-completes.</span><br /> +<br /> +<span>Here's what a session looks like:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>$ gt +> rate 100Mbps = +rate = <font color="#000000">100</font> +> time 2hr = +time = <font color="#000000">2</font> +> rate time * +<font color="#000000">200</font> Mbps +> metric show +Mbps, DataRate, base: bps, factor: <font color="#000000">1e+06</font> +> download 50GB = +download = <font color="#000000">50</font> +> speed 100Mbps = +speed = <font color="#000000">100</font> +> download speed / @min convert +<font color="#000000">83.33333333</font> +> custom define reel <font color="#000000">304.8</font> Distance +defined custom metric <font color="#808080">"reel"</font> (factor: <font color="#000000">304.8</font>, category: Distance) +> 5reel @m convert +<font color="#000000">1524</font> +> 100Mbps 50Mbps swap - +<font color="#000000">50</font> Mbps +> show +<font color="#000000">50</font> Mbps +> <font color="#000000">20</font>% of <font color="#000000">150</font> +<font color="#000000">20.00</font>% of <font color="#000000">150.00</font> = <font color="#000000">30.00</font> + Steps: (<font color="#000000">20.00</font> / <font color="#000000">100</font>) * <font color="#000000">150.00</font> = <font color="#000000">0.20</font> * <font color="#000000">150.00</font> = <font color="#000000">30.00</font> +> rat on +Rational mode enabled +> <font color="#000000">1</font> <font color="#000000">3</font> / <font color="#000000">3</font> * +<font color="#000000">1.0000000000</font> +> vars +rate = <font color="#000000">100</font> +time = <font color="#000000">2</font> +download = <font color="#000000">50</font> +speed = <font color="#000000">100</font> +</pre> +<br /> +<span>Inline help is built in. Bare <span class='inlinecode'>help</span> lists all commands, and <span class='inlinecode'>help <command></span> drills into one topic:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>> <b><u><font color="#000000">help</font></u></b> rat +rat on/off/toggle - Switch between float64 and rational number modes + rat on Enable rational mode (exact fractions) + rat off Disable rational mode (use float64) + rat toggle Toggle current mode +> <b><u><font color="#000000">help</font></u></b> clear +clear - Clear the screen +Usage: clear +</pre> +<br /> +<span>No need to leave the REPL or dig through docs when you forget a subcommand.</span><br /> +<br /> +<h2 style='display: inline' id='some-more-usage-examples'>Some more usage examples</h2><br /> +<br /> +<span>Here are some more <span class='inlinecode'>gt</span> usage examples:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre><i><font color="silver"># Download volume at 1 Gbps for an hour</font></i> +gt <font color="#808080">'1Gbps 1hr * @GB convert'</font> <i><font color="silver"># → 450</font></i> + +<i><font color="silver"># Internet speed threshold in scripts</font></i> +MIN_SPEED=$(gt <font color="#808080">'1Gbps @Mbps convert'</font>) <i><font color="silver"># → 1000</font></i> + +<i><font color="silver"># Travel planning</font></i> +gt <font color="#808080">'500mi @km convert'</font> <i><font color="silver"># → 804.67</font></i> +gt <font color="#808080">'65mph @kmh convert'</font> <i><font color="silver"># → 104.86</font></i> + +<i><font color="silver"># Tips, discounts, whatever</font></i> +gt <font color="#808080">'18% of 63.40'</font> +gt <font color="#808080">'15% of 89.99'</font> + +<i><font color="silver"># File sizes in MiB instead of bytes</font></i> +find . -exec wc -c {} + | awk <font color="#808080">'{print $1}'</font> | xargs -I{} gt <font color="#808080">'{} @MiB convert'</font> + +<i><font color="silver"># Quick math</font></i> +gt <font color="#808080">'pi 5 5 * *'</font> <i><font color="silver"># circle area, r=5 → 78.54</font></i> +gt <font color="#808080">'1000 lg'</font> <i><font color="silver"># → 10 (bits needed)</font></i> +</pre> +<br /> +<h2 style='display: inline' id='fish-shell-completions'>Fish shell completions</h2><br /> +<br /> +<span><span class='inlinecode'>gt</span> ships with a fish completion script that covers everything: operators, constants, metric units, stack commands, the <span class='inlinecode'>metric</span> and <span class='inlinecode'>custom</span> subcommand trees, and boolean literals. It's context-aware — it won't suggest <span class='inlinecode'>metric</span> subcommands in the middle of an RPN expression, and it suppresses fish's default file completions so you only see calculator tokens.</span><br /> +<br /> +<span>Install it:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>cp completions/gt.fish ~/.config/fish/completions/ +</pre> +<br /> +<span>Or system-wide:</span><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>sudo cp completions/gt.fish /usr/local/share/fish/vendor_completions.d/ +</pre> +<br /> +<span>In practice this means tab-completion for all 36 constants, every metric unit (bps through Tbps, KB through PiB, kmh, mph, knots, etc.), all arithmetic and hyper operators, and the <span class='inlinecode'>metric show</span> / <span class='inlinecode'>metric list</span> / <span class='inlinecode'>custom define</span> subcommand chains. The <span class='inlinecode'>custom define</span> subcommand even completes the valid category names so you don't have to memorize them.</span><br /> +<br /> +<h2 style='display: inline' id='installation'>Installation</h2><br /> +<br /> +<!-- Generator: GNU source-highlight 3.1.9 +by Lorenzo Bettini +http://www.lorenzobettini.it +http://www.gnu.org/software/src-highlite --> +<pre>go install codeberg.org/snonux/gt/cmd/gt@latest +</pre> +<br /> +<span>Or from the source directory: <span class='inlinecode'>mage install</span>.</span><br /> +<br /> +<h2 style='display: inline' id='wrapping-up'>Wrapping up</h2><br /> +<br /> +<span>The local LLM experiment worked. The code is clean enough, the tests pass, the docs are thorough, and I use the tool. The logo was generated by a local model too.</span><br /> +<br /> +<span>For the complete and always-up-to-date feature guide, detailed docs for every feature, and the source code, head to the repo.</span><br /> +<br /> +<a class='textlink' href='https://codeberg.org/snonux/gt'>gt on Codeberg</a><br /> +<br /> +<span>But will I now invest a couple of thousand dollars in hardware to run Qwen 2.5 35B or 27B? (I used the dense 27B model most of the time to build <span class='inlinecode'>gt</span>). Unfortunately, no. I don't think it's worth the cost yet, as cloud models are still cheaper and more convenient.</span><br /> +<br /> +<span>However, I will keep an eye on how the technology develops and continue experimenting with rented Hyperstack VMs for now; I will also default more often to smaller LLMs that could potentially run on home hardware. Ollama Cloud subscription or an OpenRouter API key are also good options alongside Claude and OpenAI Codex.</span><br /> +<br /> +<span>I will write another blog post at some point about my setup and what I learned from self-hosting models on Hyperstack.</span><br /> +<br /> +<span>Other related posts:</span><br /> +<br /> +<a class='textlink' href='./2026-06-01-gt-calculator.html'>2026-06-01 gt a calculator - a calculator built with local LLMs (You are currently reading this)</a><br /> +<a class='textlink' href='./2025-08-05-local-coding-llm-with-ollama.html'>2025-08-05 Local LLM for Coding with Ollama on macOS</a><br /> +<br /> +<span>E-Mail your comments to <span class='inlinecode'>paul@nospam.buetow.org</span> :-)</span><br /> +<br /> +<a class='textlink' href='../'>Back to the main site</a><br /> + </div> + </content> + </entry> + <entry> <title>Unveiling I/O Riot NG — Part 3: under the hood</title> <link href="https://foo.zone/gemfeed/2026-05-17-unveiling-ior-ng-part-3.html" /> <id>https://foo.zone/gemfeed/2026-05-17-unveiling-ior-ng-part-3.html</id> @@ -19910,159 +20430,4 @@ Waking up e8:ff:1e:d7:1c:a0... </div> </content> </entry> - <entry> - <title>'Staff Engineer' book notes</title> - <link href="https://foo.zone/gemfeed/2024-10-24-staff-engineer-book-notes.html" /> - <id>https://foo.zone/gemfeed/2024-10-24-staff-engineer-book-notes.html</id> - <updated>2024-10-24T20:57:44+03:00</updated> - <author> - <name>Paul Buetow aka snonux</name> - <email>paul@dev.buetow.org</email> - </author> - <summary>These are my personal takeaways after reading 'Staff Engineer' by Will Larson. Note that the book contains much more knowledge wisdom and that these notes only contain points I personally found worth writing down. This is mainly for my own use, but you might find it helpful too.</summary> - <content type="xhtml"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <h1 style='display: inline' id='staff-engineer-book-notes'>"Staff Engineer" book notes</h1><br /> -<br /> -<span class='quote'>Published at 2024-10-24T20:57:44+03:00</span><br /> -<br /> -<span>These are my personal takeaways after reading "Staff Engineer" by Will Larson. Note that the book contains much more knowledge wisdom and that these notes only contain points I personally found worth writing down. This is mainly for my own use, but you might find it helpful too.</span><br /> -<br /> -<pre> - ,.......... .........., - ,..,' '.' ',.., - ,' ,' : ', ', - ,' ,' : ', ', - ,' ,' : ', ', - ,' ,'............., : ,.............', ', -,' '............ '.' ............' ', - '''''''''''''''''';''';'''''''''''''''''' - ''' -</pre> -<br /> -<h2 style='display: inline' id='table-of-contents'>Table of Contents</h2><br /> -<br /> -<ul> -<li><a href='#staff-engineer-book-notes'>"Staff Engineer" book notes</a></li> -<li>⇢ <a href='#the-four-archetypes-of-a-staff-engineer'>The Four Archetypes of a Staff Engineer</a></li> -<li>⇢ <a href='#influence-and-impact-over-authority'>Influence and Impact over Authority</a></li> -<li>⇢ <a href='#breadth-and-depth-of-knowledge'>Breadth and Depth of Knowledge</a></li> -<li>⇢ <a href='#mentorship-and-sponsorship'>Mentorship and Sponsorship</a></li> -<li>⇢ <a href='#managing-up-and-across'>Managing Up and Across</a></li> -<li>⇢ <a href='#strategic-thinking'>Strategic Thinking</a></li> -<li>⇢ <a href='#emotional-intelligence'>Emotional Intelligence</a></li> -<li>⇢ <a href='#navigating-ambiguity'>Navigating Ambiguity</a></li> -<li>⇢ <a href='#visible-and-invisible-work'>Visible and Invisible Work</a></li> -<li>⇢ <a href='#scaling-yourself'>Scaling Yourself</a></li> -<li>⇢ <a href='#career-progression-and-title-inflation'>Career Progression and Title Inflation</a></li> -<li>⇢ <a href='#not-a-faster-senior-engineer'>Not a faster Senior Engineer</a></li> -<li>⇢ <a href='#the-balance'>The Balance</a></li> -<li>⇢ <a href='#more-things'>More things</a></li> -</ul><br /> -<h2 style='display: inline' id='t |
