geeks have feelings
Xo Wang’s blog: building bots, breaking code, and fixing motorcycles—sometimes. Chaos is a feature and design is subjective.
2023-12-14T07:00:00Z
https://geekshavefeelings.com/
Xo Wang
xo@geekshavefeelings.com
Ducati Timing Belt Replacement
2023-12-14T07:00:00Z
https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/
<p>One of my obsessions of the past year has me pouring my anguish over the (<em>twice!</em>) theft of my fourth-ever motorcycle, a 2014 Ducati Monster 796 <abbr title="anti-lock braking system">ABS</abbr>, into its replacement, a 2012 Monster 1100 <abbr title="evoluzione">EVO</abbr>, in the form of a fat tools & parts budget and sweaty wrenchwork.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/H-i4S6fWH9-690.avif 690w, https://geekshavefeelings.com/img/H-i4S6fWH9-1380.avif 1380w, https://geekshavefeelings.com/img/H-i4S6fWH9-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/H-i4S6fWH9-690.webp 690w, https://geekshavefeelings.com/img/H-i4S6fWH9-1380.webp 1380w, https://geekshavefeelings.com/img/H-i4S6fWH9-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/H-i4S6fWH9-690.jpeg 690w, https://geekshavefeelings.com/img/H-i4S6fWH9-1380.jpeg 1380w, https://geekshavefeelings.com/img/H-i4S6fWH9-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear right quarter view of my motorcycle on its work lift, disassembled with tools and parts nearby" src="https://geekshavefeelings.com/img/H-i4S6fWH9-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>But I’m still gonna cheap out on maintenance by doing it myself, so here’s how I changed the timing belts.</p>
<h2 id="approach" tabindex="-1">Approach <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h2>
<p>I bought this bike used in 2021 and the first steps were to get it into the shape that most resembled my lost 796. This was cosmetic at first—removing a few aftermarket bits I didn’t approve of<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref1">*</a></sup> and repairing some misguided “previous owner maintenance.”</p>
<p>Before long, I realized that minor provocations like discovering a “previous owner” hardware store machine screw in lieu of an Italian-made <a href="https://www.google.com/search?tbm=isch&q=tceif"><abbr title="testa cilindrica con esagono incassato, flangiato">TCEIF</abbr></a> awoke an anger in me that derived from the devastation of stepping out the door to find an empty space where my motorcycle should be. I knew what I needed to do to make myself whole from the <a href="https://en.wikipedia.org/wiki/Horse_theft">horse theft</a>: get this bike into shape, by the book, clawing back the opportunity taken from me to wrench on my 796.</p>
<p><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/files/OM_-_Monster_1100_Evo_-_EN_-_MY12.pdf" title="US owner’s manual (PDF)"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/7cQTJo6Jpg-690.avif 690w, https://geekshavefeelings.com/img/7cQTJo6Jpg-1380.avif 1380w, https://geekshavefeelings.com/img/7cQTJo6Jpg-2625.avif 2625w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/7cQTJo6Jpg-690.webp 690w, https://geekshavefeelings.com/img/7cQTJo6Jpg-1380.webp 1380w, https://geekshavefeelings.com/img/7cQTJo6Jpg-2625.webp 2625w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/7cQTJo6Jpg-690.png 690w, https://geekshavefeelings.com/img/7cQTJo6Jpg-1380.png 1380w, https://geekshavefeelings.com/img/7cQTJo6Jpg-2625.png 2625w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maintenance interval chart highlighting row “Renew the timing belts” showing “per 24,000 km or 24 months”" src="https://geekshavefeelings.com/img/7cQTJo6Jpg-690.png" width="2625" height="1862"></picture><figcaption>The owner’s manual demands that timing belts be changed every 24,000 km or 24 months, suggesting that the belt material ages</figcaption></figure></a></p>
<p>In particular, because this is a relatively recent iteration of Ducati’s traditional air-cooled Ducati 90º V-twin 2-valve<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref2">†</a></sup> engine, the “by the book” method has a few refinements to get the tension and timing right.</p>
<h2 id="tools-and-parts" tabindex="-1">Tools & Parts <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h2>
<ul>
<li><strong>Timing belts</strong> Of course, given the desire for purity in this project, I’m opting for Ducati <abbr title="original equipment manufacturer">OEM</abbr> belts, part <abbr title="cinghia dentata comando distribuzione">73740211A</abbr>. I got a pair from a Ducati Coventry eBay listing in September for £103.16, working out to $167.58 after international shipping and local tax. A quick search shows that there’s lower cost US stock right now, so it hardly seems worthwhile to use aftermarket belts at around $100/pair.
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/4UqkKezrou-690.avif 690w, https://geekshavefeelings.com/img/4UqkKezrou-1380.avif 1380w, https://geekshavefeelings.com/img/4UqkKezrou-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/4UqkKezrou-690.webp 690w, https://geekshavefeelings.com/img/4UqkKezrou-1380.webp 1380w, https://geekshavefeelings.com/img/4UqkKezrou-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/4UqkKezrou-690.jpeg 690w, https://geekshavefeelings.com/img/4UqkKezrou-1380.jpeg 1380w, https://geekshavefeelings.com/img/4UqkKezrou-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Ducati timing belt in front of my motorcycle" src="https://geekshavefeelings.com/img/4UqkKezrou-690.jpeg" width="4032" height="3024"></picture></figure></li>
<li><strong>Crankshaft turning tool with <abbr title="top dead center">TDC</abbr> lock</strong> This Ducati-specific tool (part <abbr title="fasatura puleggia testa 2 valvole">887132011</abbr>) turns the crankshaft and also screws into the case at top dead center (<abbr title="top dead center">TDC</abbr>) timing to hold the crankshaft there. I used a <a href="https://www.lasertools.co.uk/Product/6361/TDC-Timing-Tool-for-Ducati">Laser 6361</a> because almost all of the aftermarket tools looked better made than the Ducati one.
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/fbTaQshsz9-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/fbTaQshsz9-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Scanned photo of welded Ducati tool from workshop manual" src="https://geekshavefeelings.com/img/fbTaQshsz9-246.jpeg" width="246" height="193"></picture></figure>
There’s also a similar crankshaft turning tool, advertised as a replacement for Ducati part <abbr title="attrezzo porta disco graduato per contro">887130123</abbr>. These aftermarket tools are a bit chunkier because they have a turning handle rather than an hex boss for turning the crankshaft key and—more importantly for regular maintenance jobs—don’t have a locking screw for <abbr title="top dead center">TDC</abbr><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref3">‡</a></sup>.</li>
<li><strong>Camshaft locking pins</strong> Another Ducati-specific tool (part <abbr title="fasatura puleggia testa 2 valvole">887132282</abbr>), each of these pins thread into the engine case and engage an indentation on an camshaft at some valve timing datum that lines up with crankshaft <abbr title="top dead center">TDC</abbr>. This secures the the camshaft and, more importantly and as I’ll get into, actually sets the timing on these later model motors. I bought the <a href="https://www.lasertools.co.uk/Product/6367/Timing-Pin-Set-for-Ducati">Laser 6367</a> set, which again looked better than the Ducati set, but they’re just pins with M8 threads so I only had cost in mind.</li>
<li><strong>Torx T30 driver</strong> My engine uses timing pulleys assembled from two (functional) pieces: a hub keyed to the camshaft that clamps a floating toothed pulley using arced slots.
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/mMyBm4OXA5-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/mMyBm4OXA5-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Scanned diagram of Ducati timing pulley showing the two pieces plus a washer and Torx-head screws" src="https://geekshavefeelings.com/img/mMyBm4OXA5-246.jpeg" width="246" height="390"></picture></figure>
The clamping force is provided by Torx head screws<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref4">§</a></sup>, so an appropriate bit is required to drive these.</li>
<li><strong>Spark plug wrench</strong> Removes the spark plugs in order to allow the pistons to move freely—I was not gonna be able to crank a 1078 cm<sup>3</sup>, 11.3:1 compression engine by hand otherwise.</li>
<li><strong>Electronic frequency measurement tool</strong> The Ducati timing belt tension is actually specified and measured indirectly as its plucked frequency. Recall that the natural frequency of a string under tension is <a href="https://en.wikipedia.org/wiki/Mersenne%27s_laws">proportional to the square root of its tension force</a>, so this is pretty reasonable if other properties are held constant—which is only true if I measure <abbr title="original equipment manufacturer">OEM</abbr> belts, and recently-installed ones at that because of their alleged 24-month lifespan. Is this an overly-zealous engineering-to-maintenance transliteration or an Italian nanny-stealership service interval conspiracy?
I opted for the <a href="https://apps.apple.com/app/bicycle-belt-tension-meter/id438346486">Gates app</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref5">¶</a></sup> to measure the frequency with my phone.</li>
<li><strong>Hex bits, drivers, wrenches, etc.</strong></li>
</ul>
<h2 id="steps" tabindex="-1">Steps <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h2>
<p>To prepare, I removed the painted fuel tank covers, which leaves a very naked-looking naked bike, then put the seat back on.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/6vh-TYgYs2-690.avif 690w, https://geekshavefeelings.com/img/6vh-TYgYs2-1380.avif 1380w, https://geekshavefeelings.com/img/6vh-TYgYs2-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/6vh-TYgYs2-690.webp 690w, https://geekshavefeelings.com/img/6vh-TYgYs2-1380.webp 1380w, https://geekshavefeelings.com/img/6vh-TYgYs2-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/6vh-TYgYs2-690.jpeg 690w, https://geekshavefeelings.com/img/6vh-TYgYs2-1380.jpeg 1380w, https://geekshavefeelings.com/img/6vh-TYgYs2-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Monster on lowered work stand, strapped down" src="https://geekshavefeelings.com/img/6vh-TYgYs2-690.jpeg" width="4032" height="3024"></picture><figcaption>Strapped and chocked</figcaption></figure><p></p>
<p>I rode it over to City College, where I’m enrolled in <a href="https://www.ccsf.edu/degrees-certificates/motorcycle-technology">motorcycle tech classes</a> and can pop my bike onto a hydraulic work lift. This is a short enough job that it doesn’t <em>need</em> a lift but why risk my back if I don’t need to? However, this does mean I need to wait for the engine to cool down before I can start wrenching.</p>
<p>Even more importantly, while here I can tap into my instructor Andy Saunder’s vast knowledge of motorcycle maintenance, especially his decades of practical wrenching know-how.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/mml03pCkXF-690.avif 690w, https://geekshavefeelings.com/img/mml03pCkXF-1380.avif 1380w, https://geekshavefeelings.com/img/mml03pCkXF-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/mml03pCkXF-690.webp 690w, https://geekshavefeelings.com/img/mml03pCkXF-1380.webp 1380w, https://geekshavefeelings.com/img/mml03pCkXF-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/mml03pCkXF-690.jpeg 690w, https://geekshavefeelings.com/img/mml03pCkXF-1380.jpeg 1380w, https://geekshavefeelings.com/img/mml03pCkXF-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Monster on raised work stand" src="https://geekshavefeelings.com/img/mml03pCkXF-690.jpeg" width="4032" height="3024"></picture><figcaption>Up we go</figcaption></figure><p></p>
<h3 id="step-1-remove-spark-plugs" tabindex="-1">Step 1: Remove spark plugs <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>I start on the left-hand side of the bike, where the crankshaft access port, camshaft covers, and spark plugs live. The spark plug boots pop off the spark plug terminal with moderate force.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/1zdBTEKthH-690.avif 690w, https://geekshavefeelings.com/img/1zdBTEKthH-1380.avif 1380w, https://geekshavefeelings.com/img/1zdBTEKthH-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/1zdBTEKthH-690.webp 690w, https://geekshavefeelings.com/img/1zdBTEKthH-1380.webp 1380w, https://geekshavefeelings.com/img/1zdBTEKthH-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/1zdBTEKthH-690.jpeg 690w, https://geekshavefeelings.com/img/1zdBTEKthH-1380.jpeg 1380w, https://geekshavefeelings.com/img/1zdBTEKthH-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Spark plug boot off of the rear cylinder spark plug" src="https://geekshavefeelings.com/img/1zdBTEKthH-690.jpeg" width="4032" height="3024"></picture><figcaption>I still can’t believe spark plug boots are held on like this</figcaption></figure><p></p>
<p>Then I unscrew the spark plugs with a deep <sup>5</sup>⁄<sub>8</sub>″ hex socket.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/6XtOHXYdib-690.avif 690w, https://geekshavefeelings.com/img/6XtOHXYdib-1380.avif 1380w, https://geekshavefeelings.com/img/6XtOHXYdib-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/6XtOHXYdib-690.webp 690w, https://geekshavefeelings.com/img/6XtOHXYdib-1380.webp 1380w, https://geekshavefeelings.com/img/6XtOHXYdib-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/6XtOHXYdib-690.jpeg 690w, https://geekshavefeelings.com/img/6XtOHXYdib-1380.jpeg 1380w, https://geekshavefeelings.com/img/6XtOHXYdib-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Spark plug and boot off of the front cylinder" src="https://geekshavefeelings.com/img/6XtOHXYdib-690.jpeg" width="4032" height="3024"></picture><figcaption>Horizontal (front) cylinder, hence the grunginess and different orientation</figcaption></figure><p></p>
<p>Any time the spark plugs are out is a good time to “read” their residue color.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/NvqdBM3ewe-690.avif 690w, https://geekshavefeelings.com/img/NvqdBM3ewe-1380.avif 1380w, https://geekshavefeelings.com/img/NvqdBM3ewe-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/NvqdBM3ewe-690.webp 690w, https://geekshavefeelings.com/img/NvqdBM3ewe-1380.webp 1380w, https://geekshavefeelings.com/img/NvqdBM3ewe-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/NvqdBM3ewe-690.jpeg 690w, https://geekshavefeelings.com/img/NvqdBM3ewe-1380.jpeg 1380w, https://geekshavefeelings.com/img/NvqdBM3ewe-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Spark plug and boot off of the front cylinder" src="https://geekshavefeelings.com/img/NvqdBM3ewe-690.jpeg" width="4032" height="3024"></picture><figcaption>I guess it’s running a touch <a href="https://en.wikipedia.org/wiki/Air–fuel_ratio">lean</a></figcaption></figure><p></p>
<h3 id="step-2-remove-engine-timing-covers" tabindex="-1">Step 2: Remove engine timing covers <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>I remove the socket cap button head screws plugging the camshaft lock holes on the left hand camshaft access covers.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Sn_NkiFLfQ-690.avif 690w, https://geekshavefeelings.com/img/Sn_NkiFLfQ-1380.avif 1380w, https://geekshavefeelings.com/img/Sn_NkiFLfQ-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Sn_NkiFLfQ-690.webp 690w, https://geekshavefeelings.com/img/Sn_NkiFLfQ-1380.webp 1380w, https://geekshavefeelings.com/img/Sn_NkiFLfQ-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Sn_NkiFLfQ-690.jpeg 690w, https://geekshavefeelings.com/img/Sn_NkiFLfQ-1380.jpeg 1380w, https://geekshavefeelings.com/img/Sn_NkiFLfQ-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Front cylinder camshaft access cover without their middle button head screws" src="https://geekshavefeelings.com/img/Sn_NkiFLfQ-690.jpeg" width="4032" height="3024"></picture><figcaption>Hmm, this horizontal cylinder cover was missing its copper sealing washer; make a note to pick up a replacement</figcaption></figure><p></p>
<p>The aftermarketest Ducati <abbr title="computer numerical control">CNC</abbr> bling, the crankshaft access cover, comes off.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/JZ7VHAB288-690.avif 690w, https://geekshavefeelings.com/img/JZ7VHAB288-1380.avif 1380w, https://geekshavefeelings.com/img/JZ7VHAB288-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/JZ7VHAB288-690.webp 690w, https://geekshavefeelings.com/img/JZ7VHAB288-1380.webp 1380w, https://geekshavefeelings.com/img/JZ7VHAB288-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/JZ7VHAB288-690.jpeg 690w, https://geekshavefeelings.com/img/JZ7VHAB288-1380.jpeg 1380w, https://geekshavefeelings.com/img/JZ7VHAB288-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Unscrewing flathead screws holding on crankshaft access cover" src="https://geekshavefeelings.com/img/JZ7VHAB288-690.jpeg" width="4032" height="3024"></picture><figcaption>Mine could be blingier</figcaption></figure><p></p>
<h3 id="step-3-clear-fuel-tank-from-chassis" tabindex="-1">Step 3: Clear fuel tank from chassis <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>The timing belt covers are on the right-hand side under the trellis frame and some wiring, so they come out by sliding along their length rather than lifting from the engine. So, I slide the vertical (rear) cylinder timing belt cover upwards towards the tank, which I then lift to clear the cover.</p>
<p>I already removed the necessary retaining screws, so the tail of the tank pops out of the subframe with some persuasion.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/4txwL3lpkC-690.avif 690w, https://geekshavefeelings.com/img/4txwL3lpkC-1380.avif 1380w, https://geekshavefeelings.com/img/4txwL3lpkC-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/4txwL3lpkC-690.webp 690w, https://geekshavefeelings.com/img/4txwL3lpkC-1380.webp 1380w, https://geekshavefeelings.com/img/4txwL3lpkC-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/4txwL3lpkC-690.jpeg 690w, https://geekshavefeelings.com/img/4txwL3lpkC-1380.jpeg 1380w, https://geekshavefeelings.com/img/4txwL3lpkC-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear of bare fuel tank cleared from seat tray" src="https://geekshavefeelings.com/img/4txwL3lpkC-690.jpeg" width="4032" height="3024"></picture><figcaption>Ignore the extra wires and gaping void…</figcaption></figure><p></p>
<p>Then I put the tank into a position familiar to shadetree 696/796/1100 mechanics: fuel pump resting<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref6">♠</a></sup> on the vertical cylinder and front brackets resting on the airbox. This position obviates unhooking any fuel lines or even putting the tank on a nearby surface.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Uru1K03D3s-690.avif 690w, https://geekshavefeelings.com/img/Uru1K03D3s-1380.avif 1380w, https://geekshavefeelings.com/img/Uru1K03D3s-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Uru1K03D3s-690.webp 690w, https://geekshavefeelings.com/img/Uru1K03D3s-1380.webp 1380w, https://geekshavefeelings.com/img/Uru1K03D3s-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Uru1K03D3s-690.jpeg 690w, https://geekshavefeelings.com/img/Uru1K03D3s-1380.jpeg 1380w, https://geekshavefeelings.com/img/Uru1K03D3s-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Fuel tank propped up on chassis" src="https://geekshavefeelings.com/img/Uru1K03D3s-690.jpeg" width="4032" height="3024"></picture><figcaption>Watch out for the <abbr title="anti-lock braking system">ABS</abbr> modulator</figcaption></figure><p></p>
<h3 id="step-4-remove-timing-belt-covers" tabindex="-1">Step 4: Remove timing belt covers <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>Next step is to remove the timing belt covers on the right-hand side of the bike.</p>
<p><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/files/catalogo.pdf" title="Parts catalog (PDF)"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/bk0lNuaf2K-690.avif 690w, https://geekshavefeelings.com/img/bk0lNuaf2K-1380.avif 1380w, https://geekshavefeelings.com/img/bk0lNuaf2K-5256.avif 5256w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/bk0lNuaf2K-690.webp 690w, https://geekshavefeelings.com/img/bk0lNuaf2K-1380.webp 1380w, https://geekshavefeelings.com/img/bk0lNuaf2K-5256.webp 5256w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/bk0lNuaf2K-690.png 690w, https://geekshavefeelings.com/img/bk0lNuaf2K-1380.png 1380w, https://geekshavefeelings.com/img/bk0lNuaf2K-5256.png 5256w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Parts catalog page for timing belt covers" src="https://geekshavefeelings.com/img/bk0lNuaf2K-690.png" width="5256" height="3718"></picture><figcaption>The four screws for the covers have three different lengths so I gotta keep track of which go where</figcaption></figure></a></p>
<p>Besides the fuel tank, my <a href="https://bazzaz.net/available-products/z-fi-fuel-controller-f191/">Bazzaz Z-Fi</a> piggyback fuel controller harness is also in the way<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref7">♥</a></sup>, as is the lengthy crankshaft position sensor connector.</p>
<p>The vertical cylinder cover slides up, as mentioned.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/WRkwAyhNJV-690.avif 690w, https://geekshavefeelings.com/img/WRkwAyhNJV-1380.avif 1380w, https://geekshavefeelings.com/img/WRkwAyhNJV-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/WRkwAyhNJV-690.webp 690w, https://geekshavefeelings.com/img/WRkwAyhNJV-1380.webp 1380w, https://geekshavefeelings.com/img/WRkwAyhNJV-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/WRkwAyhNJV-690.jpeg 690w, https://geekshavefeelings.com/img/WRkwAyhNJV-1380.jpeg 1380w, https://geekshavefeelings.com/img/WRkwAyhNJV-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear cylinder timing belt cover halfway out" src="https://geekshavefeelings.com/img/WRkwAyhNJV-690.jpeg" width="4032" height="3024"></picture><figcaption>I marked Bazzaz-related wiring with yellow zip-ties, so there’s the <a href="https://bazzaz.net/fuel-control/z-afm-self-mapper/">Z-<abbr title="air-fuel module">AFM</abbr></a> subharness right in the way</figcaption></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/oBp9cMU3uy-690.avif 690w, https://geekshavefeelings.com/img/oBp9cMU3uy-1380.avif 1380w, https://geekshavefeelings.com/img/oBp9cMU3uy-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/oBp9cMU3uy-690.webp 690w, https://geekshavefeelings.com/img/oBp9cMU3uy-1380.webp 1380w, https://geekshavefeelings.com/img/oBp9cMU3uy-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/oBp9cMU3uy-690.jpeg 690w, https://geekshavefeelings.com/img/oBp9cMU3uy-1380.jpeg 1380w, https://geekshavefeelings.com/img/oBp9cMU3uy-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear cylinder timing belt uncovered" src="https://geekshavefeelings.com/img/oBp9cMU3uy-690.jpeg" width="4032" height="3024"></picture><figcaption>Target sighted</figcaption></figure><p></p>
<p>The horizontal cylinder timing belt cover is a bit trickier because it’s larger and has to go around the <abbr title="evoluzione">EVO</abbr>’s right-hand exhaust header routing.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/eVK0qhvKhe-690.avif 690w, https://geekshavefeelings.com/img/eVK0qhvKhe-1380.avif 1380w, https://geekshavefeelings.com/img/eVK0qhvKhe-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/eVK0qhvKhe-690.webp 690w, https://geekshavefeelings.com/img/eVK0qhvKhe-1380.webp 1380w, https://geekshavefeelings.com/img/eVK0qhvKhe-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/eVK0qhvKhe-690.jpeg 690w, https://geekshavefeelings.com/img/eVK0qhvKhe-1380.jpeg 1380w, https://geekshavefeelings.com/img/eVK0qhvKhe-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Front cylinder timing belt cover jammed against exhaust headers" src="https://geekshavefeelings.com/img/eVK0qhvKhe-690.jpeg" width="4032" height="3024"></picture><figcaption>I really should have loosened the headers for this</figcaption></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/0d8U4D-9zL-690.avif 690w, https://geekshavefeelings.com/img/0d8U4D-9zL-1380.avif 1380w, https://geekshavefeelings.com/img/0d8U4D-9zL-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/0d8U4D-9zL-690.webp 690w, https://geekshavefeelings.com/img/0d8U4D-9zL-1380.webp 1380w, https://geekshavefeelings.com/img/0d8U4D-9zL-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/0d8U4D-9zL-690.jpeg 690w, https://geekshavefeelings.com/img/0d8U4D-9zL-1380.jpeg 1380w, https://geekshavefeelings.com/img/0d8U4D-9zL-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Front cylinder timing belt uncovered" src="https://geekshavefeelings.com/img/0d8U4D-9zL-690.jpeg" width="4032" height="3024"></picture><figcaption>At least the plastic covers flex a bit and have a less critical finish than carbon fiber</figcaption></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/QjrcFdWiTl-690.avif 690w, https://geekshavefeelings.com/img/QjrcFdWiTl-1380.avif 1380w, https://geekshavefeelings.com/img/QjrcFdWiTl-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/QjrcFdWiTl-690.webp 690w, https://geekshavefeelings.com/img/QjrcFdWiTl-1380.webp 1380w, https://geekshavefeelings.com/img/QjrcFdWiTl-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/QjrcFdWiTl-690.jpeg 690w, https://geekshavefeelings.com/img/QjrcFdWiTl-1380.jpeg 1380w, https://geekshavefeelings.com/img/QjrcFdWiTl-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear cylinder header with heat shield mounting nuts" src="https://geekshavefeelings.com/img/QjrcFdWiTl-690.jpeg" width="4032" height="3024"></picture><figcaption>While I’m here, the heat shield comes off for a bit more clearance</figcaption></figure><p></p>
<h3 id="step-5-lock-camshafts-at-timing-datum" tabindex="-1">Step 5: Lock camshafts at timing datum <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>Next I was ready to start the actual work of doing the timing belt change. I mount the crankshaft turning tool by first lining up the dogs on the tool to their seats in the engine on the left hand access port.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/wpOuUa2LES-690.avif 690w, https://geekshavefeelings.com/img/wpOuUa2LES-1380.avif 1380w, https://geekshavefeelings.com/img/wpOuUa2LES-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/wpOuUa2LES-690.webp 690w, https://geekshavefeelings.com/img/wpOuUa2LES-1380.webp 1380w, https://geekshavefeelings.com/img/wpOuUa2LES-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/wpOuUa2LES-690.jpeg 690w, https://geekshavefeelings.com/img/wpOuUa2LES-1380.jpeg 1380w, https://geekshavefeelings.com/img/wpOuUa2LES-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Crankshaft turning tool and corresponding port" src="https://geekshavefeelings.com/img/wpOuUa2LES-690.jpeg" width="4032" height="3024"></picture><figcaption>The oil level is well below this port, but there still will be some oil</figcaption></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/fs45m0oq8H-690.avif 690w, https://geekshavefeelings.com/img/fs45m0oq8H-1380.avif 1380w, https://geekshavefeelings.com/img/fs45m0oq8H-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/fs45m0oq8H-690.webp 690w, https://geekshavefeelings.com/img/fs45m0oq8H-1380.webp 1380w, https://geekshavefeelings.com/img/fs45m0oq8H-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/fs45m0oq8H-690.jpeg 690w, https://geekshavefeelings.com/img/fs45m0oq8H-1380.jpeg 1380w, https://geekshavefeelings.com/img/fs45m0oq8H-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Crankshaft turning tool mounted with blue aluminum locking collar" src="https://geekshavefeelings.com/img/fs45m0oq8H-690.jpeg" width="4032" height="3024"></picture><figcaption>The inner socket head cap screw tightens down into the crankshaft</figcaption></figure><p></p>
<p>With the Laser 6361, the internal crank-turning spindle spins freely until set screws in the blue locking collar are tightened into specific spots on the spindle. The locking collar also has that spring-loaded locating screw that screws into the holes for the port cover. When the engine is at <abbr title="top dead center">TDC</abbr>, the set screws and the locating screw all line up to their holes so that they can be tightened down and lock the crankshaft in place.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ZEgC2uw4ic-690.avif 690w, https://geekshavefeelings.com/img/ZEgC2uw4ic-1380.avif 1380w, https://geekshavefeelings.com/img/ZEgC2uw4ic-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ZEgC2uw4ic-690.webp 690w, https://geekshavefeelings.com/img/ZEgC2uw4ic-1380.webp 1380w, https://geekshavefeelings.com/img/ZEgC2uw4ic-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ZEgC2uw4ic-690.jpeg 690w, https://geekshavefeelings.com/img/ZEgC2uw4ic-1380.jpeg 1380w, https://geekshavefeelings.com/img/ZEgC2uw4ic-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Demonstration of ratchet with extension and hex socket on crankshaft turning tool" src="https://geekshavefeelings.com/img/ZEgC2uw4ic-690.jpeg" width="4032" height="3024"></picture><figcaption>The outer hex allows a ratchet or T-handle to turn the crankshaft</figcaption></figure><p></p>
<p>I’m actually leaving the crankshaft <em>unlocked</em> right now, but I do need to find <abbr title="top dead center">TDC</abbr>.</p>
<p>I observe the timing dot mark on the central pulley<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref8">♦</a></sup> and turn the crankshaft until it aligns to the line mark on the crankcase, then lock the tool to the cover.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/EfCYo7x_Cr-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/EfCYo7x_Cr-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Workshop manual photo showing mark alignment" src="https://geekshavefeelings.com/img/EfCYo7x_Cr-246.jpeg" width="246" height="193"></picture></figure><p></p>
<p>I turn using the tool with the gearbox in neutral but I think it could be easier to have the rear wheel on a stand and the gearbox in sixth gear, then to turn the rear wheel without going between left and right sides of the bike to check the dot-line alignment.</p>
<p>Next, I gently thread in the camshaft locks into the left-hand camshaft port while slightly jiggling the crankshaft. If it goes well, the camshaft locks will sit completely bottomed out, with the pins engaging with indentations on the camshafts.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/nQ_O9cX7mr-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/nQ_O9cX7mr-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Workshop manual photo showing camshaft locking" src="https://geekshavefeelings.com/img/nQ_O9cX7mr-246.jpeg" width="246" height="193"></picture></figure><p></p>
<p>In my first try doing this alignment, I didn’t use the pulley mark, just the holes on the crankshaft access port, and couldn’t get the camshaft locks to engage. Recall that the crankshaft turns twice as quickly as the camshafts because its job is to convert the linear piston motion to rotary motion, while the camshafts actually govern timing through the four-stroke cycle. So the crankshaft puts each cylinder at <abbr title="top dead center">TDC</abbr> twice per rotation of the camshaft. What’s more, the crankshaft locking tool can be locked to either of the 180º-offset cover holes, with a possible 90º set screw offset. This allows locking at four different positions per crankshaft rotation: <abbr title="top dead center">TDC</abbr> or <abbr title="bottom dead center">BDC</abbr> of either of the cylinders, which are 90º out-of-phase.</p>
<p>So, I had only a <sup>1</sup>⁄<sub>2</sub> × <sup>1</sup>⁄<sub>4</sub> = <sup>1</sup>⁄<sub>8</sub>th chance of lining up the camshaft to the mark on the case—specifically for the horizontal cylinder at <abbr title="top dead center">TDC</abbr> just before its power stroke—by simplying picking one of the possible crankshaft locking positions.</p>
<h3 id="step-6-loosen-and-remove-belts" tabindex="-1">Step 6: Loosen & remove belts <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>Now’s a good time for me to loosen (but not remove) the timing belt tensioner screws. On my bike, these were well over-torqued past their 26 N·m ± 10 % spec, so they needed some creative unscrewing.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/QtoGSaEKKo-690.avif 690w, https://geekshavefeelings.com/img/QtoGSaEKKo-1380.avif 1380w, https://geekshavefeelings.com/img/QtoGSaEKKo-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/QtoGSaEKKo-690.webp 690w, https://geekshavefeelings.com/img/QtoGSaEKKo-1380.webp 1380w, https://geekshavefeelings.com/img/QtoGSaEKKo-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/QtoGSaEKKo-690.jpeg 690w, https://geekshavefeelings.com/img/QtoGSaEKKo-1380.jpeg 1380w, https://geekshavefeelings.com/img/QtoGSaEKKo-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Locking pliers around top of T-handle extending into timing belt tensioner screws" src="https://geekshavefeelings.com/img/QtoGSaEKKo-690.jpeg" width="4032" height="3024"></picture><figcaption>Slightly abusing my <a href="https://www.motionpro.com/product/08-0389">Motion Pro 08-0389</a> T-handle wrench using C.H. Hanson 06100 locking pliers to loosen tensioners</figcaption></figure><p></p>
<p>Next, I move the tensioners away from the belts to loosen them. With the extra slack in the timing belts, I work them over their pulleys’ flanges and through the gap against the engine case.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ElSbREMWSa-690.avif 690w, https://geekshavefeelings.com/img/ElSbREMWSa-1380.avif 1380w, https://geekshavefeelings.com/img/ElSbREMWSa-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ElSbREMWSa-690.webp 690w, https://geekshavefeelings.com/img/ElSbREMWSa-1380.webp 1380w, https://geekshavefeelings.com/img/ElSbREMWSa-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ElSbREMWSa-690.jpeg 690w, https://geekshavefeelings.com/img/ElSbREMWSa-1380.jpeg 1380w, https://geekshavefeelings.com/img/ElSbREMWSa-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="View of central pulley with top pulley removed" src="https://geekshavefeelings.com/img/ElSbREMWSa-690.jpeg" width="4032" height="3024"></picture><figcaption>The vertical cylinder’s timing belt is stacked underneath the horizontal cylinder’s</figcaption></figure><p></p>
<p>Here, I discover that one of the major differences between the Dayco aftermarket belts I found in here and the <abbr title="original equipment manufacturer">OEM</abbr> belts is that the former is quite a bit thicker and less flexible.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/huHi0Nq27y-690.avif 690w, https://geekshavefeelings.com/img/huHi0Nq27y-1380.avif 1380w, https://geekshavefeelings.com/img/huHi0Nq27y-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/huHi0Nq27y-690.webp 690w, https://geekshavefeelings.com/img/huHi0Nq27y-1380.webp 1380w, https://geekshavefeelings.com/img/huHi0Nq27y-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/huHi0Nq27y-690.jpeg 690w, https://geekshavefeelings.com/img/huHi0Nq27y-1380.jpeg 1380w, https://geekshavefeelings.com/img/huHi0Nq27y-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Ducati belts lying next to a removed Dayco belt" src="https://geekshavefeelings.com/img/huHi0Nq27y-690.jpeg" width="4032" height="3024"></picture><figcaption>There’s that limpness we paid for</figcaption></figure><p></p>
<p>The difficulty in pulling the aftermarket belt through the gap between the pulley flange and crankcase alone made the thinner <abbr title="original equipment manufacturer">OEM</abbr> belts’ extra cost worthwhile.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/bFNZvV7y5X-690.avif 690w, https://geekshavefeelings.com/img/bFNZvV7y5X-1380.avif 1380w, https://geekshavefeelings.com/img/bFNZvV7y5X-3024.avif 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/bFNZvV7y5X-690.webp 690w, https://geekshavefeelings.com/img/bFNZvV7y5X-1380.webp 1380w, https://geekshavefeelings.com/img/bFNZvV7y5X-3024.webp 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/bFNZvV7y5X-690.jpeg 690w, https://geekshavefeelings.com/img/bFNZvV7y5X-1380.jpeg 1380w, https://geekshavefeelings.com/img/bFNZvV7y5X-3024.jpeg 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Timing belt packaging" src="https://geekshavefeelings.com/img/bFNZvV7y5X-690.jpeg" width="3024" height="3024"></picture><figcaption>Hehe, too-thed</figcaption></figure><p></p>
<p>I give each of the tensioner rollers a few spins to feel for crunchy or bound-up bearings. This bike has lived in California for its entire 12,000-mile life, so these sealed bearings<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref9">♣</a></sup> haven’t seen much weather abuse; the risk I want to account for is misguided maintenance, e.g. overtensioned belts or even solvent intrusion.</p>
<p>After this, I break to panic about whether I’ll ever get my motorcycle back together again. This usually lasts five and a half minutes.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/596JbYI0V3-690.avif 690w, https://geekshavefeelings.com/img/596JbYI0V3-1380.avif 1380w, https://geekshavefeelings.com/img/596JbYI0V3-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/596JbYI0V3-690.webp 690w, https://geekshavefeelings.com/img/596JbYI0V3-1380.webp 1380w, https://geekshavefeelings.com/img/596JbYI0V3-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/596JbYI0V3-690.jpeg 690w, https://geekshavefeelings.com/img/596JbYI0V3-1380.jpeg 1380w, https://geekshavefeelings.com/img/596JbYI0V3-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Front right quarter view of my motorcycle on its work lift, disassembled with tools and parts nearby" src="https://geekshavefeelings.com/img/596JbYI0V3-690.jpeg" width="4032" height="3024"></picture><figcaption>Somehow it feels worse every time despite the bike looking way more complete than after my usual disassembly</figcaption></figure><p></p>
<h3 id="step-7-install-and-tension-belts" tabindex="-1">Step 7: Install & tension belts <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h3>
<p>Installing the new belts is the reverse of the removal procedure, except for being a bit more careful about the new belts since they’re not being taken out of operation.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/B_YzqO7_mQ-690.avif 690w, https://geekshavefeelings.com/img/B_YzqO7_mQ-1380.avif 1380w, https://geekshavefeelings.com/img/B_YzqO7_mQ-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/B_YzqO7_mQ-690.webp 690w, https://geekshavefeelings.com/img/B_YzqO7_mQ-1380.webp 1380w, https://geekshavefeelings.com/img/B_YzqO7_mQ-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/B_YzqO7_mQ-690.jpeg 690w, https://geekshavefeelings.com/img/B_YzqO7_mQ-1380.jpeg 1380w, https://geekshavefeelings.com/img/B_YzqO7_mQ-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Crankshaft timing pulley with new timing belt partially installed" src="https://geekshavefeelings.com/img/B_YzqO7_mQ-690.jpeg" width="4032" height="3024"></picture><figcaption>I had to disconnect the crankshaft position sensor for clearance to remove the old belt, but the slimmer <abbr title="original equipment manufacturer">OEM</abbr> belt went in smoothly</figcaption></figure><p></p>
<p>The big change for these recent model 2-valve Ducatis is in the adjustable pulleys. Recall that the timing pulleys have the toothed portion mounted on slots over a hub that’s keyed onto the camshaft.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/mMyBm4OXA5-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/mMyBm4OXA5-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Scanned diagram of Ducati timing pulley showing the separate tooth wheel and hub" src="https://geekshavefeelings.com/img/mMyBm4OXA5-246.jpeg" width="246" height="390"></picture></figure><p></p>
<p>Because the camshafts are locked in place to their factory timing datums, as is the crankshaft and central driving pulley at their corresponding position, these free floating pulleys aren’t for changing cam timing—rather, the opposite, to prevent the timing from drifting while setting the tension for the belts<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref10">¤</a></sup>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/MGKo27IPmP-690.avif 690w, https://geekshavefeelings.com/img/MGKo27IPmP-1380.avif 1380w, https://geekshavefeelings.com/img/MGKo27IPmP-3024.avif 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/MGKo27IPmP-690.webp 690w, https://geekshavefeelings.com/img/MGKo27IPmP-1380.webp 1380w, https://geekshavefeelings.com/img/MGKo27IPmP-3024.webp 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/MGKo27IPmP-690.jpeg 690w, https://geekshavefeelings.com/img/MGKo27IPmP-1380.jpeg 1380w, https://geekshavefeelings.com/img/MGKo27IPmP-3024.jpeg 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="T-handle with torx bit engaged in rear cylinder timing pulley screw" src="https://geekshavefeelings.com/img/MGKo27IPmP-690.jpeg" width="3024" height="4032"></picture><figcaption>I start to float this pulley on its hub and realize it’d be better to do it with the belt mounted so that the float can’t shift the pulley by a full tooth from nominal position</figcaption></figure><p></p>
<p>The procedure is to mount the belts, loosen the clamping screws with a Torx bit, adjust and set the tensioners, then tighten the pulley clamping screws. This mechanism decouples the pulley driving responsibility (belt velocity) from the valve timing responsibility (phase between crankshaft and camshafts), which tickles my <a href="https://en.wikipedia.org/wiki/Separation_of_concerns">software engineering brain just the right way</a>. Compared to the traditional way of <a href="https://chancemoto.com/2020/01/04/ducati-timing-belt-replacement-air-cooled-2v-motors/#attachment_7988">mounting the belts at the same tooth positions</a>, this has two advantages:</p>
<ol>
<li>It’s relatively immune to timing changes: the crankshaft and camshafts are locked and can’t be jostled out of position if I sneeze.</li>
<li>With the belt driving a free-floating pulley wheel instead of the <a href="https://en.wikipedia.org/wiki/Desmodromic_valve">desmo valvetrain</a>, there’s less friction on the belt-train as I move each tensioner into place, allowing the force to distribute into the idler run of the belt.</li>
</ol>
<p>“Traditionally,” belt tension is measured by testing measuring the belt’s deflection under a known orthogonal load. The “dark arts” shadetree procedure calls for <a href="https://chancemoto.com/2020/01/04/ducati-timing-belt-replacement-air-cooled-2v-motors/#attachment_7990">passing hex keys past the belt idler rollers</a>, with 5 mm and 6 mm used as <a href="https://en.wikipedia.org/wiki/Go/no-go_gauge">go/no-go gauges</a>.</p>
<p>Ducati’s workshop manual instead calls for the € × 10³ <abbr title="Ducati Diagnosis System">DDS</abbr> dealer shop computer and an out-of-production “kit tensionamento cinghie” to measure the plucked frequency of the belts.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/3vyPWepInC-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/3vyPWepInC-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Workshop manual photo of DDS harness being plugged in" src="https://geekshavefeelings.com/img/3vyPWepInC-246.jpeg" width="246" height="193"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/W0HJ9FIrWA-246.avif 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/W0HJ9FIrWA-246.webp 246w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Workshop manual photo of acoustic sensor mounted engine case, facing a timing belt" src="https://geekshavefeelings.com/img/W0HJ9FIrWA-246.jpeg" width="246" height="193"></picture></figure><p></p>
<p>Meanwhile, I figure frequency is frequency and use what is effectively a guitar tuner app to pick up the timing twangs with my phone.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ks-4hnP58e-690.avif 690w, https://geekshavefeelings.com/img/ks-4hnP58e-1179.avif 1179w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ks-4hnP58e-690.webp 690w, https://geekshavefeelings.com/img/ks-4hnP58e-1179.webp 1179w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/ks-4hnP58e-690.png 690w, https://geekshavefeelings.com/img/ks-4hnP58e-1179.png 1179w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Screenshot of Gates Carbon Drive app showing four measurements: 128 Hz, 119 Hz, 125 Hz, 115 Hz" src="https://geekshavefeelings.com/img/ks-4hnP58e-690.png" width="1179" height="2556"></picture><figcaption>I took this screenshot while playing around; it measured my plucks in anger with even less variance</figcaption></figure><p></p>
<p>I’m sure that I don’t have the best acoustic setup: I hold my phone up to the belt, resting its case against the engine cover to dampen out some hand jitter.</p>
<p><a href="https://www.texa.com/products/ttc/" title="TEXA TTC product page"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ZY9czA3nh2-690.avif 690w, https://geekshavefeelings.com/img/ZY9czA3nh2-1080.avif 1080w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ZY9czA3nh2-690.webp 690w, https://geekshavefeelings.com/img/ZY9czA3nh2-1080.webp 1080w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ZY9czA3nh2-690.jpeg 690w, https://geekshavefeelings.com/img/ZY9czA3nh2-1080.jpeg 1080w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="TEXA TTC belt tension meter" src="https://geekshavefeelings.com/img/ZY9czA3nh2-690.jpeg" width="1080" height="1080"></picture><figcaption>The latest Ducati dealer tool has a mic element on a wand oriented with the belt vibration for a much better non-contact acoustic coupling.</figcaption></figure></a></p>
<p>After setting the belt tension to its 140 Hz ± 5 Hz, Andy and I do a “belt and suspenders” check with the hex key method and discover that despite having similar acoustic measurements and “felt” tension, the horizontal cylinder belt is allowing <em>way</em> less deflection off of its idlers than the vertical cylinder belt. This observation seems to be <a href="https://www.ducati.ms/threads/timing-belt-tension-observations.131091/">corroborated here for its sibling <abbr title="Monster 1100S">M1100S</abbr> engine</a>, suggesting that the deflection tensioning method might have been obsoleted.</p>
<p>However, it did raise the question whether the tension spec was correct. Based on “Internet said so” evidence, it seems that the spec was downrated to 110 Hz across a number of Ducati models, including the 1100 <abbr title="evoluzione">EVO</abbr>. That’s what I’m going with—based on the experience I gained doing this, it’s now a low mental barrier to check the frequency frequently to make sure that the tension doesn’t drop much further.</p>
<p>After all this hand-wringing, it’s time for me to unfloat the timing pulleys. The clamp screws are spec’d modestly at 10 N·m ± 1 N·m which, after reaching, makes me wonder just how overtorqued they had been before I performed this service. I had photos of the pulleys before I loosened them off of their hubs and it seems like the answer is <em>a lot</em>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/TM-kKwhJxo-690.avif 690w, https://geekshavefeelings.com/img/TM-kKwhJxo-1380.avif 1380w, https://geekshavefeelings.com/img/TM-kKwhJxo-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/TM-kKwhJxo-690.webp 690w, https://geekshavefeelings.com/img/TM-kKwhJxo-1380.webp 1380w, https://geekshavefeelings.com/img/TM-kKwhJxo-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/TM-kKwhJxo-690.jpeg 690w, https://geekshavefeelings.com/img/TM-kKwhJxo-1380.jpeg 1380w, https://geekshavefeelings.com/img/TM-kKwhJxo-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear cylinder timing pulley with paint pen marks on flange screws running tangent to rotation" src="https://geekshavefeelings.com/img/TM-kKwhJxo-690.jpeg" width="4032" height="3024"></picture><figcaption>Before belt change (note that the pulley wasn’t locked at the timing datum)</figcaption></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/m0K0FOo8Rc-690.avif 690w, https://geekshavefeelings.com/img/m0K0FOo8Rc-1380.avif 1380w, https://geekshavefeelings.com/img/m0K0FOo8Rc-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/m0K0FOo8Rc-690.webp 690w, https://geekshavefeelings.com/img/m0K0FOo8Rc-1380.webp 1380w, https://geekshavefeelings.com/img/m0K0FOo8Rc-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/m0K0FOo8Rc-690.jpeg 690w, https://geekshavefeelings.com/img/m0K0FOo8Rc-1380.jpeg 1380w, https://geekshavefeelings.com/img/m0K0FOo8Rc-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rear cylinder timing pulley with paint pen marks running more than 90º off of previous photo" src="https://geekshavefeelings.com/img/m0K0FOo8Rc-690.jpeg" width="4032" height="3024"></picture><figcaption>After</figcaption></figure><p></p>
<p>The manual does not call for retaining compound, which makes sense as the pulleys’ operating temperature would make thread locker pointless, and anyways I didn’t find any on the threads. I don’t see what else besides overtorquing could have caused such a big difference between the before and after screw positions.</p>
<p>Locking down the pulleys got me thinking: this procedure crystallizes an offset in phase between the driving and driven timing pulleys, meant to compensate for an equal-magnitude offset introduced by knuckling each belt with tensioners. However, that offset in each pulley set remains fixed, while the belt or its condition can change before the pulley is floated again. So if a belt has loosened up or changed without performing this “lock shafts and float pulleys” procedure, then the offset from the previous belt change makes the timing (a little) <em>wrong</em>.</p>
<p>Indeed, a test ride with this bike showed a considerable difference on the “<a href="https://www.urbandictionary.com/define.php?term=butt-dyno">butt dyno</a>” report. I was accidentally lifting the front wheel on street-gentle second gear throttle rolls. Considering the <abbr title="evoluzione">EVO</abbr>’s likely timing sensitivity due to its <a href="https://www.bikeboy.org/duccamspec.html">relatively low-overlap exaggerated cam lift</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" id="fnref11">**</a></sup>, it’s entirely possible that I undid some timing error introduced by a combination of the aftermarket belt and unknown “previous owner” maintenance.</p>
<p>At any rate, even if it’s all placebo, I still got to exercise some reverse engineering and that’s worth even more to me than the cost of labor I saved. I got to see which pieces of my machine hold up under the scrutiny of technical judgment, and which pieces are quirks that comprise… <em>character</em>.</p>
<h2 id="appendix-expenditures" tabindex="-1">Appendix: Expenditures <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h2>
<table>
<thead>
<tr>
<th style="text-align:left">Part or tool</th>
<th style="text-align:right">Cost ($)</th>
<th style="text-align:right">Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Ducati timing belts (pair)</td>
<td style="text-align:right">167.58</td>
<td style="text-align:right">£103.16 + £17 shipping + 10.75 % sales tax</td>
</tr>
<tr>
<td style="text-align:left"><div style="text-align: right"><em>Total parts cost</em></div></td>
<td style="text-align:right"><em>167.58</em></td>
<td style="text-align:right"></td>
</tr>
<tr>
<td style="text-align:left">Laser 6367 camshaft lock pins</td>
<td style="text-align:right">21.58</td>
<td style="text-align:right">£10.50 + £5.50 shipping + 10.75 % sales tax</td>
</tr>
<tr>
<td style="text-align:left">Laser 6361 crankshaft turning/locking tool</td>
<td style="text-align:right">54.31</td>
<td style="text-align:right">$49.09 + 10.75 % sales tax</td>
</tr>
<tr>
<td style="text-align:left">ACDelco ARM602-3 <sup>3</sup>⁄<sub>8</sub>″ torque adapter</td>
<td style="text-align:right"><s>54.49</s></td>
<td style="text-align:right">Already owned</td>
</tr>
<tr>
<td style="text-align:left">Ratcheting & T-handle wrenches</td>
<td style="text-align:right"></td>
<td style="text-align:right">Already owned</td>
</tr>
<tr>
<td style="text-align:left">Hex keys and bits: 4, 5, 6 mm</td>
<td style="text-align:right"></td>
<td style="text-align:right">Already owned</td>
</tr>
<tr>
<td style="text-align:left">Torx bit: T30</td>
<td style="text-align:right"></td>
<td style="text-align:right">Already owned</td>
</tr>
<tr>
<td style="text-align:left"><div style="text-align: right"><em>Total new tools cost</em></div></td>
<td style="text-align:right"><em>75.89</em></td>
<td style="text-align:right"></td>
</tr>
</tbody>
</table>
<h2 id="references" tabindex="-1">References <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h2>
<ol>
<li>Ducati Workshop Manual, Monster 1100 <abbr title="evoluzione">EVO</abbr> <abbr title="anti-lock braking system">ABS</abbr> <abbr title="model year">MY</abbr> 2012</li>
<li><a href="http://bradthebikeboy.blogspot.com/2017/02/ducati-timing-belt-failures-and.html">Ducati timing belt failures and replacement intervals</a></li>
<li><a href="https://www.reddit.com/r/Ducati/comments/ugcr1h/lets_talk_timing_belts_a_quick_howto_the_right_way/">let's talk timing belts. A quick how-to the right way.</a></li>
<li><a href="https://chancemoto.com/2020/01/04/ducati-timing-belt-replacement-air-cooled-2v-motors/">Ducati Timing Belt Replacement (Air Cooled 2V Motors)</a></li>
</ol>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>While replacing them with similarly tasteless kit that was on my stolen bike, so there’s little umbrage for me to take on the matter of discretionary aftermarket bling. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Conventionally, this means two valves per cylinder, not per engine. However, the <a href="https://en.wikipedia.org/wiki/Honda_NR500">Honda <abbr title="new racing">NR</abbr>500</a> will always be referred to as a 32-valve engine because that’s hilariously too many valves. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Apropos of nothing, they’re not really a replacement for <abbr title="attrezzo porta disco graduato per contro"><s>887130123</s>887651635</abbr>, as the Ducati tool is more of a degree wheel intended for setting timing advance at arbitrary angles that happens to be able to turn the crankshaft. Bafflingly, the Ducati parts list for the Monster 1100 <abbr title="evoluzione">EVO</abbr> lists an unobtainium <abbr title="attrezzo porta disco graduato per controllo anticipo con disco">887651657</abbr> to perform this function. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Implying that there was an engineering tradeoff between flange space requirements and clamping force; which made me wonder: is the clamping force critical for timing? Hmm… <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>Gates produces the Ducati timing belts but the app is just an acoustic belt tension meter—not specific to Gates belts. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>I do sometimes have to renew the aluminum heat-shielding tape on the underside of the fuel pump that protects it from the rear cylinder header. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn7" class="footnote-item"><p>In fact, I use one of the timing belt cover fixing screws as a ground connection for the Z-Fi, which worked a lot better than I deserve for doing so. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn8" class="footnote-item"><p>On these engines, the 1:2 crank-to-cam reduction is done with a spur gear set driving this central pulley rather than having a toothed reduction between this central pulley and the camshaft pulleys. So each turn of this pulley is a full four-stroke cycle. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn9" class="footnote-item"><p>I found this <a href="https://forum.jorsindo.com/thread-2524970-1-7.html">Taiwanese 796 owner with a comparable fervor</a> for this model, who is adamant about replacing the tensioners at <em>each</em> timing belt change, so opinions vary (again, likely due to operating conditions). I absolutely agree with his observation that palpating bearings is not a reliable method for detecting wear and chose to ignore it this time. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn10" class="footnote-item"><p>Also, recall that timing belt tension is set between belt changes (every 12,000 km or 12 months) so this mechanism is meant to be used pretty frequently. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn11" class="footnote-item"><p>Note that the two²-ish V2-* engines in the <em>2V</em> table refer to <a href="https://www.veetwo.com">Aussie custom builder Vee Two</a>, not to <a href="https://en.wikipedia.org/wiki/Ducati_Panigale_V2">Ducati’s current V2 engine</a>, which too comes in two 4V variants. <a href="https://geekshavefeelings.com/posts/2023/ducati-timing-belt-replacement/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
C++ Corrections
2023-10-24T07:00:00Z
https://geekshavefeelings.com/posts/2023/c-corrections/
<p>It takes some courage and a heap of self-importance to keep a blog alive for two decades without giving in to the urge to burn it all then either:</p>
<ul>
<li>reboot—not remake—the whole site with a fresh WordPress installation and a “Hello, World!” page that stands solo for four years, collecting vulnerabilities</li>
<li>run screaming into the hills and let the sea swallow up the <abbr>DNS</abbr> caches</li>
</ul>
<p>If you’re reading this, then I held fast against both compulsions<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref1">*</a></sup>. The most terrifying part of preserving the teen-aged content in this new packaging has to be stumbling upon the sins of your past self. In my case, my past self <em>also</em> happened to be teenaged and even worse, a C++ embedded systems coder, and hence has a world to atone for.</p>
<p><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/#nunchuk">My 2010 post on decoding Wii Nunchuk state packets</a> made the cut for this site’s third decade. But first, I gotta set the record as straight as my third decade of writing C++ allows.</p>
<h2 id="the-code-s-goals" tabindex="-1">The Code’s Goals <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h2>
<p>The layout of the <abbr>I<sup>2</sup>C</abbr> state reports from the Nunchuk make for an interesting problem: the fields of the report are quite different in size and their bits are splashed around in the report. As a reminder of what it looks like:</p>
<table id="nunchuk-data-layout">
<tr><th>Byte ↓ </th><th>7 </th><th>6 </th><th>5 </th><th>4 </th><th>3 </th><th>2 </th><th>1 </th><th>0
</th></tr><tr>
<th>0 </th><td colspan="8">J<sub>x</sub>[7:0]
</td></tr>
<tr>
<th>1 </th><td colspan="8">J<sub>y</sub>[7:0]
</td></tr>
<tr>
<th>2 </th><td colspan="8">A<sub>x</sub>[9:2]
</td></tr>
<tr>
<th>3 </th><td colspan="8">A<sub>y</sub>[9:2]
</td></tr>
<tr>
<th>4 </th><td colspan="8">A<sub>z</sub>[9:2]
</td></tr>
<tr>
<th>5 </th><td colspan="2">A<sub>z</sub>[1:0] </td><td colspan="2">A<sub>y</sub>[1:0] </td><td colspan="2">A<sub>x</sub>[1:0] </td><td>B<sub>C</sub> </td><td>B<sub>Z</sub>
</td></tr>
<tr><th>Bit → </th><th>7 </th><th>6 </th><th>5 </th><th>4 </th><th>3 </th><th>2 </th><th>1 </th><th>0
</th></tr></table>
<h3 id="legend" tabindex="-1">Legend <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h3>
<ul>
<li>J = joystick axis (unsigned, i.e. 2<sup>7</sup> at center)</li>
<li>A = accelerometer axis (unsigned, i.e. 2<sup>11</sup> under zero acceleration)</li>
<li>B = button state (0 when down)</li>
</ul>
<p>This defined bit layout is what I’ll refer to as an example of a <a href="https://en.wikipedia.org/wiki/Wire_protocol"><em>wire protocol</em></a> or <em>wire packet</em>, where the “wire” is arguably a misnomer because we aren’t dealing with the physical order that the bits are transmitted; <abbr>I<sup>2</sup>C</abbr> is abstracting that away for us.</p>
<p>In my original code<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref2">†</a></sup>, I needed to do two things to decode this 6-byte packet:</p>
<ol>
<li>Map fields to their locations in raw bytes by name</li>
<li>Extract and assemble bits, i.e. fields smaller than a byte</li>
</ol>
<pre class="language-c" tabindex="0"><code class="language-c"><span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">__attribute__</span><span class="token punctuation">(</span><span class="token punctuation">(</span>__packed__<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token keyword">struct</span> <span class="token punctuation">{</span>
<span class="token class-name">uint8_t</span> joyX<span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> joyY<span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> accelX_HI<span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> accelY_HI<span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> accelZ_HI<span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> buttonZ <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> buttonC <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> accelX_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> accelY_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> accelZ_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token class-name">uint8_t</span> buffer<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> NunchukRegisters_t<span class="token punctuation">;</span></code></pre>
<p>Both goals were (supposedly) fulfilled by writing to the <code>buffer</code> field in this union, then reading out the fields of the anonymous internal struct, some of which have sub-octet<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref3">‡</a></sup> bit-widths defined. This looked great, and the code very much mirrored the structure of the data.</p>
<pre class="language-c" tabindex="0"><code class="language-c">nunchukData<span class="token punctuation">.</span>joyX <span class="token operator">=</span> nunchukRegs<span class="token punctuation">.</span>joyX<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>joyY <span class="token operator">=</span> nunchukRegs<span class="token punctuation">.</span>joyY<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>accelX <span class="token operator">=</span> <span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>accelX_HI <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> nunchukRegs<span class="token punctuation">.</span>accelX_LO<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>accelY <span class="token operator">=</span> <span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>accelY_HI <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> nunchukRegs<span class="token punctuation">.</span>accelY_LO<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>accelZ <span class="token operator">=</span> <span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>accelZ_HI <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> nunchukRegs<span class="token punctuation">.</span>accelZ_LO<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>buttonZ <span class="token operator">=</span> <span class="token operator">!</span>nunchukRegs<span class="token punctuation">.</span>buttonZ<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>buttonC <span class="token operator">=</span> <span class="token operator">!</span>nunchukRegs<span class="token punctuation">.</span>buttonC<span class="token punctuation">;</span></code></pre>
<p>Unfortunately, it was not so simple. Important nuances in C and C++ specifications and compiler writers’ direction made this kind of raw data destructuring a crime to write and a gamble to run. And as we’ll discover, the whole “<code>struct</code> aliasing” approach to serialization is unsalvageable.</p>
<h2 id="problem-1-type-aliasing-by-union" tabindex="-1">Problem 1: Type aliasing by union <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h2>
<p>This problem is (or at least should be) well-known by systems programmers now: it’s undefined behavior (<abbr>UB</abbr>) in C++ to <a href="https://en.wikipedia.org/wiki/Type_punning#C_and_C++">perform type-punning of an object</a> by reading from a union member other than the one last written to<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref4">§</a></sup>. This has to do with <a href="https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8">strict aliasing rules</a> that dedicate memory used through the lifetime of an object to only be used for that object, hence fixing the type at that memory.</p>
<p>This kind of type punning is defined in C<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref5">¶</a></sup>, so this isn’t a necessarily a problem with the original HÄRDBÖRD code, but I doubt 2010 Xo made that distinction.</p>
<p>This also used to work when compiler authors decided to enforce strict aliasing in pursuit of unlocking optimizations, but of course said authors still needed a way for coders to express the same intent to move bits. At this point in C++’s saga, the best way to express that you wish to move the bit representation of a type around while satisfying the rules around object lifetime is to create the object using <a href="https://en.cppreference.com/w/cpp/numeric/bit_cast"><code>std::bit_cast</code></a> or (less-ideally) create an object then <a href="https://en.cppreference.com/w/cpp/string/byte/memcpy"><code>memcpy</code></a> to and from it. The “right way” also enjoys proper optimization now—a difficult thing to come by in the transitional period when I first encountered this (<abbr>GCC</abbr> 4-ish).</p>
<p>A major advantage to using <code>std::bit_cast</code> is that it can be <code>constexpr</code> friendly:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">constexpr</span> <span class="token keyword">unsigned</span> <span class="token keyword">char</span> kRawData<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">0xff</span><span class="token punctuation">,</span> <span class="token number">0x00</span><span class="token punctuation">,</span> <span class="token number">0x01</span><span class="token punctuation">,</span> <span class="token number">0xa0</span><span class="token punctuation">,</span> <span class="token number">0x04</span><span class="token punctuation">,</span> <span class="token number">0x5b</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">constexpr</span> <span class="token keyword">auto</span> kRegister <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span><span class="token generic-function"><span class="token function">bit_cast</span><span class="token generic class-name"><span class="token operator"><</span>NunchukRegisters_t<span class="token operator">></span></span></span><span class="token punctuation">(</span>kRawData<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>However, if <a href="https://godbolt.org/z/1WjjhqGo7">we run this through a few compilers</a>, we find that <a href="https://github.com/llvm/llvm-project/blob/e90f4fc6acaffd216e06e47df0aee6a8b5b2d4a9/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp#L131-L145">Clang doesn’t yet support <code>constexpr</code> <code>std::bit_cast</code> with bit-fields</a> and <a href="https://developercommunity.visualstudio.com/t/1347081"><abbr>MSVC</abbr> only supported it starting in version 16.10</a>. This low level of support and general neglect of bit-fields from compiler writers is a <a href="https://geekshavefeelings.com/posts/2023/c-corrections/">great reason to avoid them</a>.</p>
<h2 id="problem-2-struct-packing" tabindex="-1">Problem 2: Struct packing <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h2>
<p>The original code relied on all the fields in the inner anonymous struct to be laid out tightly-packed in memory in the same order as declared.</p>
<p>“Same order as declared” is actually guaranteed by both C and C++<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref6">♠</a></sup>, but the <a href="https://en.cppreference.com/w/c/language/object#Alignment">tight packing is not</a>. In order to maintain alignment for different types, the compiler is free to add padding bytes that occupy space in the struct but are not storage for the elements.</p>
<p>With that said, the <code>uint8</code> types in the original HÄRDBÖRD code do actually pack tightly regardless of the <code>__attribute__((__packed__))</code> because no padding needs to be added to bring them into their natural alignment (which is 1). You can see that <a href="https://godbolt.org/z/o6bPMT3Pq" title="Godbolt example that compiles the original snippet to two 32-bit ARM targets">even in C++, this struct ends up at 6 bytes long</a>, implying tight packing.</p>
<p>However, there’s a glaring error that the attribute is actually applied to the wrong <code>struct</code>: the outer anonymous struct (which is itself superfluous<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref7">♥</a></sup>) doesn’t <em>directly</em> hold the fields of the data, so applying the attribute means nothing.</p>
<p>To show this, I’ll add a test field to the struct:</p>
<pre class="language-diff-c" tabindex="0"><code class="language-diff-c"><span class="token unchanged language-c"><span class="token prefix unchanged"> </span><span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">__attribute__</span><span class="token punctuation">(</span><span class="token punctuation">(</span>__packed__<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token prefix unchanged"> </span> <span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token prefix unchanged"> </span> <span class="token keyword">struct</span> <span class="token punctuation">{</span>
<span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> joyX<span class="token punctuation">;</span>
</span><span class="token inserted-sign inserted language-c"><span class="token prefix inserted">+</span> <span class="token class-name">uint16_t</span> newField<span class="token punctuation">;</span>
</span><span class="token unchanged language-c"><span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> joyY<span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> …
<span class="token prefix unchanged"> </span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span>
<span class="token unchanged language-c"><span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> buffer<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span><span class="token punctuation">}</span> NunchukRegisters_t<span class="token punctuation">;</span>
</span></code></pre>
<p>In the same Godbolt workspace, we can see that this <a href="https://godbolt.org/z/qb6eoY9Yv">new two-byte field adds four bytes to the original struct</a>: two as storage for the new <code>newField</code> field, one as padding ahead of <code>newField</code> to align it, and yet one more to ensure that the <code>struct</code> itself is aligned to its greatest alignment member (in this case, making its size even for the two-byte <code>uint16_t newField</code>).</p>
<p>To fix both the superfluous <code>struct</code> wrapper and more importantly, the incorrect packing attribute placement, I’ll move it into the inner anonymous struct:</p>
<pre class="language-diff-c" tabindex="0"><code class="language-diff-c"><span class="token deleted-sign deleted language-c"><span class="token prefix deleted">-</span><span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">__attribute__</span><span class="token punctuation">(</span><span class="token punctuation">(</span>__packed__<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token prefix deleted">-</span> <span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token prefix deleted">-</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span>
</span><span class="token inserted-sign inserted language-c"><span class="token prefix inserted">+</span><span class="token keyword">typedef</span> <span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token prefix inserted">+</span> <span class="token keyword">struct</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>gnu<span class="token operator">::</span>packed<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token punctuation">{</span>
</span><span class="token unchanged language-c"><span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> joyX<span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> <span class="token class-name">uint16_t</span> newField<span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> joyY<span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span>…
<span class="token prefix unchanged"> </span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span>
<span class="token unchanged language-c"><span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> buffer<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
</span><span class="token deleted-sign deleted language-c"><span class="token prefix deleted">-</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span><span class="token unchanged language-c"><span class="token prefix unchanged"> </span><span class="token punctuation">}</span> NunchukRegisters_t<span class="token punctuation">;</span>
</span></code></pre>
<p>At the same time, I’m also using the C++11 attribute syntax <code>[[gnu::packed]]</code><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref8">♦</a></sup> in place of <code>__attribute__((__packed__))</code> because of its consistent placement for declaring types and gentle fallback for unsupported attributes.</p>
<h2 id="problem-3-bit-fields-bad" tabindex="-1">Problem 3: Bit-fields bad <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h2>
<p>As I showed <a href="https://geekshavefeelings.com/posts/2023/c-corrections/">in an earlier example</a>, <code>constexpr</code>, <code>std::bit_cast</code>, and bit-fields don’t play nicely together. What else don’t work nicely together with bit-fields?</p>
<ul>
<li>
<p>C/C++ addressing system—the entirety of C/C++’s memory system is byte-oriented: sizes are in byte units and addresses increment by one byte at a time. Using bits and bit-widths (regardless of whether they’re bit-fields or otherwise) introduces additional mental overhead that lives outside of that byte-sized world and that means bugs. Remember, bit positions and bit widths are not simply “addresses/sizes multiplied by <a href="https://en.cppreference.com/w/c/types/limits"><code>CHAR_BIT</code></a>” but in fact totally separate addressing systems that each exist within each integer object: when addressing bits of a byte, it’s not as if you can address the first bit of the next byte as the “ninth” bit.</p>
</li>
<li>
<p>Parallel access—because bit-fields that are placed in the same storage unit or object are, from the C/C++ perspective, sharing a memory location<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref9">♣</a></sup>, writing to bit-fields can’t be guaranteed to be atomic, making them a <a href="https://wiki.sei.cmu.edu/confluence/display/c/CON32-C.+Prevent+data+races+when+accessing+bit-fields+from+multiple+threads">hazard to use for across threads</a> or (more pertinently) interrupt contexts. This is usually because writing to a bit-field is a non-atomic “read-modify-write<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref10">¤</a></sup>” combination rather than a single atomic operation, even in cases where the latter is available in the hardware<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref11">**</a></sup>.</p>
</li>
<li>
<p>Packing/straddling—the C standard has rules about bit-fields being packed into storage units when possible, but it’s also intentionally lax about what happens when a bit-field doesn’t fit<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref12">††</a></sup>:</p>
<blockquote>
<p>If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.</p>
</blockquote>
<p>Of course, there’s no warning for when you’re overflowing the current storage unit with bit-fields, like if we did this:</p>
<pre class="language-diff-c" tabindex="0"><code class="language-diff-c"><span class="token unchanged language-c"><span class="token prefix unchanged"> </span><span class="token keyword">typedef</span> <span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token prefix unchanged"> </span> <span class="token keyword">struct</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>gnu<span class="token operator">::</span>packed<span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token punctuation">{</span>
<span class="token prefix unchanged"> </span> …
<span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> buttonZ <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> buttonC <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> accelX_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> accelY_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="token deleted-sign deleted language-c"><span class="token prefix deleted">-</span> <span class="token class-name">uint8_t</span> accelZ_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
</span><span class="token inserted-sign inserted language-c"><span class="token prefix inserted">+</span> <span class="token class-name">uint8_t</span> accelZ_LO <span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">;</span> <span class="token comment">// 1+1+2+2+3 bits overflows the byte</span>
</span><span class="token unchanged language-c"><span class="token prefix unchanged"> </span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
</span>
<span class="token unchanged language-c"><span class="token prefix unchanged"> </span> <span class="token class-name">uint8_t</span> buffer<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token prefix unchanged"> </span><span class="token punctuation">}</span> NunchukRegisters_t<span class="token punctuation">;</span>
</span></code></pre>
<p>Moreover, we can’t even introspectively detect where the <code>accelZ_LO</code> field ends up because it’s <abbr>UB</abbr> to take the address of a bit-field<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref13">‡‡</a></sup>, to which <a href="https://en.cppreference.com/w/c/types/offsetof"><code>offsetof</code></a> is no exception.</p>
</li>
<li>
<p>Ordering of the bit-fields relative to each other—have you noticed that the bit-fields in the last byte of the struct are written in the reverse order of how it was written in the <a href="https://geekshavefeelings.com/posts/2023/c-corrections/">report layout table</a>? This isn’t only unfortunate, but it’s yet again a case of implementation-defined behavior. The spec says<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref14">§§</a></sup>:</p>
<blockquote>
<p>The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.</p>
</blockquote>
<p>But getting the bits from the right locations was the whole point of writing the Nunchuk decoder like this! The idea was to have the <code>struct</code> layout mirror the real wire layout, but given that bit-fields are the only way to represent fields smaller than a byte in C/C++, this restriction alone makes that goal impossible to achieve.</p>
</li>
</ul>
<p>So not only are bit-fields a neglected stepchild of C/C++ and its compilers, incurring large mental cost and incompatibilities with other features, but also fail to deliver on the actual promise of reliably establishing a struct layout for wire transmission. There isn’t really a fix here for writing a struct that looks like the Nunchuk wire packet, other than looking to languages like <a href="https://ziglang.org">Zig</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref15">¶¶</a></sup>.</p>
<p>As far as I know, to implement wire protocol decoding at the bit level in C/C++, bitmasking is the only way to go. In the Nunchuk example, reading the lowest 2 bits of the y-axis acceleration might look like:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp">buffer<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">4</span> <span class="token operator">&</span> <span class="token number">0b11</span></code></pre>
<p>When combined with code for assembling the most significant 8 bits, <a href="https://godbolt.org/z/c98YzPs79">this doesn’t look quite so great</a>:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">constexpr</span> <span class="token keyword">int16_t</span> <span class="token function">GetJoyY</span><span class="token punctuation">(</span>std<span class="token double-colon punctuation">::</span>array<span class="token operator"><</span><span class="token keyword">uint8_t</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token operator">></span> report_bytes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">uint16_t</span><span class="token punctuation">{</span>report_bytes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">}</span> <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token punctuation">(</span>report_bytes<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">4</span> <span class="token operator">&</span> <span class="token number">0b11</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>And it’s even worse if you <a href="https://godbolt.org/z/zzn4bnbGE">hide some of the magic number constants and put it under a class indentation</a>.</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">class</span> <span class="token class-name">NunchukReport</span> <span class="token punctuation">{</span>
…
<span class="token keyword">constexpr</span> <span class="token keyword">int16_t</span> <span class="token function">joyX</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">uint16_t</span><span class="token punctuation">{</span>bytes_<span class="token punctuation">[</span>JOY_X<span class="token punctuation">]</span><span class="token punctuation">}</span> <span class="token operator"><<</span> kAccelLoBitWidth<span class="token punctuation">)</span> <span class="token operator">|</span>
<span class="token punctuation">(</span>bytes_<span class="token punctuation">[</span>REG_5<span class="token punctuation">]</span> <span class="token operator">>></span> kRegister5AccelXLoBits <span class="token operator">&</span>
<span class="token function">MakeBitMask</span><span class="token punctuation">(</span>kAccelLoBitWidth<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
…
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>But, we chose C++ and this is our life now.</p>
<h2 id="conclusion" tabindex="-1">Conclusion <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h2>
<p>If I had to write this Nunchuk wire protocol decoder today, I’d be careful to work with the wire bytes directly rather than type punning them to a loosely-packed <code>struct</code> (even with <code>std::bit_cast</code> available). Given that bit-fields are not practical to use to refer to the smallest fields in the layout, we might as well address the bytes by offset using named constants:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">enum</span> <span class="token class-name">RegisterOffset</span> <span class="token punctuation">{</span>
JOY_X<span class="token punctuation">,</span>
JOY_Y<span class="token punctuation">,</span>
ACCEL_X_HI<span class="token punctuation">,</span>
ACCEL_Y_HI<span class="token punctuation">,</span>
ACCEL_Z_HI<span class="token punctuation">,</span>
REG_5<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>I would then massage the bits out using the tried-and-true methods of shifting and masking. Basically, this is a barely-dressed up way to programmatically reach into the byte buffer and pull out the bits we want rather than aliasing them into a named, formatted schema.</p>
<p>What if I wanted to handle lots of different wire packet formats? I’m not sure if there is a good solution. At Google, <a href="https://github.com/google/emboss">Emboss</a> looked great for systems that could handle more tooling than a barebones CMake + compiler setup. <a href="http://kaitai.io">Kaitai Struct</a> and <a href="https://www.protlr.com">Protlr</a> are similar in that they are also standalone tools defining a declarative schema that necessarily add a code generation stage. But, I’ve yet to see any (let alone a compelling) library that allows the developer to define a schema in only C++<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2023/c-corrections/" id="fnref16">♠♠</a></sup>. Libraries like <a href="https://github.com/serge-sans-paille/frozen">Frozen</a> certainly prove that compile-time data is practical to traverse and hence use for generating run-time code, so there is hope.</p>
<p>Finally, at a higher level of code organization, I would make sure to <a href="https://en.wikipedia.org/wiki/Dependency_injection">inject</a> the underlying <abbr>I<sup>2</sup>C</abbr> library dependency then <a href="https://en.wikipedia.org/wiki/Separation_of_concerns">separate</a> the wire communication part of the code from the wire decoding part. This would allow the <abbr>I<sup>2</sup>C</abbr> flow sequencing and data decryption to be tested separately from the hardware as well as separately from the bit decoding described above. Testing how bits move from the raw buffer into a 16-bit output should not require a real microcontroller hardware harnessed to a real Nunchuk.</p>
<p>However, with all that said, the original code <em>does</em> actually work without <abbr>UB</abbr> even though that might have been an afterthought: union type punning is defined in C, struct packedness isn’t necessary given the layout, and bit-field order is consistent for a given compiler and target. At any rate, 2010 Xo definitely acquitted himself by writing the whole project in less time than it took for 2023 Xo to write this post. ∎</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2023/c-corrections/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>For now. Though, this site’s “dark year” while I contemplated the latter has cut its “link juice” (“<abbr>SEO</abbr> mojo?” “Google voodoo?”) to a trickle. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Shown here using <a href="https://en.cppreference.com/w/cpp/types/integer"><code><cstdint></code>’s <code>uint8_t</code></a> instead of <code>uint8</code>, which was provided by the <a href="https://sites.google.com/site/pic24micro/Home">Reese <abbr>PIC24</abbr> startup code/<abbr title="Hardware abstraction layer">HAL</abbr></a> I used at the time. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>As in, less than 8. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>By way of exclusion from the list at <abbr>ISO/IEC</abbr> 14882:2017 §8.2.1 [basic.lval] ¶11 <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p><abbr>ISO/IEC</abbr> 9899:2018 §6.5.2.3 ¶3, footnote 97 <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>And notably <a href="https://doc.rust-lang.org/reference/type-layout.html#the-default-representation"><em>not</em> by Rust, by default</a>. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn7" class="footnote-item"><p>There might be some value to ensuring that the wrapper is ultimately <code>struct</code> instead of <code>union</code> but not in this case of a inner type used by the decoder routine. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn8" class="footnote-item"><p><a href="https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html">The <code>gnu</code> namespacing for attributes</a> is accepted by both <a href="https://clang.llvm.org/docs/AttributeReference.html#packed">Clang</a> and <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute"><abbr>GCC</abbr></a>. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn9" class="footnote-item"><p>Which are, again, in byte-sized units. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn10" class="footnote-item"><p>Not to be confused with an <a href="https://en.wikipedia.org/wiki/Read%E2%80%93modify%E2%80%93write"><em>atomic</em> read-modify-write</a>, which is largely an abstraction that’s <a href="https://llvm.org/docs/Atomics.html#atomics-and-codegen">likely generated</a> using a looped atomic <a href="https://en.wikipedia.org/wiki/Compare-and-swap">compare-and-swap (<abbr>CAS</abbr>)</a> anyhow. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn11" class="footnote-item"><p>This doesn’t really apply to the Nunchuk decoder because the <code>struct</code>’s bit-fields aren’t written to, but it would be an issue in the reverse (encoding) direction. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn12" class="footnote-item"><p><abbr>ISO/IEC</abbr> 9899:2018 §6.7.2.1 ¶11 <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn13" class="footnote-item"><p><abbr>ISO/IEC</abbr> 9899:2018 §6.5.3.2 ¶1 <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn14" class="footnote-item"><p><abbr>ISO/IEC</abbr> 9899:2018 §6.7.2.1 ¶11 <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn15" class="footnote-item"><p>Which has first-class support for packed structs and <a href="https://ziglang.org/documentation/master/#Primitive-Types">arbitrary fixed-width integers</a>, making “bit-fields” look just like other primitives in a struct. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn16" class="footnote-item"><p>Understandable, given that expressing some of the concepts in those schemas like arithmetic encoding and substructures can be gnarly enough in a from-scratch domain-specific language (<abbr>DSL</abbr>), let alone wrapped up in template and macro magic. <a href="https://geekshavefeelings.com/posts/2023/c-corrections/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Liftlord
2016-10-03T02:05:18Z
https://geekshavefeelings.com/posts/2016/liftlord/
<p>Liftlord is a sumo grappler robot: specifically a (brushless hipster)<sup>2</sup> metric 12 O’Clockoff featuring belt drive skate wheels, real hot dog<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/liftlord/" id="fnref1">*</a></sup> grippers, servo-actuated clamper, and <em>too many screws</em>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/6KyF_ui7D_-690.avif 690w, https://geekshavefeelings.com/img/6KyF_ui7D_-1380.avif 1380w, https://geekshavefeelings.com/img/6KyF_ui7D_-5472.avif 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/6KyF_ui7D_-690.webp 690w, https://geekshavefeelings.com/img/6KyF_ui7D_-1380.webp 1380w, https://geekshavefeelings.com/img/6KyF_ui7D_-5472.webp 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/6KyF_ui7D_-690.jpeg 690w, https://geekshavefeelings.com/img/6KyF_ui7D_-1380.jpeg 1380w, https://geekshavefeelings.com/img/6KyF_ui7D_-5472.jpeg 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord low 3/4" src="https://geekshavefeelings.com/img/6KyF_ui7D_-690.jpeg" width="5472" height="3648"></picture></figure><p></p>
<p>It wasn’t the idea, but what it became as I rolled with the punches.</p>
<p>Also, <em>it’s not a beetleweight</em> (3 lb)!</p>
<p>Held on Sunday-before-Labor-Day, the micro battles (1 and 3 lb classes) event at <a href="http://robotbattles.com">Robot Battles</a> at <a href="http://dragoncon.org">DragonCon</a> grew over the years in competitors while shrinking in schedule, turning into a single-elimination, no rumbles affair. That means half of the entered bots get exactly one fight: less than ideal odds for me considering I had just one win over the course of like ten events. So, it’s time to go big(-ger). Big enough to put me into the 12 and 30 lb fights on Labor Day!</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/8MGJxxeUY7-690.avif 690w, https://geekshavefeelings.com/img/8MGJxxeUY7-1380.avif 1380w, https://geekshavefeelings.com/img/8MGJxxeUY7-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/8MGJxxeUY7-690.webp 690w, https://geekshavefeelings.com/img/8MGJxxeUY7-1380.webp 1380w, https://geekshavefeelings.com/img/8MGJxxeUY7-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/8MGJxxeUY7-690.jpeg 690w, https://geekshavefeelings.com/img/8MGJxxeUY7-1380.jpeg 1380w, https://geekshavefeelings.com/img/8MGJxxeUY7-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon gearmotors" src="https://geekshavefeelings.com/img/8MGJxxeUY7-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>The concept started, as usual, with sourcing motors too big to be useful in a 3 lb. Normally I’d shove them into a <a href="https://geekshavefeelings.com/tags/big-data">Big Data</a> anyways and call it a day<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/liftlord/" id="fnref2">†</a></sup>, except this turned out to be a physical impossibility and w-wait… why am I still thinking beetles?</p>
<p><a href="https://geekshavefeelings.com/posts/2016/liftlord/files/Maxon-EC-max-22-283858-motor-25W.pdf" title="Motor datasheet"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/mWhOCvFwwX-690.avif 690w, https://geekshavefeelings.com/img/mWhOCvFwwX-1280.avif 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/mWhOCvFwwX-690.webp 690w, https://geekshavefeelings.com/img/mWhOCvFwwX-1280.webp 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/mWhOCvFwwX-690.png 690w, https://geekshavefeelings.com/img/mWhOCvFwwX-1280.png 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon <abbr>EC</abbr>-max 22 283858 motor 25 W datasheet" src="https://geekshavefeelings.com/img/mWhOCvFwwX-690.png" width="1280" height="1697"></picture><figcaption>Motor datasheet</figcaption></figure></a></p>
<p>These Maxon gearmotors each comprise a 25 W <a href="http://www.maxonmotorusa.com/maxon/view/product/motor/ecmotor/ecmax/ecmax22/283858"><abbr>EC</abbr>-Max 22 sensored brushless motor</a> coupled to a 19:1 <a href="http://www.maxonmotorusa.com/maxon/view/product/gear/planetary/gp22/370689"><abbr>GP</abbr> 22 <abbr>HP</abbr> (“high power”) planetary gearhead</a>. I scored four plus a spare motor (no gearhead) at an average of $45 each.</p>
<p><a href="https://geekshavefeelings.com/posts/2016/liftlord/files/Maxon-GP-22-HP-370689-gearhead-high-power.pdf" title="Gearhead datasheet"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/WxRbtC7aUK-690.avif 690w, https://geekshavefeelings.com/img/WxRbtC7aUK-1280.avif 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/WxRbtC7aUK-690.webp 690w, https://geekshavefeelings.com/img/WxRbtC7aUK-1280.webp 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/WxRbtC7aUK-690.png 690w, https://geekshavefeelings.com/img/WxRbtC7aUK-1280.png 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon GP 22 HP 370689 gearhead high power datasheet" src="https://geekshavefeelings.com/img/WxRbtC7aUK-690.png" width="1280" height="1697"></picture><figcaption>Gearhead datasheet</figcaption></figure></a></p>
<p>Now, “too big for beetle” doesn’t automatically mean I can go up to the next weight class. The gap between 3 lb and 12 lb—a factor of 4—is the biggest change in scale between any two adjacent weight classes in US combat robots<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/liftlord/" id="fnref3">‡</a></sup>. Compared to the pair of <a href="http://www.wa4dsy.com/robot/drill-motor-hack">550-ish drill motors</a> commonly used by many successful 12 lb DragonCon robots, my 22 mm diameter Maxons look positively puny. I mean look at them compared to the <a href="http://e0designs.com/products/ragebridge2/">Standard RageBridge 2</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/O52Ppdya0V-690.avif 690w, https://geekshavefeelings.com/img/O52Ppdya0V-1380.avif 1380w, https://geekshavefeelings.com/img/O52Ppdya0V-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/O52Ppdya0V-690.webp 690w, https://geekshavefeelings.com/img/O52Ppdya0V-1380.webp 1380w, https://geekshavefeelings.com/img/O52Ppdya0V-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/O52Ppdya0V-690.jpeg 690w, https://geekshavefeelings.com/img/O52Ppdya0V-1380.jpeg 1380w, https://geekshavefeelings.com/img/O52Ppdya0V-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord traction motors mounted" src="https://geekshavefeelings.com/img/O52Ppdya0V-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Why, then, did I think this setup could work?</p>
<ol>
<li>The windings on the motors, rated for 24 V, are relatively “cool.” Even as two-pole inrunners, they clock in at a low, low <a href="https://en.wikipedia.org/wiki/Motor_constants#Motor_velocity_constant.2C_back_EMF_constant"><em>mechanical</em> K<sub>v</sub></a> of 549 <sup>RPM</sup>⁄<sub>V</sub>, a figure you might expect from a 22-pole 50 mm hobby outrunner. As a result, I can expect them to produce a fair amount of torque without running outrageous current through them.</li>
<li>The motors have Hall-effect sensors that allow their controllers to determine to read—at any speed and within ±15°—the rotor angle and thus the appropriate stator current to produce torque. This helps close the gap between brushless and brushed traction systems at low speed.</li>
<li>You don’t have to even peek at the datasheets on the planetary gearheads to tell they’re <em>srs business</em>. The 6 mm diameter shaft supported by sealed 696 bearings looks comically oversized relative to the gearhead body.</li>
</ol>
<p>Running the numbers, I can tell that with a 6-series lithium-polymer pack, this setup can push out similar peak mechanical power to drill motors, but in a smaller, lighter package<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/liftlord/" id="fnref4">§</a></sup>. Unfortunately, a smaller, lighter package has less cooling capacity and thermal mass, thanks to lower surface area and <em>actual</em> mass. So average power dissipated during a three minute fight was gonna be a problem.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/DInwIUWoM3-690.avif 690w, https://geekshavefeelings.com/img/DInwIUWoM3-1380.avif 1380w, https://geekshavefeelings.com/img/DInwIUWoM3-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/DInwIUWoM3-690.webp 690w, https://geekshavefeelings.com/img/DInwIUWoM3-1380.webp 1380w, https://geekshavefeelings.com/img/DInwIUWoM3-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/DInwIUWoM3-690.png 690w, https://geekshavefeelings.com/img/DInwIUWoM3-1380.png 1380w, https://geekshavefeelings.com/img/DInwIUWoM3-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord top traction motors highlighted" src="https://geekshavefeelings.com/img/DInwIUWoM3-690.png" width="2847" height="1703"></picture></figure><p></p>
<p>By the way, the absurd aspect ratio of industrial gearmotors make it look like I’m only mounting them by their face. In actuality, 41% of the overall length of each gearmotor (the entire planetary gearhead, adapter plate, and change) is supported by frame material.</p>
<p>How do you resolve design uncertainty and in the process dip your toes into the 12 lb pool? Build a brick bot with four of these motors for traction to see how things would work out.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/NHyLhS3Gui-690.avif 690w, https://geekshavefeelings.com/img/NHyLhS3Gui-1380.avif 1380w, https://geekshavefeelings.com/img/NHyLhS3Gui-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/NHyLhS3Gui-690.webp 690w, https://geekshavefeelings.com/img/NHyLhS3Gui-1380.webp 1380w, https://geekshavefeelings.com/img/NHyLhS3Gui-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/NHyLhS3Gui-690.png 690w, https://geekshavefeelings.com/img/NHyLhS3Gui-1380.png 1380w, https://geekshavefeelings.com/img/NHyLhS3Gui-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Brickt" src="https://geekshavefeelings.com/img/NHyLhS3Gui-690.png" width="2847" height="1703"></picture></figure><p></p>
<p>except lol jk no I didn’t. Too much pride. Due to the Wang-wedge arbitrary negative double standard (“other people can build wedges but I can’t”), I just couldn’t bring myself to do it and had to put in some kind of active weapon?</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/eSSLbLQX-H-690.avif 690w, https://geekshavefeelings.com/img/eSSLbLQX-H-1380.avif 1380w, https://geekshavefeelings.com/img/eSSLbLQX-H-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/eSSLbLQX-H-690.webp 690w, https://geekshavefeelings.com/img/eSSLbLQX-H-1380.webp 1380w, https://geekshavefeelings.com/img/eSSLbLQX-H-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/eSSLbLQX-H-690.png 690w, https://geekshavefeelings.com/img/eSSLbLQX-H-1380.png 1380w, https://geekshavefeelings.com/img/eSSLbLQX-H-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord render" src="https://geekshavefeelings.com/img/eSSLbLQX-H-690.png" width="2847" height="1703"></picture></figure><p></p>
<p>Given that exactly one event in the country runs 12 lb sumo fights and it’s dominated by the lifter/flipper–clamper/grappler spectrum, I figured I’d build this new bot as a clone of the most iconic of that event, the 30 lb <a href="http://www.etotheipiplusone.net/?page_id=2844">Überclocker</a>. I even named the <abbr>CAD</abbr> model as such:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/DzfybmaeJ4-690.avif 690w, https://geekshavefeelings.com/img/DzfybmaeJ4-1380.avif 1380w, https://geekshavefeelings.com/img/DzfybmaeJ4-1536.avif 1536w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/DzfybmaeJ4-690.webp 690w, https://geekshavefeelings.com/img/DzfybmaeJ4-1380.webp 1380w, https://geekshavefeelings.com/img/DzfybmaeJ4-1536.webp 1536w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/DzfybmaeJ4-690.png 690w, https://geekshavefeelings.com/img/DzfybmaeJ4-1380.png 1380w, https://geekshavefeelings.com/img/DzfybmaeJ4-1536.png 1536w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="CLOCKOFF model on Dropbox" src="https://geekshavefeelings.com/img/DzfybmaeJ4-690.png" width="1536" height="300"></picture></figure><p></p>
<p>But ego struck again. I made it a design goal to NOT be like Clocker aside from the overall concept of a four wheel drive grappling bot. This meant no looking at reference photos. It meant intentionally stuffing in different components from what I can recall Charles using. It also meant replacing entire subsystems with silly junk: servos instead of leadscrew to actuate the clamper, no spring legs instead of yes spring legs, belt drive lifter instead of gear drive lifter. After all, it’s not truly Clocker without its <a href="http://www.etotheipiplusone.net/?p=4019">lift gear</a>, right?</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/F3l2-Iq65l-690.avif 690w, https://geekshavefeelings.com/img/F3l2-Iq65l-1380.avif 1380w, https://geekshavefeelings.com/img/F3l2-Iq65l-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/F3l2-Iq65l-690.webp 690w, https://geekshavefeelings.com/img/F3l2-Iq65l-1380.webp 1380w, https://geekshavefeelings.com/img/F3l2-Iq65l-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/F3l2-Iq65l-690.jpeg 690w, https://geekshavefeelings.com/img/F3l2-Iq65l-1380.jpeg 1380w, https://geekshavefeelings.com/img/F3l2-Iq65l-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord lifter drive pretendo" src="https://geekshavefeelings.com/img/F3l2-Iq65l-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Turns out “not looking” and “don’t rip off” are mutually exclusive criteria. Yes, I avoided the gear drive, but still ended up with a hollow aluminum lifter live shaft running in sleeve bearings with clamp shaft collars for shaft-to-arm torque transfer, because I literally forgot that’s what’s on Überclocker but had enough subconscious fanboy memory to design it like that anyways.</p>
<p>Finally, everything had to be metric. At this point, this has almost nothing to do with round numbers and standardization than to do with my gradual switch to building almost everything with a hefty helping of “Chinesium,” the bot community’s term for materiel sourced (nearly) directly from East Asian suppliers through the likes of eBay, HobbyKing, AliExpress, and Banggood. At first I thought the term implied low quality (for some folks, they’re synonymous) but more accurately it describes the <em>uncertainty</em> of these items’ origin and durability than a clear statement against them. Regardless, Chinesium’s all metric, since little of it is necessarily intended for direct American consumption.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/SNQb47pxDs-690.avif 690w, https://geekshavefeelings.com/img/SNQb47pxDs-1380.avif 1380w, https://geekshavefeelings.com/img/SNQb47pxDs-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/SNQb47pxDs-690.webp 690w, https://geekshavefeelings.com/img/SNQb47pxDs-1380.webp 1380w, https://geekshavefeelings.com/img/SNQb47pxDs-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/SNQb47pxDs-690.jpeg 690w, https://geekshavefeelings.com/img/SNQb47pxDs-1380.jpeg 1380w, https://geekshavefeelings.com/img/SNQb47pxDs-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt=""I wouldn't put it past you guys to use real hot dog in a bot."" src="https://geekshavefeelings.com/img/SNQb47pxDs-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Metric means hardware with metric screw threads, belt pitch, bearing bores, everything but wire gauge and raw stock (don’t give me ideas). It also means components that fit metric stuff: thus 80 mm inline skate wheels made to mount 608 bearings and <a href="https://www.aliexpress.com/store/product/DC-PG45-775-planet-gear-motor-12V-24V/1724883_32473586630.html">775 motor lift motor with a 42 mm gearbox</a> (10 mm output shaft with 4 mm keyway ;). Side note: RageBridge 2’s heatsink mounting holes will clear M3 screws just fine.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/5RxLts06O9-690.avif 690w, https://geekshavefeelings.com/img/5RxLts06O9-1380.avif 1380w, https://geekshavefeelings.com/img/5RxLts06O9-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/5RxLts06O9-690.webp 690w, https://geekshavefeelings.com/img/5RxLts06O9-1380.webp 1380w, https://geekshavefeelings.com/img/5RxLts06O9-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/5RxLts06O9-690.jpeg 690w, https://geekshavefeelings.com/img/5RxLts06O9-1380.jpeg 1380w, https://geekshavefeelings.com/img/5RxLts06O9-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord filing bottom plate" src="https://geekshavefeelings.com/img/5RxLts06O9-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>After moving to California and thus away from the <a href="http://inventionstudio.gatech.edu">Invention Studio</a>, I’ve been in enough of a waterjet drought to have forgotten how to properly design for it. I put in 0.05 mm clearance between tabs and slots in my part, which wasn’t enough for <a href="http://www.bigbluesaw.com">BigBlueSaw</a>’s OMAX quality 3 cut for ¼ inch 6061. Fortunately, I consider manual filing an exciting sub-hobby of combat robotics (and of life, even), so this is A-alright.</p>
<p>As a aside, <a href="http://www.bigbluesaw.com">BigBlueSaw</a> is ludicrous in the best way. The web quote interface literally dumps into a full <abbr>DXF</abbr> ingest/process pipeline (written by Simon <abbr>IIRC</abbr>) that computes cutting length, number of pierces, image previews, and I assume some approximate part nesting to get you an exact price nearly instantaneously. If that’s just my experience with the frontend, the automation going on from site to machining must be something delightful.</p>
<p>Oh and Julie runs the customer service so if you order parts through <abbr>BBS</abbr>, it’s like ordering from team <a href="http://battlebots.com/robot/bombshell/">Chaos Corps</a>. ^_^</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/sd9ybyzwVa-690.avif 690w, https://geekshavefeelings.com/img/sd9ybyzwVa-1380.avif 1380w, https://geekshavefeelings.com/img/sd9ybyzwVa-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/sd9ybyzwVa-690.webp 690w, https://geekshavefeelings.com/img/sd9ybyzwVa-1380.webp 1380w, https://geekshavefeelings.com/img/sd9ybyzwVa-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/sd9ybyzwVa-690.jpeg 690w, https://geekshavefeelings.com/img/sd9ybyzwVa-1380.jpeg 1380w, https://geekshavefeelings.com/img/sd9ybyzwVa-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord milling bearing bore" src="https://geekshavefeelings.com/img/sd9ybyzwVa-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>The bronze sleeve bearings for the lift shaft needed an exact circular press fit, so those were waterjat to exact dimension and finished on the Google Workshops <abbr>CNC</abbr> mill, although not before I ruined two bearings by pressing them into the rough waterjet bore anyways…</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/rQfEmwF5ct-690.avif 690w, https://geekshavefeelings.com/img/rQfEmwF5ct-1380.avif 1380w, https://geekshavefeelings.com/img/rQfEmwF5ct-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/rQfEmwF5ct-690.webp 690w, https://geekshavefeelings.com/img/rQfEmwF5ct-1380.webp 1380w, https://geekshavefeelings.com/img/rQfEmwF5ct-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/rQfEmwF5ct-690.jpeg 690w, https://geekshavefeelings.com/img/rQfEmwF5ct-1380.jpeg 1380w, https://geekshavefeelings.com/img/rQfEmwF5ct-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord turning down wheel spacers" src="https://geekshavefeelings.com/img/rQfEmwF5ct-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Similar idea here: these spacers (hubs?) go into the 22 mm bore normally occupied by a 608 “skate” bearing, so I’m finishing their outside diameters on the lathe to clean up waterjet taper and non-circularity (waterjets are X-Y machines, after all). The live center was not a good idea. I should have used purely axial force to jam the hubs against the jaws.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/mOlsSkTqEo-690.avif 690w, https://geekshavefeelings.com/img/mOlsSkTqEo-1380.avif 1380w, https://geekshavefeelings.com/img/mOlsSkTqEo-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/mOlsSkTqEo-690.webp 690w, https://geekshavefeelings.com/img/mOlsSkTqEo-1380.webp 1380w, https://geekshavefeelings.com/img/mOlsSkTqEo-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/mOlsSkTqEo-690.jpeg 690w, https://geekshavefeelings.com/img/mOlsSkTqEo-1380.jpeg 1380w, https://geekshavefeelings.com/img/mOlsSkTqEo-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord milling keyway lift gearmotor" src="https://geekshavefeelings.com/img/mOlsSkTqEo-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Kind of silly but the 4 mm keyway was undersized on this gearhead output shaft, so I expanded it real quick. I should have clamped the shaft, not the motor.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/FMh9jeTD9H-690.avif 690w, https://geekshavefeelings.com/img/FMh9jeTD9H-1380.avif 1380w, https://geekshavefeelings.com/img/FMh9jeTD9H-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/FMh9jeTD9H-690.webp 690w, https://geekshavefeelings.com/img/FMh9jeTD9H-1380.webp 1380w, https://geekshavefeelings.com/img/FMh9jeTD9H-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/FMh9jeTD9H-690.jpeg 690w, https://geekshavefeelings.com/img/FMh9jeTD9H-1380.jpeg 1380w, https://geekshavefeelings.com/img/FMh9jeTD9H-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord traction pulley tapped" src="https://geekshavefeelings.com/img/FMh9jeTD9H-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>We don’t talk about this.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/rlKvZuRjfJ-690.avif 690w, https://geekshavefeelings.com/img/rlKvZuRjfJ-1380.avif 1380w, https://geekshavefeelings.com/img/rlKvZuRjfJ-3024.avif 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/rlKvZuRjfJ-690.webp 690w, https://geekshavefeelings.com/img/rlKvZuRjfJ-1380.webp 1380w, https://geekshavefeelings.com/img/rlKvZuRjfJ-3024.webp 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/rlKvZuRjfJ-690.jpeg 690w, https://geekshavefeelings.com/img/rlKvZuRjfJ-1380.jpeg 1380w, https://geekshavefeelings.com/img/rlKvZuRjfJ-3024.jpeg 3024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord wheel, trilobularly expandified" src="https://geekshavefeelings.com/img/rlKvZuRjfJ-690.jpeg" width="3024" height="4032"></picture></figure><p></p>
<p>Or this.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/7K8-mt6COL-690.avif 690w, https://geekshavefeelings.com/img/7K8-mt6COL-1380.avif 1380w, https://geekshavefeelings.com/img/7K8-mt6COL-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/7K8-mt6COL-690.webp 690w, https://geekshavefeelings.com/img/7K8-mt6COL-1380.webp 1380w, https://geekshavefeelings.com/img/7K8-mt6COL-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/7K8-mt6COL-690.jpeg 690w, https://geekshavefeelings.com/img/7K8-mt6COL-1380.jpeg 1380w, https://geekshavefeelings.com/img/7K8-mt6COL-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord milling side armor" src="https://geekshavefeelings.com/img/7K8-mt6COL-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Needs more chmafer.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/yr-Lvxw0sV-690.avif 690w, https://geekshavefeelings.com/img/yr-Lvxw0sV-1380.avif 1380w, https://geekshavefeelings.com/img/yr-Lvxw0sV-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/yr-Lvxw0sV-690.webp 690w, https://geekshavefeelings.com/img/yr-Lvxw0sV-1380.webp 1380w, https://geekshavefeelings.com/img/yr-Lvxw0sV-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/yr-Lvxw0sV-690.jpeg 690w, https://geekshavefeelings.com/img/yr-Lvxw0sV-1380.jpeg 1380w, https://geekshavefeelings.com/img/yr-Lvxw0sV-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord clamper and lifter" src="https://geekshavefeelings.com/img/yr-Lvxw0sV-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>All the black plastic you see is <a href="https://markforged.com/onyx/">Onyx</a> carbon composite parts that <a href="http://thevariableconstant.blogspot.com">Jamo</a> <abbr>3D</abbr> printed for me on a <a href="https://markforged.com/mark-two/">Markforged Mark Two</a>. These parts are unbelievably stiff and light. The quality of the printing is outrageous; most of the circular bores were designed to exact dimension and ended up perfect press fit. I had originally intended for all the plastic to be milled from <abbr>UHMW</abbr> but this opportunity came up and saved me a lot of machine time.</p>
<h2 id="lolservos" tabindex="-1">lolservos <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/4pf4dFryK2-690.avif 690w, https://geekshavefeelings.com/img/4pf4dFryK2-1380.avif 1380w, https://geekshavefeelings.com/img/4pf4dFryK2-5472.avif 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/4pf4dFryK2-690.webp 690w, https://geekshavefeelings.com/img/4pf4dFryK2-1380.webp 1380w, https://geekshavefeelings.com/img/4pf4dFryK2-5472.webp 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/4pf4dFryK2-690.jpeg 690w, https://geekshavefeelings.com/img/4pf4dFryK2-1380.jpeg 1380w, https://geekshavefeelings.com/img/4pf4dFryK2-5472.jpeg 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord left high" src="https://geekshavefeelings.com/img/4pf4dFryK2-690.jpeg" width="5472" height="3648"></picture></figure><p></p>
<p>One thing I think is reasonably unique to Liftlord is the servo clamper mechanism. Normally hobby servos are too wimpy to use for securing another 12 lb bot. But I figured if I add a slightly compliant link—in this case, ultra-high molecular weight polyethylene (<abbr>UHMW-PE</abbr>) stranded fishing line—and remove the clamper from self-righting forces by using a spring to open the jaws, a pair of “standard” hobby servos might survive combat load. The original idea involved adding even more compliance to the fishing line link with a short high-rate spring on the servo horn, which you can see in the photo (not attached). However, I couldn’t run them as far past their spec as I wanted to. They stretched little before plastically deforming.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/C-bw45ZvtV-690.avif 690w, https://geekshavefeelings.com/img/C-bw45ZvtV-1380.avif 1380w, https://geekshavefeelings.com/img/C-bw45ZvtV-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/C-bw45ZvtV-690.webp 690w, https://geekshavefeelings.com/img/C-bw45ZvtV-1380.webp 1380w, https://geekshavefeelings.com/img/C-bw45ZvtV-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/C-bw45ZvtV-690.jpeg 690w, https://geekshavefeelings.com/img/C-bw45ZvtV-1380.jpeg 1380w, https://geekshavefeelings.com/img/C-bw45ZvtV-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord opposing clamper servos" src="https://geekshavefeelings.com/img/C-bw45ZvtV-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>I forgot that all this would take up five output channels—two for traction drive, one for lifter, and two for the servos—on my <a href="http://www.frsky-rc.com/product/pro.php?pro_id=134">FrSky X4R</a> radio receiver (<abbr>RX</abbr>), which had only four: one more than I had ever previously used, except for <a href="http://blog.aaronbot3000.com/2013/02/gyro-king-electronic-design-and.html">Gyro King which had a laptop link and <abbr>PS</abbr>3 controller</a>.</p>
<p>Why couldn’t I run both servos from the same signal with a splitter? Well, the servos are facing in opposite directions. Running off of the same signal, they’d each spin in the same direction that’s actually opposite directions. I need one servo to run on a channel that’s reversed in transmitter software.</p>
<p>Or do I? What if I were to reverse one of the servos? In hardware?</p>
<p>After all, these servos are just a <a href="https://en.wikipedia.org/wiki/Negative_feedback">negative feedback</a> amplifier around an analog potentiometer (“pot”) and a brushed (<abbr>DC</abbr>) motor. The potentiometer linearly maps rotary position to analog voltage. If I were to reverse that mapping, say by <em>swapping the pot’s outside terminals</em>, then I’d reverse that mapping, so that the analog voltage now maps to a rotary position mirrored across the pot’s mechanical range.</p>
<p>Finally, I’d have to negate the gain of the controller too, say by <em>swapping the leads of the motor</em> to reverse its polarity, so that the feedback to angular position change remains negative.</p>
<p>Now I have a reversed servo<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/liftlord/" id="fnref5">¶</a></sup>!</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/NYNFfOjXRw-690.avif 690w, https://geekshavefeelings.com/img/NYNFfOjXRw-1380.avif 1380w, https://geekshavefeelings.com/img/NYNFfOjXRw-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/NYNFfOjXRw-690.webp 690w, https://geekshavefeelings.com/img/NYNFfOjXRw-1380.webp 1380w, https://geekshavefeelings.com/img/NYNFfOjXRw-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/NYNFfOjXRw-690.jpeg 690w, https://geekshavefeelings.com/img/NYNFfOjXRw-1380.jpeg 1380w, https://geekshavefeelings.com/img/NYNFfOjXRw-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Rewuzzled servo comparison" src="https://geekshavefeelings.com/img/NYNFfOjXRw-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>I tested this on some cheap servos, taking care to mark the servo I reversed. To my surprise, this hack just worked.</p>
<p>Less to my surprise, servo reversing turned out to be a fairly common hack, with docs all over the internet. It’s almost like some people prefer to change things in hardware rather than in software or something.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/gddaMCotS--690.avif 690w, https://geekshavefeelings.com/img/gddaMCotS--1380.avif 1380w, https://geekshavefeelings.com/img/gddaMCotS--4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/gddaMCotS--690.webp 690w, https://geekshavefeelings.com/img/gddaMCotS--1380.webp 1380w, https://geekshavefeelings.com/img/gddaMCotS--4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/gddaMCotS--690.jpeg 690w, https://geekshavefeelings.com/img/gddaMCotS--1380.jpeg 1380w, https://geekshavefeelings.com/img/gddaMCotS--4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord rewarzed servo mounted" src="https://geekshavefeelings.com/img/gddaMCotS--690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>But of course, the high-power servos I intended to use were outrageously difficult to reverse like this. Its motor, control board, and pot were all one beefy unit hard soldered together. I can’t even bring myself to describe the horrible next level hacking I improvised to make them work.</p>
<h2 id="epic-ship-day-extrafirmware" tabindex="-1">Epic ship day extrafirmware <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<p>The day before I left for DragonCon, Liftlord’s state was roughly “the parts fit and are holes are tapped.” This left open the problem of <em>how the hell does this move</em>, which, as I expounded on above, was the most urgent and important problem in the whole design. Goes to show how great I am with priorities.</p>
<p>The original least common denominator for traction electronics was to use <a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even">cheap Chinese controllers (<abbr>CCC</abbr>s) flashed with SimonK</a>. This was easy and derpy (because it didn’t take advantage of the Maxons’ sensors): the absolute worst case backup plan, which is to say it was plan A on account of all other plans being not even conceived.</p>
<p>Unfortunately, SimonK’s default startup routine didn’t “take” on my motors. I didn’t want to figure out why or do the tuning because I wasn’t confident I <em>could</em> make it work in 12 hours. So time for plan B, which as I mentioned, didn’t exist or anything.</p>
<p>UHHHHHHH.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/VsMF1X3dOw-690.avif 690w, https://geekshavefeelings.com/img/VsMF1X3dOw-1380.avif 1380w, https://geekshavefeelings.com/img/VsMF1X3dOw-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/VsMF1X3dOw-690.webp 690w, https://geekshavefeelings.com/img/VsMF1X3dOw-1380.webp 1380w, https://geekshavefeelings.com/img/VsMF1X3dOw-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/VsMF1X3dOw-690.jpeg 690w, https://geekshavefeelings.com/img/VsMF1X3dOw-1380.jpeg 1380w, https://geekshavefeelings.com/img/VsMF1X3dOw-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="HÄRDBÖRD controller" src="https://geekshavefeelings.com/img/VsMF1X3dOw-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>I started going through random boxes on my shelf because I figured, <em>WELL DANG I should be able to drive some motors</em>. What do I find but the control/power distribution board from <a href="https://geekshavefeelings.com/tags/haerdboerd">HÄRDBÖRD</a>, complete with <abbr>PIC24</abbr>, XBee module, and most importantly <a href="http://www.maxonmotorusa.com/maxon/view/product/control/1-Q-EC-Verstaerker/380200">Maxon <abbr>DEC</abbr> 50/5 motor control modules</a>.</p>
<p>This was maybe the second or third printed circuit board (<abbr>PCB</abbr>) I had ever designed, from way back in the heady days of 2010, and part of the first thing I ever worked on with Jamo. It even has a <a href="https://www.sparkfun.com/news/1138">Batch<abbr>PCB</abbr></a> <abbr>ID</abbr> mark on it, from the times when hobbyists were willing to <em>wait two months for <abbr>PCB</abbr>s and we were happy to do it because they had white silkscreen on green soldermask just like the pros and only for like fifty bucks my god this is so amazing we’re living in real time like all effecting a desktop manufacturing REVOLUTIONNNNNN</em>.</p>
<p><a href="https://geekshavefeelings.com/posts/2016/liftlord/files/Maxon-1-Q-EC-Amplifier-DEC-50_5-380200-Operating-Instruction-En.pdf" title="1-Q-EC Amplifier DEC Module 50/5"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/zUkRRp411O-690.avif 690w, https://geekshavefeelings.com/img/zUkRRp411O-1280.avif 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/zUkRRp411O-690.webp 690w, https://geekshavefeelings.com/img/zUkRRp411O-1280.webp 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/zUkRRp411O-690.png 690w, https://geekshavefeelings.com/img/zUkRRp411O-1280.png 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="maxon-1-q-ec-amplifier-dec-50_5-380200-operating-instruction-en" src="https://geekshavefeelings.com/img/zUkRRp411O-690.png" width="1280" height="1810"></picture><figcaption>Motor controller manual</figcaption></figure></a></p>
<p>Once I came down from the <a href="https://en.wikipedia.org/wiki/Bre_Pettis">Bre</a>-stolgia, I dug up the docs for the modules and found that they have a 0–5 V input for speed control, an enable pin, and a direction pin. This meant that I needed a microcontroller to convert the digital pulse-width modulated (<abbr>PWM</abbr>) signal of my receiver (<abbr>RX</abbr>) into what the <abbr>DEC</abbr> 50/5s understand. The <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits"><abbr>PIC24</abbr> code on the board</a> actually did something similar: convert Wii Nunchuk data received over XBee to Maxon <abbr>DEC</abbr> analog. Unfortunately I couldn’t find a 16-bit <abbr>PIC</abbr> programmer anywhere so I couldn’t just hack up that code; I’d have to find a small, general purpose microcontroller to use in the <abbr>PIC</abbr>’s place.</p>
<p>You might expect me to be trippin’ boards. But I don’t normally need small, general purpose microcontrollers because my projects tend to be the opposite of general purpose. So I don’t have any <a href="https://www.arduino.cc/en/Main/ArduinoBoardMicro">Arduinos Micro</a> chilling about. Or <a href="https://developer.mbed.org/platforms/">mbeds <abbr>LPC</abbr>1768</a>. Hell, I didn’t even have an <abbr>STM32F</abbr>xENDEAVOUR.</p>
<p><a href="http://store.oshpark.com/products/teensy-lc" title="Teensy LC product page"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/nJweCaUI5x-690.avif 690w, https://geekshavefeelings.com/img/nJweCaUI5x-1380.avif 1380w, https://geekshavefeelings.com/img/nJweCaUI5x-2048.avif 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/nJweCaUI5x-690.webp 690w, https://geekshavefeelings.com/img/nJweCaUI5x-1380.webp 1380w, https://geekshavefeelings.com/img/nJweCaUI5x-2048.webp 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/nJweCaUI5x-690.jpeg 690w, https://geekshavefeelings.com/img/nJweCaUI5x-1380.jpeg 1380w, https://geekshavefeelings.com/img/nJweCaUI5x-2048.jpeg 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Teensy LC front" src="https://geekshavefeelings.com/img/nJweCaUI5x-690.jpeg" width="2048" height="986"></picture></figure></a></p>
<p>What I did find was a <a href="http://store.oshpark.com/products/teensy-lc">Teensy <abbr>LC</abbr> purple edition</a> in a fiber grocery tote that I scored in some swag bag at a computers conference (both the board and the bag). This… this is my San Francisco life.</p>
<p>This is the “low-cost” (<abbr>LC</abbr>) version of a Teensy, using a ARM Cortex-M0+ core Freescale microcontroller that has non-5 V tolerant input pins. This means that the Teensy <abbr>LC</abbr> can’t directly take the 5 V “READY” signal from the <abbr>DEC</abbr> modules. More critically, it also means I can’t slap a pull-up resistor to 5 V onto an open-drain <abbr>PWM</abbr> pin and expect 5 V <abbr>PWM</abbr> output, with which I’d use to synthesize 0–5 V analog. I need a level shifter for each input and a buffer (or level shifter, which is like a bidirectional buffer) for each output.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/DnGNMCKGfD-690.avif 690w, https://geekshavefeelings.com/img/DnGNMCKGfD-1380.avif 1380w, https://geekshavefeelings.com/img/DnGNMCKGfD-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/DnGNMCKGfD-690.webp 690w, https://geekshavefeelings.com/img/DnGNMCKGfD-1380.webp 1380w, https://geekshavefeelings.com/img/DnGNMCKGfD-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/DnGNMCKGfD-690.jpeg 690w, https://geekshavefeelings.com/img/DnGNMCKGfD-1380.jpeg 1380w, https://geekshavefeelings.com/img/DnGNMCKGfD-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord dead bug controller" src="https://geekshavefeelings.com/img/DnGNMCKGfD-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>I ended up wiring things up “dead bug” style on the back side of a blank HÄRDBÖRD <abbr>PCB</abbr>. The red board is a <a href="https://www.sparkfun.com/products/12009">SparkFun Logic Level Converter – Bi-Directional</a> with four level shifters. The Teensy <abbr>LC</abbr> itself also has a 5 V-buffered <abbr>PWM</abbr> output, which I used. The <abbr>DEC</abbr> modules’ digital inputs have 2.4 V thresholds, so they didn’t need buffering from the Teensy <abbr>LC</abbr>. But wait, why is the the 5 V digital <abbr>PWM</abbr> output connected straight to the <abbr>DEC</abbr> module’s speed value input? Don’t you need to filter it to analog? Isn’t the 10 kΩ output of the level shifter too high compared to the 107 kΩ <abbr>DEC</abbr> input impedance? The answer is the same as always: <abbr>STFU</abbr> about my hardware bug and fix it in your firmware.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/mO0BirWFCZ-690.avif 690w, https://geekshavefeelings.com/img/mO0BirWFCZ-1380.avif 1380w, https://geekshavefeelings.com/img/mO0BirWFCZ-1650.avif 1650w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/mO0BirWFCZ-690.webp 690w, https://geekshavefeelings.com/img/mO0BirWFCZ-1380.webp 1380w, https://geekshavefeelings.com/img/mO0BirWFCZ-1650.webp 1650w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/mO0BirWFCZ-690.png 690w, https://geekshavefeelings.com/img/mO0BirWFCZ-1380.png 1380w, https://geekshavefeelings.com/img/mO0BirWFCZ-1650.png 1650w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord Arduino code" src="https://geekshavefeelings.com/img/mO0BirWFCZ-690.png" width="1650" height="1528"></picture></figure><p></p>
<p>Teensy uses the Arduino <abbr>IDE</abbr> and libraries. They mostly don’t get in the way of writing normal C++, except for egregious novice mistakes <em>designed into</em> the Arduino library like <a href="https://www.arduino.cc/en/Reference/Max">min/max macros</a>. The libraries are extended with additional calls by Teensy. The Teensy-specific extensions saved my bacon this time, because they include <code>analogWriteFrequency</code> and less critically <code>analogWriteResolution</code>, which allowed me to run <abbr>PWM</abbr> output at <abbr>CPU</abbr> frequency / (1024-step resolution), or roughly 47 kHz.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Jend2oeyyR-690.avif 690w, https://geekshavefeelings.com/img/Jend2oeyyR-1380.avif 1380w, https://geekshavefeelings.com/img/Jend2oeyyR-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Jend2oeyyR-690.webp 690w, https://geekshavefeelings.com/img/Jend2oeyyR-1380.webp 1380w, https://geekshavefeelings.com/img/Jend2oeyyR-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Jend2oeyyR-690.jpeg 690w, https://geekshavefeelings.com/img/Jend2oeyyR-1380.jpeg 1380w, https://geekshavefeelings.com/img/Jend2oeyyR-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord disassembled back high" src="https://geekshavefeelings.com/img/Jend2oeyyR-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>This was apparently fast enough to be cut out by whatever low-pass filter was on the <abbr>DEC</abbr>s’ speed inputs.</p>
<p>https://www.youtube.com/watch?v=5HfYhEHL0og</p>
<p>Now you can see that all of my belt tensioners are M5 shoulder screws with sleeve bearings, bolted into frame slots with nylon lock nuts. Also, jaw/spider shaft couplers because why not.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/C3c9BEwcc_-690.avif 690w, https://geekshavefeelings.com/img/C3c9BEwcc_-1380.avif 1380w, https://geekshavefeelings.com/img/C3c9BEwcc_-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/C3c9BEwcc_-690.webp 690w, https://geekshavefeelings.com/img/C3c9BEwcc_-1380.webp 1380w, https://geekshavefeelings.com/img/C3c9BEwcc_-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/C3c9BEwcc_-690.jpeg 690w, https://geekshavefeelings.com/img/C3c9BEwcc_-1380.jpeg 1380w, https://geekshavefeelings.com/img/C3c9BEwcc_-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord controller with IMU" src="https://geekshavefeelings.com/img/C3c9BEwcc_-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Once I realized it all worked, I threw on an <abbr>IMU</abbr> (why not?) and mummified it all in electrical tape. Oh, remind me to never again use high strand count silicone-insulated wire for board-to-board connections because you have to twist and tin stripped ends before soldering them to pads. Huge <abbr>PITA</abbr>.</p>
<h2 id="weapon-testing" tabindex="-1">Weapon testing <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<p>Around this time I also discovered that my attempts to engineer out the uncertainty around the 27:1 775 Chinesium gearmotor might have landed this bot well into overkill territory. It was no longer accurate to call it a lifter, since it was more than happy to toss my 3 lb bots into the roof at 50% transmitter rate gain and lowest RageBridge current limit. It blurred the lines between lifter and flipper.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Whh02EQ_EO-690.avif 690w, https://geekshavefeelings.com/img/Whh02EQ_EO-1380.avif 1380w, https://geekshavefeelings.com/img/Whh02EQ_EO-5472.avif 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Whh02EQ_EO-690.webp 690w, https://geekshavefeelings.com/img/Whh02EQ_EO-1380.webp 1380w, https://geekshavefeelings.com/img/Whh02EQ_EO-5472.webp 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Whh02EQ_EO-690.jpeg 690w, https://geekshavefeelings.com/img/Whh02EQ_EO-1380.jpeg 1380w, https://geekshavefeelings.com/img/Whh02EQ_EO-5472.jpeg 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="DC 2016 taking over dining table" src="https://geekshavefeelings.com/img/Whh02EQ_EO-690.jpeg" width="5472" height="3648"></picture><figcaption>Looking for googly eyes installation sites</figcaption></figure><p></p>
<h2 id="dragoncon" tabindex="-1">DragonCon <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<p>DragonCon 2016, held in downtown Atlanta, GA on Labor Day weekend, was whatever DragonCon is. It’s hard enough to describe DragonCon relative to what I think other cons are like, but it’s impossible to explain in absolute terms. Instead I’ll just point out that it has the second-oldest robot combat competition in the world and fascinating cosplay.</p>
<p>https://www.youtube.com/watch?v=DLroRhylMY0</p>
<p>Actually, I’ve been given plenty of chances to plug DragonCon cosplay and never did. I shouldn’t pass up this one.</p>
<p>DragonCon’s lack of focus on any particular genre—though it’s heavy on fantasy and sci-fi—gives it a multifaceted identity that bleeds into its cosplayers.</p>
<p><a href="http://www.clatl.com/news/article/13084784/time-and-place-potential" title="Creative Loafing article on attending DragonCon parade"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/VjvCTavRrM-640.avif 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/VjvCTavRrM-640.webp 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Pinocchio as a motivational speaker, holding a sign reading "YOU HAVE POTENTIAL"" src="https://geekshavefeelings.com/img/VjvCTavRrM-640.jpeg" width="640" height="427"></picture><figcaption>Don't miss the parade</figcaption></figure></a></p>
<p>This and the participants’ devotion to their product results in very eye-catching costumes that don’t necessarily reproduce characters from any particular intellectual property (<abbr>IP</abbr>).</p>
<p><a href="http://www.cosplaycomet.com/?p=1636" title="Iron Man King Triton at Cosplay Comet"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/hNrtagQSdL-690.avif 690w, https://geekshavefeelings.com/img/hNrtagQSdL-1380.avif 1380w, https://geekshavefeelings.com/img/hNrtagQSdL-1536.avif 1536w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/hNrtagQSdL-690.webp 690w, https://geekshavefeelings.com/img/hNrtagQSdL-1380.webp 1380w, https://geekshavefeelings.com/img/hNrtagQSdL-1536.webp 1536w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/hNrtagQSdL-690.jpeg 690w, https://geekshavefeelings.com/img/hNrtagQSdL-1380.jpeg 1380w, https://geekshavefeelings.com/img/hNrtagQSdL-1536.jpeg 1536w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Iron Man King Triton" src="https://geekshavefeelings.com/img/hNrtagQSdL-690.jpeg" width="1536" height="2048"></picture><figcaption>There's top tier people watching outside of tracks</figcaption></figure></a></p>
<p>In fact, some of my favorite costumes are the ones that juxtapose unrelated <abbr>IP</abbr>s, generating humor by surprise and sometimes détournement. Iron King Triton is pretty emblematic of <abbr>DC</abbr>’s “why not” remix cosplay performance.</p>
<p>My favorite three elements of DragonCon came in one hella splendid mishmash this year: battlebots, cosplay, and my friends. Check it outtt: <a href="http://cynaesthetics.blogspot.com/2016/09/female-hanzo-battlebots-cosplay.html">cynaesthetics: FEMALE HANZO + BATTLEBOTS COSPLAY</a></p>
<p>They did some outstanding work. I’m in total awe at the hustle they and other folks at Con put into their various projects, all of which I consider performances: parade costumes and vehicles, knowledge exchange panels, even prepping themselves for partying is a planned endeavor. I got some sharp regret for not walking around with a camera; after all, I had less to work on so I feel I was obligated to capture it all. Instead, I have three photos of food. Thanks, everyone else who did document!</p>
<h2 id="competition" tabindex="-1">Competition <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Q7sEdUKz9D-690.avif 690w, https://geekshavefeelings.com/img/Q7sEdUKz9D-1380.avif 1380w, https://geekshavefeelings.com/img/Q7sEdUKz9D-5472.avif 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Q7sEdUKz9D-690.webp 690w, https://geekshavefeelings.com/img/Q7sEdUKz9D-1380.webp 1380w, https://geekshavefeelings.com/img/Q7sEdUKz9D-5472.webp 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Q7sEdUKz9D-690.jpeg 690w, https://geekshavefeelings.com/img/Q7sEdUKz9D-1380.jpeg 1380w, https://geekshavefeelings.com/img/Q7sEdUKz9D-5472.jpeg 5472w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Liftlord fight prep" src="https://geekshavefeelings.com/img/Q7sEdUKz9D-690.jpeg" width="5472" height="3648"></picture><figcaption>Liftlord gets its privilege checked</figcaption></figure><p></p>
<p>After all that, I became uh, indisposed. So <a href="http://aaronbot3000.com">Aaron</a> drove Liftlord for me. He had brought a <a href="https://geekshavefeelings.com/posts/2016/liftlord/files/FLAIL.png">3 lb flail bot</a>, which fought in the previous day. He’s better at driving Liftlord than I am without having even tried it previously, while I had <em>at least</em> 20 minutes of driving practice.</p>
<p>https://www.youtube.com/watch?v=ydGFg8ibnVg</p>
<p>In fact he even beat DragonCon <a href="http://www.battlebots.com/robot/bronco/">Bronco</a>, <a href="http://www.wa4dsy.com/robot/t-boner-2-0">Dale’s T-Boner 2.0</a>. I can’t help but admit that the win, as well as the first win against <a href="http://www.evilrobotsinc.com">Jason “Evil” Brown</a>, were aided in part by malfunction in their bots.</p>
<p>I think Liftlord eventually exited the bracket as a quarterfinalist? I’m kind of hazy on that one. Oh did I mention that the tournament was single elimination, just like the insect (1 and 3 lb) classes? There goes 50% of my motivation for building a stage bot.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/e3IwAYSbtE-690.avif 690w, https://geekshavefeelings.com/img/e3IwAYSbtE-1380.avif 1380w, https://geekshavefeelings.com/img/e3IwAYSbtE-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/e3IwAYSbtE-690.webp 690w, https://geekshavefeelings.com/img/e3IwAYSbtE-1380.webp 1380w, https://geekshavefeelings.com/img/e3IwAYSbtE-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/e3IwAYSbtE-690.jpeg 690w, https://geekshavefeelings.com/img/e3IwAYSbtE-1380.jpeg 1380w, https://geekshavefeelings.com/img/e3IwAYSbtE-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="12 O'Clocker and Liftlord" src="https://geekshavefeelings.com/img/e3IwAYSbtE-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>I was giddy seeing this side-by-side because I honestly didn’t expect Liftlord to be so similar to Charles’s 12 lb version of Überclocker, <a href="http://www.etotheipiplusone.net/?page_id=2970">12 O’Clocker</a>, given my requirements on “not looking at references.” It’s not as adorable as 12 O’Clocker though.</p>
<p>https://www.youtube.com/watch?v=Zm7_GpbFQLc</p>
<p>Meanwhile in the 30 lb class, <a href="http://4threv.com">Andrew’s Pusheen</a>, a <em>wooden</em> bot (also brushless hipster, maybe even more so), won against <a href="http://nearchaos.net/robots/">Near Chaos’s <em>chainsaw</em> bot</a>. It’s even better than the time <a href="http://sparc.tools/BotRank/detail.php?bn=V2VkZ2Vl&wc=3&ty=R">Wedgee</a> took out <a href="https://www.youtube.com/watch?v=3WwjYuywWlA">team Invention Studio’s assbot</a>. #dragoncon</p>
<p>https://www.youtube.com/watch?v=rxE7r9susxU</p>
<p>https://www.youtube.com/watch?v=KUobVbDhB4Q</p>
<p>Finally I got up to the stage for rumbles. As I understand, I won the second one but as I continued to be uh, indisposed… I don’t really remember it. I’m feeling too embarrassed to watch the video since I was probably driving like derp.</p>
<p>Driving this bot really made me realize what a nonsensical amount of coordination is required to pull off a <a href="https://youtu.be/W4RRR0a0aDk?t=2m45s">Charles-style grappling performance</a>. And Liftlord’s clamper has position control while Überclocker has first- or second-derivative control. I had decided while practicing before the tournament that I wasn’t even going to bother with the clamping. I just wasn’t able to do the whole maneuver-scoop-clamp-lift sequence with authority. It also helped me appreciate what a huge hindrance the stage risers’ joints were to bot mobility. If you don’t raise the lifter wedgelets and keep them raised, they <em>will</em> jam beneath the cheese-grade steel frame. I’m impressed with the practice that the veteran bot builders must have put in to put on the show that they do.</p>
<p>This is actually my first win at DragonCon in I think six odd years of trying to compete in it. I felt kind of validated that I could suppress my urge to build <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack">nutty curios</a> and put in the attention to detail—Loctite every screw, wrap all electronics—to enter something competitive. It pointed out driving as something to work on: my crappy tournament record and frequent malfunctions means I’ve had relatively little arena time in the years I’ve been doing this hobby. Maybe it’s time for a strategy rework? ∎</p>
<p><em>Shouts out to Jamo for the Markforgery, Aaron for the hacks/driving/photos, <a href="http://fenstar.co">Wes</a> for googly eyes/tape work, Big Blue Saw for their help, and everyone else at DragonCon 2016 who made it an incredible experience.</em></p>
<h2 id="specifications" tabindex="-1">Specifications <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<ul>
<li><strong>Frame</strong> <a href="http://www.bigbluesaw.com/">waterjet cut</a> ¼ in 6061 aluminum, <abbr>3D</abbr> printed <a href="https://markforged.com/onyx/">Markforged Onyx</a> chopped carbon fiber nylon bulkheads, computer numerical control (<abbr>CNC</abbr>) milled ½ in ultra-high molecular weight polyethylene (<abbr>UHMW-PE</abbr>) armor</li>
<li><strong>Wheels</strong> 4× 80 mm Shore A 74 durometer indoor inline skate wheels each running on 2× HK0810 needle roller bearings inside 22 mm hubs through-clamped to pulleys</li>
<li><strong>Lifter motor</strong> <a href="http://www.andymark.com/Gearmotor-p/am-2923.htm">AndyMark <abbr>PG27</abbr> Planetary Gearbox with RS775 Motor</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/liftlord/" id="fnref6">♠</a></sup></li>
<li><strong>Lifter final drive</strong> 25-tooth 3 mm diametral pitch timing pulley driving 50-tooth pulley through fiberglass-reinforced rubber timing belt; driven pulley is screwed to clamp shaft collars driving 20 mm outside diameter (<abbr>OD</abbr>) 2024 aluminum hollow shaft</li>
<li><strong>Lifter controller</strong> <a href="http://e0designs.com/products/ragebridge2/">Equals Zero Designs RageBridge 2</a> in single-input mode, at minimum current limit</li>
<li><strong>Traction motors</strong> 2× 24 V, 25 W <a href="http://www.maxonmotorusa.com/maxon/view/product/motor/ecmotor/ecmax/ecmax22/283858">Maxon <abbr>EC</abbr>-Max 22 sensored brushless motor</a> each coupled to a 19:1 <a href="http://www.maxonmotorusa.com/maxon/view/product/gear/planetary/gp22/370689">Maxon <abbr>GP</abbr> 22 <abbr>HP</abbr> planetary gearhead</a></li>
<li><strong>Traction final drive</strong> 2× 36-tooth 3 mm diametral pitch timing pulleys driving 4× 30-tooth pulleys through fiberglass-reinforced rubber timing belts</li>
<li><strong>Traction controller</strong> 2× <a href="http://www.maxonmotorusa.com/maxon/view/product/control/1-Q-EC-Verstaerker/380200">Maxon <abbr>DEC</abbr> Module 50/5, digital 1-Q-<abbr>EC</abbr> Amplifier</a> with half-resistance current sense shunts, soldered to custom power distribution board, controlled by <a href="https://www.pjrc.com/teensy/teensyLC.html">Teensy <abbr>LC</abbr></a></li>
<li><strong>Clamper motors</strong> 2× <a href="https://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=55645">RotorStar <abbr>RS</abbr>-550<abbr>MGC</abbr>-<abbr>HV</abbr> Helicopter Cyclic <abbr>BB</abbr>/<abbr>DS</abbr>/<abbr>MG</abbr> Servo</a> (ball bearing, digital, standard, metal gear)</li>
<li><strong>Traction and lifter batteries</strong> 2× <a href="https://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=18639">ZIPPY Flightmax 2200mAh 3S</a> lithium polymer, in series for 22.2 V</li>
<li><strong>Clamper battery</strong> <a href="https://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=21113">Turnigy 800mAh 2S</a> lithium polymer, 7.4 V</li>
</ul>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/liftlord/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>“I wouldn’t put it past you guys to use real hot dog in a bot.” —Lucy <a href="https://geekshavefeelings.com/posts/2016/liftlord/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>The Portescap traction motors in Big Data <abbr>DVT</abbr> and <abbr>PVT</abbr> are <em>more powerful</em> than these. <a href="https://geekshavefeelings.com/posts/2016/liftlord/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Actually on the West Coast, the 15 lb class replaces 12 lb for an even bigger “class divide.” <a href="https://geekshavefeelings.com/posts/2016/liftlord/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Also doesn’t run at significantly higher efficiency, since pushing high currents into a cool-wound core creates crappy copper losses. <a href="https://geekshavefeelings.com/posts/2016/liftlord/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p><abbr>IRL</abbr> this involved zero engineer words and several minutes of staring at servos before going, “OH what if I just swap these and these wires?” <a href="https://geekshavefeelings.com/posts/2016/liftlord/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>This is a rebadged Chinesium “<abbr>PG45</abbr>” 775 gearmotor that I wouldn’t buy from AndyMark at their 2.5× markup except for their US stock. <a href="http://www.lynxmotion.com/p-1074-planetary-gear-motor-pgm45-2691.aspx">A less overpriced but wimpier US-stocked 775 gearmotor is available from Lynxmotion</a>. <a href="https://geekshavefeelings.com/posts/2016/liftlord/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Sensorless Brushless Can’t Even
2016-05-17T11:19:25Z
https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/
<p><em>Charles wrote a practical and less pointlessly technical <a href="http://www.etotheipiplusone.net/?p=3985">post about his SimonK experiments, complete with a 250 lb system prototype</a>. These are my hopefully in-phase science notes.</em></p>
<p>If you’ve spent any time on hobby avionics and mobile robotics in the last few years, you’ve heard of the “SimonK reflash.” This refers to firmware written by the eponymous Simon Kirby based on the work of Bernhard Konze for the hobby-grade ATmega8-based sensorless controllers for brushless motors.</p>
<p><a href="https://github.com/sim-/tgy">sim-/tgy</a></p>
<p>Quadrotor folks use controllers flashed with SimonK firmware because it does almost no input filtering, nearly directly converting its input, a remote control (<abbr title="remote control">R/C</abbr>) style pulse signals, into its output, a pulse-width modulation (<abbr title="pulse-width modulation">PWM</abbr>) duty cycle, scaled to to drive a brushless motor. Mobile robotics folks, including those in my combat circles, use SimonK’s effective sensorless startup routines and reversible operation to run traction systems. They speak reverently of the Simon’s amazing powers over aircraft electronic speed controllers (<abbr>ESC</abbr>s).</p>
<p>The most bizarre part of this is that the controllers these people are using and hacking are available from the likes of Hong Kong-based <a href="http://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idproduct=98054">HobbyKing for $5</a>.</p>
<p><a href="http://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idproduct=98054"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/gUTAWDq4Hm-690.avif 690w, https://geekshavefeelings.com/img/gUTAWDq4Hm-1380.avif 1380w, https://geekshavefeelings.com/img/gUTAWDq4Hm-1628.avif 1628w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/gUTAWDq4Hm-690.webp 690w, https://geekshavefeelings.com/img/gUTAWDq4Hm-1380.webp 1380w, https://geekshavefeelings.com/img/gUTAWDq4Hm-1628.webp 1628w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/gUTAWDq4Hm-690.png 690w, https://geekshavefeelings.com/img/gUTAWDq4Hm-1380.png 1380w, https://geekshavefeelings.com/img/gUTAWDq4Hm-1628.png 1628w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="HobbyKing store screenshot" src="https://geekshavefeelings.com/img/gUTAWDq4Hm-690.png" width="1628" height="1086"></picture></figure></a></p>
<p>Five friggin’ dollars.</p>
<p>I live down the street from <a href="http://www.themillsf.com/menu/">$4</a> <a href="http://www.blacksandsbeer.com/menu/">toast</a>. So the idea that for 20% more than a slice of flame-kissed bran smeared with Fresh Meadows Farm mulberry compote, one can spin three-phase motors sounded serious skeptic alarms in my head.</p>
<p><a href="https://commons.wikimedia.org/wiki/File:McDonald%27s_Double_Cheeseburger_(1).jpg"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/LctU5iKZfn-690.avif 690w, https://geekshavefeelings.com/img/LctU5iKZfn-1380.avif 1380w, https://geekshavefeelings.com/img/LctU5iKZfn-2720.avif 2720w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/LctU5iKZfn-690.webp 690w, https://geekshavefeelings.com/img/LctU5iKZfn-1380.webp 1380w, https://geekshavefeelings.com/img/LctU5iKZfn-2720.webp 2720w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/LctU5iKZfn-690.jpeg 690w, https://geekshavefeelings.com/img/LctU5iKZfn-1380.jpeg 1380w, https://geekshavefeelings.com/img/LctU5iKZfn-2720.jpeg 2720w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="McDonald's McDouble" src="https://geekshavefeelings.com/img/LctU5iKZfn-690.jpeg" width="2720" height="1640"></picture></figure></a></p>
<p>By the way, a <a href="http://www.mcdonalds.com/us/en/food/product_nutrition.burgerssandwiches.592.mcdouble.html">McDouble</a> is $1. Not that it should be, but it is. Bullied farmers, countless suffering animals, and underpaid service workers made it possible.</p>
<p>I bought six units of these (<abbr title="electronic speed controller">ESC</abbr>s, not McDoubles) with the intention of figuring out what they’re <em>really</em> worth. Questions I want to answer start with,</p>
<ol>
<li>Can this controller spin a motor?</li>
<li>Can I reconfigure SimonK for this controller so that when reflashed, it still spins a motor?</li>
<li>Do the cool SimonK features that combat robot folks use work with it?</li>
</ol>
<p>For brevity (lol.), I’m going to refer to this family of ATmega8A-based sensorless brushless controllers with virtual neutral (explained later) as <em><abbr>CCC</abbr>s</em>: cheap Chinese controllers.</p>
<p>To start, I’m not critically examining <abbr title="cheap Chinese controller">CCC</abbr>s’ or this particular controller’s design and construction. I first want to see it work as rumored. Not to mention that for $5, we know that I’ve bought crappy hardware. It doesn’t do me any good to point out the turd nuggets until later, except as prep work and due diligence.</p>
<h2 id="can-this-controller-spin-a-motor" tabindex="-1">Can this controller spin a motor? <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p>Yes.</p>
<p>This on its own is astonishing. The global manufacturing economy has cut out enough middlepeople to offer unit quantity computerized power electronics through retail outfits taking credit card payments in US Dollars, shipped to your door. Take a breath.</p>
<h2 id="simonk-functional-test" tabindex="-1">SimonK functional test <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/f8MZamX5eY-690.avif 690w, https://geekshavefeelings.com/img/f8MZamX5eY-1380.avif 1380w, https://geekshavefeelings.com/img/f8MZamX5eY-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/f8MZamX5eY-690.webp 690w, https://geekshavefeelings.com/img/f8MZamX5eY-1380.webp 1380w, https://geekshavefeelings.com/img/f8MZamX5eY-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/f8MZamX5eY-690.jpeg 690w, https://geekshavefeelings.com/img/f8MZamX5eY-1380.jpeg 1380w, https://geekshavefeelings.com/img/f8MZamX5eY-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="ESC heat shrink removal" src="https://geekshavefeelings.com/img/f8MZamX5eY-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>OK, I said I wasn’t gonna delve into the details, but the reflashing requires access to the microcontroller, so I do at least need to take it apart.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/xP2YXvu1k5-690.avif 690w, https://geekshavefeelings.com/img/xP2YXvu1k5-1380.avif 1380w, https://geekshavefeelings.com/img/xP2YXvu1k5-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/xP2YXvu1k5-690.webp 690w, https://geekshavefeelings.com/img/xP2YXvu1k5-1380.webp 1380w, https://geekshavefeelings.com/img/xP2YXvu1k5-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/xP2YXvu1k5-690.jpeg 690w, https://geekshavefeelings.com/img/xP2YXvu1k5-1380.jpeg 1380w, https://geekshavefeelings.com/img/xP2YXvu1k5-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Multistar 20A 6S Slim top" src="https://geekshavefeelings.com/img/xP2YXvu1k5-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/1KjdSHqkY8-690.avif 690w, https://geekshavefeelings.com/img/1KjdSHqkY8-1380.avif 1380w, https://geekshavefeelings.com/img/1KjdSHqkY8-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/1KjdSHqkY8-690.webp 690w, https://geekshavefeelings.com/img/1KjdSHqkY8-1380.webp 1380w, https://geekshavefeelings.com/img/1KjdSHqkY8-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/1KjdSHqkY8-690.jpeg 690w, https://geekshavefeelings.com/img/1KjdSHqkY8-1380.jpeg 1380w, https://geekshavefeelings.com/img/1KjdSHqkY8-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Multistar 20A 6S Slim bottom" src="https://geekshavefeelings.com/img/1KjdSHqkY8-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>Yup, that’s a motor controller.</p>
<h2 id="flashing-the-firmware" tabindex="-1">Flashing the firmware <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p>“Reflashing” refers to programming the device-internal flash memory in the Atmel ATmega8A microcontroller that runs the motor controller with different firmware.</p>
<p>Confession: I’ve never actually programmed an <abbr>AVR</abbr> (the Atmel 8-bit microcontroller class of which the ATmega8A is a member) over its in-system programming (<abbr>ISP</abbr>) interface before. I’ve “uploaded” a few Arduino “sketches,” but that’s sending the code over a serial link to the Arduino’s already-running <abbr>AVR</abbr>, which programs the code to itself.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/nFMuODbxaA-690.avif 690w, https://geekshavefeelings.com/img/nFMuODbxaA-1280.avif 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/nFMuODbxaA-690.webp 690w, https://geekshavefeelings.com/img/nFMuODbxaA-1280.webp 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/nFMuODbxaA-690.png 690w, https://geekshavefeelings.com/img/nFMuODbxaA-1280.png 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Arduino upload sketch" src="https://geekshavefeelings.com/img/nFMuODbxaA-690.png" width="1280" height="464"></picture></figure><p></p>
<p>In hobbyist argot, the program the microcontroller is running to do this self-programming is called a <em>bootloader</em>, which confusingly is a definition contrary to the use of the word outside of internal-flash system-on-chip (<abbr>SoC</abbr>) devices<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" id="fnref1">*</a></sup>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/0dSLA2kbS2-580.avif 580w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/0dSLA2kbS2-580.webp 580w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="AVR ISP connections" src="https://geekshavefeelings.com/img/0dSLA2kbS2-580.png" width="580" height="358"></picture></figure><p></p>
<p>The alternative is to connect an <abbr title="in-system programming">ISP</abbr> device that externally drives the programming process. I want to program with an <abbr title="in-system programming">ISP</abbr> programmer because I don’t know if the <abbr title="electronic speed controller">ESC</abbr>s have a bootloader that I could rely on. External programming allows you to recover from mistakes (bootloaders can and do erase themselves) and is robust over different microcontroller models.</p>
<p>Inexplicably, <abbr>AVR</abbr> <abbr title="in-system programming">ISP</abbr> has two different standard connectors for its physical interface, a 6- and a 10-pin. You could argue that the pinout on the 10-pin <a href="https://en.wikipedia.org/wiki/Insulation-displacement_connector">insulation-displacement contact (<abbr>IDC</abbr>) connector</a> puts a ground wire between every signal-carrying conductor, improving signal integrity, but it’s a several megahertz protocol that doesn’t really need that kind of consideration.</p>
<p>In my pile of crap, I found a <a href="http://dangerousprototypes.com/docs/Bus_Pirate">Bus Pirate</a>, <a href="https://www.sparkfun.com/products/12942">Sparkfun Edition</a> that has a 10-pin <abbr title="insulation-displacement contact">IDC</abbr> header <em>not</em> for <abbr title="in-system programming">ISP</abbr> programming and for some reason, a <a href="https://www.pololu.com/docs/0J36/all">Pololu <abbr>USB AVR</abbr> programmer</a> that has a 6-pin header.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/4iU0ARlsng-690.avif 690w, https://geekshavefeelings.com/img/4iU0ARlsng-1380.avif 1380w, https://geekshavefeelings.com/img/4iU0ARlsng-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/4iU0ARlsng-690.webp 690w, https://geekshavefeelings.com/img/4iU0ARlsng-1380.webp 1380w, https://geekshavefeelings.com/img/4iU0ARlsng-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/4iU0ARlsng-690.jpeg 690w, https://geekshavefeelings.com/img/4iU0ARlsng-1380.jpeg 1380w, https://geekshavefeelings.com/img/4iU0ARlsng-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Jumpers between 10-pin and 6-pin adapter" src="https://geekshavefeelings.com/img/4iU0ARlsng-690.jpeg" width="4032" height="3024"></picture><figcaption>Impromptu programmer adapter</figcaption></figure><p></p>
<p>I hacked up an adapter and promptly ordered a <a href="http://amazon.com/dp/B00AX4WQ00">programmer with a 10-pin header</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/lpF2IOXVQE-690.avif 690w, https://geekshavefeelings.com/img/lpF2IOXVQE-1380.avif 1380w, https://geekshavefeelings.com/img/lpF2IOXVQE-4032.avif 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/lpF2IOXVQE-690.webp 690w, https://geekshavefeelings.com/img/lpF2IOXVQE-1380.webp 1380w, https://geekshavefeelings.com/img/lpF2IOXVQE-4032.webp 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/lpF2IOXVQE-690.jpeg 690w, https://geekshavefeelings.com/img/lpF2IOXVQE-1380.jpeg 1380w, https://geekshavefeelings.com/img/lpF2IOXVQE-4032.jpeg 4032w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="USBasp clone with socket programmer" src="https://geekshavefeelings.com/img/lpF2IOXVQE-690.jpeg" width="4032" height="3024"></picture></figure><p></p>
<p>The most notable thing about this setup is what the 10-pin header is attached to. It’s a <a href="http://www.hobbyking.com/hobbyking/store/uh_viewitem.asp?idproduct=46316">socket programming fixture</a> for the <abbr>TQFP</abbr>32-packaged ATmega8A. It routes the programming signals to spring-loaded claw pins positioned over the correct gull wing leads. This lets you program a chip that’s soldered down, even if its board has no programming header exposed. I suspect it’s the tool used by HobbyKing for production on some its boards that lack test points, although these points are present as a row of solder blobs adjacent to the microcontroller on the 20 A board.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/4CH7nO9viK-690.avif 690w, https://geekshavefeelings.com/img/4CH7nO9viK-1280.avif 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/4CH7nO9viK-690.webp 690w, https://geekshavefeelings.com/img/4CH7nO9viK-1280.webp 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/4CH7nO9viK-690.png 690w, https://geekshavefeelings.com/img/4CH7nO9viK-1280.png 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="AVRDUDE" src="https://geekshavefeelings.com/img/4CH7nO9viK-690.png" width="1280" height="700"></picture><figcaption><abbr>AVRDUDE</abbr> installation and connection test to see if it can read the target ATmega8A’s fuse bits</figcaption></figure><p></p>
<p>Other than that, it’s a straightforward invocation of <a href="http://www.ladyada.net/learn/avr/avrdude.html"><abbr>AVRDUDE</abbr></a> to flash each controller. On <abbr>OS X</abbr>, <abbr>AVRDUDE</abbr> is available on <a href="http://brew.sh">Homebrew</a>.</p>
<h2 id="building-the-code" tabindex="-1">Building the code <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p>Now the question is how to get and build the SimonK code for this controller. The easiest way to do this is to have bought a controller on this Google spreadsheet to begin with: <a href="https://docs.google.com/spreadsheets/d/13tMlu5ldLNpZXwbe6UhDHJhcgTVuljm8HDiDp9WO9Pk/edit#gid=0"><abbr title="electronic speed controller">ESC</abbr> specs for Simonk / <abbr title="brushless">BL</abbr>Heli <abbr title="firmware">FW</abbr> flash</a>. My controller (product <abbr>ID</abbr> 9351000061-0) isn’t on there, so I looked at the closest ones in the HobbyKing Multistar section.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/rwV-zXMm-R-690.avif 690w, https://geekshavefeelings.com/img/rwV-zXMm-R-1380.avif 1380w, https://geekshavefeelings.com/img/rwV-zXMm-R-2660.avif 2660w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/rwV-zXMm-R-690.webp 690w, https://geekshavefeelings.com/img/rwV-zXMm-R-1380.webp 1380w, https://geekshavefeelings.com/img/rwV-zXMm-R-2660.webp 2660w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/rwV-zXMm-R-690.png 690w, https://geekshavefeelings.com/img/rwV-zXMm-R-1380.png 1380w, https://geekshavefeelings.com/img/rwV-zXMm-R-2660.png 2660w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="SimonK compatibility spreadsheet" src="https://geekshavefeelings.com/img/rwV-zXMm-R-690.png" width="2660" height="566"></picture></figure><p></p>
<p>That gives me the choices of <code>kda.hex</code>, <code>kda_nfet.hex</code>, <code>kda_nfet_ni.hex</code>, <code>kda_8khz.hex</code>, and <code>dlu40a.hex</code>, each a board target for which the SimonK code can be configured to build. There’s also a chance that the design is totally different from those entirely, since the form factor did change and thus <a href="http://www.etotheipiplusone.net">Charles’s</a> “Law of Chinese Packaging Inertia (‘If the Chinese product looks the same, it probably is the same’)” doesn’t quite apply.</p>
<p>In the <a href="https://github.com/sim-/tgy/blob/master/Makefile">Makefile</a>, there’s a <a href="https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html#Suffix-Rules">suffix rule</a> for <code>.inc</code> to <code>.hex</code>, so I know each of those <code>.hex</code> targets were built from the corresponding <code>.inc</code> (by symlinking ¯\_(ツ)_/¯ the source basename to that of its target…).</p>
<p>Looking at the board, I know it’s all N-channel power transistors (<a href="https://en.wikipedia.org/wiki/Field-effect_transistor"><abbr title="field-effect transistor">FET</abbr>s</a>) so <code>kda.hex</code> and <code>kda_8khz.hex</code> are out. <code>dlu40a.inc</code> mentions opto-isolators and has the wrong resistor values (<code>O_POWER</code> and <code>O_GROUND</code>) so its target <abbr>HEX</abbr> can be eliminated as well.</p>
<p>That leaves <code>kda_nfet.hex</code> and <code>kda_nfet_ni.hex</code>. Their <code>.inc</code>’s differ only on whether they invert the pulse width input signal. I couldn’t trace any inverting transistor from said input (the orange wire) to the microcontroller so I was leaning 80% towards <code>kda_nfet_ni.hex</code>. Getting that wrong doesn’t blow anything up, but getting the power stage polarity or pinout wrong does, so I double checked the <code>.inc</code> declarations against the board. The resistor divider values were also wrong, but I had a hunch they didn’t matter too much.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/DYZQZvTRQX-690.avif 690w, https://geekshavefeelings.com/img/DYZQZvTRQX-1280.avif 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/DYZQZvTRQX-690.webp 690w, https://geekshavefeelings.com/img/DYZQZvTRQX-1280.webp 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/DYZQZvTRQX-690.png 690w, https://geekshavefeelings.com/img/DYZQZvTRQX-1280.png 1280w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="SimonK flash make target" src="https://geekshavefeelings.com/img/DYZQZvTRQX-690.png" width="1280" height="1180"></picture><figcaption>Download, compiling, and flashing SimonK firmware</figcaption></figure><p></p>
<p>Downloading the code is fairly straightforward, since it’s on GitHub. I also needed to install <a href="http://avra.sourceforge.net">avra</a>, an <abbr>AVR</abbr> assembler.</p>
<pre class="language-sh" tabindex="0"><code class="language-sh">brew <span class="token function">install</span> avra
<span class="token function">git</span> clone https://github.com/sim-/tgy.git
<span class="token builtin class-name">cd</span> tgy/
<span class="token function">make</span> kda_nfet_ni.hex
avrdude <span class="token parameter variable">-c</span> usbasp <span class="token parameter variable">-p</span> m8 <span class="token parameter variable">-U</span> flash:w:kda_nfet_ni.hex:i</code></pre>
<p>After that, it was just a matter of building the <code>.hex</code> target with <code>make</code> and flashing the file to the controller.</p>
<p></p><figure><picture><source type="image/webp" srcset="https://geekshavefeelings.com/img/k5UePY7Ry5-500.webp 500w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Lego Batman first try" src="https://geekshavefeelings.com/img/k5UePY7Ry5-500.gif" width="500" height="205"></picture></figure><p></p>
<p>And it worked. First try.</p>
<p>https://www.youtube.com/watch?v=vin7yKi08oM</p>
<p>Now, this all seemed “easy” because I yolo’d my controller using an educated guess at a working config. However, you should never take the account of something being easy from an embedded systems engineer at face value, because we’re about as credible on easy things as is an email from Lagos promising rewards for breaking Bernie Madoff out of prison, especially if firmware is involved.</p>
<p><a href="https://en.wikipedia.org/wiki/File:Operation_Crossroads_Baker_Edit.jpg"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/nBg2xuNHok-690.avif 690w, https://geekshavefeelings.com/img/nBg2xuNHok-1380.avif 1380w, https://geekshavefeelings.com/img/nBg2xuNHok-5137.avif 5137w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/nBg2xuNHok-690.webp 690w, https://geekshavefeelings.com/img/nBg2xuNHok-1380.webp 1380w, https://geekshavefeelings.com/img/nBg2xuNHok-5137.webp 5137w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/nBg2xuNHok-690.jpeg 690w, https://geekshavefeelings.com/img/nBg2xuNHok-1380.jpeg 1380w, https://geekshavefeelings.com/img/nBg2xuNHok-5137.jpeg 5137w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Bikini Atoll nuclear test" src="https://geekshavefeelings.com/img/nBg2xuNHok-690.jpeg" width="5137" height="2696"></picture><figcaption>don't screw up</figcaption></figure></a></p>
<p>More importantly, you shouldn’t be yolo’ing non-$5 hardware. The remaining 20% outcome of my 80% confidence in <code>kda_nfet_ni.hex</code> was that the controller <em>literally catches fire</em>. There’s a real discovery process to finding—or writing—a board config (the <code>.inc</code> file) appropriate to your controller before you flash it. It’s a combination of tracing connections on its printed circuit board (<abbr>PCB</abbr>) for microcontroller pin assignments and analyzing polarities used by the stock firmware with a multimeter or oscilloscope. <a href="http://www.etotheipiplusone.net/?p=3985#5">Charles’s writeup</a> has an example of this and the <a href="https://github.com/sim-/tgy/blob/master/README.md">SimonK <abbr>README</abbr></a> describes the full setup process.</p>
<h2 id="customizing-options" tabindex="-1">Customizing options <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p>Since the setup went so smoothly, I jumped directly into configuring SimonK for “robot drive.” These are control paradigms that set controllers used for mobile robot traction operation apart from say, <abbr title="remote control">R/C</abbr> airplane propeller drive.</p>
<p>I deduced what these options mean through a combination of reading the <a href="https://github.com/sim-/tgy/blob/master/tgy.asm">code</a> (it’s 4000 lines of <abbr>AVR</abbr> assembler, by the way), guessing “how I’d implement it,” and through empirical testing with a radio/servo tester and an oscilloscope.</p>
<h3 id="regenerative-braking-comp-pwm" tabindex="-1">Regenerative braking (<code>COMP_PWM</code>) <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h3>
<p></p><figure><picture><source type="image/webp" srcset="https://geekshavefeelings.com/img/WQeQxCKViG-690.webp 690w, https://geekshavefeelings.com/img/WQeQxCKViG-1380.webp 1380w, https://geekshavefeelings.com/img/WQeQxCKViG-3840.webp 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/gif" srcset="https://geekshavefeelings.com/img/WQeQxCKViG-690.gif 690w, https://geekshavefeelings.com/img/WQeQxCKViG-1380.gif 1380w, https://geekshavefeelings.com/img/WQeQxCKViG-3840.gif 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Brushless inverter passive diode" src="https://geekshavefeelings.com/img/WQeQxCKViG-690.gif" width="3840" height="2400"></picture><figcaption>Non-regenerative default <abbr title="pulse-width modulation">PWM</abbr> with passive diode freewheeling. Base image from <a href="http://www.atmel.com/images/doc8012.pdf">Atmel Application Note <abbr>AVR</abbr>444</a></figcaption></figure><p></p>
<p>With SimonK in its default configuration, the action of the three-phase inverter in the controller is alternating between exciting the in-phase coils (one high-side leg on and one low-side on<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" id="fnref2">†</a></sup>) and diode freewheeling (only one high side on). The fraction of the time spent exciting the coils is then the fraction of the bus voltage that is applied to the motor; the motor will accelerate until its <a href="https://en.wikipedia.org/wiki/Counter-electromotive_force">induced back-EMF (<abbr>BEMF</abbr>)</a> reaches this fraction.</p>
<p>However, neither of those states allows the motor to return energy to the bus, unless its <abbr title="back-EMF">BEMF</abbr> (which is linear to its speed) exceeds the bus voltage plus the <abbr title="field-effect transistor">FET</abbr>s’ body diode forward voltage<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" id="fnref3">‡</a></sup>. In the first video above, you can see that reducing the throttle causes the motors to coast and slowly reduce its speed until it matches the applied (fractional) voltage.</p>
<p></p><figure><picture><source type="image/webp" srcset="https://geekshavefeelings.com/img/-UptcRBKXC-690.webp 690w, https://geekshavefeelings.com/img/-UptcRBKXC-1380.webp 1380w, https://geekshavefeelings.com/img/-UptcRBKXC-3840.webp 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/gif" srcset="https://geekshavefeelings.com/img/-UptcRBKXC-690.gif 690w, https://geekshavefeelings.com/img/-UptcRBKXC-1380.gif 1380w, https://geekshavefeelings.com/img/-UptcRBKXC-3840.gif 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Brushless inverter synchronous rectification" src="https://geekshavefeelings.com/img/-UptcRBKXC-690.gif" width="3840" height="2400"></picture><figcaption>Regenerative <abbr title="pulse-width modulation">PWM</abbr> with high-side synchronous rectification/active freewheeling; note the V phase high-side switch turning on synchronously with the low-side switch turning off. Base image from <a href="http://www.atmel.com/images/doc8012.pdf">Atmel Application Note <abbr>AVR</abbr>444</a></figcaption></figure><p></p>
<p>Regenerative braking is a result of using different pulse-width modulation (<abbr title="pulse-width modulation">PWM</abbr>) schemes that allow the motor to flow current back into the controller’s bus during at least part of the cycle. SimonK’s optional <abbr title="pulse-width modulation">PWM</abbr> scheme alternates between exciting the in-phase coils (one high-side leg on and one low-side on) and “active” freewheeling (two high-side legs on). The active freewheeling both brakes the motor (applies torque in the opposite direction of motion) and allows the driven phase windings act as a <a href="https://en.wikipedia.org/wiki/Boost_converter">boost converter</a>.</p>
<p>https://www.youtube.com/watch?v=EUbHGjDRloQ</p>
<p>Now you can see that the motor’s speed closely tracks the applied throttle. This is because when the <abbr title="back-EMF">BEMF</abbr> of the motor exceeds the <abbr title="pulse-width modulation">PWM</abbr> duty cycle × bus voltage, the motor returns current to the bus. This is the reverse of exciting the motor, so current is allowed to flow in both directions and will want to flow until the motor’s <abbr title="back-EMF">BEMF</abbr> matches its applied voltage.</p>
<p>This is called <code>COMP_PWM</code> in the code because the phase that switches between high-side conducting and low-side conducting is toggling between its <em>complementary</em> <abbr title="field-effect transistor">FET</abbr>s.</p>
<p></p><figure><picture><source type="image/webp" srcset="https://geekshavefeelings.com/img/fwEc0S2mRZ-690.webp 690w, https://geekshavefeelings.com/img/fwEc0S2mRZ-1380.webp 1380w, https://geekshavefeelings.com/img/fwEc0S2mRZ-3840.webp 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/gif" srcset="https://geekshavefeelings.com/img/fwEc0S2mRZ-690.gif 690w, https://geekshavefeelings.com/img/fwEc0S2mRZ-1380.gif 1380w, https://geekshavefeelings.com/img/fwEc0S2mRZ-3840.gif 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Brushless inverter locked antiphase" src="https://geekshavefeelings.com/img/fwEc0S2mRZ-690.gif" width="3840" height="2400"></picture><figcaption>Regenerative <abbr title="pulse-width modulation">PWM</abbr> with locked antiphase; not supported by SimonK. Base image from <a href="http://www.atmel.com/images/doc8012.pdf">Atmel Application Note <abbr>AVR</abbr>444</a></figcaption></figure><p></p>
<p>This is slightly misleading because other <abbr title="pulse-width modulation">PWM</abbr> schemes like locked antiphase or <a href="https://en.wikipedia.org/wiki/Space_vector_modulation">space vector modulation (<abbr title="space-vector modulation">SVM</abbr>)</a> also use complementary <abbr title="pulse-width modulation">PWM</abbr>.</p>
<p><a href="https://commons.wikimedia.org/wiki/File:RLC_series_circuit_v1.svg" title="Series resistor-inductor-capacitor circuit"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/W9eydt1lOe-690.avif 690w, https://geekshavefeelings.com/img/W9eydt1lOe-1380.avif 1380w, https://geekshavefeelings.com/img/W9eydt1lOe-2000.avif 2000w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/W9eydt1lOe-690.webp 690w, https://geekshavefeelings.com/img/W9eydt1lOe-1380.webp 1380w, https://geekshavefeelings.com/img/W9eydt1lOe-2000.webp 2000w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/W9eydt1lOe-690.png 690w, https://geekshavefeelings.com/img/W9eydt1lOe-1380.png 1380w, https://geekshavefeelings.com/img/W9eydt1lOe-2000.png 2000w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="RLC series schematic" src="https://geekshavefeelings.com/img/W9eydt1lOe-690.png" width="2000" height="2770"></picture></figure></a></p>
<p>An electrical engineer might consider that motor speed changes don’t happen instantaneously, but instead acts analogously to a <a href="https://en.wikipedia.org/wiki/RLC_circuit#Series_RLC_circuit">series <abbr title="resistor inductor capacitor">RLC</abbr> (resistor-inductor-capacitor) circuit</a>. The motor speeds up or slows down (increasing and decreasing <abbr title="back-EMF">BEMF</abbr>) like the charging and discharging of the capacitor (C). The inductance (L) of the phase windings offers “inertia” against current (I) changes. The stiff voltage source is the battery with bus capacitance, and its voltage (V) varies with <abbr title="pulse-width modulation">PWM</abbr> duty cycle. And to damp the current sloshing in and out of the capacitor/motor speed/induced <abbr title="back-EMF">BEMF</abbr> is the resistance (R) provided by the motor windings, inverter r<sub>DS (on)</sub>, and to some degree, the bus capacitors’ <a href="https://en.wikipedia.org/wiki/Equivalent_series_resistance">equivalent series resistance (<abbr>ESR</abbr>)</a>.</p>
<p>You might also consider that this is very little damping, so regenerative braking results in massive current spikes, and you’d be right. Without some limit to how quickly the <abbr title="pulse-width modulation">PWM</abbr> duty cycle slews or better yet, <a href="http://e0designs.com/products/ragebridge2/">feedback control against sensed current</a>, complementary <abbr title="pulse-width modulation">PWM</abbr> destroys motor controllers.</p>
<h3 id="reversible-operation-rc-puls-reverse" tabindex="-1">Reversible operation (<code>RC_PULS_REVERSE</code>) <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h3>
<p>SimonK has an option to interpret its throttle input as bidirectional, with commanded speeds in opposite directions mirrored across a neutral point between the extremes of the input range.</p>
<p>https://www.youtube.com/watch?v=iV8bKyUxft0</p>
<p>Combined with <code>COMP_PWM</code>, this <code>RC_PULS_REVERSE</code> option allows “four-quadrant” (4Q) control of your brushless motor. This means that either forward or reverse torque can be applied to a motor that is spinning forward or in reverse. As you can imagine, this is critical to brushless motors used for mobile robot traction applications, where differential steering like on <a href="https://en.wikipedia.org/wiki/Skid-steer_loader">skid-steer loaders</a> and tanks is the norm. In this drivetrain scheme, torques are commanded in either direction while at any position or velocity.</p>
<p>I’m pretty impressed by the firmware’s ability to maintain rotor tracking during directional changes<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" id="fnref4">§</a></sup>.</p>
<h3 id="neutral-braking-motor-brake" tabindex="-1">Neutral braking (<code>MOTOR_BRAKE</code>) <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h3>
<p>While it’s a bit hard to tell that the motor is reversing in the <code>RC_PULS_REVERSE</code> video, it’s easier to tell that when the motor is command to zero speed, it’ll coast until it comes to a stop.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/1032-xarO6-690.avif 690w, https://geekshavefeelings.com/img/1032-xarO6-1380.avif 1380w, https://geekshavefeelings.com/img/1032-xarO6-3840.avif 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/1032-xarO6-690.webp 690w, https://geekshavefeelings.com/img/1032-xarO6-1380.webp 1380w, https://geekshavefeelings.com/img/1032-xarO6-3840.webp 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/1032-xarO6-690.png 690w, https://geekshavefeelings.com/img/1032-xarO6-1380.png 1380w, https://geekshavefeelings.com/img/1032-xarO6-3840.png 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Brushless inverter brake" src="https://geekshavefeelings.com/img/1032-xarO6-690.png" width="3840" height="2400"></picture><figcaption>Brake activation using two high-side switches. Base image from <a href="http://www.atmel.com/images/doc8012.pdf">Atmel Application Note <abbr>AVR</abbr>444</a></figcaption></figure><p></p>
<p>SimonK (and even most stock airplane <abbr title="electronic speed controller">ESC</abbr> firmwares) provides an option to brake the motor by turning on <abbr title="field-effect transistor">FET</abbr>s along one side of the inverter. This short circuits the induced current through the inverter. Due to <a href="https://en.wikipedia.org/wiki/Lenz%27s_law">Lenz’s law</a>, the direction of the induced current creates a torque that brakes the motor. Like when driving the motor, the braking can also be <abbr title="pulse-width modulation">PWM</abbr>’d so it’s only active for some fraction of time (<code>BRAKE_POWER</code> setting).</p>
<p>https://www.youtube.com/watch?v=odm_H0dj0w4</p>
<p>The result is quicker stopping when the motor is commanded to neutral or zero speed. This stopping torque would be more significant when multiplied by gearing as in a traction system.</p>
<p>A lot of <a href="http://www.etotheipiplusone.net/?p=3985#6">additional settings</a> cover braking torque and ramping.</p>
<h3 id="variable-timing-advance-motor-advance-timing-offset" tabindex="-1">Variable timing advance (<code>MOTOR_ADVANCE</code>, <code>TIMING_OFFSET</code>) <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h3>
<p>“Six-step” sensorless controllers like <abbr title="cheap Chinese controllers">CCC</abbr>s are so named because they approximate three-phase alternating current (<abbr title="alternating current">AC</abbr>) output using six steps of <abbr title="pulse-width modulation">PWM</abbr>’d direct current (<abbr>DC</abbr>) output, with each step representing one-sixth or 60° of a rotation. <abbr title="direct current">DC</abbr> drive takes up only two motor phases, leaving the third undriven and monitored for the motor’s <abbr title="back-EMF">BEMF</abbr>. The transition between each step is called <em>commutation</em>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/OFWBY2iIX6-690.avif 690w, https://geekshavefeelings.com/img/OFWBY2iIX6-1380.avif 1380w, https://geekshavefeelings.com/img/OFWBY2iIX6-3840.avif 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/OFWBY2iIX6-690.webp 690w, https://geekshavefeelings.com/img/OFWBY2iIX6-1380.webp 1380w, https://geekshavefeelings.com/img/OFWBY2iIX6-3840.webp 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/OFWBY2iIX6-690.png 690w, https://geekshavefeelings.com/img/OFWBY2iIX6-1380.png 1380w, https://geekshavefeelings.com/img/OFWBY2iIX6-3840.png 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Six step brushless commutation" src="https://geekshavefeelings.com/img/OFWBY2iIX6-690.png" width="3840" height="2400"></picture><figcaption>Six step sensorless commutation; <a href="https://en.wikipedia.org/wiki/Without_loss_of_generality">without loss of generality</a>, zero-cross detection timing (in the highlighted step) is shown in detail in following diagram. Base image from <a href="http://www.atmel.com/images/doc8012.pdf">Atmel Application Note <abbr>AVR</abbr>444</a></figcaption></figure><p></p>
<p>Notice that when a phase is left undriven, the <abbr title="back-EMF">BEMF</abbr> it shows moves from its previous step’s <abbr title="direct current">DC</abbr> state (+ or −) to its next step’s <abbr title="direct current">DC</abbr> state (− or +). The controller monitors this transition specifically looking for a negative-to-positive or positive-to-negative sign change, or <em>zero-cross</em>, because it occurs at 30° of rotation past the previous commutation.</p>
<p>By the way, the “zero” referred to isn’t the negative bus voltage (i.e. the inverter’s zero), but rather the voltage at the <em>motor’s</em> star—or “neutral”—connection (i.e. the motor’s zero). For simplicity with <abbr title="pulse-width modulation">PWM</abbr> at 100% duty cycle as shown, the voltage at the motor’s zero is roughly equal to (V<sub>bus+</sub> + V<sub>bus−</sub>) ÷ 2, the <a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued">average</a> of the inverter’s buses. So for these voltage timing diagrams, you should picture it from the motor’s perspective with zero volts floating at half bus voltage.</p>
<p>Assuming the rotor is spinning at constant speed, the zero-cross occurs halfway in time through each step. Given the duration (<em>T</em><sub>zero-cross</sub> in the timing diagram) between the previous commutation and the zero-cross, the firmware extrapolates the time it takes to rotate to the step’s full 60°. It schedules the next commutation for that time, which theoretically is <em>T</em><sub>zero-cross</sub> from when zero-cross happened.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/GS9e9TPtDW-690.avif 690w, https://geekshavefeelings.com/img/GS9e9TPtDW-1380.avif 1380w, https://geekshavefeelings.com/img/GS9e9TPtDW-3840.avif 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/GS9e9TPtDW-690.webp 690w, https://geekshavefeelings.com/img/GS9e9TPtDW-1380.webp 1380w, https://geekshavefeelings.com/img/GS9e9TPtDW-3840.webp 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/GS9e9TPtDW-690.png 690w, https://geekshavefeelings.com/img/GS9e9TPtDW-1380.png 1380w, https://geekshavefeelings.com/img/GS9e9TPtDW-3840.png 3840w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Commutation timing advance diagram" src="https://geekshavefeelings.com/img/GS9e9TPtDW-690.png" width="3840" height="2400"></picture><figcaption>Six-step sensorless zero-cross detection timing. Base image from <a href="http://www.atmel.com/images/doc8012.pdf">Atmel Application Note <abbr>AVR</abbr>444</a>. Diagram is intended to be generic to all six-step sensorless controllers, so it glosses over some SimonK implementation details like when the timer really resets its counter</figcaption></figure><p></p>
<p>However, “commutation” from the point of view of the motor controller is simply the voltage applied to the motor. It doesn’t reflect the current running through the motor, which can be delayed significantly by the phase windings’ inductance. So like most sensorless firmwares, SimonK provides a timing advance option. It schedules commutation events to occur ahead of reaching the 60° rotation mark, all the way up to advancing to the next step immediately after detecting zero-cross at the 30° rotation mark<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" id="fnref5">¶</a></sup>. The <code>MOTOR_ADVANCE</code> option expresses the number of degrees by which to advance (i.e. to subtract from the ideal 60° step duration), corresponding to the θ<sub>advance</sub> parameter in the timing diagram.</p>
<p>Moreover, there’s yet another option, <code>TIMING_OFFSET</code>, that expresses the microseconds by which to advance the next commutation. As you might imagine, a fixed amount of advance time represents a greater fraction of a cycle as speed increases (and cycle times go down), creating a greater effective phase advance. This setting corresponds to the <em>T</em><sub>offset</sub> parameter in the timing diagram.</p>
<p><a href="http://owenduffy.net/rc/tools/bldca.htm"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/oq-cpVut8w-690.avif 690w, https://geekshavefeelings.com/img/oq-cpVut8w-936.avif 936w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/oq-cpVut8w-690.webp 690w, https://geekshavefeelings.com/img/oq-cpVut8w-936.webp 936w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/oq-cpVut8w-690.png 690w, https://geekshavefeelings.com/img/oq-cpVut8w-936.png 936w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Commutation advance" src="https://geekshavefeelings.com/img/oq-cpVut8w-690.png" width="936" height="702"></picture></figure></a></p>
<p>So, this option in effect creates variable timing that commands a more aggressive timing with increasing speed. There’s even a <a href="http://owenduffy.net/rc/tools/bldca.htm">fan-made calculator</a> to compute how much timing advance you get at different speeds. In my videos, I was running 2° of <code>MOTOR_ADVANCE</code> and 37 μs of <code>TIMING_OFFSET</code> that I found to hit a happy local minima for low-throttle current draw.</p>
<h3 id="other-tweaks" tabindex="-1">Other tweaks <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h3>
<p>SimonK has a huge number of configuration options, without much organization between board configuration, controller functionality, and user preference customization.</p>
<ul>
<li><strong>Input range:</strong> <code>STOP_RC_PULS</code> and <code>FULL_RC_PULS</code> represent the range of pulse widths to use as throttle input. With <code>RC_PULS_REVERSE</code>, they are actually max speeds at opposite polarities, with a zero speed input at their <a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued">average</a>. SimonK firmware can also be “calibrated” to store these endpoints in non-volatile memory (the <a href="http://www.scienceprog.com/atmega-eeprom-memory-writing/"><abbr>AVR</abbr>’s <abbr title="electronically erasable programmable read-only memory">EEPROM</abbr></a>). Also of note are limits for too-short and too-long pulses that should be rejected: <code>MIN_RC_PULS</code> and <code>MAX_RC_PULS</code>. Pulse widths that fall outside of the [<code>STOP_RC_PULS</code>, <code>FULL_RC_PULS</code>] range but fall within [<code>MIN_RC_PULS</code>, <code>MAX_RC_PULS</code>] are clamped to valid power values. For the tests above, I set my limits to [1100 μs, 1900 μs].</li>
<li><strong>Deadband:</strong> with <code>RC_PULS_REVERSE</code>, the controller needs a region in the center of the input range that represents a “zero speed” command. Due to timing variations in <abbr title="remote control">R/C</abbr> systems (whose transmitters also have non-negligible slop in their control sticks) and even microcontrollers, it’s difficult send a pulse that is guaranteed to be received as a certain width by the <abbr title="electronic speed controller">ESC</abbr>. I set my <code>RCP_DEADBAND</code> to be 20 μs on either side of the center of my input range (1500 μs).</li>
<li><strong><abbr title="pulse-width modulation">PWM</abbr> frequency:</strong> the <abbr title="pulse-width modulation">PWM</abbr> generation in the SimonK code is done by loading the duration of on and off intervals into a timer and waiting for its overflow interrupt, so the resulting frequency isn’t exact (and probably has some jitter). However, it’s roughly a touch less than <code>F_CPU</code> / <code>POWER_RANGE</code>. My 16 MHz board with a <code>POWER_RANGE</code> of 856 was then running at something like 18 kHz, which is corroborated by oscilloscope shots.</li>
<li><strong>Minimum duty cycle:</strong> once the motor is running, <code>MIN_DUTY</code> is the minimum time in each <abbr title="pulse-width modulation">PWM</abbr> cycle that the inverter is exciting the active phases. This is limited by how quickly the low-side <abbr title="field-effect transistor">FET</abbr>s can turn on then off (i.e. apply torque) and by how little average voltage will spin the motor quickly enough to generate a usable <abbr title="back-EMF">BEMF</abbr> signal. With the aggressive default timing advance of 18° and a default minimum duty cycle of 6.5%, the minimum no-load speed of this <abbr title="electronic speed controller">ESC</abbr>/motor combination was unreasonably high. Moreover, for human control it’s kind of unexpected that the effective commanded throttle should jump from 0 to 6.5% at a few percent stick position.</li>
</ul>
<p>There are more options related to motor start behavior (on its own a broad topic) and I want to explore them in greater depth before offering remarks.</p>
<h2 id="what-s-with-the-assembly-code" tabindex="-1">What’s with the assembly code? <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p>These days it’s pretty rare that a widely used open source project is written in some computer’s assembly language. The code is basically unreadable to even most electrical/software engineers. Writing assembly requires a lot of tedious busy work like register management and call variable passing, so a lot of functionality is hidden behind verbose “boilerplate” code for say, subtracting 24-bit numbers.</p>
<p>On the other hand, given that the code is wholly optimized for a single (very limited) microcontroller running on a narrow family of <abbr title="electronic speed controller">ESC</abbr> boards, assembly makes sense. Really, the tiny code space available on the microcontroller and the verbosity of <abbr>AVR</abbr>’s <a href="https://en.wikipedia.org/wiki/Reduced_instruction_set_computing"><abbr>RISC</abbr></a> instruction set assembly puts a soft limit on how complex the code can get. To me, that’s a blessing. As a result, the complexity of functionality in the firmware is fairly manageable, even if writing and debugging new features might be difficult without a lot of underdamped head-desk interaction.</p>
<h2 id="next-how-does-this-even-work" tabindex="-1">Next: How does this even work? <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<p>Now that I’ve looked <em>whether</em> the firmware/controller combination works, I wanted to dig into <em>how</em> it works.</p>
<p>The most pressing question for me is, how do <abbr title="cheap Chinese controllers">CCC</abbr>s spin motors with such minimal microcontroller hardware? How does it, running SimonK or not, perform all the sensorless motor control tasks like detect <abbr title="back-EMF">BEMF</abbr> zero-crossing and switch shoot-through unprotected inverters without exploding them?</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/6fp10k8uSN-690.avif 690w, https://geekshavefeelings.com/img/6fp10k8uSN-800.avif 800w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/6fp10k8uSN-690.webp 690w, https://geekshavefeelings.com/img/6fp10k8uSN-800.webp 800w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/6fp10k8uSN-690.png 690w, https://geekshavefeelings.com/img/6fp10k8uSN-800.png 800w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="CCC phases with virtual" src="https://geekshavefeelings.com/img/6fp10k8uSN-690.png" width="800" height="480"></picture></figure><p></p>
<p><em>SCIENCE TO BE CONTINUED.</em></p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Everywhere else, it means a program that reads and <em>loads</em> the code to <em>boot</em>, not a program that writes software to storage. <a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Remember, one phase is left undriven, with its high- and low-side legs both off. Also, the opposing high- and low-side legs in each phase can’t both be on or the bus would short through them. <a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>This only occurs when the motor spins faster than the bus voltage can drive it, so it is not a particularly useful mode of operation. <a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>i.e. When speed is close to zero and <abbr title="back-EMF">BEMF</abbr> is low in amplitude to being undetectable. <a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>You might note that since “commutation timing” is a delay from the 30° point, zero-cross detection-based controllers can’t advance timing more aggressively than (60° − 30°) = 30° ahead of normal. This limitation is not usually a problem. <a href="https://geekshavefeelings.com/posts/2016/sensorless-brushless-cant-even/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Big Data: Test & Refresh
2015-11-03T04:56:51Z
https://geekshavefeelings.com/posts/2015/big-data-test-refresh/
<p>When I built the first <a href="https://geekshavefeelings.com/posts/2014/big-data-evt">Big Data</a> in 2013, I was just getting to grips with my new surroundings. I even added the EVT moniker from my new job: in hardware development, “engineering validation test” means both testing the earliest prototypes and the prototypes themselves.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/abLlFT0tNL-690.avif 690w, https://geekshavefeelings.com/img/abLlFT0tNL-1380.avif 1380w, https://geekshavefeelings.com/img/abLlFT0tNL-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/abLlFT0tNL-690.webp 690w, https://geekshavefeelings.com/img/abLlFT0tNL-1380.webp 1380w, https://geekshavefeelings.com/img/abLlFT0tNL-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/abLlFT0tNL-690.jpeg 690w, https://geekshavefeelings.com/img/abLlFT0tNL-1380.jpeg 1380w, https://geekshavefeelings.com/img/abLlFT0tNL-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="So overweight it needed its letters clipped..." src="https://geekshavefeelings.com/img/abLlFT0tNL-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<h2 id="spring" tabindex="-1">Spring <a class="header-anchor" href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/">§</a></h2>
<p>I was overwhelmed by the Bay Area and toned down my typically masochistic design philosophy. I used a less-experimental (proven, even) weapon system<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/" id="fnref1">*</a></sup> and relied on tried-and-true waterjet-style design.</p>
<p>I allowed one indulgence, which was building a new brushless controller appropriate for this scale and for the sensored 22 mm traction motors.</p>
<p>This is all great except the mechanical design didn’t work. The wheels were nowhere near the center of gravity, so that it didn’t really move except in short bursts, and the traction motors were each held in with five threads worth of four M2 screws on the face, which is to say they weren’t held in.</p>
<p>https://www.youtube.com/watch?v=4_ywkPRrz4E</p>
<p>https://www.youtube.com/watch?v=H-UNtyhgeYM</p>
<h2 id="summer" tabindex="-1">Summer <a class="header-anchor" href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/">§</a></h2>
<p>Then came <a href="https://geekshavefeelings.com/posts/2014/the-orange-involute">Big Data DVT</a> (design validation test) and the start of the orange. Emboldened by familiarity with new capabilities, I used the CNC mills available to me and casted parts from polyurethane. Traction motors got even beefier while the weapon became more optimized… to the point of unreliability. The wheels shift so close to the center of gravity that just 0.54 <em>g</em> of acceleration causes DVT to pop a wheelie.</p>
<p>https://www.youtube.com/watch?v=0lgurYrMQ2w</p>
<p>Naked wheels held on with un-threadlockered shoulder screws reflected an optimism and nonchalance to robot building of college days past. The trip to Atlanta, comped by association to Google’s recruiting at Georgia Tech and house calls to the local datacenter, laid excruciatingly bare how not to construct a vacation (or robot).</p>
<p>https://www.youtube.com/watch?v=W5-fZvdN8wM</p>
<p>An aside: there’s a certain art to expressing yourself during a bot match. <a href="http://thevariableconstant.blogspot.com/">Jamo</a> is a virtuoso both with the R/C transmitter and with situationally appropriate utterances of raw emotion. I might be on the other end of that spectrum with my twitchy fingers and a vocabulary of only “oh” and “no.”</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/OWOii_Numo-690.avif 690w, https://geekshavefeelings.com/img/OWOii_Numo-1380.avif 1380w, https://geekshavefeelings.com/img/OWOii_Numo-2843.avif 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/OWOii_Numo-690.webp 690w, https://geekshavefeelings.com/img/OWOii_Numo-1380.webp 1380w, https://geekshavefeelings.com/img/OWOii_Numo-2843.webp 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/OWOii_Numo-690.png 690w, https://geekshavefeelings.com/img/OWOii_Numo-1380.png 1380w, https://geekshavefeelings.com/img/OWOii_Numo-2843.png 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data DVT CAD" src="https://geekshavefeelings.com/img/OWOii_Numo-690.png" width="2843" height="1660"></picture></figure><p></p>
<p>Also of note is that I’ve ditched machined horizontal chassis elements completely; i.e. there is no top or bottom plate that holds other components in place. I’ve favored this vertical construction style since <a href="https://geekshavefeelings.com/posts/2009/harpy-sumo-bots-2009">building sumo in high school</a>. I reused the round-standoff-between-plates technique used in <a href="https://geekshavefeelings.com/tags/flapjack">Flapjack’s</a> base because of the easy assembly and smooth curves it lends to a design. In Flapjack they were used to mount bearings for the shell; here, one of the beams—a hardened steel shaft, bored through and threaded on both ends—likewise supports the weapon from the milled aluminum “bookends.” To not load the screws in shear, the chassis is counterbored for the shaft to nestle into.</p>
<h2 id="autumn" tabindex="-1">Autumn <a class="header-anchor" href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/">§</a></h2>
<p>With all the cool logic of a frustrated toddler spurned at the toy store (“I WANT IT”), Big Data—and by Big Data I mean I—doubled down on the design out in the parking lot (“BUT BUT I NEEEED IT”). Production verification test (PVT) rang me up demanding none other than a weapon and drivetrain each taking up 30% of the weight. That left just 40% for a weapon motor, chassis (with all the bits & bobs), and electronics.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/XeYqWBYJ8u-690.avif 690w, https://geekshavefeelings.com/img/XeYqWBYJ8u-1380.avif 1380w, https://geekshavefeelings.com/img/XeYqWBYJ8u-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/XeYqWBYJ8u-690.webp 690w, https://geekshavefeelings.com/img/XeYqWBYJ8u-1380.webp 1380w, https://geekshavefeelings.com/img/XeYqWBYJ8u-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/XeYqWBYJ8u-690.png 690w, https://geekshavefeelings.com/img/XeYqWBYJ8u-1380.png 1380w, https://geekshavefeelings.com/img/XeYqWBYJ8u-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data PVT" src="https://geekshavefeelings.com/img/XeYqWBYJ8u-690.png" width="2847" height="1662"></picture></figure><p></p>
<p>Whereas DVT used aluminum traction motor mounts fixed to the chassis’s two round beams, PVT’s drive motors were contained along with PCBs and batteries in a 3D printed “scaffold” wrapped around its three frame beams.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/hFoL9aMylV-690.avif 690w, https://geekshavefeelings.com/img/hFoL9aMylV-1380.avif 1380w, https://geekshavefeelings.com/img/hFoL9aMylV-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/hFoL9aMylV-690.webp 690w, https://geekshavefeelings.com/img/hFoL9aMylV-1380.webp 1380w, https://geekshavefeelings.com/img/hFoL9aMylV-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/hFoL9aMylV-690.jpeg 690w, https://geekshavefeelings.com/img/hFoL9aMylV-1380.jpeg 1380w, https://geekshavefeelings.com/img/hFoL9aMylV-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Machining right chassis case" src="https://geekshavefeelings.com/img/hFoL9aMylV-690.jpeg" width="3264" height="2448"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/MHbOBYK9f3-690.avif 690w, https://geekshavefeelings.com/img/MHbOBYK9f3-1380.avif 1380w, https://geekshavefeelings.com/img/MHbOBYK9f3-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/MHbOBYK9f3-690.webp 690w, https://geekshavefeelings.com/img/MHbOBYK9f3-1380.webp 1380w, https://geekshavefeelings.com/img/MHbOBYK9f3-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/MHbOBYK9f3-690.jpeg 690w, https://geekshavefeelings.com/img/MHbOBYK9f3-1380.jpeg 1380w, https://geekshavefeelings.com/img/MHbOBYK9f3-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Test fit right chassis case" src="https://geekshavefeelings.com/img/MHbOBYK9f3-690.jpeg" width="3264" height="2448"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Lw-A16fokJ-690.avif 690w, https://geekshavefeelings.com/img/Lw-A16fokJ-1380.avif 1380w, https://geekshavefeelings.com/img/Lw-A16fokJ-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Lw-A16fokJ-690.webp 690w, https://geekshavefeelings.com/img/Lw-A16fokJ-1380.webp 1380w, https://geekshavefeelings.com/img/Lw-A16fokJ-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Lw-A16fokJ-690.jpeg 690w, https://geekshavefeelings.com/img/Lw-A16fokJ-1380.jpeg 1380w, https://geekshavefeelings.com/img/Lw-A16fokJ-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Test fit whole chassis" src="https://geekshavefeelings.com/img/Lw-A16fokJ-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>PVT was the first Big Data that entered combat with any semblance of armor. Its outside aluminum rails (15 g) served as double supports for the geartrain dead shafts and protected the wheels and gears a bit. They’re pretty.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/KFm2yxL_Du-690.avif 690w, https://geekshavefeelings.com/img/KFm2yxL_Du-1380.avif 1380w, https://geekshavefeelings.com/img/KFm2yxL_Du-2909.avif 2909w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/KFm2yxL_Du-690.webp 690w, https://geekshavefeelings.com/img/KFm2yxL_Du-1380.webp 1380w, https://geekshavefeelings.com/img/KFm2yxL_Du-2909.webp 2909w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/KFm2yxL_Du-690.jpeg 690w, https://geekshavefeelings.com/img/KFm2yxL_Du-1380.jpeg 1380w, https://geekshavefeelings.com/img/KFm2yxL_Du-2909.jpeg 2909w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data PVT side rails" src="https://geekshavefeelings.com/img/KFm2yxL_Du-690.jpeg" width="2909" height="1636"></picture></figure><p></p>
<p>Unfortunately, my custom motor drivers were less protected against the ESD hazards of dry winter air. Nor could the 3D printed scaffold withstand direct attacks from Chad’s saw and Kyle’s horizontal bar.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/d0obfEbl8m-690.avif 690w, https://geekshavefeelings.com/img/d0obfEbl8m-1380.avif 1380w, https://geekshavefeelings.com/img/d0obfEbl8m-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/d0obfEbl8m-690.webp 690w, https://geekshavefeelings.com/img/d0obfEbl8m-1380.webp 1380w, https://geekshavefeelings.com/img/d0obfEbl8m-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/d0obfEbl8m-690.jpeg 690w, https://geekshavefeelings.com/img/d0obfEbl8m-1380.jpeg 1380w, https://geekshavefeelings.com/img/d0obfEbl8m-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Assembled Big Data PVT" src="https://geekshavefeelings.com/img/d0obfEbl8m-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Why do I have to fight Georgia Tech RoboJackets?</p>
<p>https://www.youtube.com/watch?v=1GqXrSOW_0E</p>
<p>WHY DO I HAVE TO FIGHT MY ROOMMATE?</p>
<p>https://www.youtube.com/watch?v=GpFH_I3dKgQ</p>
<p>KYLE NO MY RECEIVER AND BATTERY</p>
<p>https://www.youtube.com/watch?v=iK9gKgF87pg</p>
<p>PVT was underweight by at least 80 grams, and the frame shows basically no damage. Its access hatch made it much easier to work on than any other Big Data. If it weren’t for the too-wimpy weapon motor and that I misplaced half the chassis, I’d even consider using it again.</p>
<h2 id="winter" tabindex="-1">Winter <a class="header-anchor" href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/">§</a></h2>
<p>I sold out. Brushless traction power affords me ridiculous speed but I’m not a good enough driver nor do I have enough time to practice to take advantage of that. And to be honest, I was getting a tad bored with this design.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ujU9itFK4_-690.avif 690w, https://geekshavefeelings.com/img/ujU9itFK4_-1380.avif 1380w, https://geekshavefeelings.com/img/ujU9itFK4_-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ujU9itFK4_-690.webp 690w, https://geekshavefeelings.com/img/ujU9itFK4_-1380.webp 1380w, https://geekshavefeelings.com/img/ujU9itFK4_-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ujU9itFK4_-690.jpeg 690w, https://geekshavefeelings.com/img/ujU9itFK4_-1380.jpeg 1380w, https://geekshavefeelings.com/img/ujU9itFK4_-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4" src="https://geekshavefeelings.com/img/ujU9itFK4_-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>I acquiesced to the voices calling for a bigger weapon motor and smaller brushed traction motors. Big Data 4 finally has armor, and loads of it. I even tossed in my first ever wedges in combat.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/OM4uESFff6-690.avif 690w, https://geekshavefeelings.com/img/OM4uESFff6-1380.avif 1380w, https://geekshavefeelings.com/img/OM4uESFff6-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/OM4uESFff6-690.webp 690w, https://geekshavefeelings.com/img/OM4uESFff6-1380.webp 1380w, https://geekshavefeelings.com/img/OM4uESFff6-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/OM4uESFff6-690.jpeg 690w, https://geekshavefeelings.com/img/OM4uESFff6-1380.jpeg 1380w, https://geekshavefeelings.com/img/OM4uESFff6-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Hoop armor wedgelet" src="https://geekshavefeelings.com/img/OM4uESFff6-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Although at DragonCon 2015 I kind of just knifed those in.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/teIq6T8x6n-690.avif 690w, https://geekshavefeelings.com/img/teIq6T8x6n-1380.avif 1380w, https://geekshavefeelings.com/img/teIq6T8x6n-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/teIq6T8x6n-690.webp 690w, https://geekshavefeelings.com/img/teIq6T8x6n-1380.webp 1380w, https://geekshavefeelings.com/img/teIq6T8x6n-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/teIq6T8x6n-690.jpeg 690w, https://geekshavefeelings.com/img/teIq6T8x6n-1380.jpeg 1380w, https://geekshavefeelings.com/img/teIq6T8x6n-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Whittling UHMW hoop" src="https://geekshavefeelings.com/img/teIq6T8x6n-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<h2 id="fear-of-design-spaces" tabindex="-1">Fear of Design Spaces <a class="header-anchor" href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/">§</a></h2>
<p>Another aside: I suffer from what I call <em>creative agoraphobia</em>. I’m paralyzed by too open of a design space, too many free variables, too few constraints. When I’m designing, this is the screen that panics me the most.</p>
<p><a href="https://commons.wikimedia.org/wiki/File:Image_plan.png"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/tqVCTWn1Ju-602.avif 602w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/tqVCTWn1Ju-602.webp 602w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="SolidWorks user interface" src="https://geekshavefeelings.com/img/tqVCTWn1Ju-602.png" width="602" height="345"></picture></figure></a></p>
<p>Having a free-to-use weapon bar and a gung-ho attitude to brushless traction were “hard” constraints that helped shape the last three Big Datas. I’ve heard that called “component-based design.”</p>
<p>Conversely if I consider the frame design a fixed establishment, transformed from free variable to set constraint, it gets easier to tweak other components I took for granted, like the silly-ly large traction motors. To get a design that worked, it was time to back off from those Portescap motors.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/CKSnE1u-SV-690.avif 690w, https://geekshavefeelings.com/img/CKSnE1u-SV-1380.avif 1380w, https://geekshavefeelings.com/img/CKSnE1u-SV-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/CKSnE1u-SV-690.webp 690w, https://geekshavefeelings.com/img/CKSnE1u-SV-1380.webp 1380w, https://geekshavefeelings.com/img/CKSnE1u-SV-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/CKSnE1u-SV-690.jpeg 690w, https://geekshavefeelings.com/img/CKSnE1u-SV-1380.jpeg 1380w, https://geekshavefeelings.com/img/CKSnE1u-SV-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon 139885 Gearmotor" src="https://geekshavefeelings.com/img/CKSnE1u-SV-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>These are 13 mm diameter Maxon 67:1 gearmotors, sold as “235 RPM” units on eBay. They’re… OK. The construction is great, with large robust steel gears and gearhead mating threads built into the motor itself. But, they’re definitely slow for beetleweight combat and their precious metal brushes do not enjoy overvoltage operation at all. Maybe they become more useful after removing a stage of planetary gear reduction.</p>
<p>For now, they serve to provide slow but torquey drive traction for Big Data 4.</p>
<p>https://www.youtube.com/watch?v=izmZ55_7LPE</p>
<p>In its debut fight, BD4 promptly gets bottomed out like a Google shuttle at 23rd St.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/YaDWdvqZlI-690.avif 690w, https://geekshavefeelings.com/img/YaDWdvqZlI-1380.avif 1380w, https://geekshavefeelings.com/img/YaDWdvqZlI-1600.avif 1600w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/YaDWdvqZlI-690.webp 690w, https://geekshavefeelings.com/img/YaDWdvqZlI-1380.webp 1380w, https://geekshavefeelings.com/img/YaDWdvqZlI-1600.webp 1600w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/YaDWdvqZlI-690.jpeg 690w, https://geekshavefeelings.com/img/YaDWdvqZlI-1380.jpeg 1380w, https://geekshavefeelings.com/img/YaDWdvqZlI-1600.jpeg 1600w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Google Shuttle Stuck" src="https://geekshavefeelings.com/img/YaDWdvqZlI-690.jpeg" width="1600" height="1200"></picture></figure><p></p>
<p>At this point, the hoop armor has yet any wedgelets at the front, although they’d be ineffective anyways against the floor-scraping scoop on Wedgee. Also at this point, I’m still tipsy from the night before and have had three hours of likewise ineffective sleep. Which somehow leads to better driving than ever before. ¯\_(ツ)_/¯</p>
<p>https://www.youtube.com/watch?v=UnaQOW7wg6Q</p>
<p>Of course in my next match, I drive myself right out through the pushout.</p>
<p>Two months later I fight Aaron’s Margin of Safety, the new DragonCon champion. It went as you might expect.</p>
<p>https://www.youtube.com/watch?v=WI2h588uuLM</p>
<p>So before I get to the design vulnerabilities this revealed, let me get to the crippling mismanaged state that BD4 was in for the ComBugs Cup fight. None of the screws had threadlocker on them because I had taken Big Data apart for shipping. The loose left-side weapon shaft screw comes off with a “PING!” and a black blur at 0:39 in the video, so the shaft is single-supported after that.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/__tGkHM0Qi-690.avif 690w, https://geekshavefeelings.com/img/__tGkHM0Qi-1380.avif 1380w, https://geekshavefeelings.com/img/__tGkHM0Qi-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/__tGkHM0Qi-690.webp 690w, https://geekshavefeelings.com/img/__tGkHM0Qi-1380.webp 1380w, https://geekshavefeelings.com/img/__tGkHM0Qi-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/__tGkHM0Qi-690.png 690w, https://geekshavefeelings.com/img/__tGkHM0Qi-1380.png 1380w, https://geekshavefeelings.com/img/__tGkHM0Qi-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4 Eating Itself" src="https://geekshavefeelings.com/img/__tGkHM0Qi-690.png" width="2847" height="1662"></picture></figure><p></p>
<p>Also, the set screw that holds the weapon motor in its firewall mount had never been tightened. This lets the the motor slide out of position and… into the weapon bar.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/KBtbuGALPu-690.avif 690w, https://geekshavefeelings.com/img/KBtbuGALPu-1380.avif 1380w, https://geekshavefeelings.com/img/KBtbuGALPu-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/KBtbuGALPu-690.webp 690w, https://geekshavefeelings.com/img/KBtbuGALPu-1380.webp 1380w, https://geekshavefeelings.com/img/KBtbuGALPu-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/KBtbuGALPu-690.jpeg 690w, https://geekshavefeelings.com/img/KBtbuGALPu-1380.jpeg 1380w, https://geekshavefeelings.com/img/KBtbuGALPu-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4 Weapon Motor/Pulley" src="https://geekshavefeelings.com/img/KBtbuGALPu-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>On the other hand, the UHMW hoop armor works well at keeping Margin’s disk away from the vulnerable nylon shell. It’s not low or thick enough to protect the wheels, but that’s a constant danger in any fight against an undercutter.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/PA2j8KAOt--690.avif 690w, https://geekshavefeelings.com/img/PA2j8KAOt--1380.avif 1380w, https://geekshavefeelings.com/img/PA2j8KAOt--4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/PA2j8KAOt--690.webp 690w, https://geekshavefeelings.com/img/PA2j8KAOt--1380.webp 1380w, https://geekshavefeelings.com/img/PA2j8KAOt--4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/PA2j8KAOt--690.jpeg 690w, https://geekshavefeelings.com/img/PA2j8KAOt--1380.jpeg 1380w, https://geekshavefeelings.com/img/PA2j8KAOt--4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4 Post-Fight" src="https://geekshavefeelings.com/img/PA2j8KAOt--690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>The killing blow (1:36 in the video) was an incredibly vicious hit with Margin’s single tooth engaging the full wall thickness of the chassis piece.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/2-lTrcGUr4-690.avif 690w, https://geekshavefeelings.com/img/2-lTrcGUr4-1380.avif 1380w, https://geekshavefeelings.com/img/2-lTrcGUr4-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/2-lTrcGUr4-690.webp 690w, https://geekshavefeelings.com/img/2-lTrcGUr4-1380.webp 1380w, https://geekshavefeelings.com/img/2-lTrcGUr4-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/2-lTrcGUr4-690.jpeg 690w, https://geekshavefeelings.com/img/2-lTrcGUr4-1380.jpeg 1380w, https://geekshavefeelings.com/img/2-lTrcGUr4-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4 Frontal Damage" src="https://geekshavefeelings.com/img/2-lTrcGUr4-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>It applied forces towards the outside of the piece (i.e. towards the hogout wall). This concentrates stress into the sharp inside corners of the hogout, causing a fracture that propagated into the walls of the bulkhead.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/O3jGoVTu89-690.avif 690w, https://geekshavefeelings.com/img/O3jGoVTu89-1380.avif 1380w, https://geekshavefeelings.com/img/O3jGoVTu89-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/O3jGoVTu89-690.webp 690w, https://geekshavefeelings.com/img/O3jGoVTu89-1380.webp 1380w, https://geekshavefeelings.com/img/O3jGoVTu89-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/O3jGoVTu89-690.jpeg 690w, https://geekshavefeelings.com/img/O3jGoVTu89-1380.jpeg 1380w, https://geekshavefeelings.com/img/O3jGoVTu89-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4 Chassis Damage" src="https://geekshavefeelings.com/img/O3jGoVTu89-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>As designed, the piece is meant to break or wear down at the lower corner when hit without distorting the frame geometry. Unfortunately it fractured way more than expected and the loss of the weapon shaft screw allowed the shaft counterbore to distort, making reassembly impossible.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/j0ZU9llKeQ-690.avif 690w, https://geekshavefeelings.com/img/j0ZU9llKeQ-1380.avif 1380w, https://geekshavefeelings.com/img/j0ZU9llKeQ-4160.avif 4160w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/j0ZU9llKeQ-690.webp 690w, https://geekshavefeelings.com/img/j0ZU9llKeQ-1380.webp 1380w, https://geekshavefeelings.com/img/j0ZU9llKeQ-4160.webp 4160w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/j0ZU9llKeQ-690.jpeg 690w, https://geekshavefeelings.com/img/j0ZU9llKeQ-1380.jpeg 1380w, https://geekshavefeelings.com/img/j0ZU9llKeQ-4160.jpeg 4160w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data 4 Dead Piece" src="https://geekshavefeelings.com/img/j0ZU9llKeQ-690.jpeg" width="4160" height="2340"></picture></figure><p></p>
<p>However, the “hard parts” like weapon shaft and wheel axles survived with minimal distortion or thread damage, ready for reuse in another frame. All the motors and drivetrain are fine as well. For my first fight with a spinner, it wasn’t altogether that bad.</p>
<p>It’s an engineer’s natural instinct to tinker with an existing design. However, I’m not going to mess with Big Data too much; I promise to refine and ship a more reliable—not sexier—product.</p>
<p>See you at Motorama 2016?</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Although that would be a first for me, so does it still count? <a href="https://geekshavefeelings.com/posts/2015/big-data-test-refresh/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
The Orange Involute
2014-09-15T11:26:12Z
https://geekshavefeelings.com/posts/2014/the-orange-involute/
<p><a href="https://geekshavefeelings.com/posts/2014/big-data-evt" title="Big Data EVT">Big Data</a> needed more drivetrain power. How do you get more of that sweet, sweet sensored brushless power?</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/HQdfbUCJ0l-690.avif 690w, https://geekshavefeelings.com/img/HQdfbUCJ0l-1380.avif 1380w, https://geekshavefeelings.com/img/HQdfbUCJ0l-2432.avif 2432w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/HQdfbUCJ0l-690.webp 690w, https://geekshavefeelings.com/img/HQdfbUCJ0l-1380.webp 1380w, https://geekshavefeelings.com/img/HQdfbUCJ0l-2432.webp 2432w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/HQdfbUCJ0l-690.jpeg 690w, https://geekshavefeelings.com/img/HQdfbUCJ0l-1380.jpeg 1380w, https://geekshavefeelings.com/img/HQdfbUCJ0l-2432.jpeg 2432w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Portescap 22BL-8B-P17" src="https://geekshavefeelings.com/img/HQdfbUCJ0l-690.jpeg" width="2432" height="4320"></picture></figure><p></p>
<p>More motor.</p>
<p>These are eBay-supplied Portescap 22BL-8B-P motors, precursors to the <a href="http://www.portescap.com/products/brushless-dc-motor/22bhl" title="22BHL brushless DC slotless motor">current Portescap lineup of 22 mm motors</a>. With different magnets on the rotor and a higher thermal resistance of 13 °C/W, they are rated for 20 W continuous rather than 70 W, but that’s still much more than a beetle weight (3 lb) robot needs, especially since drivetrain power comes in short bursts.</p>
<p><a href="https://geekshavefeelings.com/posts/2014/the-orange-involute/files/Portescap-22BL.pdf"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/U8twBMAEXn-690.avif 690w, https://geekshavefeelings.com/img/U8twBMAEXn-1380.avif 1380w, https://geekshavefeelings.com/img/U8twBMAEXn-2858.avif 2858w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/U8twBMAEXn-690.webp 690w, https://geekshavefeelings.com/img/U8twBMAEXn-1380.webp 1380w, https://geekshavefeelings.com/img/U8twBMAEXn-2858.webp 2858w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/U8twBMAEXn-690.png 690w, https://geekshavefeelings.com/img/U8twBMAEXn-1380.png 1380w, https://geekshavefeelings.com/img/U8twBMAEXn-2858.png 2858w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="22BL drawing" src="https://geekshavefeelings.com/img/U8twBMAEXn-690.png" width="2858" height="1124"></picture></figure></a></p>
<p>The mounting pattern in the diagram doesn’t quite match that in the photo. I’ll deal with that.</p>
<p>The more pressing concern is the outrageous speed. The hobby R/C world would describe this motor as a 1500 Kv “inrunner” with a no-load speed of 36800 RPM at 24V. With a continuous stall torque of 21.6 mNm and assuming 70 mm diameter wheels, each motor would have to be reduced at a ratio of 1:10.8 to be able to win a static pushing match against another beetle.</p>
<p>Even with that much reduction Big Data’s second coming would still have an estimated top speed of over 10 m/s (20 mph). The max power is limited by heat, not windings, so for short bursts the motors can drive Big Data to a full 1 G of horizontal acceleration at any speed within 90% of their top speed. Remember that this is the fastest that a robot can accelerate within the normal limits of traction (i.e., no tire adhesion, no magnets, no suction, etc.).</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/gvO2EZl2Yx-690.avif 690w, https://geekshavefeelings.com/img/gvO2EZl2Yx-1380.avif 1380w, https://geekshavefeelings.com/img/gvO2EZl2Yx-2843.avif 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/gvO2EZl2Yx-690.webp 690w, https://geekshavefeelings.com/img/gvO2EZl2Yx-1380.webp 1380w, https://geekshavefeelings.com/img/gvO2EZl2Yx-2843.webp 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/gvO2EZl2Yx-690.png 690w, https://geekshavefeelings.com/img/gvO2EZl2Yx-1380.png 1380w, https://geekshavefeelings.com/img/gvO2EZl2Yx-2843.png 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Gear train design" src="https://geekshavefeelings.com/img/gvO2EZl2Yx-690.png" width="2843" height="1660"></picture></figure><p></p>
<p>This design calls for at least two stages of gear reduction. I decided on 8:42 on the first stage and 28:68 on the second for an overall reduction of 1:12.75, using spur gears with a 0.8 mm diametral pitch (“Module 0.8”) and a 20° pressure angle.</p>
<p>I didn’t even know they made 8-tooth pinion gears, but there they are from Stock Drive Products<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2014/the-orange-involute/" id="fnref1">*</a></sup>. Unfortunately, they don’t make a stepped spur gear with 42 and 28 teeth, so I had to make my own.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/T9xfRKY9gS-690.avif 690w, https://geekshavefeelings.com/img/T9xfRKY9gS-1380.avif 1380w, https://geekshavefeelings.com/img/T9xfRKY9gS-2643.avif 2643w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/T9xfRKY9gS-690.webp 690w, https://geekshavefeelings.com/img/T9xfRKY9gS-1380.webp 1380w, https://geekshavefeelings.com/img/T9xfRKY9gS-2643.webp 2643w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/T9xfRKY9gS-690.png 690w, https://geekshavefeelings.com/img/T9xfRKY9gS-1380.png 1380w, https://geekshavefeelings.com/img/T9xfRKY9gS-2643.png 2643w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Planning mill tool paths" src="https://geekshavefeelings.com/img/T9xfRKY9gS-690.png" width="2643" height="1660"></picture></figure><p></p>
<p>First I drew up the involute gear profiles as equation driven splines in SolidWorks and designed a machining solution using HSMXpress, my preferred computer-aided machining (CAM) package.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/FUeEdZbdkX-690.avif 690w, https://geekshavefeelings.com/img/FUeEdZbdkX-1380.avif 1380w, https://geekshavefeelings.com/img/FUeEdZbdkX-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/FUeEdZbdkX-690.webp 690w, https://geekshavefeelings.com/img/FUeEdZbdkX-1380.webp 1380w, https://geekshavefeelings.com/img/FUeEdZbdkX-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/FUeEdZbdkX-690.jpeg 690w, https://geekshavefeelings.com/img/FUeEdZbdkX-1380.jpeg 1380w, https://geekshavefeelings.com/img/FUeEdZbdkX-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Roughing positive mold with a 6 mm tool" src="https://geekshavefeelings.com/img/FUeEdZbdkX-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Then I milled the positive mold cavity from Freeman Supply’s “<a href="http://www.machinablewax.net" title="Machinable Wax">purple machinable wax</a>,” which is basically hardened and plasticized paraffin. The machine is a Roland MDX-40<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2014/the-orange-involute/" id="fnref2">†</a></sup> on loan to the Garage, the makerspace on Google’s Mountain View campus.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/E9z8q9n7oK-690.avif 690w, https://geekshavefeelings.com/img/E9z8q9n7oK-1380.avif 1380w, https://geekshavefeelings.com/img/E9z8q9n7oK-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/E9z8q9n7oK-690.webp 690w, https://geekshavefeelings.com/img/E9z8q9n7oK-1380.webp 1380w, https://geekshavefeelings.com/img/E9z8q9n7oK-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/E9z8q9n7oK-690.jpeg 690w, https://geekshavefeelings.com/img/E9z8q9n7oK-1380.jpeg 1380w, https://geekshavefeelings.com/img/E9z8q9n7oK-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Finishing wax mold with a 0.4 mm tool" src="https://geekshavefeelings.com/img/E9z8q9n7oK-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>It gets pretty scary when I spin the 0.4 mm four-flute end mill to 15000 RPM and finish the teeth at over 250 mm/min. The high feed rate keeps the tool from melting the wax. Molten wax chips tend to stick back onto the mold and are tedious to get rid of.</p>
<p>No tools were broken in the making of these gears.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/UUMfT-MZlj-690.avif 690w, https://geekshavefeelings.com/img/UUMfT-MZlj-1380.avif 1380w, https://geekshavefeelings.com/img/UUMfT-MZlj-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/UUMfT-MZlj-690.webp 690w, https://geekshavefeelings.com/img/UUMfT-MZlj-1380.webp 1380w, https://geekshavefeelings.com/img/UUMfT-MZlj-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/UUMfT-MZlj-690.jpeg 690w, https://geekshavefeelings.com/img/UUMfT-MZlj-1380.jpeg 1380w, https://geekshavefeelings.com/img/UUMfT-MZlj-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Degassing silicone in wax mold cavity" src="https://geekshavefeelings.com/img/UUMfT-MZlj-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Next I mix up some <a href="http://www.quantumsilicones.com/qm-270/" title="Addition cure silicone mold making material">Quantum Silicone QM 270</a> and drop it in the positive mold cavity. Under a strong vacuum, the air trapped under the silicone in the mold’s nooks and crannies balloon up and writhe to the surface, where they pop rather satisfyingly (and silently!).</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ElwCOw8ane-690.avif 690w, https://geekshavefeelings.com/img/ElwCOw8ane-1380.avif 1380w, https://geekshavefeelings.com/img/ElwCOw8ane-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ElwCOw8ane-690.webp 690w, https://geekshavefeelings.com/img/ElwCOw8ane-1380.webp 1380w, https://geekshavefeelings.com/img/ElwCOw8ane-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ElwCOw8ane-690.jpeg 690w, https://geekshavefeelings.com/img/ElwCOw8ane-1380.jpeg 1380w, https://geekshavefeelings.com/img/ElwCOw8ane-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="silicone ready to demold" src="https://geekshavefeelings.com/img/ElwCOw8ane-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>I kept the backside of the negative mold flat using a sheet of acrylic. Silicone doesn’t stick to anything, so this worked well.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/rl8VP1N0Yq-690.avif 690w, https://geekshavefeelings.com/img/rl8VP1N0Yq-1380.avif 1380w, https://geekshavefeelings.com/img/rl8VP1N0Yq-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/rl8VP1N0Yq-690.webp 690w, https://geekshavefeelings.com/img/rl8VP1N0Yq-1380.webp 1380w, https://geekshavefeelings.com/img/rl8VP1N0Yq-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/rl8VP1N0Yq-690.jpeg 690w, https://geekshavefeelings.com/img/rl8VP1N0Yq-1380.jpeg 1380w, https://geekshavefeelings.com/img/rl8VP1N0Yq-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Silicone mold and polyurethane gears" src="https://geekshavefeelings.com/img/rl8VP1N0Yq-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Now the negative mold is out and I have a reusable, flexible silicone negative for plastic gears. I dump in some <a href="http://www.innovative-polymers.com/classic-polyurethanes-shore-d" title="IE Series Urethane Plastics">Innovative Polymers IE-3075</a> and a <em>lot</em> of the orangest dye I have ever seen. Unfortunately, polyurethane does stick to acrylic.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/BDHVPJdNlG-690.avif 690w, https://geekshavefeelings.com/img/BDHVPJdNlG-1380.avif 1380w, https://geekshavefeelings.com/img/BDHVPJdNlG-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/BDHVPJdNlG-690.webp 690w, https://geekshavefeelings.com/img/BDHVPJdNlG-1380.webp 1380w, https://geekshavefeelings.com/img/BDHVPJdNlG-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/BDHVPJdNlG-690.jpeg 690w, https://geekshavefeelings.com/img/BDHVPJdNlG-1380.jpeg 1380w, https://geekshavefeelings.com/img/BDHVPJdNlG-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="gear separation" src="https://geekshavefeelings.com/img/BDHVPJdNlG-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>BAM, I got some gears. I love that the machining marks from the original positive wax mold are preserved through the process to the final part.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/-Ntvfckffa-690.avif 690w, https://geekshavefeelings.com/img/-Ntvfckffa-1380.avif 1380w, https://geekshavefeelings.com/img/-Ntvfckffa-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/-Ntvfckffa-690.webp 690w, https://geekshavefeelings.com/img/-Ntvfckffa-1380.webp 1380w, https://geekshavefeelings.com/img/-Ntvfckffa-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/-Ntvfckffa-690.jpeg 690w, https://geekshavefeelings.com/img/-Ntvfckffa-1380.jpeg 1380w, https://geekshavefeelings.com/img/-Ntvfckffa-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Geartrain test fit" src="https://geekshavefeelings.com/img/-Ntvfckffa-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Seems to fit.</p>
<p>Thanks Dan for loaning us the Roland mill and thanks Michal for the superb <a href="http://lcamtuf.coredump.cx/gcnc/" title="Guerrilla guide to CNC machining, mold making, and resin casting">CNC and resin casting guide</a>.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2014/the-orange-involute/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>I’m not linking to them because I’ve always had such a terrible experience with them. I’m finally taking my business away from SDP/SI for good. <a href="https://geekshavefeelings.com/posts/2014/the-orange-involute/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Not MDX-40A, which takes G-code, but the older model that takes Roland Machine Language (RML). <a href="https://geekshavefeelings.com/posts/2014/the-orange-involute/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Big Data EVT
2014-09-10T03:40:09Z
https://geekshavefeelings.com/posts/2014/big-data-evt/
<p>“8 oz” you said. This dang bar, man.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/tyaRj62vvs-690.avif 690w, https://geekshavefeelings.com/img/tyaRj62vvs-1380.avif 1380w, https://geekshavefeelings.com/img/tyaRj62vvs-2850.avif 2850w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/tyaRj62vvs-690.webp 690w, https://geekshavefeelings.com/img/tyaRj62vvs-1380.webp 1380w, https://geekshavefeelings.com/img/tyaRj62vvs-2850.webp 2850w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/tyaRj62vvs-690.png 690w, https://geekshavefeelings.com/img/tyaRj62vvs-1380.png 1380w, https://geekshavefeelings.com/img/tyaRj62vvs-2850.png 2850w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Conception" src="https://geekshavefeelings.com/img/tyaRj62vvs-690.png" width="2850" height="588"></picture></figure><p></p>
<h2 id="battlebots-in-the-cloud" tabindex="-1">Battlebots in the Cloud <a class="header-anchor" href="https://geekshavefeelings.com/posts/2014/big-data-evt/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/OrGY4p9Zmr-690.avif 690w, https://geekshavefeelings.com/img/OrGY4p9Zmr-1380.avif 1380w, https://geekshavefeelings.com/img/OrGY4p9Zmr-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/OrGY4p9Zmr-690.webp 690w, https://geekshavefeelings.com/img/OrGY4p9Zmr-1380.webp 1380w, https://geekshavefeelings.com/img/OrGY4p9Zmr-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/OrGY4p9Zmr-690.png 690w, https://geekshavefeelings.com/img/OrGY4p9Zmr-1380.png 1380w, https://geekshavefeelings.com/img/OrGY4p9Zmr-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data EVT drive" src="https://geekshavefeelings.com/img/OrGY4p9Zmr-690.png" width="2847" height="1679"></picture></figure><p></p>
<p>To celebrate moving to the Bay Area, and by “celebrate” I mean “forgot that I registered for a <a href="http://www.motoramaevents.com/robots" title="Motorama Robot Conflict">robot combat event in a farm show complex in Harrisburg</a> back when I was still living on the East Coast and now have to beast one so I can fly it into aforementioned Pennsylvanian snow pile,” I started living in the Google Workshops around January with a 12.4 oz chunk of hardened steel, a feverishly drafted new design, and dreams of brushless synergy.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/XpYjmrGrHa-690.avif 690w, https://geekshavefeelings.com/img/XpYjmrGrHa-1380.avif 1380w, https://geekshavefeelings.com/img/XpYjmrGrHa-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/XpYjmrGrHa-690.webp 690w, https://geekshavefeelings.com/img/XpYjmrGrHa-1380.webp 1380w, https://geekshavefeelings.com/img/XpYjmrGrHa-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/XpYjmrGrHa-690.jpeg 690w, https://geekshavefeelings.com/img/XpYjmrGrHa-1380.jpeg 1380w, https://geekshavefeelings.com/img/XpYjmrGrHa-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data bar" src="https://geekshavefeelings.com/img/XpYjmrGrHa-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>The concept for my “new<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2014/big-data-evt/" id="fnref1">*</a></sup>” beetleweight (3 lb) Big Data is simple: a “high” voltage<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2014/big-data-evt/" id="fnref2">†</a></sup> sensored brushless drivetrain coupled to the beater bar from <a href="http://thevariableconstant.blogspot.com/2011/10/this-is-remix.html" title="This is the Remix">Cake ReMix</a>. With a vertically-hitting weapon like the bar, the robot has to hit the wall in order to right itself to the correct orientation.</p>
<p>https://www.youtube.com/watch?v=iBAUKqYNWYo</p>
<p>This means that the robot needs be able to drive upside-down. The drivetrain was designed around ridiculous sensored inrunners.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/jgQg9CRw74-690.avif 690w, https://geekshavefeelings.com/img/jgQg9CRw74-1380.avif 1380w, https://geekshavefeelings.com/img/jgQg9CRw74-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/jgQg9CRw74-690.webp 690w, https://geekshavefeelings.com/img/jgQg9CRw74-1380.webp 1380w, https://geekshavefeelings.com/img/jgQg9CRw74-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/jgQg9CRw74-690.jpeg 690w, https://geekshavefeelings.com/img/jgQg9CRw74-1380.jpeg 1380w, https://geekshavefeelings.com/img/jgQg9CRw74-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon 200118" src="https://geekshavefeelings.com/img/jgQg9CRw74-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>These <a href="https://geekshavefeelings.com/posts/2014/big-data-evt/files/Maxon-EC-22-200118-motor.pdf">Maxon EC 22 200118 motors</a> are tuned for mo’ torque. They’re filled inside with globs of hundreds of turns of magnet wire thinner than hair to create a 400 RPM/V motor that’s only 22 mm in diameter. To give you an idea of how “cool” these are wound, they have 11.7 Ohms of phase-to-phase resistance.</p>
<p>The first order of business is to take the gearhead off, since it was so well jammed on the motor that I couldn’t get it off even with a heat gun and much vice gripping.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/MBlS-BFIxD-690.avif 690w, https://geekshavefeelings.com/img/MBlS-BFIxD-1380.avif 1380w, https://geekshavefeelings.com/img/MBlS-BFIxD-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/MBlS-BFIxD-690.webp 690w, https://geekshavefeelings.com/img/MBlS-BFIxD-1380.webp 1380w, https://geekshavefeelings.com/img/MBlS-BFIxD-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/MBlS-BFIxD-690.jpeg 690w, https://geekshavefeelings.com/img/MBlS-BFIxD-1380.jpeg 1380w, https://geekshavefeelings.com/img/MBlS-BFIxD-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon meets hacksaw" src="https://geekshavefeelings.com/img/MBlS-BFIxD-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>The connectors are huge!</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/iMnEbU39ED-690.avif 690w, https://geekshavefeelings.com/img/iMnEbU39ED-1380.avif 1380w, https://geekshavefeelings.com/img/iMnEbU39ED-2448.avif 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/iMnEbU39ED-690.webp 690w, https://geekshavefeelings.com/img/iMnEbU39ED-1380.webp 1380w, https://geekshavefeelings.com/img/iMnEbU39ED-2448.webp 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/iMnEbU39ED-690.jpeg 690w, https://geekshavefeelings.com/img/iMnEbU39ED-1380.jpeg 1380w, https://geekshavefeelings.com/img/iMnEbU39ED-2448.jpeg 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Bare motors" src="https://geekshavefeelings.com/img/iMnEbU39ED-690.jpeg" width="2448" height="3264"></picture></figure><p></p>
<p>These were well used bargains from eBay. On one motor, a hall sensor which detects the rotor position was stuck at zero volts all the time. The motor had some visible rust on it, so I pulled it apart to have a look at the damage.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/da1kNw1WMO-690.avif 690w, https://geekshavefeelings.com/img/da1kNw1WMO-1380.avif 1380w, https://geekshavefeelings.com/img/da1kNw1WMO-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/da1kNw1WMO-690.webp 690w, https://geekshavefeelings.com/img/da1kNw1WMO-1380.webp 1380w, https://geekshavefeelings.com/img/da1kNw1WMO-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/da1kNw1WMO-690.jpeg 690w, https://geekshavefeelings.com/img/da1kNw1WMO-1380.jpeg 1380w, https://geekshavefeelings.com/img/da1kNw1WMO-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Oh shi-" src="https://geekshavefeelings.com/img/da1kNw1WMO-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>@#$%.</p>
<p>Pulling off the ass of the motor had the exact same tugging and twanging as plucking three pairs of hairs out of your head. The hall sensor board also terminates the six leads out of the windings<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2014/big-data-evt/" id="fnref3">‡</a></sup>, and I had pulled it clean off.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/8OTXpWM7SD-690.avif 690w, https://geekshavefeelings.com/img/8OTXpWM7SD-1380.avif 1380w, https://geekshavefeelings.com/img/8OTXpWM7SD-2448.avif 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/8OTXpWM7SD-690.webp 690w, https://geekshavefeelings.com/img/8OTXpWM7SD-1380.webp 1380w, https://geekshavefeelings.com/img/8OTXpWM7SD-2448.webp 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/8OTXpWM7SD-690.jpeg 690w, https://geekshavefeelings.com/img/8OTXpWM7SD-1380.jpeg 1380w, https://geekshavefeelings.com/img/8OTXpWM7SD-2448.jpeg 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Sensor water damage" src="https://geekshavefeelings.com/img/8OTXpWM7SD-690.jpeg" width="2448" height="3264"></picture></figure><p></p>
<p>Also that round magnet, shaft, and a sensor all definitely have rust on them. Time for some shady repairs.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/vs2hBI8Exh-690.avif 690w, https://geekshavefeelings.com/img/vs2hBI8Exh-1380.avif 1380w, https://geekshavefeelings.com/img/vs2hBI8Exh-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/vs2hBI8Exh-690.webp 690w, https://geekshavefeelings.com/img/vs2hBI8Exh-1380.webp 1380w, https://geekshavefeelings.com/img/vs2hBI8Exh-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/vs2hBI8Exh-690.jpeg 690w, https://geekshavefeelings.com/img/vs2hBI8Exh-1380.jpeg 1380w, https://geekshavefeelings.com/img/vs2hBI8Exh-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Maxon winding "repair"" src="https://geekshavefeelings.com/img/vs2hBI8Exh-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>With tweezers I tied more magnet wire onto the remaining stubs and soldered them in place. Pencil eraser for scale.</p>
<p>As for the dead sensor… well, let’s see if you can figure out what I did.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Qg7KasAahc-690.avif 690w, https://geekshavefeelings.com/img/Qg7KasAahc-1380.avif 1380w, https://geekshavefeelings.com/img/Qg7KasAahc-2448.avif 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Qg7KasAahc-690.webp 690w, https://geekshavefeelings.com/img/Qg7KasAahc-1380.webp 1380w, https://geekshavefeelings.com/img/Qg7KasAahc-2448.webp 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Qg7KasAahc-690.jpeg 690w, https://geekshavefeelings.com/img/Qg7KasAahc-1380.jpeg 1380w, https://geekshavefeelings.com/img/Qg7KasAahc-2448.jpeg 2448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Sensor repair 2" src="https://geekshavefeelings.com/img/Qg7KasAahc-690.jpeg" width="2448" height="3264"></picture></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/RJCIQWNrQ3-690.avif 690w, https://geekshavefeelings.com/img/RJCIQWNrQ3-1380.avif 1380w, https://geekshavefeelings.com/img/RJCIQWNrQ3-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/RJCIQWNrQ3-690.webp 690w, https://geekshavefeelings.com/img/RJCIQWNrQ3-1380.webp 1380w, https://geekshavefeelings.com/img/RJCIQWNrQ3-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/RJCIQWNrQ3-690.jpeg 690w, https://geekshavefeelings.com/img/RJCIQWNrQ3-1380.jpeg 1380w, https://geekshavefeelings.com/img/RJCIQWNrQ3-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Sensor repair 1" src="https://geekshavefeelings.com/img/RJCIQWNrQ3-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>I may or may not have tried to sand down the new sensor to make it thinner and had to repeat this whole repair because electronics don’t work like that. >.></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/hAfpzD4-Qu-690.avif 690w, https://geekshavefeelings.com/img/hAfpzD4-Qu-1380.avif 1380w, https://geekshavefeelings.com/img/hAfpzD4-Qu-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/hAfpzD4-Qu-690.webp 690w, https://geekshavefeelings.com/img/hAfpzD4-Qu-1380.webp 1380w, https://geekshavefeelings.com/img/hAfpzD4-Qu-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/hAfpzD4-Qu-690.jpeg 690w, https://geekshavefeelings.com/img/hAfpzD4-Qu-1380.jpeg 1380w, https://geekshavefeelings.com/img/hAfpzD4-Qu-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="IMG_1055" src="https://geekshavefeelings.com/img/hAfpzD4-Qu-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Done!</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/-JmGVxsJsX-690.avif 690w, https://geekshavefeelings.com/img/-JmGVxsJsX-1380.avif 1380w, https://geekshavefeelings.com/img/-JmGVxsJsX-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/-JmGVxsJsX-690.webp 690w, https://geekshavefeelings.com/img/-JmGVxsJsX-1380.webp 1380w, https://geekshavefeelings.com/img/-JmGVxsJsX-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/-JmGVxsJsX-690.jpeg 690w, https://geekshavefeelings.com/img/-JmGVxsJsX-1380.jpeg 1380w, https://geekshavefeelings.com/img/-JmGVxsJsX-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="SKI" src="https://geekshavefeelings.com/img/-JmGVxsJsX-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Also I took a trip to Squaw Valley woooo Northern California.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/9sFFVi-hl3-690.avif 690w, https://geekshavefeelings.com/img/9sFFVi-hl3-1380.avif 1380w, https://geekshavefeelings.com/img/9sFFVi-hl3-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/9sFFVi-hl3-690.webp 690w, https://geekshavefeelings.com/img/9sFFVi-hl3-1380.webp 1380w, https://geekshavefeelings.com/img/9sFFVi-hl3-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/9sFFVi-hl3-690.jpeg 690w, https://geekshavefeelings.com/img/9sFFVi-hl3-1380.jpeg 1380w, https://geekshavefeelings.com/img/9sFFVi-hl3-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="IMG_1037" src="https://geekshavefeelings.com/img/9sFFVi-hl3-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Wire it up and it runs. Ship it!</p>
<p>Oh and what are they connected to, you ask?</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/AO2Fr-9VsO-690.avif 690w, https://geekshavefeelings.com/img/AO2Fr-9VsO-1380.avif 1380w, https://geekshavefeelings.com/img/AO2Fr-9VsO-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/AO2Fr-9VsO-690.webp 690w, https://geekshavefeelings.com/img/AO2Fr-9VsO-1380.webp 1380w, https://geekshavefeelings.com/img/AO2Fr-9VsO-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/AO2Fr-9VsO-690.jpeg 690w, https://geekshavefeelings.com/img/AO2Fr-9VsO-1380.jpeg 1380w, https://geekshavefeelings.com/img/AO2Fr-9VsO-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Cornflakes" src="https://geekshavefeelings.com/img/AO2Fr-9VsO-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>These are Cornflakes, version 3.0 of the beloved Corntroller series. Same good ol’ ingredients, new packaging.</p>
<p>The motor bell is a new design. The face of the bell has magnets pressed in that grip the steel weapon bar and transmit torque through friction. This allows slip when the bar is hit, reducing damage to the motor in the worst case, or preventing sensorless driver desync in the best case.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/bH-wX6wxXB-690.avif 690w, https://geekshavefeelings.com/img/bH-wX6wxXB-1380.avif 1380w, https://geekshavefeelings.com/img/bH-wX6wxXB-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/bH-wX6wxXB-690.webp 690w, https://geekshavefeelings.com/img/bH-wX6wxXB-1380.webp 1380w, https://geekshavefeelings.com/img/bH-wX6wxXB-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/bH-wX6wxXB-690.jpeg 690w, https://geekshavefeelings.com/img/bH-wX6wxXB-1380.jpeg 1380w, https://geekshavefeelings.com/img/bH-wX6wxXB-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Green sauce" src="https://geekshavefeelings.com/img/bH-wX6wxXB-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>The motor can is literally glued in with “green sauce,” or Loctite press fit retaining compound. It’s anaerobic methyl acrylate adhesive that activates in the absence of air in tight spaces. There’s also a less viscous version of green sauce that can wick into slip fits through capillary action.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/5MOBrtqMq_-690.avif 690w, https://geekshavefeelings.com/img/5MOBrtqMq_-1380.avif 1380w, https://geekshavefeelings.com/img/5MOBrtqMq_-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/5MOBrtqMq_-690.webp 690w, https://geekshavefeelings.com/img/5MOBrtqMq_-1380.webp 1380w, https://geekshavefeelings.com/img/5MOBrtqMq_-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/5MOBrtqMq_-690.jpeg 690w, https://geekshavefeelings.com/img/5MOBrtqMq_-1380.jpeg 1380w, https://geekshavefeelings.com/img/5MOBrtqMq_-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Big Data EVT" src="https://geekshavefeelings.com/img/5MOBrtqMq_-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>The whole thing was designed in a week and built in a week. It was seriously tremendously rushed job, with most of the design work put towards reducing manual tasks (more waterjet!) and cutting many corners (inaccurate mass modeling, missing holes and fasteners).</p>
<p>I usually spend months designing and committing thoughts to paper notes, before transferring to SolidWorks features over a week or two. But in this case, the whole process was compressed down to a week. I had doubts about it before even sending off the waterjet files.</p>
<p>Anyways, ship it (to Harrisburg)!</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/fyda70553e-690.avif 690w, https://geekshavefeelings.com/img/fyda70553e-1380.avif 1380w, https://geekshavefeelings.com/img/fyda70553e-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/fyda70553e-690.webp 690w, https://geekshavefeelings.com/img/fyda70553e-1380.webp 1380w, https://geekshavefeelings.com/img/fyda70553e-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/fyda70553e-690.jpeg 690w, https://geekshavefeelings.com/img/fyda70553e-1380.jpeg 1380w, https://geekshavefeelings.com/img/fyda70553e-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Dan, Aaron, and Jim setting up" src="https://geekshavefeelings.com/img/fyda70553e-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<h2 id="everything-about-this-robot-sucks" tabindex="-1">Everything about this robot sucks <a class="header-anchor" href="https://geekshavefeelings.com/posts/2014/big-data-evt/">§</a></h2>
<p>Seriously. Even when not damaged, the weight distribution is so far forward that Big Data could use hardly any of its beefy drive, the HobbyKing 6S controller could sync only to the weapon motor once every ten tries, and even when it did the magnetic clutch didn’t grip the beater bar tightly enough to spin it well.</p>
<p>https://www.youtube.com/watch?v=4_ywkPRrz4E</p>
<p>The real clincher was how fragile everything was. The drive motors were only face mounted with three M2 screws each to a frame rail, so after the first hit the mount points stripped out and both motors were hanging out in free space.</p>
<p>Using a 5-face box made of 1/4 in 7075 was also a bad idea, as was putting the weapon between two unsupported rails that easily snapped off. Various screws were loaded in shear. Heck, even the drive gears didn’t mesh that well. Everything that could be crappy about an honest attempt at a non-<a href="https://www.youtube.com/watch?v=-buqqEaRkHM" title="Assbots for Dragon*Con #2: Melty Butt">ass bot</a>, I made crappy.</p>
<p>But the Cornflakes held up fine, so I taped the drive motors back in, fixed the weight distribution by removing the beater bar, and tossed it once more unto the breach.</p>
<p>https://www.youtube.com/watch?v=H-UNtyhgeYM</p>
<p>This is one cloud technology that failed to disrupt.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/knj7l2VVtd-690.avif 690w, https://geekshavefeelings.com/img/knj7l2VVtd-1380.avif 1380w, https://geekshavefeelings.com/img/knj7l2VVtd-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/knj7l2VVtd-690.webp 690w, https://geekshavefeelings.com/img/knj7l2VVtd-1380.webp 1380w, https://geekshavefeelings.com/img/knj7l2VVtd-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/knj7l2VVtd-690.jpeg 690w, https://geekshavefeelings.com/img/knj7l2VVtd-1380.jpeg 1380w, https://geekshavefeelings.com/img/knj7l2VVtd-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Disrupt" src="https://geekshavefeelings.com/img/knj7l2VVtd-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>On the other hand, Sheboygan.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/k5yP-OAsNt-690.avif 690w, https://geekshavefeelings.com/img/k5yP-OAsNt-1380.avif 1380w, https://geekshavefeelings.com/img/k5yP-OAsNt-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/k5yP-OAsNt-690.webp 690w, https://geekshavefeelings.com/img/k5yP-OAsNt-1380.webp 1380w, https://geekshavefeelings.com/img/k5yP-OAsNt-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/k5yP-OAsNt-690.jpeg 690w, https://geekshavefeelings.com/img/k5yP-OAsNt-1380.jpeg 1380w, https://geekshavefeelings.com/img/k5yP-OAsNt-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="IMG_1075" src="https://geekshavefeelings.com/img/k5yP-OAsNt-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2014/big-data-evt/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Remember I’m backtracking to early 2014. <a href="https://geekshavefeelings.com/posts/2014/big-data-evt/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>At 6S: six lithium polymer cells in series, for a maximum of 6 × 4.2 V = 25.2 V. <a href="https://geekshavefeelings.com/posts/2014/big-data-evt/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Configured in a “wye” termination, if you cared. <a href="https://geekshavefeelings.com/posts/2014/big-data-evt/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Integer Arithmetic Continued
2013-08-15T05:23:58Z
https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/
<p>I continue my <a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic" title="Real Talk: Integer Arithmetic">thing about integer arithmetic</a>. The plan is to add so much math to this blog that nobody will read it, although to be fair, the amount of math that takes is “any” and nobody was reading to begin with.</p>
<h2 id="avg" tabindex="-1">avg <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/">§</a></h2>
<p>Taking the average of two numbers is important. Super important. But how do you do it?</p>
<p><a href="http://www.flickr.com/photos/afireinwinter/9304484918/" title="No, you can’t just add them up and divide by 2."><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/QuBL3cxDHB-690.avif 690w, https://geekshavefeelings.com/img/QuBL3cxDHB-1380.avif 1380w, https://geekshavefeelings.com/img/QuBL3cxDHB-3508.avif 3508w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/QuBL3cxDHB-690.webp 690w, https://geekshavefeelings.com/img/QuBL3cxDHB-1380.webp 1380w, https://geekshavefeelings.com/img/QuBL3cxDHB-3508.webp 3508w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/QuBL3cxDHB-690.jpeg 690w, https://geekshavefeelings.com/img/QuBL3cxDHB-1380.jpeg 1380w, https://geekshavefeelings.com/img/QuBL3cxDHB-3508.jpeg 3508w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="avg" src="https://geekshavefeelings.com/img/QuBL3cxDHB-690.jpeg" width="3508" height="2339"></picture></figure></a></p>
<p>It’s been over seven years since Peter Norvig posted “<a href="http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html" title="Extra, Extra - Read All About It: Nearly All Binary Searches and Mergesorts are Broken">Nearly All Binary Searches and Mergesorts are Broken</a>” and still, the <a href="http://www.programmingsimplified.com/c/source-code/c-program-binary-search" title="C program for binary search">top result</a> for “binary search in C” has these maths for the indices:</p>
<pre class="language-c" tabindex="0"><code class="language-c">first <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
last <span class="token operator">=</span> n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
middle <span class="token operator">=</span> <span class="token punctuation">(</span>first<span class="token operator">+</span>last<span class="token punctuation">)</span><span class="token operator">/</span><span class="token number">2</span><span class="token punctuation">;</span></code></pre>
<p>Of course, the problem here is that if <code>first+last</code> exceeds 2<sup>31</sup>-1 or 2147483647, then it overflows into the negative, and using the now-negative <code>middle</code> as an index will cause “undefined behavior<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/" id="fnref1">*</a></sup>.”</p>
<p>Before jumping into fixes, let’s take a second to appreciate that page. I didn’t expect anything that bad to come up as the first result. Let’s take in the link to a compiled EXE (!), a screenshot of it running (?), and this brilliant programmers’ admonishment about using binary search (?!):</p>
<blockquote>
<p>Binary search is faster than linear search but list should be sorted, hashing is faster than binary search and perform searches in constant time.</p>
</blockquote>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/0lMhdz26cM-690.avif 690w, https://geekshavefeelings.com/img/0lMhdz26cM-1380.avif 1380w, https://geekshavefeelings.com/img/0lMhdz26cM-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/0lMhdz26cM-690.webp 690w, https://geekshavefeelings.com/img/0lMhdz26cM-1380.webp 1380w, https://geekshavefeelings.com/img/0lMhdz26cM-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/0lMhdz26cM-690.png 690w, https://geekshavefeelings.com/img/0lMhdz26cM-1380.png 1380w, https://geekshavefeelings.com/img/0lMhdz26cM-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="?!" src="https://geekshavefeelings.com/img/0lMhdz26cM-690.png" width="1920" height="1200"></picture></figure><p></p>
<p>Alright then.</p>
<p>In this case, the fix is really very simple: since both <code>first</code> and <code>last</code> are known to be positive, their difference can’t overflow the range of integers and you can do this:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp">middle <span class="token operator">=</span> first <span class="token operator">+</span> <span class="token punctuation">(</span>last <span class="token operator">-</span> first<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span></code></pre>
<p>Guaranteed to not overflow. However, what happens when you need to take an average of two numbers that may not be positive? If <code>first</code> is very large and positive and <code>last</code> is very large and negative, <code>last - first</code> could overflow.</p>
<p>One naïve solution would be to use both formulae, and switch between them based on the inputs. After all, if <code>(a+b)/2</code> works when <code>a</code> and <code>b</code> have different signs, and <code>a+(b-a)/2</code> works when they’re both positive, then we just write a routine that applies them at the right times, right?</p>
<p>Except… I kind of ignored how the expression <code>last - first</code> is guaranteed to be positive. But if the order of our <code>avg</code> function’s two input values is not known, then that value can be negative. Why is this a problem?</p>
<p>As you might guess, it’s rounding. See, division in C++ is defined to truncate towards zero, and in C it’s a frequent default to do the same. So, negative numbers round up and positive numbers round down. You see the problem when you have an order-dependent operation like subtraction in the expression <code>(b-a)/2</code>?</p>
<p>Let’s try an example; let’s take the average of 2 and 7.</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -4.385ex;" xmlns="http://www.w3.org/2000/svg" width="47.317ex" height="9.9ex" role="img" focusable="false" viewBox="0 -2438 20914.2 4376" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,1086)"><g data-mml-node="mtd" transform="translate(1556,0)"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1028,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1528,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1917,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2417,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2861.7,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3361.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4028.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(5084.2,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5806.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(6806.7,0)"><g data-mml-node="mrow" transform="translate(220,676)"><g data-mml-node="mn"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(500,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(1000,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(720,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="1700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(9024.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(10080.2,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10802.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11802.7,0)"><path data-c="230A" d="M174 734Q174 735 175 737T177 740T180 744T184 747T189 749T196 750Q206 748 214 735V-210H310H373Q401 -210 411 -213T422 -230T411 -247T369 -251Q362 -251 338 -251T298 -250H190Q178 -246 174 -234V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(12246.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(13524.7,0)"><path data-c="230B" d="M229 734Q229 735 230 737T232 740T235 744T239 747T244 749T251 750Q262 748 269 735V-235Q266 -240 256 -249L147 -250H77Q43 -250 32 -247T21 -230T32 -213T72 -209Q79 -209 99 -209T133 -210H229V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(14246.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(15302.2,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(16024.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(17024.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(17802.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(18858.2,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-1252)"><g data-mml-node="mtd"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1028,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1528,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1917,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2417,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2861.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3361.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4028.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(5084.2,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5806.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(6806.7,0)"><g data-mml-node="mrow" transform="translate(220,676)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(500,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(1000,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(720,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="1700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(9024.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(10080.2,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10802.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11802.7,0)"><path data-c="2308" d="M174 734Q178 746 190 750H298H369Q400 750 411 747T422 730T411 713T372 709Q365 709 345 709T310 710H214V-235Q206 -248 196 -250Q192 -250 189 -249T184 -247T180 -244T178 -241T176 -237T174 -234V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12246.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(13024.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(14302.7,0)"><path data-c="2309" d="M21 717T21 730T32 746T75 750H147H256Q266 742 269 735V-235Q262 -248 251 -250Q247 -250 244 -249T239 -247T235 -244T233 -241T231 -237T229 -234V710H133Q119 710 99 710T71 709Q43 709 32 713Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(15024.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(16080.2,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(16802.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(17802.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(18580.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(19358.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(20414.2,0)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right" columnspacing="" rowspacing="3pt"><mtr><mtd><mtext>avg</mtext><mo stretchy="false">(</mo><mn>2</mn><mo>,</mo><mn>7</mn><mo stretchy="false">)</mo><mo>=</mo><mn>2</mn><mo>+</mo><mfrac><mrow><mn>7</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>2</mn></mrow><mn>2</mn></mfrac><mo>=</mo><mn>2</mn><mo>+</mo><mo fence="false" stretchy="false">⌊</mo><mn>2.5</mn><mo fence="false" stretchy="false">⌋</mo><mo>=</mo><mn>2</mn><mo>+</mo><mn>2</mn><mo>=</mo><mn>4</mn></mtd></mtr><mtr><mtd><mtext>avg</mtext><mo stretchy="false">(</mo><mn>7</mn><mo>,</mo><mn>2</mn><mo stretchy="false">)</mo><mo>=</mo><mn>7</mn><mo>+</mo><mfrac><mrow><mn>2</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>7</mn></mrow><mn>2</mn></mfrac><mo>=</mo><mn>7</mn><mo>+</mo><mo fence="false" stretchy="false">⌈</mo><mo>−</mo><mn>2.5</mn><mo fence="false" stretchy="false">⌉</mo><mo>=</mo><mn>7</mn><mo>+</mo><mo>−</mo><mn>2</mn><mo>=</mo><mn>5</mn></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>Yeah, we ended up with an <code>avg</code> function where <code>avg(a, b) != avg(b, a)</code>. Not good. Sure, we could just correct for this with another conditional to check if <code>(b-a) < 0</code> and subtract one from the result if one input is odd and the other even<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/" id="fnref2">†</a></sup>. But you’d agree that’s pretty complicated, right?</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">// note: this is to prove a point. It's not been tested.</span>
<span class="token keyword">int32_t</span> <span class="token function">avg</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span> a<span class="token punctuation">,</span> <span class="token keyword">int32_t</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span>a <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token punctuation">(</span>b <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>a <span class="token operator">+</span> b<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> a <span class="token operator">+</span> <span class="token punctuation">(</span>b <span class="token operator">-</span> a<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span> <span class="token operator">+</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span>b <span class="token operator">-</span> a <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span>a <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token punctuation">(</span>b <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/aKchfb2edw-690.avif 690w, https://geekshavefeelings.com/img/aKchfb2edw-1380.avif 1380w, https://geekshavefeelings.com/img/aKchfb2edw-1440.avif 1440w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/aKchfb2edw-690.webp 690w, https://geekshavefeelings.com/img/aKchfb2edw-1380.webp 1380w, https://geekshavefeelings.com/img/aKchfb2edw-1440.webp 1440w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/aKchfb2edw-690.jpeg 690w, https://geekshavefeelings.com/img/aKchfb2edw-1380.jpeg 1380w, https://geekshavefeelings.com/img/aKchfb2edw-1440.jpeg 1440w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="WATMAN" src="https://geekshavefeelings.com/img/aKchfb2edw-690.jpeg" width="1440" height="900"></picture><figcaption>What the hell, Batman?</figcaption></figure><p></p>
<p>Let’s try another approach. Maybe we should divide each input value first, then add the halves together.</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int32_t</span> <span class="token function">avg</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span> a<span class="token punctuation">,</span> <span class="token keyword">int32_t</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>a <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>b <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>The error here should be obvious now. I’ll show you with examples.</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -4.374ex;" xmlns="http://www.w3.org/2000/svg" width="46.299ex" height="9.88ex" role="img" focusable="false" viewBox="0 -2433.5 20464.2 4367" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,1080.5)"><g data-mml-node="mtd" transform="translate(6888,0)"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1028,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1528,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1917,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2417,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2861.7,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3361.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4028.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(5084.2,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(6246.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(7246.7,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(8464.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9520.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10242.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(11242.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12020.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(13076.2,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-1247.5)"><g data-mml-node="mtd"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1028,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1528,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1917,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2417,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2861.7,0)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3361.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4028.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(5084.2,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(6246.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(7246.7,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(8464.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9520.2,0)"><path data-c="230A" d="M174 734Q174 735 175 737T177 740T180 744T184 747T189 749T196 750Q206 748 214 735V-210H310H373Q401 -210 411 -213T422 -230T411 -247T369 -251Q362 -251 338 -251T298 -250H190Q178 -246 174 -234V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9964.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11242.2,0)"><path data-c="230B" d="M229 734Q229 735 230 737T232 740T235 744T239 747T244 749T251 750Q262 748 269 735V-235Q266 -240 256 -249L147 -250H77Q43 -250 32 -247T21 -230T32 -213T72 -209Q79 -209 99 -209T133 -210H229V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11908.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12908.7,0)"><path data-c="230A" d="M174 734Q174 735 175 737T177 740T180 744T184 747T189 749T196 750Q206 748 214 735V-210H310H373Q401 -210 411 -213T422 -230T411 -247T369 -251Q362 -251 338 -251T298 -250H190Q178 -246 174 -234V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(13352.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(14630.7,0)"><path data-c="230B" d="M229 734Q229 735 230 737T232 740T235 744T239 747T244 749T251 750Q262 748 269 735V-235Q266 -240 256 -249L147 -250H77Q43 -250 32 -247T21 -230T32 -213T72 -209Q79 -209 99 -209T133 -210H229V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(15352.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(16408.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(17130.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(18130.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(18908.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(19964.2,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right" columnspacing="" rowspacing="3pt"><mtr><mtd><mtext>avg</mtext><mo stretchy="false">(</mo><mn>2</mn><mo>,</mo><mn>4</mn><mo stretchy="false">)</mo><mo>=</mo><mfrac><mn>2</mn><mn>2</mn></mfrac><mo>+</mo><mfrac><mn>4</mn><mn>2</mn></mfrac><mo>=</mo><mn>1</mn><mo>+</mo><mn>2</mn><mo>=</mo><mn>3</mn></mtd></mtr><mtr><mtd><mtext>avg</mtext><mo stretchy="false">(</mo><mn>3</mn><mo>,</mo><mn>5</mn><mo stretchy="false">)</mo><mo>=</mo><mfrac><mn>3</mn><mn>2</mn></mfrac><mo>+</mo><mfrac><mn>5</mn><mn>2</mn></mfrac><mo>=</mo><mo fence="false" stretchy="false">⌊</mo><mn>1.5</mn><mo fence="false" stretchy="false">⌋</mo><mo>+</mo><mo fence="false" stretchy="false">⌊</mo><mn>2.5</mn><mo fence="false" stretchy="false">⌋</mo><mo>=</mo><mn>1</mn><mo>+</mo><mn>2</mn><mo>=</mo><mn>3</mn></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>Wait. So our <code>avg</code> function works as if <code>avg(a, b) = avg(a + 1, b + 1)</code>? That’s… kind of wrong. But at least <code>avg(a, b) = avg(b, a)</code>!</p>
<p>Let’s see here. So in order to build a function that works similarly to <code>(a+b)/2</code>, the gold standard of midpointing, we must satisfy the following:</p>
<ol>
<li><code>avg(a, b) = avg(b, a)</code></li>
<li><code>avg(a + 1, b + 1) = avg(a, b) + 1</code></li>
<li><code>avg(-a, -b) = -avg(a, b)</code></li>
</ol>
<p>That last one actually specifies a wholly different and yet unexplained requirement: symmetry about zero. I just feel that if you’re gonna be averaging signed numbers together, the function ought to work similarly on either side of the number line and not bias results in either direction. So it only makes sense to round the results toward zero.</p>
<p>Anyways, so how do with address our problem with the “sum of halves” solution? Can we fix it without adding a bunch of branches like with the former “conditional half of difference” solution?</p>
<p><a href="http://www.flickr.com/photos/ataradrac/4263144497/"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/9SOU_Y7EAF-690.avif 690w, https://geekshavefeelings.com/img/9SOU_Y7EAF-1380.avif 1380w, https://geekshavefeelings.com/img/9SOU_Y7EAF-1409.avif 1409w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/9SOU_Y7EAF-690.webp 690w, https://geekshavefeelings.com/img/9SOU_Y7EAF-1380.webp 1380w, https://geekshavefeelings.com/img/9SOU_Y7EAF-1409.webp 1409w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/9SOU_Y7EAF-690.jpeg 690w, https://geekshavefeelings.com/img/9SOU_Y7EAF-1380.jpeg 1380w, https://geekshavefeelings.com/img/9SOU_Y7EAF-1409.jpeg 1409w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Sum of Halves" src="https://geekshavefeelings.com/img/9SOU_Y7EAF-690.jpeg" width="1409" height="1184"></picture></figure></a></p>
<p>Well, let’s think about why it happens. The error manifests when both halves have a half aftering halving: that is, when both <code>a / 2</code> and <code>b / 2</code> are something.5 (read that as “something point five”). This results in both parts being rounded down before getting summed. But, since both parts were decreased by .5, this causes a total decrease of 1 in the sum!</p>
<p>Of course, <code>x / 2</code> needs only be rounded if <code>x</code> is odd, so the only time the above error manifests is then if both inputs are odd. So it’s a simple matter of adding one to the result when both are odd, right?</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int32_t</span> <span class="token function">avg</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span> a<span class="token punctuation">,</span> <span class="token keyword">int32_t</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>a <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>b <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>a <span class="token operator">&</span> b <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// can also be + (a % 2 && b % 2)</span>
<span class="token punctuation">}</span></code></pre>
<p>Kind of. See, this does take care of most of the errors, but there’s still a subtle bug that causes it to not satisfy requirement <em>2. <code>avg(a + 1, b + 1) = avg(a, b) + 1</code></em>. Can you spot it?</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -4.361ex;" xmlns="http://www.w3.org/2000/svg" width="45.684ex" height="9.853ex" role="img" focusable="false" viewBox="0 -2427.5 20192.2 4355" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,1086.5)"><g data-mml-node="mtd" transform="translate(5390,0)"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1028,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1528,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1917,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2417,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2861.7,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3361.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4028.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(5084.2,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5806.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(6806.7,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(8024.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9080.2,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9802.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10802.7,0)"><path data-c="230A" d="M174 734Q174 735 175 737T177 740T180 744T184 747T189 749T196 750Q206 748 214 735V-210H310H373Q401 -210 411 -213T422 -230T411 -247T369 -251Q362 -251 338 -251T298 -250H190Q178 -246 174 -234V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(11246.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12524.7,0)"><path data-c="230B" d="M229 734Q229 735 230 737T232 740T235 744T239 747T244 749T251 750Q262 748 269 735V-235Q266 -240 256 -249L147 -250H77Q43 -250 32 -247T21 -230T32 -213T72 -209Q79 -209 99 -209T133 -210H229V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(13246.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(14302.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-1241.5)"><g data-mml-node="mtd"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="76" d="M338 431Q344 429 422 429Q479 429 503 431H508V385H497Q439 381 423 345Q421 341 356 172T288 -2Q283 -11 263 -11Q244 -11 239 -2Q99 359 98 364Q93 378 82 381T43 385H19V431H25L33 430Q41 430 53 430T79 430T104 429T122 428Q217 428 232 431H240V385H226Q187 384 184 370Q184 366 235 234L286 102L377 341V349Q377 363 367 372T349 383T335 385H331V431H338Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1028,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1528,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1917,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2695,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3195,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3639.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4139.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4806.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(5862.2,0)"><g data-mml-node="mrow" transform="translate(220,676)"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(609,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="1478" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(7802.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(8802.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9580.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10636.2,0)"><path data-c="2308" d="M174 734Q178 746 190 750H298H369Q400 750 411 747T422 730T411 713T372 709Q365 709 345 709T310 710H214V-235Q206 -248 196 -250Q192 -250 189 -249T184 -247T180 -244T178 -241T176 -237T174 -234V734Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11080.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(11858.2,0)"><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12636.2,0)"><path data-c="2309" d="M21 717T21 730T32 746T75 750H147H256Q266 742 269 735V-235Q262 -248 251 -250Q247 -250 244 -249T239 -247T235 -244T233 -241T231 -237T229 -234V710H133Q119 710 99 710T71 709Q43 709 32 713Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(13302.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(14302.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(15080.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(16136.2,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(16858.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(17858.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(18636.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(19692.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right" columnspacing="" rowspacing="3pt"><mtr><mtd><mtext>avg</mtext><mo stretchy="false">(</mo><mn>0</mn><mo>,</mo><mn>3</mn><mo stretchy="false">)</mo><mo>=</mo><mn>0</mn><mo>+</mo><mfrac><mn>3</mn><mn>2</mn></mfrac><mo>=</mo><mn>0</mn><mo>+</mo><mo fence="false" stretchy="false">⌊</mo><mn>1.5</mn><mo fence="false" stretchy="false">⌋</mo><mo>=</mo><mn>1</mn></mtd></mtr><mtr><mtd><mtext>avg</mtext><mo stretchy="false">(</mo><mo>−</mo><mn>1</mn><mo>,</mo><mn>2</mn><mo stretchy="false">)</mo><mo>=</mo><mfrac><mrow><mo>−</mo><mn>1</mn></mrow><mn>2</mn></mfrac><mo>+</mo><mn>1</mn><mo>=</mo><mo fence="false" stretchy="false">⌈</mo><mo>−</mo><mn>.5</mn><mo fence="false" stretchy="false">⌉</mo><mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn><mo>+</mo><mn>1</mn><mo>=</mo><mn>1</mn></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>I’ll give it to ya straight: when <code>a</code> and <code>b</code> have opposite signs, they are rounded in opposite directions. Negatives are rounded up, and positives are rounded down. Not a big deal if both inputs are odd or both are even. In fact, the error only manifests when one input is odd and the other is even, as well as another condition that I haven’t even yet been able to divine. Suffice to say that it’s not really the right path to go down.</p>
<p><a href="http://www.flickr.com/photos/stankuns/8738770989/"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/fsKPrtylXZ-690.avif 690w, https://geekshavefeelings.com/img/fsKPrtylXZ-1380.avif 1380w, https://geekshavefeelings.com/img/fsKPrtylXZ-1620.avif 1620w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/fsKPrtylXZ-690.webp 690w, https://geekshavefeelings.com/img/fsKPrtylXZ-1380.webp 1380w, https://geekshavefeelings.com/img/fsKPrtylXZ-1620.webp 1620w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/fsKPrtylXZ-690.jpeg 690w, https://geekshavefeelings.com/img/fsKPrtylXZ-1380.jpeg 1380w, https://geekshavefeelings.com/img/fsKPrtylXZ-1620.jpeg 1620w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="What a mess." src="https://geekshavefeelings.com/img/fsKPrtylXZ-690.jpeg" width="1620" height="1080"></picture></figure></a></p>
<p>So what <em>can</em> we do? The easiest thing I figured out is to simply use a division that consistently rounds in the same direction, then round the result as needed. To do that, we’ll use an <a href="http://en.wikipedia.org/wiki/Arithmetic_shift" title="Wikipedia: Arithmetic shift">arithmetic right shift</a> by 1 in order to perform a divide-by-2.</p>
<p>It’s a common misconception that the C expressions <code>x / 2</code> and <code>x >> 1</code> are equivalent. In fact, for unsigned integers, they are. However, the major distinction is that <a href="http://en.wikipedia.org/wiki/Arithmetic_shift#Non-equivalence_of_arithmetic_right_shift_and_division" title="Wikipedia: Arithmetic shift#Non-equivalence of arithmetic right shift and division">the latter <em>rounds towards negative infinity</em></a> on most platforms<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/" id="fnref3">‡</a></sup>! This is much more convenient for us to use, since corrections happen consistently across the range of integers.</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int32_t</span> <span class="token function">avg</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span> a<span class="token punctuation">,</span> <span class="token keyword">int32_t</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>a <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>b <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>a <span class="token operator">&</span> b <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// can also be + (a % 2 && b % 2)</span>
<span class="token punctuation">}</span></code></pre>
<p>Already, this is a correct midpoint function. However, it’s still just a bit off my mark: it doesn’t meet our third requirement, symmetry on the number line about zero. That’s a simple fix though. Toss in a 1 when parities don’t match but the sum of halves is negative, and voilà, we have a winner! Rounds towards zero and everything!</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">/* SPDX-License-Identifier: MIT OR Apache-2.0 */</span>
<span class="token comment">/**
* Overflow-safe average of two signed integers. The naive average function is
* erroneous when the sum of the inputs overflows integer limits; this average
* works by summing the halves of the input values and then correcting the sum
* for rounding.
*
* @param a first value, as a 32-bit signed integer
* @param b second value, as a 32-bit signed integer
* @return signed average of the two values, rounded towards zero if their
* average is not an integer
*/</span>
<span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token keyword">int32_t</span> <span class="token function">avg</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span> a<span class="token punctuation">,</span> <span class="token keyword">int32_t</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// shifts divide by two, rounded towards negative infinity</span>
<span class="token keyword">const</span> <span class="token keyword">int32_t</span> sumHalves <span class="token operator">=</span> <span class="token punctuation">(</span>a <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token punctuation">(</span>b <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// this has error of magnitude one if both are odd</span>
<span class="token keyword">const</span> <span class="token keyword">uint32_t</span> bothOdd <span class="token operator">=</span> <span class="token punctuation">(</span>a <span class="token operator">&</span> b<span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token comment">// round toward zero; add one if one input is odd and sum is negative</span>
<span class="token keyword">const</span> <span class="token keyword">uint32_t</span> roundToZero <span class="token operator">=</span> <span class="token punctuation">(</span>sumHalves <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token punctuation">(</span>a <span class="token operator">^</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// result is sum of halves corrected for rounding</span>
<span class="token keyword">return</span> sumHalves <span class="token operator">+</span> bothOdd <span class="token operator">+</span> roundToZero<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>C programmer catch-all for any sort of problem the people who make C tools don’t care to have already solved for the programmer. <a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><code>(a&1) != (b&1)</code> or <code>(a%2) != (b%2)</code> <a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Sadly, this isn’t really defined by the C or C++ standards. <a href="https://geekshavefeelings.com/posts/2013/integer-arithmetic-continued/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Real Talk: Integer Arithmetic
2013-08-14T05:13:11Z
https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/
<p>Time for real talk, friends-o. We gotta address the bread and butter of we who massage code into machines: basic integer arithmetic. That’s right,</p>
<ul>
<li><strong>absolute value</strong> <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.564ex;" xmlns="http://www.w3.org/2000/svg" width="2.552ex" height="2.26ex" role="img" focusable="false" viewBox="0 -749.5 1128 999" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(278,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(850,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mi>x</mi><mo data-mjx-texclass="ORD" stretchy="false">|</mo></math></mjx-assistive-mml></mjx-container></li>
<li><strong>two-integer average</strong> <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.781ex;" xmlns="http://www.w3.org/2000/svg" width="3.773ex" height="2.791ex" role="img" focusable="false" viewBox="0 -888.7 1667.5 1233.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mrow" transform="translate(220,398) scale(0.707)"><g data-mml-node="mi"><path data-c="1D44E" d="M33 157Q33 258 109 349T280 441Q331 441 370 392Q386 422 416 422Q429 422 439 414T449 394Q449 381 412 234T374 68Q374 43 381 35T402 26Q411 27 422 35Q443 55 463 131Q469 151 473 152Q475 153 483 153H487Q506 153 506 144Q506 138 501 117T481 63T449 13Q436 0 417 -8Q409 -10 393 -10Q359 -10 336 5T306 36L300 51Q299 52 296 50Q294 48 292 46Q233 -10 172 -10Q117 -10 75 30T33 157ZM351 328Q351 334 346 350T323 385T277 405Q242 405 210 374T160 293Q131 214 119 129Q119 126 119 118T118 106Q118 61 136 44T179 26Q217 26 254 59T298 110Q300 114 325 217T351 328Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(529,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1307,0)"><path data-c="1D44F" d="M73 647Q73 657 77 670T89 683Q90 683 161 688T234 694Q246 694 246 685T212 542Q204 508 195 472T180 418L176 399Q176 396 182 402Q231 442 283 442Q345 442 383 396T422 280Q422 169 343 79T173 -11Q123 -11 82 27T40 150V159Q40 180 48 217T97 414Q147 611 147 623T109 637Q104 637 101 637H96Q86 637 83 637T76 640T73 647ZM336 325V331Q336 405 275 405Q258 405 240 397T207 376T181 352T163 330L157 322L136 236Q114 150 114 114Q114 66 138 42Q154 26 178 26Q211 26 245 58Q270 81 285 114T318 219Q336 291 336 325Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(657,-345) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="1427.5" height="60" x="120" y="220"></rect></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow><mn>2</mn></mfrac></math></mjx-assistive-mml></mjx-container></li>
</ul>
<p>I know, I know, you take your vitamin 0s and 1s and <code>SELECT</code> steel-cut rows for breakfast, but this is more fundamental than that; it’s about the core algos you learned in university, and how you’re implementing them with serious bugs because you thought these two were <em>so obvi</em>.</p>
<p>Keep your suspenders in suspense though, because we’re not going to wave our hands and say <em>anything</em> is outside of the scope of our recruiter’s 30-minute phone screen. Today, we’re gonna ditch our rockstar coder company hoodies and strap on fake embedded engineer neckbeards to look at those corner cases. Overflows matter, we care about rounding and fenceposts, and <code>INT_MIN</code> and <code>INT_MAX</code> are definitely gonna be tested inputs.</p>
<h2 id="abs" tabindex="-1">abs <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/">§</a></h2>
<p>Let’s start simple. What’s the big deal with <code>abs</code>? Well, for one, the C standard doesn’t actually define this function over all possible integer inputs<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/" id="fnref1">*</a></sup>. In particular, it isn’t defined for <a href="http://en.cppreference.com/w/c/types/limits" title="cppreference: C Numeric limits"><code>INT_MIN</code></a>—better known to C++ coders as <a href="http://en.cppreference.com/w/cpp/types/numeric_limits" title="cppreference: C++ numeric limits"><code>std::numeric_limits<int>::min()</code></a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/" id="fnref2">†</a></sup>. Let’s give it a shot:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp">cout <span class="token operator"><<</span> <span class="token class-name">numeric_limits</span><span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span><span class="token double-colon punctuation">::</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator"><<</span> <span class="token string">"\n"</span><span class="token punctuation">;</span>
cout <span class="token operator"><<</span> <span class="token function">abs</span><span class="token punctuation">(</span><span class="token class-name">numeric_limits</span><span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span><span class="token double-colon punctuation">::</span><span class="token function">min</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator"><<</span> <span class="token string">"\n"</span><span class="token punctuation">;</span></code></pre>
<p><a href="http://codepad.org/7PYcZWQE" title="codepad.org example for abs(INT_MIN)">If we run this on a regular x86 computer</a>, we get this somewhat unexpected result:</p>
<pre><code>-2147483648
-2147483648
</code></pre>
<p>That’s right; the absolute value of the most negative 32-bit integer is... the most negative 32-bit integer. This actually happens for any bit width, and it’s really because of the way <code>abs</code> works on our 2’s complement computers. Let’s try to see it better:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.148ex;" xmlns="http://www.w3.org/2000/svg" width="54.335ex" height="5.428ex" role="img" focusable="false" viewBox="0 -1449.5 24015.9 2399" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1056,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1450,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1839,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2411,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3077.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(4133.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7B" d="M618 -943L612 -949H582L568 -943Q472 -903 411 -841T332 -703Q327 -682 327 -653T325 -350Q324 -28 323 -18Q317 24 301 61T264 124T221 171T179 205T147 225T132 234Q130 238 130 250Q130 255 130 258T131 264T132 267T134 269T139 272T144 275Q207 308 256 367Q310 436 323 519Q324 529 325 851Q326 1124 326 1154T332 1205Q369 1358 566 1443L582 1450H612L618 1444V1429Q618 1413 616 1411L608 1406Q599 1402 585 1393T552 1372T515 1343T479 1305T449 1257T429 1200Q425 1180 425 1152T423 851Q422 579 422 549T416 498Q407 459 388 424T346 364T297 318T250 284T214 264T197 254L188 251L205 242Q290 200 345 138T416 3Q421 -18 421 -48T423 -349Q423 -397 423 -472Q424 -677 428 -694Q429 -697 429 -699Q434 -722 443 -743T465 -782T491 -816T519 -845T548 -868T574 -886T595 -899T610 -908L616 -910Q618 -912 618 -928V-943Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(750,0)"><g data-mml-node="mtr" transform="translate(0,600)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1350,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(2628,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3C" d="M694 -11T694 -19T688 -33T678 -40Q671 -40 524 29T234 166L90 235Q83 240 83 250Q83 261 91 266Q664 540 678 540Q681 540 687 534T694 519T687 505Q686 504 417 376L151 250L417 124Q686 -4 687 -5Q694 -11 694 -19Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(3239.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(1362,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1612,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2112,0)" style="stroke-width: 3;"></path><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2501,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3057,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3501,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(3893,0)" style="stroke-width: 3;"></path><path data-c="77" d="M90 368Q84 378 76 380T40 385H18V431H24L43 430Q62 430 84 429T116 428Q206 428 221 431H229V385H215Q177 383 177 368Q177 367 221 239L265 113L339 328L333 345Q323 374 316 379Q308 384 278 385H258V431H264Q270 428 348 428Q439 428 454 431H461V385H452Q404 385 404 369Q404 366 418 324T449 234T481 143L496 100L537 219Q579 341 579 347Q579 363 564 373T530 385H522V431H529Q541 428 624 428Q692 428 698 431H703V385H697Q696 385 691 385T682 384Q635 377 619 334L559 161Q546 124 528 71Q508 12 503 1T487 -11H479Q460 -11 456 -4Q455 -3 407 133L361 267Q359 263 266 -4Q261 -11 243 -11H238Q225 -11 220 -3L90 368Z" transform="translate(4143,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(4865,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5365,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(5757,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(6313,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(6707,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(10196.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11046.3,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11991.1,0)"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12269.1,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(13047.1,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(14337.2,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(14781.9,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(15281.9,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-683.9)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(572,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(2628,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="2265" d="M83 616Q83 624 89 630T99 636Q107 636 253 568T543 431T687 361Q694 356 694 346T687 331Q685 329 395 192L107 56H101Q83 58 83 76Q83 77 83 79Q82 86 98 95Q117 105 248 167Q326 204 378 228L626 346L360 472Q291 505 200 548Q112 589 98 597T83 616ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(3239.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(1362,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1612,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2112,0)" style="stroke-width: 3;"></path><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2501,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3057,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3501,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(3893,0)" style="stroke-width: 3;"></path><path data-c="77" d="M90 368Q84 378 76 380T40 385H18V431H24L43 430Q62 430 84 429T116 428Q206 428 221 431H229V385H215Q177 383 177 368Q177 367 221 239L265 113L339 328L333 345Q323 374 316 379Q308 384 278 385H258V431H264Q270 428 348 428Q439 428 454 431H461V385H452Q404 385 404 369Q404 366 418 324T449 234T481 143L496 100L537 219Q579 341 579 347Q579 363 564 373T530 385H522V431H529Q541 428 624 428Q692 428 698 431H703V385H697Q696 385 691 385T682 384Q635 377 619 334L559 161Q546 124 528 71Q508 12 503 1T487 -11H479Q460 -11 456 -4Q455 -3 407 133L361 267Q359 263 266 -4Q261 -11 243 -11H238Q225 -11 220 -3L90 368Z" transform="translate(4143,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(4865,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5365,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(5757,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(6313,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(6707,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(10196.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11046.3,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11991.1,0)"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(12269.1,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12769.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(13213.8,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(14726.1,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(15726.3,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(16226.3,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(19882.3,0) translate(0 250)"></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtext>abs</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing=".2em"><mtr><mtd><mo>−</mo><mi>x</mi><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo><</mo><mn>0</mn><mtext>, in other words </mtext><mi>x</mi><mo>∈</mo><mo stretchy="false">[</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>,</mo><mn>0</mn><mo stretchy="false">)</mo></mtd></mtr><mtr><mtd><mi>x</mi><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>≥</mo><mn>0</mn><mtext>, in other words </mtext><mi>x</mi><mo>∈</mo><mo stretchy="false">[</mo><mn>0</mn><mo>,</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE" fence="true" stretchy="true" symmetric="true"></mo></mrow></math></mjx-assistive-mml></mjx-container><p>I included the 32-bit integer limits to demonstrate the ranges of numbers that <code>abs</code> is forced to map one another. Let's try to visualize how this mapping works:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -9.617ex;" xmlns="http://www.w3.org/2000/svg" width="80.149ex" height="20.366ex" role="img" focusable="false" viewBox="0 -4750.9 35425.9 9001.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1056,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1450,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1839,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2411,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3077.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(4133.6,0)"><g data-mml-node="mo"><path data-c="23A7" d="M712 899L718 893V876V865Q718 854 704 846Q627 793 577 710T510 525Q510 524 509 521Q505 493 504 349Q504 345 504 334Q504 277 504 240Q504 -2 503 -4Q502 -8 494 -9T444 -10Q392 -10 390 -9Q387 -8 386 -5Q384 5 384 230Q384 262 384 312T383 382Q383 481 392 535T434 656Q510 806 664 892L677 899H712Z" transform="translate(0,3851.9)" style="stroke-width: 3;"></path><path data-c="23A9" d="M718 -893L712 -899H677L666 -893Q542 -825 468 -714T385 -476Q384 -466 384 -282Q384 3 385 5L389 9Q392 10 444 10Q486 10 494 9T503 4Q504 2 504 -239V-310V-366Q504 -470 508 -513T530 -609Q546 -657 569 -698T617 -767T661 -812T699 -843T717 -856T718 -876V-893Z" transform="translate(0,-3351.9)" style="stroke-width: 3;"></path><path data-c="23A8" d="M389 1159Q391 1160 455 1160Q496 1160 498 1159Q501 1158 502 1155Q504 1145 504 924Q504 691 503 682Q494 549 425 439T243 259L229 250L243 241Q349 175 421 66T503 -182Q504 -191 504 -424Q504 -600 504 -629T499 -659H498Q496 -660 444 -660T390 -659Q387 -658 386 -655Q384 -645 384 -425V-282Q384 -176 377 -116T342 10Q325 54 301 92T255 155T214 196T183 222T171 232Q170 233 170 250T171 268Q171 269 191 284T240 331T300 407T354 524T383 679Q384 691 384 925Q384 1152 385 1155L389 1159Z" transform="translate(0,0)" style="stroke-width: 3;"></path><svg width="889" height="2881.9" y="1060" x="0" viewBox="0 507.9 889 2881.9"><path data-c="23AA" d="M384 150V266Q384 304 389 309Q391 310 455 310Q496 310 498 309Q502 308 503 298Q504 283 504 150Q504 32 504 12T499 -9H498Q496 -10 444 -10T390 -9Q386 -8 385 2Q384 17 384 150Z" transform="scale(1,14.173)" style="stroke-width: 3;"></path></svg><svg width="889" height="2881.9" y="-3441.9" x="0" viewBox="0 507.9 889 2881.9"><path data-c="23AA" d="M384 150V266Q384 304 389 309Q391 310 455 310Q496 310 498 309Q502 308 503 298Q504 283 504 150Q504 32 504 12T499 -9H498Q496 -10 444 -10T390 -9Q386 -8 385 2Q384 17 384 150Z" transform="scale(1,14.173)" style="stroke-width: 3;"></path></svg></g><g data-mml-node="mtable" transform="translate(889,0)"><g data-mml-node="mtr" transform="translate(0,4000.9)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(572,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(3568.1,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="2265" d="M83 616Q83 624 89 630T99 636Q107 636 253 568T543 431T687 361Q694 356 694 346T687 331Q685 329 395 192L107 56H101Q83 58 83 76Q83 77 83 79Q82 86 98 95Q117 105 248 167Q326 204 378 228L626 346L360 472Q291 505 200 548Q112 589 98 597T83 616ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,2800.9)"><g data-mml-node="mtd"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(500,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(3568.1,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2739.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3517.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,1600.9)"><g data-mml-node="mtd"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(500,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(3568.1,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2739.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3517.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-149.1)"><g data-mml-node="mtd"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="22EE" d="M78 30Q78 54 95 72T138 90Q162 90 180 74T199 31Q199 6 182 -12T139 -30T96 -13T78 30ZM78 440Q78 464 95 482T138 500Q162 500 180 484T199 441Q199 416 182 398T139 380T96 397T78 440ZM78 840Q78 864 95 882T138 900Q162 900 180 884T199 841Q199 816 182 798T139 780T96 797T78 840Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mtr" transform="translate(0,-1433)"><g data-mml-node="mtd"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1290.1,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(1790.1,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2290.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(3568.1,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2739.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(3517.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(5029.9,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(6030.1,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-2717)"><g data-mml-node="mtd"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1290.1,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(1790.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2290.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(3568.1,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2739.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(3517.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(5029.9,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(6030.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(6530.1,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(639,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1195,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1695,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2084,0)" style="stroke-width: 3;"></path><path data-c="3A" d="M78 370Q78 394 95 412T138 430Q162 430 180 414T199 371Q199 346 182 328T139 310T96 327T78 370ZM78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(2528,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(2806,0)" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(9586.1,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(10876.2,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(11376.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(11876.2,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(528,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(922,0)" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1172,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(2005,0)" style="stroke-width: 3;"></path><path data-c="78" d="M201 0Q189 3 102 3Q26 3 17 0H11V46H25Q48 47 67 52T96 61T121 78T139 96T160 122T180 150L226 210L168 288Q159 301 149 315T133 336T122 351T113 363T107 370T100 376T94 379T88 381T80 383Q74 383 44 385H16V431H23Q59 429 126 429Q219 429 229 431H237V385Q201 381 201 369Q201 367 211 353T239 315T268 274L272 270L297 304Q329 345 329 358Q329 364 327 369T322 376T317 380T310 384L307 385H302V431H309Q324 428 408 428Q487 428 493 431H499V385H492Q443 385 411 368Q394 360 377 341T312 257L296 236L358 151Q424 61 429 57T446 50Q464 46 499 46H516V0H510H502Q494 1 482 1T457 2T432 2T414 3Q403 3 377 3T327 1L304 0H295V46H298Q309 46 320 51T331 63Q331 65 291 120L250 175Q249 174 219 133T185 88Q181 83 181 74Q181 63 188 55T206 46Q208 46 208 23V0H201Z" transform="translate(2505,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(3033,0)" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(3311,0)" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(4144,0)" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(4700,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(5533,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(5783,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(6177,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(6455,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(6955,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(7511,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(7955,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(8511,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(8761,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(9261,0)" style="stroke-width: 3;"></path><path data-c="2D" d="M11 179V252H277V179H11Z" transform="translate(9761,0)" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(10094,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(10650,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(10928,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(11317,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(11567,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(11845,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(12401,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(12790,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(13234,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(13734,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(14178,0)" style="stroke-width: 3;"></path><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" transform="translate(14570,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-4000.9)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="3F" d="M226 668Q190 668 162 656T124 632L114 621Q116 621 119 620T130 616T145 607T157 591T162 567Q162 544 147 529T109 514T71 528T55 566Q55 625 100 661T199 704Q201 704 210 704T224 705H228Q281 705 320 692T378 656T407 612T416 567Q416 503 361 462Q267 395 247 303Q242 279 242 241V224Q242 205 239 202T222 198T205 201T202 218V249Q204 320 220 371T255 445T292 491T315 537Q317 546 317 574V587Q317 604 315 615T304 640T277 661T226 668ZM162 61Q162 89 180 105T224 121Q247 119 264 104T281 61Q281 31 264 16T222 1Q197 1 180 16T162 61Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(472,0)"><path data-c="3F" d="M226 668Q190 668 162 656T124 632L114 621Q116 621 119 620T130 616T145 607T157 591T162 567Q162 544 147 529T109 514T71 528T55 566Q55 625 100 661T199 704Q201 704 210 704T224 705H228Q281 705 320 692T378 656T407 612T416 567Q416 503 361 462Q267 395 247 303Q242 279 242 241V224Q242 205 239 202T222 198T205 201T202 218V249Q204 320 220 371T255 445T292 491T315 537Q317 546 317 574V587Q317 604 315 615T304 640T277 661T226 668ZM162 61Q162 89 180 105T224 121Q247 119 264 104T281 61Q281 31 264 16T222 1Q197 1 180 16T162 61Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(944,0)"><path data-c="3F" d="M226 668Q190 668 162 656T124 632L114 621Q116 621 119 620T130 616T145 607T157 591T162 567Q162 544 147 529T109 514T71 528T55 566Q55 625 100 661T199 704Q201 704 210 704T224 705H228Q281 705 320 692T378 656T407 612T416 567Q416 503 361 462Q267 395 247 303Q242 279 242 241V224Q242 205 239 202T222 198T205 201T202 218V249Q204 320 220 371T255 445T292 491T315 537Q317 546 317 574V587Q317 604 315 615T304 640T277 661T226 668ZM162 61Q162 89 180 105T224 121Q247 119 264 104T281 61Q281 31 264 16T222 1Q197 1 180 16T162 61Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1416,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(3568.1,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2739.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(3517.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g></g></g></g><g data-mml-node="mo" transform="translate(31292.3,0) translate(0 250)"></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtext>abs</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing=".2em"><mtr><mtd><mi>x</mi><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>≥</mo><mn>0</mn></mtd></mtr><mtr><mtd><mn>1</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mo>−</mo><mn>1</mn></mtd></mtr><mtr><mtd><mn>2</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mo>−</mo><mn>2</mn></mtd></mtr><mtr><mtd><mrow data-mjx-texclass="ORD"><mo>⋮</mo></mrow></mtd></mtr><mtr><mtd><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>2</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>+</mo><mn>2</mn></mtd></mtr><mtr><mtd><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>1</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>+</mo><mn>1</mn><mtext> (note: </mtext><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>1</mn><mtext> is maximum signed 32-bit integer)</mtext></mtd></mtr><mtr><mtd><mo>?</mo><mo>?</mo><mo>?</mo><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE" fence="true" stretchy="true" symmetric="true"></mo></mrow></math></mjx-assistive-mml></mjx-container><p>That “???” is because <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: 0;" xmlns="http://www.w3.org/2000/svg" width="2.919ex" height="1.887ex" role="img" focusable="false" viewBox="0 -833.9 1290.1 833.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup></math></mjx-assistive-mml></mjx-container> can’t be represented as a signed 32-bit integer, yet <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="9.72ex" height="2.452ex" role="img" focusable="false" viewBox="0 -833.9 4296.1 1083.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1056,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1450,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1839,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(2617,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(3907.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>abs</mtext><mo stretchy="false">(</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> needs to equal <em>something</em>. Strictly following our earlier definition of <code>abs</code>, we’d try to negate it anyways. By a <a href="https://en.wikipedia.org/wiki/Two's_complement#Most_negative_number" title="Wikipedia: Two's complement (The most negative number)">cruel trick of binary arithmetic</a>, we get <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="15.895ex" height="2.452ex" role="img" focusable="false" viewBox="0 -833.9 7025.8 1083.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(778,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1167,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(1945,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(3235.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3901.9,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4957.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(5735.7,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo>−</mo><mo stretchy="false">(</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo stretchy="false">)</mo><mo>=</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup></math></mjx-assistive-mml></mjx-container>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/F5kop3qCOb-690.avif 690w, https://geekshavefeelings.com/img/F5kop3qCOb-1380.avif 1380w, https://geekshavefeelings.com/img/F5kop3qCOb-2560.avif 2560w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/F5kop3qCOb-690.webp 690w, https://geekshavefeelings.com/img/F5kop3qCOb-1380.webp 1380w, https://geekshavefeelings.com/img/F5kop3qCOb-2560.webp 2560w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/F5kop3qCOb-690.jpeg 690w, https://geekshavefeelings.com/img/F5kop3qCOb-1380.jpeg 1380w, https://geekshavefeelings.com/img/F5kop3qCOb-2560.jpeg 2560w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Damn it abs. You had one job!" src="https://geekshavefeelings.com/img/F5kop3qCOb-690.jpeg" width="2560" height="1920"></picture></figure><p></p>
<p>Well isn't that just great? Because there are <em>more negative numbers</em> than positive numbers in conventional computer integer math, it's <em>impossible</em> to define an absolute value function where negative inputs always turn into their positive counterparts. This inescapable consequence of including zero in a number system (binary) that has equal quantities of even and odd numbers always bothered me.</p>
<p>Now that I’ve rocked your world, what am I going to do about it? Well… I can’t fix <code>abs</code>. Sorry. But, I can raise awareness!</p>
<p>No wait, I got it. Real talk: we’re gonna use negative absolute value, or <code>nabs</code> from now on. It’s like upside-down <code>abs</code>; it takes in integers and negates the positive ones. Check it:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.148ex;" xmlns="http://www.w3.org/2000/svg" width="55.844ex" height="5.428ex" role="img" focusable="false" viewBox="0 -1449.5 24682.9 2399" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(556,0)" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(1056,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1612,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2006,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2395,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2967,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3633.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(4689.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="7B" d="M618 -943L612 -949H582L568 -943Q472 -903 411 -841T332 -703Q327 -682 327 -653T325 -350Q324 -28 323 -18Q317 24 301 61T264 124T221 171T179 205T147 225T132 234Q130 238 130 250Q130 255 130 258T131 264T132 267T134 269T139 272T144 275Q207 308 256 367Q310 436 323 519Q324 529 325 851Q326 1124 326 1154T332 1205Q369 1358 566 1443L582 1450H612L618 1444V1429Q618 1413 616 1411L608 1406Q599 1402 585 1393T552 1372T515 1343T479 1305T449 1257T429 1200Q425 1180 425 1152T423 851Q422 579 422 549T416 498Q407 459 388 424T346 364T297 318T250 284T214 264T197 254L188 251L205 242Q290 200 345 138T416 3Q421 -18 421 -48T423 -349Q423 -397 423 -472Q424 -677 428 -694Q429 -697 429 -699Q434 -722 443 -743T465 -782T491 -816T519 -845T548 -868T574 -886T595 -899T610 -908L616 -910Q618 -912 618 -928V-943Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(750,0)"><g data-mml-node="mtr" transform="translate(0,600)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1350,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(2628,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3E" d="M84 520Q84 528 88 533T96 539L99 540Q106 540 253 471T544 334L687 265Q694 260 694 250T687 235Q685 233 395 96L107 -40H101Q83 -38 83 -20Q83 -19 83 -17Q82 -10 98 -1Q117 9 248 71Q326 108 378 132L626 250L378 368Q90 504 86 509Q84 513 84 520Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(3239.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(1362,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1612,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2112,0)" style="stroke-width: 3;"></path><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2501,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3057,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3501,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(3893,0)" style="stroke-width: 3;"></path><path data-c="77" d="M90 368Q84 378 76 380T40 385H18V431H24L43 430Q62 430 84 429T116 428Q206 428 221 431H229V385H215Q177 383 177 368Q177 367 221 239L265 113L339 328L333 345Q323 374 316 379Q308 384 278 385H258V431H264Q270 428 348 428Q439 428 454 431H461V385H452Q404 385 404 369Q404 366 418 324T449 234T481 143L496 100L537 219Q579 341 579 347Q579 363 564 373T530 385H522V431H529Q541 428 624 428Q692 428 698 431H703V385H697Q696 385 691 385T682 384Q635 377 619 334L559 161Q546 124 528 71Q508 12 503 1T487 -11H479Q460 -11 456 -4Q455 -3 407 133L361 267Q359 263 266 -4Q261 -11 243 -11H238Q225 -11 220 -3L90 368Z" transform="translate(4143,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(4865,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5365,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(5757,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(6313,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(6707,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(10196.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11046.3,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11991.1,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(12380.1,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12880.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(13324.8,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(14837.1,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(15837.3,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(16337.3,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-683.9)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(572,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(2628,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(3239.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(528,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(1362,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(1612,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(2112,0)" style="stroke-width: 3;"></path><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2501,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(3057,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3501,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(3893,0)" style="stroke-width: 3;"></path><path data-c="77" d="M90 368Q84 378 76 380T40 385H18V431H24L43 430Q62 430 84 429T116 428Q206 428 221 431H229V385H215Q177 383 177 368Q177 367 221 239L265 113L339 328L333 345Q323 374 316 379Q308 384 278 385H258V431H264Q270 428 348 428Q439 428 454 431H461V385H452Q404 385 404 369Q404 366 418 324T449 234T481 143L496 100L537 219Q579 341 579 347Q579 363 564 373T530 385H522V431H529Q541 428 624 428Q692 428 698 431H703V385H697Q696 385 691 385T682 384Q635 377 619 334L559 161Q546 124 528 71Q508 12 503 1T487 -11H479Q460 -11 456 -4Q455 -3 407 133L361 267Q359 263 266 -4Q261 -11 243 -11H238Q225 -11 220 -3L90 368Z" transform="translate(4143,0)" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(4865,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5365,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(5757,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(6313,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(6707,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(10196.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11046.3,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(11991.1,0)"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12269.1,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(13047.1,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(14337.2,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(14781.9,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(15281.9,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(19993.3,0) translate(0 250)"></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtext>nabs</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing=".2em"><mtr><mtd><mo>−</mo><mi>x</mi><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>></mo><mn>0</mn><mtext>, in other words </mtext><mi>x</mi><mo>∈</mo><mo stretchy="false">(</mo><mn>0</mn><mo>,</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo></mtd></mtr><mtr><mtd><mi>x</mi><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>≤</mo><mn>0</mn><mtext>, in other words </mtext><mi>x</mi><mo>∈</mo><mo stretchy="false">[</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>,</mo><mn>0</mn><mo stretchy="false">]</mo></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE" fence="true" stretchy="true" symmetric="true"></mo></mrow></math></mjx-assistive-mml></mjx-container><p>BOOM. Positive integers map to their negatives, and negative integers stay where they are. Check it:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -8.165ex;" xmlns="http://www.w3.org/2000/svg" width="35.468ex" height="17.461ex" role="img" focusable="false" viewBox="0 -4108.9 15676.8 7717.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(556,0)" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(1056,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1612,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2006,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2395,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2967,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3633.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(4689.6,0)"><g data-mml-node="mo"><path data-c="23A7" d="M712 899L718 893V876V865Q718 854 704 846Q627 793 577 710T510 525Q510 524 509 521Q505 493 504 349Q504 345 504 334Q504 277 504 240Q504 -2 503 -4Q502 -8 494 -9T444 -10Q392 -10 390 -9Q387 -8 386 -5Q384 5 384 230Q384 262 384 312T383 382Q383 481 392 535T434 656Q510 806 664 892L677 899H712Z" transform="translate(0,3209.9)" style="stroke-width: 3;"></path><path data-c="23A9" d="M718 -893L712 -899H677L666 -893Q542 -825 468 -714T385 -476Q384 -466 384 -282Q384 3 385 5L389 9Q392 10 444 10Q486 10 494 9T503 4Q504 2 504 -239V-310V-366Q504 -470 508 -513T530 -609Q546 -657 569 -698T617 -767T661 -812T699 -843T717 -856T718 -876V-893Z" transform="translate(0,-2709.9)" style="stroke-width: 3;"></path><path data-c="23A8" d="M389 1159Q391 1160 455 1160Q496 1160 498 1159Q501 1158 502 1155Q504 1145 504 924Q504 691 503 682Q494 549 425 439T243 259L229 250L243 241Q349 175 421 66T503 -182Q504 -191 504 -424Q504 -600 504 -629T499 -659H498Q496 -660 444 -660T390 -659Q387 -658 386 -655Q384 -645 384 -425V-282Q384 -176 377 -116T342 10Q325 54 301 92T255 155T214 196T183 222T171 232Q170 233 170 250T171 268Q171 269 191 284T240 331T300 407T354 524T383 679Q384 691 384 925Q384 1152 385 1155L389 1159Z" transform="translate(0,0)" style="stroke-width: 3;"></path><svg width="889" height="2239.9" y="1060" x="0" viewBox="0 394.7 889 2239.9"><path data-c="23AA" d="M384 150V266Q384 304 389 309Q391 310 455 310Q496 310 498 309Q502 308 503 298Q504 283 504 150Q504 32 504 12T499 -9H498Q496 -10 444 -10T390 -9Q386 -8 385 2Q384 17 384 150Z" transform="scale(1,11.016)" style="stroke-width: 3;"></path></svg><svg width="889" height="2239.9" y="-2799.9" x="0" viewBox="0 394.7 889 2239.9"><path data-c="23AA" d="M384 150V266Q384 304 389 309Q391 310 455 310Q496 310 498 309Q502 308 503 298Q504 283 504 150Q504 32 504 12T499 -9H498Q496 -10 444 -10T390 -9Q386 -8 385 2Q384 17 384 150Z" transform="scale(1,11.016)" style="stroke-width: 3;"></path></svg></g><g data-mml-node="mtable" transform="translate(889,0)"><g data-mml-node="mtr" transform="translate(0,3358.9)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(572,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(5068.6,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,2158.9)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1278,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(5068.6,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,958.9)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1278,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(5068.6,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2739.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-791.1)"><g data-mml-node="mtd"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="22EE" d="M78 30Q78 54 95 72T138 90Q162 90 180 74T199 31Q199 6 182 -12T139 -30T96 -13T78 30ZM78 440Q78 464 95 482T138 500Q162 500 180 484T199 441Q199 416 182 398T139 380T96 397T78 440ZM78 840Q78 864 95 882T138 900Q162 900 180 884T199 841Q199 816 182 798T139 780T96 797T78 840Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mtr" transform="translate(0,-2075)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(778,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(2290.3,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3290.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3790.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(5068.6,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(2739.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4029.7,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(4529.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-3358.9)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(778,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(2290.3,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3290.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3790.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(5068.6,0)"><g data-mml-node="mtext"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" transform="translate(278,0)" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(584,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1683.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(2739.6,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4029.7,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(4529.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(10987.2,0) translate(0 250)"></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtext>nabs</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing=".2em"><mtr><mtd><mi>x</mi><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>≤</mo><mn>0</mn></mtd></mtr><mtr><mtd><mo>−</mo><mn>1</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mn>1</mn></mtd></mtr><mtr><mtd><mo>−</mo><mn>2</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><mn>2</mn></mtd></mtr><mtr><mtd><mrow data-mjx-texclass="ORD"><mo>⋮</mo></mrow></mtd></mtr><mtr><mtd><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>+</mo><mn>2</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>2</mn></mtd></mtr><mtr><mtd><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mo>+</mo><mn>1</mn><mo>,</mo></mtd><mtd><mtext>if </mtext><mi>x</mi><mo>=</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>31</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>1</mn></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE" fence="true" stretchy="true" symmetric="true"></mo></mrow></math></mjx-assistive-mml></mjx-container><p>See? No problems. Now you hate yourself for ever using <code>abs</code>. Here, have a documented branch-free implementation on me.</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">/* SPDX-License-Identifier: MIT OR Apache-2.0 */</span>
<span class="token comment">/**
* Negative absolute value. Used to avoid undefined behavior for most negative
* integer (see C99 standard 7.20.6.1.2 and footnote 265 for the description of
* abs/labs/llabs behavior).
*
* @param i 32-bit signed integer
* @return negative absolute value of i; defined for all values of i
*/</span>
<span class="token keyword">int32_t</span> <span class="token function">nabs</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span> i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">if</span> <span class="token expression"><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int32_t</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span></span></span>
<span class="token comment">// signed right shift sign-extends (arithmetic)</span>
<span class="token keyword">const</span> <span class="token keyword">int32_t</span> negSign <span class="token operator">=</span> <span class="token operator">~</span><span class="token punctuation">(</span>i <span class="token operator">>></span> <span class="token number">31</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// splat sign bit into all 32 and complement</span>
<span class="token comment">// if i is positive (negSign is -1), xor will invert i and sub will add 1</span>
<span class="token comment">// otherwise i is unchanged</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>i <span class="token operator">^</span> negSign<span class="token punctuation">)</span> <span class="token operator">-</span> negSign<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">else</span></span>
<span class="token keyword">return</span> i <span class="token operator"><</span> <span class="token number">0</span> <span class="token operator">?</span> i <span class="token operator">:</span> <span class="token operator">-</span>i<span class="token punctuation">;</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">endif</span></span>
<span class="token punctuation">}</span></code></pre>
<p>But wait, you say. How do I use this pizza shate function in my code? It gives me nasty nelly negative numbers! WHAT I DO HERE LOL.</p>
<p>No worries! Think about when you normally use absolute value. Maybe you’re <a href="http://codepad.org/p2xBDN7B" title="codepad.org example for abs usage">comparing the magnitude</a> of some possibly negative number with a constant?</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">const</span> <span class="token keyword">int</span> a <span class="token operator">=</span> <span class="token number">51</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> b <span class="token operator">=</span> <span class="token number">85</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">abs</span><span class="token punctuation">(</span>a <span class="token operator">-</span> b<span class="token punctuation">)</span> <span class="token operator"><</span> <span class="token number">100</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> <span class="token string">"a and b are within 100 of each other."</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>This works just as well with our bulletproof <code>nabs</code>. <a href="http://codepad.org/zvoqQcYh" title="codepad.org example for nabs usage">Just negate the constant and flip the logic</a>!</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">nabs</span><span class="token punctuation">(</span>a <span class="token operator">-</span> b<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token operator">-</span><span class="token number">100</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
std<span class="token double-colon punctuation">::</span>cout <span class="token operator"><<</span> <span class="token string">"a and b are within 100 of each other."</span> <span class="token operator"><<</span> std<span class="token double-colon punctuation">::</span>endl<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Or maybe you’re <a href="http://en.wikipedia.org/wiki/Sum_of_absolute_differences" title="Wikipedia: Sum of absolute differences">computing SAD</a> on some pixels?</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int</span> sad <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> size<span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
sad <span class="token operator">+=</span> <span class="token function">abs</span><span class="token punctuation">(</span>p1<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">-</span> p2<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>You could instead flip the sign and use <code>nabs</code>!</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int</span> sad <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> size<span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
sad <span class="token operator">-=</span> <span class="token function">nabs</span><span class="token punctuation">(</span>p1<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">-</span> p2<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>To be fair, this specific example didn’t fix the overflow problem. See, the only case for which <code>abs</code> and <code>nabs</code> are different is with <code>INT_MIN</code>. However, the expressions <code>sad + abs(INT_MIN)</code> and <code>sad - nabs(INT_MIN)</code> are actually equivalent.</p>
<p><a href="http://flickr.com/photos/aduki/340003201/"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ByGRZ8iO5l-690.avif 690w, https://geekshavefeelings.com/img/ByGRZ8iO5l-1380.avif 1380w, https://geekshavefeelings.com/img/ByGRZ8iO5l-2520.avif 2520w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ByGRZ8iO5l-690.webp 690w, https://geekshavefeelings.com/img/ByGRZ8iO5l-1380.webp 1380w, https://geekshavefeelings.com/img/ByGRZ8iO5l-2520.webp 2520w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ByGRZ8iO5l-690.jpeg 690w, https://geekshavefeelings.com/img/ByGRZ8iO5l-1380.jpeg 1380w, https://geekshavefeelings.com/img/ByGRZ8iO5l-2520.jpeg 2520w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="OK, maybe not that kind of sad." src="https://geekshavefeelings.com/img/ByGRZ8iO5l-690.jpeg" width="2520" height="1531"></picture></figure></a></p>
<p>Nevertheless, there are cases when this is useful. In this case, SAD is frequently computed on 8-bit pixels using a 16- or 32-bit accumulator for the difference. So our <code>nabs</code> function would be for 8-bit integers, and <code>sad + abs_8(CHAR_MIN)</code> and <code>sad - nabs_8(CHAR_MIN)</code> would certainly not be equivalent. See?</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int8_t</span> <span class="token function">abs_8</span><span class="token punctuation">(</span><span class="token keyword">int8_t</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int8_t</span> <span class="token function">nabs_8</span><span class="token punctuation">(</span><span class="token keyword">int8_t</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> sum <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
sum <span class="token operator">+=</span> <span class="token function">abs_8</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">128</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// WRONG: this is like subtracting 128 from sad</span>
sum <span class="token operator">-=</span> <span class="token function">nabs_8</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">128</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// RIGHT: this is like adding 128 to sad</span></code></pre>
<p>Don’t forget about embedded systems coding either: on microcontrollers, you’ll use values of different bit widths all the time. What’s more, the signals coming in from ADCs and timer captures can be highly dynamic, often changing non-deterministically. As in all cases when you can’t predict the inputs to your program, it’s critical to use robust routines like <code>nabs</code> to safeguard your robot or device from math errors.</p>
<h2 id="avg" tabindex="-1">avg <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/">§</a></h2>
<p>Oh look, I ran out of words. I guess I’ll have to post about overflow-safe, rounding-correct <code>avg</code> next time! Your broken mergesort will just have to wait. 🙁</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf">C99 standard</a> §7.20.6.1 ¶2 and footnote 265 <a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>The ++ in C++ is for extra verbosity. <a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Why Microsoft’s 3D Printing Rocks
2013-06-29T22:24:19Z
https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/G5TCfCbY1f-690.avif 690w, https://geekshavefeelings.com/img/G5TCfCbY1f-1024.avif 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/G5TCfCbY1f-690.webp 690w, https://geekshavefeelings.com/img/G5TCfCbY1f-1024.webp 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/G5TCfCbY1f-690.png 690w, https://geekshavefeelings.com/img/G5TCfCbY1f-1024.png 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Windows-3DP" src="https://geekshavefeelings.com/img/G5TCfCbY1f-690.png" width="1024" height="576"></picture></figure><p></p>
<p>Microsoft has just made its mark on 3D printing with its announcement of built-in support for <a href="http://www.microsoft.com/3d" title="Microsoft 3D printing">3D printing in Windows 8.1</a>. Now I don’t usually do blog posts like this where I pretend to keep up with news, but I see nothing but hollow rehashes (actual headline: “Microsoft Moves to Simplify 3-D Printing”) and vaguely 3D printing related filler (<a href="http://www.publicknowledge.org/blog/legislating-headlines-makes-you-look-jerk" title="Thanks for not being a jerk, Councilman Dan Halloran /s">LOL GUNZ</a>) on the tech pop media about this story.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/8w_oYyiTUa-690.avif 690w, https://geekshavefeelings.com/img/8w_oYyiTUa-1206.avif 1206w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/8w_oYyiTUa-690.webp 690w, https://geekshavefeelings.com/img/8w_oYyiTUa-1206.webp 1206w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/8w_oYyiTUa-690.png 690w, https://geekshavefeelings.com/img/8w_oYyiTUa-1206.png 1206w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="NYT-screenshot" src="https://geekshavefeelings.com/img/8w_oYyiTUa-690.png" width="1206" height="1596"></picture></figure><p></p>
<p>Heck, even <a href="http://blogs.technet.com/b/microsoft_blog/archive/2013/06/26/3d-printing-with-windows.aspx" title="TechNet blog">Microsoft’s own blog post from a general manager</a> is 100% devoid of information on what they’ve introduced. That’s a real shame, because the new Windows components advance the 3D printing field by quite a bit while fixing many of the glaring technical issues.</p>
<h2 id="hotfix" tabindex="-1">Hotfix <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/">§</a></h2>
<p>Before I jump into what the Microsoft announcement is about and why I think it’s great, I want to address a couple of couple of knee-jerk opinions about the story I saw stated as fact.</p>
<ul>
<li><strong>Microsoft “simplified” 3D printing</strong>… in the sense that it’ll be easier for Joe Sixpack to buy a retail boxed printer and hit “print” from Windows applications to print parts. However, what they’ve done is actually added <em>more</em> steps in the 3D printing chain—but that’s a good thing. I’ll get to why in just a second. <figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/DICNaymfHL-690.avif 690w, https://geekshavefeelings.com/img/DICNaymfHL-1024.avif 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/DICNaymfHL-690.webp 690w, https://geekshavefeelings.com/img/DICNaymfHL-1024.webp 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/DICNaymfHL-690.png 690w, https://geekshavefeelings.com/img/DICNaymfHL-1024.png 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Microsoft-pipeline" src="https://geekshavefeelings.com/img/DICNaymfHL-690.png" width="1024" height="576"></picture></figure></li>
<li><strong>Windows 8.1’s 3D printing support tries to supplant preprocessors and printing hosts by developers</strong>. Nope. Instead it creates a framework around the existing slicers and printer hosts (for example Slic3r and Repetier-Host, two software packages we use in the Georgia Tech Invention Studio for RepRap-based printers), which abstracts away their operational details. This means that all printers will have a common Microsoft-designed software interface for getting printed to, and that’s great for developers. However, it’s still up to manufacturers to actually write drivers within this framework.</li>
<li><strong>Microsoft is making a move into 3D printing</strong>. Technically they <em>are</em>, but they’re not building 3D printers and they don’t appear to be affiliated with any one manufacturer. They also don’t appear to be abandoning open source either; if anything, inclusion of the open source printers seems to be a priority for even the first release, as <a href="http://channel9.msdn.com/Events/Build/2013/3-9027#c635079142971349775" title="Mr. Iverson's comment about RepRap printers">they had a demo</a> with a <a href="http://typeamachines.com" title="Type A Machines">Type A printer</a> at the San Francisco event. As I mentioned, their new components don’t replace anything already on the market; they’re building around, not in, the existing structures. I think their “move” here is a land grab as the first platform to have meaningful standards and support for 3D printing. If played right, that will then make them <em>the</em> 3D printing platform (not that that’s a good thing).</li>
</ul>
<p>I should also note that I am neither a Microsoft apologist (I prepare presentations in Keynote for crying out loud) nor a 3D printing fanboy (I instinctively assault anyone who uses the term “desktop manufacturing revolution” unironically). It’s just that people on the Internet were wrong and I had to correct them.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/2_hNP4MGCE-690.avif 690w, https://geekshavefeelings.com/img/2_hNP4MGCE-1380.avif 1380w, https://geekshavefeelings.com/img/2_hNP4MGCE-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/2_hNP4MGCE-690.webp 690w, https://geekshavefeelings.com/img/2_hNP4MGCE-1380.webp 1380w, https://geekshavefeelings.com/img/2_hNP4MGCE-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/2_hNP4MGCE-690.jpeg 690w, https://geekshavefeelings.com/img/2_hNP4MGCE-1380.jpeg 1380w, https://geekshavefeelings.com/img/2_hNP4MGCE-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="GTIS does lots of printing" src="https://geekshavefeelings.com/img/2_hNP4MGCE-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Also, my experience with 3D printing comes from my time helping to run the <a href="http://inventionstudio.org" title="GT Invention Studio">Georgia Tech Invention Studio</a>. As students, we maintain a fleet of 14 3D printers, including open-source printers like RepRap variants, MakerBot junk, and Afinia/Up bots, as well as professional printers from Objet and Stratasys. These get (ab)used almost 24/7 in incredible volume by students and faculty (the hobby printers are free to use) and we’re even developing custom hardware and software for them, so please remember I’m talking as little out of my ass as I can.</p>
<p>Now let’s get to some of the innovations that Microsoft introduced and the problems they solved.</p>
<h2 id="deciphering-the-news" tabindex="-1">Deciphering the News <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/">§</a></h2>
<p>Keep in mind that most of my information here is gleaned off of the 30 seconds of concrete information in the <a href="http://channel9.msdn.com/Events/Build/2013/3-9027" title="3D Printing with Windows">16:21 video</a> and some <a href="http://code.msdn.microsoft.com/windowsapps/3D-Printing-Sample-b5b75c86" title="3D Printing Sample (Windows 8.1)">C++ SDK samples</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/iVmpp8BIu2-690.avif 690w, https://geekshavefeelings.com/img/iVmpp8BIu2-1024.avif 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/iVmpp8BIu2-690.webp 690w, https://geekshavefeelings.com/img/iVmpp8BIu2-1024.webp 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/iVmpp8BIu2-690.png 690w, https://geekshavefeelings.com/img/iVmpp8BIu2-1024.png 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="SampleCode-screenshot" src="https://geekshavefeelings.com/img/iVmpp8BIu2-690.png" width="1024" height="576"></picture></figure><p></p>
<p>But here’s what I think are their biggest innovations in 3D printing:</p>
<ul>
<li>A new <strong>software interface for printing 3D models from applications</strong> and a <strong>framework for 3D printer drivers</strong>. This means there’s now a standard way for software to pass 3D models as jobs to 3D printers, as well as a standard that 3D printing software chains will conform to. This solves the problem of getting an application to programmatically start a print job. We’re pretty familiar with that problem at the Invention Studio; our printers—Lulzbot AO-101s, Makerbot Replicators 2, Afinia H-Series—each have different APIs for printing to them, and it makes software automation a complete pain of a task to tackle.</li>
<li><strong>Standard 3D model interchange format</strong> designed especially for 3D printing. This is a big deal if only because the current standard format, STL, sucks (and somehow it is standard; even our Stratasys and Objet professional 3D printers use it). The <a href="http://download.microsoft.com/download/C/6/C/C6C3C6F1-E84A-44EF-82A9-49BD3AAD8F58/Windows/MS-TDPRP.pdf" title="3D Manufacturing Format specification">new format that Microsoft is calling 3MF</a> (“3D manufacturing format”) is quite neat: it’s still a mesh-based format (to be practical), but it supports specifying different materials for each volume, as well as supporting color textures (for coloring surfaces). STL, meanwhile, can’t even specify that two faces in a mesh are adjacent to each other.</li>
<li><strong>Print spooler for 3D printer jobs</strong>. The new print spooler is a part of Windows that sits between applications spitting out 3D print jobs and the printer-specific drivers. It serves as a purgatorial buffer for yet-unrealized print jobs that haven’t been processed/sliced/sent off to a machine. You already have a 2D print spooler now that lets you print off 2D documents for 2D printers, without even having any such said 2D printer connected.</li>
<li><strong>Support for 3D printers using a USB printer interface</strong>. I’m not a big USB or drivers person, so I’m not able to expound on whether using the “class 7, type 3” interface<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/" id="fnref1">*</a></sup> was the right choice. However, I heartily support their view of serial over USB<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/" id="fnref2">†</a></sup> as a “legacy” interface. That truly is the legacy of 3D printer designs relying too much on every part of the underendowed Arduino for their brains. Arduino’s use of COM ports may be convenient for a quick and dirty prototype, but I can’t believe folks are selling products that use it. I’m glad somebody at Microsoft agrees and is taking a step away from that awfulness. <figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Yb6ckLCPcD-690.avif 690w, https://geekshavefeelings.com/img/Yb6ckLCPcD-1024.avif 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Yb6ckLCPcD-690.webp 690w, https://geekshavefeelings.com/img/Yb6ckLCPcD-1024.webp 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/Yb6ckLCPcD-690.png 690w, https://geekshavefeelings.com/img/Yb6ckLCPcD-1024.png 1024w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Microsoft-hardware-support" src="https://geekshavefeelings.com/img/Yb6ckLCPcD-690.png" width="1024" height="576"></picture></figure></li>
</ul>
<p>Normally I’m not down for ending a post with Silicon Valley-esque last-paragraph upturn in optimism (what is this, a <a href="http://qr.ae/p6tMB" title="What's the dark side of Silicon Valley?">Quora answer</a>?), but I really do believe that this is a huge step forward in 3D printing, injecting a direly needed infusion of professional engineering into a community dominated by part-time hobbyists struggling to develop complete products. I really want reliable, well-designed 3D printing software platforms to succeed so we can get on with developing actual advances in printing technology, and it’s great to see a big player like Microsoft making that move.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>1284.4 compatible bi-directional interface: <a href="http://www.usb.org/developers/devclass_docs/usbprint11.pdf" title="Universal Serial Bus Device Class Definition for Printing Devices">http://www.usb.org/developers/devclass_docs/usbprint11.pdf</a> <a href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Communication device class: <a href="http://www.usb.org/developers/devclass_docs/usbcdc11.pdf" title="Universal Serial Bus Class Definitions for Communication Devices">http://www.usb.org/developers/devclass_docs/usbcdc11.pdf</a> <a href="https://geekshavefeelings.com/posts/2013/why-microsofts-3d-printing-rocks/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Flapjack Stator Thoughts
2013-03-04T10:34:46Z
https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/
<p><em>WARNING: THIS POST CONTAINS EXTREMELY SHADY ENGINEERING. HOLD NO ILLUSIONS ABOUT THE LEGITIMACY OF THE FIGURES AND METHODS. DO NOT TRY THIS AT HOME.</em></p>
<p>I’ve been thinking about alternatives in constructing the stator for <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack" title="Delicious Axial Flux Flapjack">Flapjack, my latest 3 lb R/C combat bot</a>, besides milling it out of 5 oz copper-clad circuit board material. I think I can wind coils that would be epoxied into the cutouts on a stator retainer plate like this one:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/QYzd2DEEH4-690.avif 690w, https://geekshavefeelings.com/img/QYzd2DEEH4-1380.avif 1380w, https://geekshavefeelings.com/img/QYzd2DEEH4-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/QYzd2DEEH4-690.webp 690w, https://geekshavefeelings.com/img/QYzd2DEEH4-1380.webp 1380w, https://geekshavefeelings.com/img/QYzd2DEEH4-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/QYzd2DEEH4-690.png 690w, https://geekshavefeelings.com/img/QYzd2DEEH4-1380.png 1380w, https://geekshavefeelings.com/img/QYzd2DEEH4-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Stator coil retainer plate" src="https://geekshavefeelings.com/img/QYzd2DEEH4-690.png" width="1920" height="1200"></picture></figure><p></p>
<h2 id="physical-fit" tabindex="-1">Physical fit <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/">§</a></h2>
<p>The retainer is cut out of 1/8 in thick polycarbonate, and my windings would be four strands of 22 AWG magnet wire with double-thickness enamel. That would be 4 × 0.0276 in = 0.110 in tall within the cutout, save for the terminal of the coil which needs to come out somewhere, which makes this a 5 × 0.0276 in = <strong>0.138 in</strong> overall height coil. If I file some away some indents in plastic between windings, then they stick just 13 mil out of the retainer. Overall, there’s a hair<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/" id="fnref1">*</a></sup> shy of <strong>1/16 in</strong> of clearance on either side of the stator with respect to the magnets on the stator.</p>
<p>I’m concerned that a vertical strike to the weapon can deform the mild steel rotor plates more than that and cause the magnets and magnet retainers to rub against the stator assembly.</p>
<h2 id="weight" tabindex="-1">Weight <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/">§</a></h2>
<p>To save weight and to increase Kv, I would use seven turns in each coil, versus the eight on the P.S. WTFLOLs. This should have less effect on the motor than it initially appears, as each loop of the wire coils is significantly larger (on average) than the spiraling trace coils in the P.S. WTFLOL.</p>
<p>Generously speaking, each turn of this coil is, on average, 3.0 in of wire (the perimeter of the cutout is about 3.4 in while the innermost loop will be just 2.6 in in perimeter).</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.727ex;" xmlns="http://www.w3.org/2000/svg" width="54.234ex" height="6.392ex" role="img" focusable="false" viewBox="0 -1620 23971.3 2825.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mrow" transform="translate(220,760)"><g data-mml-node="mpadded"><g data-mml-node="mrow"></g></g><g data-mml-node="mstyle"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1667,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(2973.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3973.4,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4473.4,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(389,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(945,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1337,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1893,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(7232.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(8232.9,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(8732.9,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(9816.9,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10428.1,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(11428.3,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(12428.3,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(944,0)" style="stroke-width: 3;"></path><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1222,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1500,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(14794.6,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(15794.8,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(16294.8,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(394,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(783,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1175,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1675,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(2231,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2787,0)" style="stroke-width: 3;"></path></g></g></g></g></g><g data-mml-node="mrow" transform="translate(8304,-852.5)"><g data-mml-node="mpadded"><g data-mml-node="mrow"></g></g><g data-mml-node="mstyle"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(2278,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2528,0)"><g data-mml-node="TeXAtom" transform="translate(269.1,394) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(306,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="TeXAtom" transform="translate(220,-345) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(278,0)" style="stroke-width: 3;"></path></g></g><rect width="789.7" height="60" x="120" y="220"></rect></g></g></g></g><rect width="19925.8" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(20443.6,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(21499.3,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(22777.3,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" style="stroke-width: 3;"></path><path data-c="7A" d="M42 263Q44 270 48 345T53 423V431H393Q399 425 399 415Q399 403 398 402L381 378Q364 355 331 309T265 220L134 41L182 40H206Q254 40 283 46T331 77Q352 105 359 185L361 201Q361 202 381 202H401V196Q401 195 393 103T384 6V0H209L34 1L31 3Q28 8 28 17Q28 30 29 31T160 210T294 394H236Q169 393 152 388Q127 382 113 367Q89 344 82 264V255H42V263Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mfrac><mrow><mpadded height="8.6pt" depth="3pt" width="0"><mrow></mrow></mpadded><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mo stretchy="false">(</mo><mn>3.0</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">in</mi></mrow><mo>×</mo><mn>7</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">turns</mi></mrow><mo>+</mo><mn>2</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">in</mi></mrow><mo stretchy="false">)</mo><mo>×</mo><mn>12</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">coils</mi></mrow><mo>×</mo><mn>4</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">strands</mi></mrow></mrow></mstyle></mrow><mrow><mpadded height="8.6pt" depth="3pt" width="0"><mrow></mrow></mpadded><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mn>501.5</mn><mtext> </mtext><mfrac><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">ft</mi></mrow><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">lb</mi></mrow></mfrac></mrow></mstyle></mrow></mfrac><mo>=</mo><mn>2.9</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">oz</mi></mrow></math></mjx-assistive-mml></mjx-container><p>Now, I’ve got about 3.5 oz of weight to spend on the stator excluding fasteners, so with the polycarbonate retainers at 0.18 oz each, that leaves me with a quarter ounce of epoxy and tape to secure and insulate the coils with. That seems shady<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/" id="fnref2">†</a></sup>; I might drop down to six turns or three strands in order to make weight.</p>
<h2 id="resistance" tabindex="-1">Resistance <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/">§</a></h2>
<p>Now for the whole point of moving to wire-wound coils: lower resistance.</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.534ex;" xmlns="http://www.w3.org/2000/svg" width="65.062ex" height="6.389ex" role="img" focusable="false" viewBox="0 -1703.9 28757.3 2823.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1667,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(2973.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3973.4,0)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4473.4,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(389,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(945,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1337,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1893,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(7232.7,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(8232.9,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(8732.9,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(278,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(9816.9,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10428.1,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(11428.3,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(11928.3,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(944,0)" style="stroke-width: 3;"></path><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1222,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1500,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(14294.6,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(15294.8,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(15794.8,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="70" d="M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z" style="stroke-width: 3;"></path><path data-c="68" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 124T102 167T103 217T103 272T103 329Q103 366 103 407T103 482T102 542T102 586T102 603Q99 622 88 628T43 637H25V660Q25 683 27 683L37 684Q47 685 66 686T103 688Q120 689 140 690T170 693T181 694H184V367Q244 442 328 442Q451 442 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(556,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1112,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(1612,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(2006,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2450,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(19111,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(20111.2,0)"><g data-mml-node="mrow" transform="translate(220,812.1)"><g data-mml-node="mpadded"><g data-mml-node="mrow"></g></g><g data-mml-node="mstyle"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(2278,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2528,0)"><g data-mml-node="TeXAtom" transform="translate(220,394) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(833,0)"><path data-c="3A9" d="M55 454Q55 503 75 546T127 617T197 665T272 695T337 704H352Q396 704 404 703Q527 687 596 615T666 454Q666 392 635 330T559 200T499 83V80H543Q589 81 600 83T617 93Q622 102 629 135T636 172L637 177H677V175L660 89Q645 3 644 2V0H552H488Q461 0 456 3T451 20Q451 89 499 235T548 455Q548 512 530 555T483 622T424 656T361 668Q332 668 303 658T243 626T193 560T174 456Q174 380 222 233T270 20Q270 7 263 0H77V2Q76 3 61 89L44 175V177H84L85 172Q85 171 88 155T96 119T104 93Q109 86 120 84T178 80H222V83Q206 132 162 199T87 329T55 454Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="TeXAtom" transform="translate(524.1,-345) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="66" d="M273 0Q255 3 146 3Q43 3 34 0H26V46H42Q70 46 91 49Q99 52 103 60Q104 62 104 224V385H33V431H104V497L105 564L107 574Q126 639 171 668T266 704Q267 704 275 704T289 705Q330 702 351 679T372 627Q372 604 358 590T321 576T284 590T270 627Q270 647 288 667H284Q280 668 273 668Q245 668 223 647T189 592Q183 572 182 497V431H293V385H185V225Q185 63 186 61T189 57T194 54T199 51T206 49T213 48T222 47T231 47T241 46T251 46H282V0H273Z" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(306,0)" style="stroke-width: 3;"></path></g></g><rect width="1299.6" height="60" x="120" y="220"></rect></g></g></g></g><g data-mml-node="mrow" transform="translate(288.3,-820)"><g data-mml-node="mpadded"><g data-mml-node="mrow"></g></g><g data-mml-node="mstyle"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(500,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(394,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(783,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1175,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1675,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(2231,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2787,0)" style="stroke-width: 3;"></path></g></g></g></g></g><rect width="4267.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(24896.6,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(25952.3,0)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(26952.3,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(250,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1083,0)"><path data-c="3A9" d="M55 454Q55 503 75 546T127 617T197 665T272 695T337 704H352Q396 704 404 703Q527 687 596 615T666 454Q666 392 635 330T559 200T499 83V80H543Q589 81 600 83T617 93Q622 102 629 135T636 172L637 177H677V175L660 89Q645 3 644 2V0H552H488Q461 0 456 3T451 20Q451 89 499 235T548 455Q548 512 530 555T483 622T424 656T361 668Q332 668 303 658T243 626T193 560T174 456Q174 380 222 233T270 20Q270 7 263 0H77V2Q76 3 61 89L44 175V177H84L85 172Q85 171 88 155T96 119T104 93Q109 86 120 84T178 80H222V83Q206 132 162 199T87 329T55 454Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mo stretchy="false">(</mo><mn>3.0</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">in</mi></mrow><mo>×</mo><mn>7</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">turns</mi></mrow><mo>+</mo><mn>2</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">in</mi></mrow><mo stretchy="false">)</mo><mo>×</mo><mn>4</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">coils</mi></mrow><mo>×</mo><mn>2</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">phases</mi></mrow><mo>×</mo><mfrac><mrow><mpadded height="8.6pt" depth="3pt" width="0"><mrow></mrow></mpadded><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mn>16.14</mn><mtext> </mtext><mfrac><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">m</mi><mi mathvariant="normal">Ω</mi></mrow><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">ft</mi></mrow></mfrac></mrow></mstyle></mrow><mrow><mpadded height="8.6pt" depth="3pt" width="0"><mrow></mrow></mpadded><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mn>4</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi data-mjx-auto-op="false">strands</mi></mrow></mrow></mstyle></mrow></mfrac><mo>=</mo><mn>62</mn><mrow data-mjx-texclass="ORD"><mtext> </mtext><mi mathvariant="normal">m</mi><mi mathvariant="normal">Ω</mi></mrow></math></mjx-assistive-mml></mjx-container><p>By the way, I’m adding 2 in to each coil for termination, connection to the next phase, etc. The overall phase-to-phase resistance of <strong>62 mΩ</strong> is a greater than 70% reduction in wye-terminated phase-to-phase resistance compared to the 0.226 Ω of the <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/#pmcafsms-p-s-wtflol" title="Delicious Axial Flux Flapjack">P.S. WTFLOLs</a>.</p>
<h2 id="summary" tabindex="-1">Summary <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/">§</a></h2>
<p>Using these coils would remove a big “ass” component of the permanent magnet coreless axial flux synchronous motor shell and printed spiral wound trace flux linking outer loops (PMCAFSMS, P.S. WTFLOL). Namely, I lose the P.S. WTFLOL part, but I am confident a suitable replacement acronym will come up. Moreover, a bigger proportion of the air gap between rotor sets will be filled with torque-producing copper and make for a much more powerful, efficient motor.</p>
<p>Efficiency becomes a big deal when you consider how much power needs to be dissipated from such a compact robot, and the fact that the energy onboard is limited: the ~50 kJ stored in the batteries means I can draw less than 23 W on copper heating is definitely something I worry about.</p>
<p>These windings I’m thinking of make for just <strong>6%</strong> of motor loss at 10 A × 11.1 V = 111 W input power, but that’s not including eddy current losses nor the high ripple currents sloshing around the motor due to PWM. That’s still a huge improvement over the trace windings, where that loss is <strong>20%</strong> at the same input power.</p>
<p>Eddy current losses would be much lower in comparison too, as each turn of copper is vertically oriented and separated into four conductors. However, unlike real <a href="http://en.wikipedia.org/wiki/Litz_wire" title="Litz wire at Wikipedia">litz wire</a>, these conductor sets are not twisted together. So, the slight differences in flux density axially (see <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/#pmcafsms-p-s-wtflol" title="FEMM simulation of airgap">simulation results</a>) mean that each strand produces a different EMF and that there will still some eddy currents between them.</p>
<h2 id="to-do" tabindex="-1">To do <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/">§</a></h2>
<ul>
<li>Build test jig for motor testing</li>
<li>Print a new chassis which can hold the external <a href="http://www.digikey.com/product-detail/en/IHLP6767GZER100M11/541-1286-1-ND" title="Digi-Key">big-ass ass-inductors</a> for the motor</li>
<li>Build winding tool for coils</li>
<li>Wind, compact, pot, secure, and insulate coils into stator retainer plate</li>
</ul>
<p>Wah.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Coarse East Asian hair ~170 μm thick <a href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>It’s about three post-1982 US copper-clad nickel pennies <a href="https://geekshavefeelings.com/posts/2013/flapjack-stator-thoughts/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Delicious Axial Flux Flapjack
2013-02-25T01:08:02Z
https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/
<p><em>WARNING: THIS POST CONTAINS EXTREMELY SHADY ENGINEERING. HOLD NO ILLUSIONS ABOUT THE LEGITIMACY OF THE FIGURES AND METHODS. DO NOT TRY THIS AT HOME.</em></p>
<p>We’re back to über-technical posts again. Today I’m introducing my current project, a new beetleweight (3lb) combat bot called Flapjack.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/0RNKNWqIxS-690.avif 690w, https://geekshavefeelings.com/img/0RNKNWqIxS-1380.avif 1380w, https://geekshavefeelings.com/img/0RNKNWqIxS-2843.avif 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/0RNKNWqIxS-690.webp 690w, https://geekshavefeelings.com/img/0RNKNWqIxS-1380.webp 1380w, https://geekshavefeelings.com/img/0RNKNWqIxS-2843.webp 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/0RNKNWqIxS-690.png 690w, https://geekshavefeelings.com/img/0RNKNWqIxS-1380.png 1380w, https://geekshavefeelings.com/img/0RNKNWqIxS-2843.png 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="pancake" src="https://geekshavefeelings.com/img/0RNKNWqIxS-690.png" width="2843" height="1660"></picture></figure><p></p>
<p>When complete, it will be a super-compact shell spinner where the shell is a unique brushless motor. Here’s the skinny:</p>
<ul>
<li>Shell 140 mm in diameter constructed from steel disks separated by aluminum spacers and tool steel teeth</li>
<li>Custom axial flux 3-phase brushless motor built into the shell, driven by a stator made up of spiral coil traces on printed circuit boards (PCBs)</li>
<li>Electronics package featuring High Fructose, my custom controller integrating dual brushed direct current (DC) motor drivers, a three-phase brushless motor driver, and gyroscope steering correction</li>
<li>Four Sanyo-style <a href="http://www.pololu.com/catalog/product/1093" title="30:1 Micro Metal Gearmotor HP">Pololu gearmotors</a> driving waterjet-cut ultra high molecular weight (UHMW) polyethylene wheels with neoprene tires</li>
<li>Light, compact chassis made from 3D printed ABS, waterjet-cut polycarbonate and 7075 grade aluminum</li>
<li>Lithium ion polymer battery providing up to 300 W of power</li>
</ul>
<p>After watching Dragon*Con, Atlanta Mini Maker Faire, Geek Media Expo, and now Motorama, I’ve gotten just a bit bored of ultra-destructive spinning kinetic energy weapons. Wait, nah; the weapons are always a blast to watch in the arena. What I’m really bored with are the tiny incremental tweaks made to very solid designs that make weapons and armor harder, faster, and bigger, but only in itty bitty steps that aren’t relevant to anyone but other builders.</p>
<p>If I was going to get into the battlebots game, then I wanted to build a game changer. Or at least an attempt at a facsimile of a photo of a game changer. And it’s gotta be a real crowd pleaser too; my previous bot and my first real entry into the hobby, <a href="http://aaronbot3000.blogspot.com/p/gyro-king-meltybrain-beetleweight.html" title="Gyro King at Aaron's blog">Gyro King</a>, while destructive and nearly bulletproof, was just not that interesting to watch<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref1">*</a></sup>.</p>
<p>So I figured I could either produce a cool, effective design that doesn’t use rotational kinetic energy as a weapon (very unlikely) or I could try to make a Great Leap Forward in spinner design that makes previous hard hitting bot matches look like church. While I’ve actually achieved neither of those design goals, at least I drew up something where a comically enormous proportion of the weight, power, and space budgets are reserved by a bizarre-looking shell.</p>
<p>Let’s look at a cutaway view of Flapjack.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/21yX7K1-eL-690.avif 690w, https://geekshavefeelings.com/img/21yX7K1-eL-1380.avif 1380w, https://geekshavefeelings.com/img/21yX7K1-eL-2843.avif 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/21yX7K1-eL-690.webp 690w, https://geekshavefeelings.com/img/21yX7K1-eL-1380.webp 1380w, https://geekshavefeelings.com/img/21yX7K1-eL-2843.webp 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/21yX7K1-eL-690.png 690w, https://geekshavefeelings.com/img/21yX7K1-eL-1380.png 1380w, https://geekshavefeelings.com/img/21yX7K1-eL-2843.png 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="pancake cutaway" src="https://geekshavefeelings.com/img/21yX7K1-eL-690.png" width="2843" height="1660"></picture></figure><p></p>
<p>Here you can see two of the 28 <a href="http://www.magnet4less.com/product_info.php?cPath=1_5&products_id=28" title="N48 block magnets">3/4″ × 1/2″ × 1/4″ neodymium-iron-boron (NdFeB) magnets</a> arrayed between low carbon 1018 steel plates, creating a 14-pole axial flux rotor. Also, check out the stainless steel standoffs used to support the internal chassis as well as serve as shafts for the weapon’s bearings to ride on. In addition, the shell has a <a href="http://www.vxb.com/page/bearings/PROD/Kit7278" title="VXB 5200ZZ">30mm diameter double-row angular contact bearing</a> that can take loads in axial directions (up and down in this case).</p>
<p>Nearly everything but the fasteners, standoffs, and magnets are designed for 2/3-axis waterjet cutting. The other exceptions include the lithium polymer battery (in blue), which had more or less determined the overall height and diameter of the shell. The stator (in green), a printed circuit board milled out from copper-clad fiberglass laminate, was designed to fit in the airgap of the rotor. Finally, the space inside of the chassis was filled by a 3D printed block (in yellow) holding down the gearmotors, battery, and High Fructose (not pictured).</p>
<p>Now, I was rushing (along with the rest of the Georgia Tech crew) to get Flapjack done in time for Motorama 2013, which was last weekend. And by rush, I mean I <em>really</em> beasted hardcore. High Fructose went from raw parts outta Digi-Key and PCB Unlimited to functional motor controller hooked up to a Hobby King radio set in about four days, and Flapjack went from fresh plates of material from McMaster-Carr and Online Metals to a driving 1290 g bot in about three days. Those timeframes are overlapping, too<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref2">†</a></sup>.</p>
<p>Documentation and rigor suffered. All I have to justify the designs are barely comprehensible scratches in my notebook. Almost all the hard parts were basically guesstimated. Blogging about Flapjack is my attempt to go back and legitimize some of the horribly back-of-napkinloped numbers I used. <a href="http://hellofanengineer.blogspot.com/" title="Hello Fan Engineer">Jeff</a> said it best when he pointed out that I basically built a legit-ish bot using <a href="http://www.youtube.com/watch?v=-buqqEaRkHM" title="Melty Butt">ass(bot)</a> techniques.</p>
<p>I’ll start with the glaringly obviously ass part, the permanent magnet coreless axial flux synchronous motor shell and printed spiral wound trace flux linking outer loops, known for short as</p>
<h2 id="pmcafsms-p-s-wtflol" tabindex="-1">PMCAFSMS, P.S. WTFLOL <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/OD6CamHFkU-690.avif 690w, https://geekshavefeelings.com/img/OD6CamHFkU-1380.avif 1380w, https://geekshavefeelings.com/img/OD6CamHFkU-2843.avif 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/OD6CamHFkU-690.webp 690w, https://geekshavefeelings.com/img/OD6CamHFkU-1380.webp 1380w, https://geekshavefeelings.com/img/OD6CamHFkU-2843.webp 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/OD6CamHFkU-690.png 690w, https://geekshavefeelings.com/img/OD6CamHFkU-1380.png 1380w, https://geekshavefeelings.com/img/OD6CamHFkU-2843.png 2843w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="pancake exploded" src="https://geekshavefeelings.com/img/OD6CamHFkU-690.png" width="2843" height="1660"></picture></figure><p></p>
<p>You can see in the cutaway that the rotor, while strictly speaking a shell, is designed more like a ring spinner. So, it really had to respect the outer diameter of the chassis “puck,” which was about 100mm. Given that constraint as well as the weight budget and the magnets available to me, I went with a 14-pole rotor where the lengths of the magnets were lined up tangentially.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/bXldC5FGnQ-690.avif 690w, https://geekshavefeelings.com/img/bXldC5FGnQ-1380.avif 1380w, https://geekshavefeelings.com/img/bXldC5FGnQ-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/bXldC5FGnQ-690.webp 690w, https://geekshavefeelings.com/img/bXldC5FGnQ-1380.webp 1380w, https://geekshavefeelings.com/img/bXldC5FGnQ-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/bXldC5FGnQ-690.jpeg 690w, https://geekshavefeelings.com/img/bXldC5FGnQ-1380.jpeg 1380w, https://geekshavefeelings.com/img/bXldC5FGnQ-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Two rotor plates with magnets facing "outwards" so that they press against the steel as the epoxy cures" src="https://geekshavefeelings.com/img/bXldC5FGnQ-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Sadly, I was only able to use 1/8″ of steel for my magnet back iron. According to my FEMM simulation (and real life testing), this means a few flux lines will leak out into the world, sucking up filings off of other bots and otherwise not contributing to torque production.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/8QUDru2PfK-690.avif 690w, https://geekshavefeelings.com/img/8QUDru2PfK-1380.avif 1380w, https://geekshavefeelings.com/img/8QUDru2PfK-2847.avif 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/8QUDru2PfK-690.webp 690w, https://geekshavefeelings.com/img/8QUDru2PfK-1380.webp 1380w, https://geekshavefeelings.com/img/8QUDru2PfK-2847.webp 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/8QUDru2PfK-690.png 690w, https://geekshavefeelings.com/img/8QUDru2PfK-1380.png 1380w, https://geekshavefeelings.com/img/8QUDru2PfK-2847.png 2847w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="pancake sim n52" src="https://geekshavefeelings.com/img/8QUDru2PfK-690.png" width="2847" height="1677"></picture></figure><p></p>
<p>Flux density in the 1/4″ airgap is about 0.8 Tesla, and increasing the back iron thickness to 3/16″ increases this by more than 10%, as does decreasing the airgap to 1/8″. Sadly, the former would make the weapon weigh over 2.5 pounds, while the latter compromises the low-hitting ability of the shell and tolerance to deformation.</p>
<p>Going with a 14-pole, 12-coil design is great for iron-stator motors because it kills cogging torque, but in this coreless motor it just provides a conveniently high Wickelfaktor according to the <a href="https://geekshavefeelings.com/file/bewicklungsrechner" title="Windings calculator">Bewicklungsrechner</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref3">‡</a></sup>, which helps to produce more torque with less current (I think). This comes into play because I figured that with my P.S. WTFLOLs, otherwise known as PCB trace windings, I won’t be able to have many turns and thus link a whole lotta flux. Instead, I’ll have to rely on my coil configuration & termination as well as a high airgap flux density to get a reasonable amount of torque. Speaking of windings…</p>
<h2 id="what-the-flux-linking-outer-loops" tabindex="-1">What the Flux Linking Outer Loops? <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/">§</a></h2>
<p>Occasionally you have a brainfart and carry it way too far. This whole robot is like that, except worse, because every component was taken the whole nine yards in terms of stupid.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/798BshXnoY-690.avif 690w, https://geekshavefeelings.com/img/798BshXnoY-1380.avif 1380w, https://geekshavefeelings.com/img/798BshXnoY-3402.avif 3402w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/798BshXnoY-690.webp 690w, https://geekshavefeelings.com/img/798BshXnoY-1380.webp 1380w, https://geekshavefeelings.com/img/798BshXnoY-3402.webp 3402w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/798BshXnoY-690.png 690w, https://geekshavefeelings.com/img/798BshXnoY-1380.png 1380w, https://geekshavefeelings.com/img/798BshXnoY-3402.png 3402w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="flapjack batter" src="https://geekshavefeelings.com/img/798BshXnoY-690.png" width="3402" height="1904"></picture></figure><p></p>
<p>Yeah, that happened. It was formed by a bunch of EAGLE commands generated in an Excel worksheet that I scripted (sigh). I then milled it out on the GVU Prototyping Lab’s LPKF S62 circuit plotter:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/--ZitzdvD4-690.avif 690w, https://geekshavefeelings.com/img/--ZitzdvD4-1380.avif 1380w, https://geekshavefeelings.com/img/--ZitzdvD4-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/--ZitzdvD4-690.webp 690w, https://geekshavefeelings.com/img/--ZitzdvD4-1380.webp 1380w, https://geekshavefeelings.com/img/--ZitzdvD4-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/--ZitzdvD4-690.jpeg 690w, https://geekshavefeelings.com/img/--ZitzdvD4-1380.jpeg 1380w, https://geekshavefeelings.com/img/--ZitzdvD4-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="P.S. WTFLOL" src="https://geekshavefeelings.com/img/--ZitzdvD4-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>Something of note here is that the board is actually 5 oz/ft² copper clad, which is to say that the copper on it is 175 μm thick as opposed to typical copper clad where it’s just 1 oz/ft² or 35 μm thick. The trace width is 1.7 mm, so if I cram 10 A through the coils, that’s about 34 A/mm² of current density, which is incredibly shady.</p>
<p>Also, I measured four of the coils to be 14 milliohms on each four-turn<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref4">§</a></sup> side, with about 0.6 μH of inductance. Since the board is double sided (the other side is just the mirrored coil spiralling in reverse), and doubling turns (i.e. one coil on top of another) quadruples inductance, then each full double-sided coil will have 2.4 μH of inductance with 28 mOhm of resistance.</p>
<p>I’ll be connecting four of these in series<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref5">¶</a></sup>, so in a wye termination, I’ll have 0.226 Ohms of phase-to-phase resistance and 19 μH of inductance (I think; I don’t really know how to combine inductances in this case).</p>
<p>With inductance that low, I’m really thinking about adding external inductors to smooth out the current ripples in the motor, since otherwise Flapjack’s motor looks more like straight strips of copper and less like inductive coils.</p>
<p>Sadly, it’s also a (10 A)² × 0.226 Ohm = 22.6 W loss to just copper heating, and that’s not accounting for eddy current losses from using flat copper <em>oriented the wrong way</em> and not clearing excess copper off of the board. With that efficiency (80% max at 111 W input and 59% at 222W input), Flapjack won’t be driving solar cars any time soon. At least as a coreless motor, I won’t have any stator losses due to magnetic hysteresis, iron eddy currents, etc.</p>
<p>Aside from that, I just feel bad for completely destroying 10 mil and 15.7 mil end mills at the GVU while milling my ridiculous 5oz boards. Notice the difference in quality between that of a fresh end mill (from where I started on the board) and when it got a little less fresh (towards the end of the milling):</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/HDZ2wtJUqs-690.avif 690w, https://geekshavefeelings.com/img/HDZ2wtJUqs-1380.avif 1380w, https://geekshavefeelings.com/img/HDZ2wtJUqs-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/HDZ2wtJUqs-690.webp 690w, https://geekshavefeelings.com/img/HDZ2wtJUqs-1380.webp 1380w, https://geekshavefeelings.com/img/HDZ2wtJUqs-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/HDZ2wtJUqs-690.jpeg 690w, https://geekshavefeelings.com/img/HDZ2wtJUqs-1380.jpeg 1380w, https://geekshavefeelings.com/img/HDZ2wtJUqs-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Trace begin" src="https://geekshavefeelings.com/img/HDZ2wtJUqs-690.jpeg" width="3264" height="2448"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/o1WLcDrl1p-690.avif 690w, https://geekshavefeelings.com/img/o1WLcDrl1p-1380.avif 1380w, https://geekshavefeelings.com/img/o1WLcDrl1p-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/o1WLcDrl1p-690.webp 690w, https://geekshavefeelings.com/img/o1WLcDrl1p-1380.webp 1380w, https://geekshavefeelings.com/img/o1WLcDrl1p-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/o1WLcDrl1p-690.jpeg 690w, https://geekshavefeelings.com/img/o1WLcDrl1p-1380.jpeg 1380w, https://geekshavefeelings.com/img/o1WLcDrl1p-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Trace end" src="https://geekshavefeelings.com/img/o1WLcDrl1p-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>WTFLOL indeed.</p>
<h2 id="numbers" tabindex="-1">Numbers <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/">§</a></h2>
<p>I didn’t really feel like setting up a fancier simulation for this thing, since there’s so much fudge to begin with and my controller has even less rigor applied to its numbers<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref6">♠</a></sup>. Instead I’ll just napkin it up here.</p>
<p>Running 10 A through eight of the twelve eight-turn coils yields, through nibbler (NIBLR):</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.186ex;" xmlns="http://www.w3.org/2000/svg" width="55.847ex" height="1.805ex" role="img" focusable="false" viewBox="0 -716 24684.2 798" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D70F" d="M39 284Q18 284 18 294Q18 301 45 338T99 398Q134 425 164 429Q170 431 332 431Q492 431 497 429Q517 424 517 402Q517 388 508 376T485 360Q479 358 389 358T299 356Q298 355 283 274T251 109T233 20Q228 5 215 -4T186 -13Q153 -13 153 20V30L203 192Q214 228 227 272T248 336L254 357Q254 358 208 358Q206 358 197 358T183 359Q105 359 61 295Q56 287 53 286T39 284Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(794.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1850.6,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2572.8,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3573,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4295.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(5295.4,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6017.7,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(7017.9,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(8017.9,0)"><g data-mml-node="mi"><path data-c="41" d="M255 0Q240 3 140 3Q48 3 39 0H32V46H47Q119 49 139 88Q140 91 192 245T295 553T348 708Q351 716 366 716H376Q396 715 400 709Q402 707 508 390L617 67Q624 54 636 51T687 46H717V0H708Q699 3 581 3Q458 3 437 0H427V46H440Q510 46 510 64Q510 66 486 138L462 209H229L209 150Q189 91 189 85Q189 72 209 59T259 46H264V0H255ZM447 255L345 557L244 256Q244 255 345 255H447Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(8990.1,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9990.3,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(11268.3,0)"><g data-mml-node="mi"><path data-c="54" d="M36 443Q37 448 46 558T55 671V677H666V671Q667 666 676 556T685 443V437H645V443Q645 445 642 478T631 544T610 593Q593 614 555 625Q534 630 478 630H451H443Q417 630 414 618Q413 616 413 339V63Q420 53 439 50T528 46H558V0H545L361 3Q186 1 177 0H164V46H194Q264 46 283 49T309 63V339V550Q309 620 304 625T271 630H244H224Q154 630 119 601Q101 585 93 554T81 486T76 443V437H36V443Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(12212.6,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(13212.8,0)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(13712.8,0)"><g data-mml-node="mi"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(833,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(15601,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(16601.2,0)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(17601.2,0)"><g data-mml-node="mi"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(833,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(19545,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(20600.8,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(22378.8,0)"><g data-mml-node="mi"><path data-c="4E" d="M42 46Q74 48 94 56T118 69T128 86V634H124Q114 637 52 637H25V683H232L235 680Q237 679 322 554T493 303L578 178V598Q572 608 568 613T544 627T492 637H475V683H483Q498 680 600 680Q706 680 715 683H724V637H707Q634 633 622 598L621 302V6L614 0H600Q585 0 582 3T481 150T282 443T171 605V345L172 86Q183 50 257 46H274V0H265Q250 3 150 3Q48 3 33 0H25V46H42Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(972.2,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1472.4,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>τ</mi><mo>=</mo><mn>4</mn><mo>×</mo><mn>4</mn><mo>×</mo><mn>8</mn><mo>×</mo><mn>10</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">A</mi></mrow><mo>×</mo><mn>0.8</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">T</mi></mrow><mo>×</mo><mn>8</mn><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">mm</mi></mrow><mo>×</mo><mn>60</mn><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">mm</mi></mrow><mo>=</mo><mn>0.49</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">N</mi><mo>⋅</mo><mi mathvariant="normal">m</mi></mrow></math></mjx-assistive-mml></mjx-container><p>If you’re on top of this, that’s a Kt of 49.2 millinewton-meter/A, or a Kv of 20.3 radian/second/V, also expressed as 194 RPM/V. Now, since I’m using spiral trace coils that don’t link flux nearly as well as normal circular-section wire wound coils, I’m just going to give my torque constant a fudge factor of 0.7, which makes the Kv 1.43 times higher.</p>
<p>Now we’re talking about a motor putting out 0.34 Nm of torque at 10 A and spinning 3080 RPM at no-load on a 11.1V battery (three-cell lithium). I know from SolidWorks that all the spinny parts of the shell<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" id="fnref7">♥</a></sup> weigh just about 2 lb and has a moment of inertia of 3.32 g-m².</p>
<p>If I can control current (and thus torque) to be constant, then I can get to my no-load speed in:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.534ex;" xmlns="http://www.w3.org/2000/svg" width="29.441ex" height="6.374ex" role="img" focusable="false" viewBox="0 -1697.5 13012.9 2817.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mrow" transform="translate(220,812.8)"><g data-mml-node="mpadded"><g data-mml-node="mrow"></g></g><g data-mml-node="mstyle"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1778,0)"><g data-mml-node="TeXAtom" transform="translate(220,394) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(392,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(892,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="TeXAtom" transform="translate(592.6,-345) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path></g></g><rect width="1223.9" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(3464.1,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(4464.3,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(6242.3,0)"><g data-mml-node="mi"><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(1222.4,0)"><g data-mml-node="mi"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(833,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1699,363) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g></g></g></g></g><g data-mml-node="mrow" transform="translate(2961.9,-820)"><g data-mml-node="mpadded"><g data-mml-node="mrow"></g></g><g data-mml-node="mstyle"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1778,0)"><g data-mml-node="mi"><path data-c="4E" d="M42 46Q74 48 94 56T118 69T128 86V634H124Q114 637 52 637H25V683H232L235 680Q237 679 322 554T493 303L578 178V598Q572 608 568 613T544 627T492 637H475V683H483Q498 680 600 680Q706 680 715 683H724V637H707Q634 633 622 598L621 302V6L614 0H600Q585 0 582 3T481 150T282 443T171 605V345L172 86Q183 50 257 46H274V0H265Q250 3 150 3Q48 3 33 0H25V46H42Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(972.2,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1472.4,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path></g></g></g></g></g><rect width="9767.3" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(10285.1,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(11340.9,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(12618.9,0)"><g data-mml-node="mi"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mfrac><mrow><mpadded height="8.6pt" depth="3pt" width="0"><mrow></mrow></mpadded><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mn>51.4</mn><mfrac><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">rad</mi></mrow><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">s</mi></mrow></mfrac><mo>×</mo><mn>3.32</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">g</mi><mo>⋅</mo><msup><mi data-mjx-auto-op="false">mm</mi><mn>2</mn></msup></mrow></mrow></mstyle></mrow><mrow><mpadded height="8.6pt" depth="3pt" width="0"><mrow></mrow></mpadded><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mn>0.34</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">N</mi><mo>⋅</mo><mi mathvariant="normal">m</mi></mrow></mrow></mstyle></mrow></mfrac><mo>=</mo><mn>3.1</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">s</mi></mrow></math></mjx-assistive-mml></mjx-container><p>Also, the weapon kinetic energy would be:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.148ex;" xmlns="http://www.w3.org/2000/svg" width="39.389ex" height="5.876ex" role="img" focusable="false" viewBox="0 -1647.5 17410 2597" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1162.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2162.4,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(3940.4,0)"><g data-mml-node="mi"><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(722.2,0)"><path data-c="22C5" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(1222.4,0)"><g data-mml-node="mi"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(833,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1699,413) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(7487.7,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(8487.9,0)"><g data-mml-node="mrow"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(736,0)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2514,0)"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(220,676)"><g data-mml-node="mi"><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(392,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(892,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(747,-686)"><g data-mml-node="mi"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path></g></g><rect width="1648" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(4402,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(5171,1176.6) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(14340.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(15396,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(16896,0)"><g data-mml-node="mi"><path data-c="4A" d="M89 177Q115 177 133 160T152 112Q152 88 137 72T102 52Q99 51 101 49Q106 43 129 29Q159 15 190 15Q232 15 256 48T286 126Q286 127 286 142T286 183T286 238T287 306T287 378Q287 403 287 429T287 479T287 524T286 563T286 593T286 614V621Q281 630 263 633T182 637H154V683H166Q187 680 332 680Q439 680 457 683H465V637H449Q422 637 401 634Q393 631 389 623Q388 621 388 376T387 123Q377 61 322 20T194 -22Q188 -22 177 -21T160 -20Q96 -9 61 29T25 110Q25 144 44 160T89 177Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>×</mo><mn>3.32</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">g</mi><mo>⋅</mo><msup><mi data-mjx-auto-op="false">mm</mi><mn>2</mn></msup></mrow><mo>×</mo><msup><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mn>51.4</mn><mfrac><mrow data-mjx-texclass="ORD"><mi data-mjx-auto-op="false">rad</mi></mrow><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">s</mi></mrow></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow><mn>2</mn></msup><mo>=</mo><mn>173</mn><mrow data-mjx-texclass="ORD"><mi mathvariant="normal">J</mi></mrow></math></mjx-assistive-mml></mjx-container><p>which is comparable to just dropping the whole robot 5 stories.</p>
<h2 id="current-progress" tabindex="-1">Current progress <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/">§</a></h2>
<p>I actually beasted this thing to 90% completion in time for Motorama, but then blew it up the night before in the hotel (details later). With that deadline over, I’m taking some time to relax and go through some details with more rigor (or at least document the lack of rigor where it exists).</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/jh17Db204y-690.avif 690w, https://geekshavefeelings.com/img/jh17Db204y-1380.avif 1380w, https://geekshavefeelings.com/img/jh17Db204y-3264.avif 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/jh17Db204y-690.webp 690w, https://geekshavefeelings.com/img/jh17Db204y-1380.webp 1380w, https://geekshavefeelings.com/img/jh17Db204y-3264.webp 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/jh17Db204y-690.jpeg 690w, https://geekshavefeelings.com/img/jh17Db204y-1380.jpeg 1380w, https://geekshavefeelings.com/img/jh17Db204y-3264.jpeg 3264w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Pancake progress" src="https://geekshavefeelings.com/img/jh17Db204y-690.jpeg" width="3264" height="2448"></picture></figure><p></p>
<p>With that said, it drives pretty well, the stators are milled and ready to be wired up, and I just need to make myself a little jig to hold the stator and rotor for testing (the actual chassis isn’t easy or safe to grab onto, for obvious reasons).</p>
<p>Await my next post on the electronics package I whipped up for Flapjack, High Fructose. If you’re really impatient, you can check out <a href="https://github.com/GHF/hfcs" title="GitHub GHF/hfcs">High Fructose’s GitHub firmware repository, hfcs</a> (High Fructose corn software).</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Nor to pilot, really, since the drive system was fully automated and the operator just pushes a single joystick <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Plus my laptop was out of commission for three days, I took daily showers, and I managed to do laundry four hours before we left on our road trip to Pennsylvania <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Relax, I have no idea what I’m talking about either <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>“Turn” is used loosely here since it’s a fat spiral coil and the active lengths aren’t really equal <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>Probably; putting them in a 2S2P configuration puts half the current in each coil, solving the current density issue, but probably puts this motor out of High Fructose’s class <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>Hell, I didn’t even guesstimate anything for High Fructose; I just put some components down and said it looks about right <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn7" class="footnote-item"><p>Two rotor plates, 28 magnets, two UHMW magnet retainers, two tool steel teeth, two aluminum tooth-like spacers, eight 8-32 screws, and a UHMW bearing retainer <a href="https://geekshavefeelings.com/posts/2013/delicious-axial-flux-flapjack/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
How to teach how to PCB?
2012-12-30T00:42:53Z
https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/
<p>These days, a useful quality to have is the endurance to weather the disinterested gaze—collimated through glasses thick and transparent as hockey pucks—of gathered young engineers listening with open mouths and a slightly hunched backs. It freaks me out that I now have a solid decade’s worth of practice doing this, thanks to leading and teaching proto-engineers since middle school, yet humbling to think that there are heroes who do this as a lifelong career.</p>
<p>The trick is to ignore the complete apathy and listless boredom your audience wears on their faces. That’s just how engineers show interest. Now that everyone has smartphones, a higher quality signal for your patrons’ fascination with you is noticing the low frequency by which they poke at Facebook.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/47Ev_W9WE6-690.avif 690w, https://geekshavefeelings.com/img/47Ev_W9WE6-1380.avif 1380w, https://geekshavefeelings.com/img/47Ev_W9WE6-2048.avif 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/47Ev_W9WE6-690.webp 690w, https://geekshavefeelings.com/img/47Ev_W9WE6-1380.webp 1380w, https://geekshavefeelings.com/img/47Ev_W9WE6-2048.webp 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/47Ev_W9WE6-690.jpeg 690w, https://geekshavefeelings.com/img/47Ev_W9WE6-1380.jpeg 1380w, https://geekshavefeelings.com/img/47Ev_W9WE6-2048.jpeg 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Photo by Gabe Ochoa" src="https://geekshavefeelings.com/img/47Ev_W9WE6-690.jpeg" width="2048" height="1536"></picture></figure><p></p>
<p>Most recently, I’m proud to have taught a three-part workshop on printed circuit board (PCB) fabrication as part of the <a href="http://inventionstudio.gatech.edu/news/workshop-schedule/" title="Workshop Schedule">GT Invention Studio/Makers Club fall series</a>. Among other records set this semester, this was the first time ever that the <a href="http://inventionstudio.gatech.edu/about/" title="Invention Studio">Invention Studio</a> was inhabited by an electrical engineering majority<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/" id="fnref1">*</a></sup>, when otherwise it comprises mechanical engineers with grease guns and crescent wren—UGGHRRR WOW THREADS SUCH METAL MUCH FEEDS & SPEEDS. It felt weird, but smelled better than anyone hoped for.</p>
<p>On top of attendance, reception to the PCB workshop was great. People had all pulled out their laptops with EAGLE already installed, as if they had read the emails I had sent out. I was surprised to hear that useful knowledge had diffused into the crowd.</p>
<p>The workshop was split over three days, and I had digital materials prepared for each one. The first and last sessions used Keynote presentations, while the in-between session had paper handouts. You can download these in PDF by clicking on them.</p>
<h2 id="day-1" tabindex="-1">Day 1 <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/">§</a></h2>
<p>Overview of hacking hardware and EAGLE demo. I used my interpretation of the <a href="http://etotheipiplusone.net" title="equals zero (Charles's blog)">Charles</a> flavor of imparting knowledge—learning by facilitating projects. I disclosed my ideology and motivation, then deciphered jargon with a glossary, and finally provided a list of tools and vendors. At the end, I had everyone design a board on the spot.</p>
<p><a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/files/PCB-Part-I-slides.pdf"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/TEyMVg-_EK-690.avif 690w, https://geekshavefeelings.com/img/TEyMVg-_EK-1380.avif 1380w, https://geekshavefeelings.com/img/TEyMVg-_EK-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/TEyMVg-_EK-690.webp 690w, https://geekshavefeelings.com/img/TEyMVg-_EK-1380.webp 1380w, https://geekshavefeelings.com/img/TEyMVg-_EK-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/TEyMVg-_EK-690.png 690w, https://geekshavefeelings.com/img/TEyMVg-_EK-1380.png 1380w, https://geekshavefeelings.com/img/TEyMVg-_EK-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="PCB workshop I" src="https://geekshavefeelings.com/img/TEyMVg-_EK-690.png" width="1920" height="1080"></picture></figure></a></p>
<h2 id="day-2" tabindex="-1">Day 2 <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/">§</a></h2>
<p>How to create custom parts in EAGLE. I snuck in some keyboard shortcuts and best practices talks in here. This is the tricky part of hands-on teaching: to pass on knowledge through osmosis by working next to each other. Normally this is while working on similar projects, but that’s difficult to replicate for the sake of a workshop.</p>
<p><a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/files/PCB-Part-II-handout.pdf"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/zAnnIRLYqf-690.avif 690w, https://geekshavefeelings.com/img/zAnnIRLYqf-1380.avif 1380w, https://geekshavefeelings.com/img/zAnnIRLYqf-2550.avif 2550w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/zAnnIRLYqf-690.webp 690w, https://geekshavefeelings.com/img/zAnnIRLYqf-1380.webp 1380w, https://geekshavefeelings.com/img/zAnnIRLYqf-2550.webp 2550w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/zAnnIRLYqf-690.png 690w, https://geekshavefeelings.com/img/zAnnIRLYqf-1380.png 1380w, https://geekshavefeelings.com/img/zAnnIRLYqf-2550.png 2550w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="PCB workshop II" src="https://geekshavefeelings.com/img/zAnnIRLYqf-690.png" width="2550" height="3300"></picture></figure></a></p>
<h2 id="day-3" tabindex="-1">Day 3 <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/">§</a></h2>
<p>Where and how to make boards or get boards made. Since I was sick and this was during <a href="http://en.wikipedia.org/wiki/Dead_week" title="Dead Week">Dead Week</a>, this became more of a round-table Q&A session than a lecture. However, this worked out to be a great “wrap” for the workshop and I was able to get a bit of feedback through it.</p>
<p>The slides I created for this session, however, are the most useful out of all the materials. The set contains tables of various PCB fabs that I’ve had some sort of experience with. They include poorly researched specs, lead times, and true costs<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/" id="fnref2">†</a></sup> (setup fees, unit cost, shipping & handling) along with some anecdotal notes.</p>
<p><a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/files/PCB-Part-III-slides.pdf"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/9NhPsgOUnS-690.avif 690w, https://geekshavefeelings.com/img/9NhPsgOUnS-1380.avif 1380w, https://geekshavefeelings.com/img/9NhPsgOUnS-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/9NhPsgOUnS-690.webp 690w, https://geekshavefeelings.com/img/9NhPsgOUnS-1380.webp 1380w, https://geekshavefeelings.com/img/9NhPsgOUnS-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/9NhPsgOUnS-690.png 690w, https://geekshavefeelings.com/img/9NhPsgOUnS-1380.png 1380w, https://geekshavefeelings.com/img/9NhPsgOUnS-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="PCB workshop III" src="https://geekshavefeelings.com/img/9NhPsgOUnS-690.png" width="1920" height="1080"></picture></figure></a></p>
<p>I was a bit shocked that everything had gone so smoothly. The pacing was especially important in the first session’s EAGLE demo. There, I put up each part I used and its library on the whiteboard, and secondly I had prepared EAGLE libraries and finished schematics/layouts to be shared on Dropbox.</p>
<p>The former meant everyone could follow regardless of their pace, and the latter meant I only needed to show EAGLE techniques once—after that, I’m free to pull out the neat, proofread design files like Rachel Ray pulls out chicken drumettes marinated overnight in lemon and soy sauce. In addition to minimizing Murphy’s Law demo mishaps, it also gave me the chance to take a breather, walk around, and do one-on-one’s with anyone having trouble.</p>
<p>Obviously, what also helps pacing is having a controlled number of focused, eager students. With a class of about 10 to 15, it wasn’t impossible to make sure everyone was following.</p>
<p>By the last session, people were bringing in their projects and devkits they had bought to play with. That was nifty! I’m incredibly fortunate to have had such an excellent audience. I’m super motivated to try this again, hopefully with improvements.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Aside from when I’m in there alone. >.> <a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Using <a href="https://geekshavefeelings.com/tags/babycorntroller" title="BabyCorntroller">BabyCorntroller</a>'s 4.95″×4.95″ power stage TinyHusk as an example. <a href="https://geekshavefeelings.com/posts/2012/how-to-teach-how-to-pcb/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Fixed-point atan2
2012-12-27T09:42:54Z
https://geekshavefeelings.com/posts/2012/fixed-point-atan2/
<p><em>First published February 6, 2012 then taken down for revision. Updated further in January 2017 to correct errors and expand explanations.</em></p>
<p><a href="http://en.wikipedia.org/wiki/Atan2" title="atan2"><code>atan2</code></a> is a freaking useful function: given some <a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system" title="Cartesian coordinate system">y and x</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref1">*</a></sup>, it computes their “four-quadrant” arctangent<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref2">†</a></sup>, which is basically that coordinate’s angle in <a href="http://en.wikipedia.org/wiki/Polar_coordinate_system" title="Polar coordinate system">polar form</a>.</p>
<p>These two beautiful Wikipedia diagrams explain why it’s so much better than the naïve <code>atan(y/x)</code>:</p>
<p><a href="http://en.wikipedia.org/wiki/File:Atan2Diagram.png"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/XMl3914cSq-690.avif 690w, https://geekshavefeelings.com/img/XMl3914cSq-880.avif 880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/XMl3914cSq-690.webp 690w, https://geekshavefeelings.com/img/XMl3914cSq-880.webp 880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/XMl3914cSq-690.png 690w, https://geekshavefeelings.com/img/XMl3914cSq-880.png 880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Atan2Diagram" src="https://geekshavefeelings.com/img/XMl3914cSq-690.png" width="880" height="768"></picture></figure></a><a href="http://en.wikipedia.org/wiki/File:AtanDiagram.png"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/c9T0XIGApK-690.avif 690w, https://geekshavefeelings.com/img/c9T0XIGApK-880.avif 880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/c9T0XIGApK-690.webp 690w, https://geekshavefeelings.com/img/c9T0XIGApK-880.webp 880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/c9T0XIGApK-690.png 690w, https://geekshavefeelings.com/img/c9T0XIGApK-880.png 880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="AtanDiagram" src="https://geekshavefeelings.com/img/c9T0XIGApK-690.png" width="880" height="768"></picture></figure></a></p>
<p>It also shows the reasons why I suffered a stroke of unsanity and whipped up my own <code>atan2</code> function in Q15 fixed point/1.0.15/1.15/whycan’twehaveonenameforthis format that’s so commonly used by DSP chips:</p>
<ol>
<li>You see how smooth that thing is? That’s because it was generated in some high-falutin’ floating point on a fancy machine with a sweet <a href="http://en.wikipedia.org/wiki/Floating-point_unit" title="Floating-point unit">FPU</a>. Well, I program itty-bitty embedded microcontrollers with nary a hardware integer divider, so I use <a href="http://en.wikipedia.org/wiki/Fixed-point_arithmetic" title="Fixed-point arithmetic">fixed-point arithmetic</a> for my math. One of the more popular fixed-point formats is Q15, which is taking a 16-bit signed two’s complement integer<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref3">‡</a></sup> and instead of having it represent <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="15.336ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 6778.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1056,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3556,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(4000.7,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6500.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mn>32768</mn><mo>,</mo><mn>32767</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>, have it represent <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="11.581ex" height="2.452ex" role="img" focusable="false" viewBox="0 -833.9 5118.9 1083.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1056,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1556,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2000.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2500.7,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="msup" transform="translate(3000.7,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(4840.9,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mn>1</mn><mo>,</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mo>−</mo><mn>15</mn></mrow></msup><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref4">§</a></sup>. I used it out of convenience since I knew a few of the tricks for making Q15 computations go fast.</li>
<li>The range on <code>atan2</code> output is <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="6.603ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 2918.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1056,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1626,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2070.7,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2640.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mi>π</mi><mo>,</mo><mi>π</mi><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>. That’s nice and mathemagicatical, but not so useful an angle representation on a microcontroller. See, first, that doesn’t fit inside of a Q15 number. Then even if it did, it’d still be wasteful to have your angle’s range be bookended by transcendental numbers. You got only 16 bits! You want every possible 16-bit number to be a valid and useful angle, evenly covering the whole range of possible angular positions still without redundancy. For example, there shouldn’t be different representations for both <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="3.085ex" height="2.773ex" role="img" focusable="false" viewBox="0 -864.9 1363.6 1225.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><rect width="553.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(793.6,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mn>2</mn><mn>3</mn></mfrac><mi>π</mi></math></mjx-assistive-mml></mjx-container> and <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="4.845ex" height="2.79ex" role="img" focusable="false" viewBox="0 -872.7 2141.6 1233.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(778,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><rect width="553.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(1571.6,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo>−</mo><mfrac><mn>4</mn><mn>3</mn></mfrac><mi>π</mi></math></mjx-assistive-mml></mjx-container>, since they’re the same angular position. So, let’s map our 16-bit range <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="12.124ex" height="2.452ex" role="img" focusable="false" viewBox="0 -833.9 5358.9 1083.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(1056,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(2346.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(2790.8,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4080.9,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(4580.9,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5080.9,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>15</mn></mrow></msup><mo>,</mo><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>15</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>1</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> or <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="15.336ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 6778.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1056,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3556,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(4000.7,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6500.7,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mn>32768</mn><mo>,</mo><mn>32767</mn><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> to (almost) a full turn of the circle <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.854ex;" xmlns="http://www.w3.org/2000/svg" width="23.222ex" height="3.079ex" role="img" focusable="false" viewBox="0 -983.7 10264.3 1361" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1056,0)"><g data-mml-node="msup" transform="translate(220,394) scale(0.707)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="msup" transform="translate(220,-377.4) scale(0.707)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,289) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><rect width="1112.2" height="60" x="120" y="220"></rect></g><g data-mml-node="mtext" transform="translate(2408.2,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(639,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1195,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1587,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2143,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4945.2,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(5389.9,0)"><g data-mml-node="mrow" transform="translate(220,394) scale(0.707)"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(1290.1,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mn" transform="translate(1790.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="msup" transform="translate(573.6,-377.4) scale(0.707)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,289) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><rect width="1819.4" height="60" x="120" y="220"></rect></g><g data-mml-node="mtext" transform="translate(7449.3,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(639,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1195,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1587,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2143,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9986.3,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mfrac><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>15</mn></mrow></msup><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>16</mn></mrow></msup></mfrac><mtext> turns</mtext><mo>,</mo><mfrac><mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>15</mn></mrow></msup><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mn>1</mn></mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>16</mn></mrow></msup></mfrac><mtext> turns</mtext><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> which is really <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="22.294ex" height="2.789ex" role="img" focusable="false" viewBox="0 -872 9854 1232.6" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1056,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="553.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mtext" transform="translate(1849.6,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(639,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1195,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1587,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2143,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4386.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(4831.2,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><rect width="1967.8" height="60" x="120" y="220"></rect></g><g data-mml-node="mtext" transform="translate(7039,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="75" d="M383 58Q327 -10 256 -10H249Q124 -10 105 89Q104 96 103 226Q102 335 102 348T96 369Q86 385 36 385H25V408Q25 431 27 431L38 432Q48 433 67 434T105 436Q122 437 142 438T172 441T184 442H187V261Q188 77 190 64Q193 49 204 40Q224 26 264 26Q290 26 311 35T343 58T363 90T375 120T379 144Q379 145 379 161T380 201T380 248V315Q380 361 370 372T320 385H302V431Q304 431 378 436T457 442H464V264Q464 84 465 81Q468 61 479 55T524 46H542V0Q540 0 467 -5T390 -11H383V58Z" transform="translate(639,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(1195,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1587,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(2143,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9576,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mtext> turns</mtext><mo>,</mo><mfrac><mn>32767</mn><mn>65536</mn></mfrac><mtext> turns</mtext><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>.</li>
</ol>
<h2 id="fixed-point-angular-representation" tabindex="-1">Fixed point angular representation <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>A <a href="http://en.wikipedia.org/wiki/Turn_(geometry)"><em>turn</em></a> here is of course a rotation of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="2.421ex" height="1.532ex" role="img" focusable="false" viewBox="0 -666 1070 677" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>2</mn><mi>π</mi></math></mjx-assistive-mml></mjx-container> radians, so all this mapping does is assign a scaling factor between radians and 16-bit numbers in a unit we’ll call <em>binary radians</em>, or <em>brads</em>. Specifically, between one turn’s worth of radians and the whole 16-bit space’s worth of brads.</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -1.654ex;" xmlns="http://www.w3.org/2000/svg" width="44.683ex" height="4.753ex" role="img" focusable="false" viewBox="0 -1370 19750.1 2100.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1056,0)" style="stroke-width: 3;"></path><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1556,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1834,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(2278,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2528,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2806,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(3362,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(3612,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(4004,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(4504,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(5060,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(5338,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(5838,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(6394,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(7065.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(8121.6,0)"><g data-mml-node="mrow" transform="translate(608.1,676)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(1070,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(642,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1142,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(220,-719.9)"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,289) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtext" transform="translate(1290.1,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1198,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1698,0)" style="stroke-width: 3;"></path></g></g><rect width="3744.1" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(12327.9,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(13328.1,0)"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="67" d="M329 409Q373 453 429 453Q459 453 472 434T485 396Q485 382 476 371T449 360Q416 360 412 390Q410 404 415 411Q415 412 416 414V415Q388 412 363 393Q355 388 355 386Q355 385 359 381T368 369T379 351T388 325T392 292Q392 230 343 187T222 143Q172 143 123 171Q112 153 112 133Q112 98 138 81Q147 75 155 75T227 73Q311 72 335 67Q396 58 431 26Q470 -13 470 -72Q470 -139 392 -175Q332 -206 250 -206Q167 -206 107 -175Q29 -140 29 -75Q29 -39 50 -15T92 18L103 24Q67 55 67 108Q67 155 96 193Q52 237 52 292Q52 355 102 398T223 442Q274 442 318 416L329 409ZM299 343Q294 371 273 387T221 404Q192 404 171 388T145 343Q142 326 142 292Q142 248 149 227T179 192Q196 182 222 182Q244 182 260 189T283 207T294 227T299 242Q302 258 302 292T299 343ZM403 -75Q403 -50 389 -34T348 -11T299 -2T245 0H218Q151 0 138 -6Q118 -15 107 -34T95 -74Q95 -84 101 -97T122 -127T170 -155T250 -167Q319 -167 361 -139T403 -75Z" transform="translate(1056,0)" style="stroke-width: 3;"></path><path data-c="6C" d="M42 46H56Q95 46 103 60V68Q103 77 103 91T103 124T104 167T104 217T104 272T104 329Q104 366 104 407T104 482T104 542T103 586T103 603Q100 622 89 628T44 637H26V660Q26 683 28 683L38 684Q48 685 67 686T104 688Q121 689 141 690T171 693T182 694H185V379Q185 62 186 60Q190 52 198 49Q219 46 247 46H263V0H255L232 1Q209 2 183 2T145 3T107 3T57 1L34 0H26V46H42Z" transform="translate(1556,0)" style="stroke-width: 3;"></path><path data-c="65" d="M28 218Q28 273 48 318T98 391T163 433T229 448Q282 448 320 430T378 380T406 316T415 245Q415 238 408 231H126V216Q126 68 226 36Q246 30 270 30Q312 30 342 62Q359 79 369 104L379 128Q382 131 395 131H398Q415 131 415 121Q415 117 412 108Q393 53 349 21T250 -11Q155 -11 92 58T28 218ZM333 275Q322 403 238 411H236Q228 411 220 410T195 402T166 381T143 340T127 274V267H333V275Z" transform="translate(1834,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(2278,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(2528,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2806,0)" style="stroke-width: 3;"></path><path data-c="20" d="" transform="translate(3362,0)" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(3612,0)" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(4168,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(4446,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(5002,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(5502,0)" style="stroke-width: 3;"></path><path data-c="79" d="M69 -66Q91 -66 104 -80T118 -116Q118 -134 109 -145T91 -160Q84 -163 97 -166Q104 -168 111 -168Q131 -168 148 -159T175 -138T197 -106T213 -75T225 -43L242 0L170 183Q150 233 125 297Q101 358 96 368T80 381Q79 382 78 382Q66 385 34 385H19V431H26L46 430Q65 430 88 429T122 428Q129 428 142 428T171 429T200 430T224 430L233 431H241V385H232Q183 385 185 366L286 112Q286 113 332 227L376 341V350Q376 365 366 373T348 383T334 385H331V431H337H344Q351 431 361 431T382 430T405 429T422 429Q477 429 503 431H508V385H497Q441 380 422 345Q420 343 378 235T289 9T227 -131Q180 -204 113 -204Q69 -204 44 -177T19 -116Q19 -89 35 -78T69 -66Z" transform="translate(5894,0)" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtext>angle in radians</mtext><mo>=</mo><mfrac><mrow><mn>2</mn><mi>π</mi><mtext> rad</mtext></mrow><mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>16</mn></mrow></msup><mtext> brad</mtext></mrow></mfrac><mo>×</mo><mtext>angle in binary</mtext></math></mjx-assistive-mml></mjx-container><p>However, this particular factor does more than only preserve precision. It aligns the <a href="http://en.wikipedia.org/wiki/Integer_overflow" title="Integer overflow">overflow</a> boundary of 16-bit integers to the wrapping that happens to angles each turn. It elegantly exploits the <a href="https://en.wikipedia.org/wiki/Modular_arithmetic">modular arithmetic</a> property of binary numbers to provide angle wrapping and canonicalization. Just like adding 1° to 359° gives 0°, adding 1 to 32767 fixed point units gives −32768 fixed point units.</p>
<p>This avoids having to perform <a href="http://en.wikipedia.org/wiki/Modulo_operation">modulo</a> during angle computations to keep them “in range,” including the fairly expensive <a href="http://en.cppreference.com/w/cpp/numeric/math/fmod"><code>fmod</code></a>.</p>
<p>Even more conveniently, signed binary integers can be converted to and from unsigned “for free,” as they are simply different ways to interpret the same bit pattern. Guess what? This works perfectly on angles in brads because it’s analogous to converting between <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="6.854ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 3029.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1056,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1626,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2070.7,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2640.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mi>π</mi><mo>,</mo><mi>π</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container> and <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="6.067ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 2681.7 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(278,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(778,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1222.7,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1722.7,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2292.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mn>0</mn><mo>,</mo><mn>2</mn><mi>π</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>. As an example, let’s say you have the angle <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="3.085ex" height="2.79ex" role="img" focusable="false" viewBox="0 -872.7 1363.6 1233.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><rect width="553.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(793.6,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mn>4</mn><mn>3</mn></mfrac><mi>π</mi></math></mjx-assistive-mml></mjx-container>, initially represented as 43691 brads:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -10.41ex;" xmlns="http://www.w3.org/2000/svg" width="46.916ex" height="21.952ex" role="img" focusable="false" viewBox="0 -5101.4 20736.9 9702.8" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,3591.5)"><g data-mml-node="mtd"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(940,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(1510,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(642,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1142,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3430.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(4430.4,0)"><g data-mml-node="mrow" transform="translate(220,676)"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtext" transform="translate(1290.1,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1198,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1698,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(858.1,-686)"><g data-mml-node="mi"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(570,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(642,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1142,0)" style="stroke-width: 3;"></path></g></g><rect width="3744.1" height="60" x="120" y="220"></rect></g></g><g data-mml-node="mtd" transform="translate(8414.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1333.6,0)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(3833.6,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1198,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1698,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,1699.5)"><g data-mml-node="mtd" transform="translate(8414.6,0)"></g><g data-mml-node="mtd" transform="translate(8414.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="2261" d="M56 444Q56 457 70 464H707Q722 456 722 444Q722 430 706 424H72Q56 429 56 444ZM56 237T56 250T70 270H707Q722 262 722 250T707 230H70Q56 237 56 250ZM56 56Q56 71 72 76H706Q722 70 722 56Q722 44 707 36H70Q56 43 56 56Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1333.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2111.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mspace" transform="translate(4611.6,0)"></g><g data-mml-node="mo" transform="translate(5611.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(6000.6,0)"><path data-c="6D" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q351 442 364 440T387 434T406 426T421 417T432 406T441 395T448 384T452 374T455 366L457 361L460 365Q463 369 466 373T475 384T488 397T503 410T523 422T546 432T572 439T603 442Q729 442 740 329Q741 322 741 190V104Q741 66 743 59T754 49Q775 46 803 46H819V0H811L788 1Q764 2 737 2T699 3Q596 3 587 0H579V46H595Q656 46 656 62Q657 64 657 200Q656 335 655 343Q649 371 635 385T611 402T585 404Q540 404 506 370Q479 343 472 315T464 232V168V108Q464 78 465 68T468 55T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(833,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1333,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mspace" transform="translate(7889.6,0)"></g><g data-mml-node="msup" transform="translate(8389.2,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,413) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(9679.3,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(10068.3,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1198,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1698,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-220.5)"><g data-mml-node="mtd" transform="translate(8414.6,0)"></g><g data-mml-node="mtd" transform="translate(8414.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1333.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2111.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(1000,0)" style="stroke-width: 3;"></path><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" transform="translate(1500,0)" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(2000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(4611.6,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1198,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1698,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(7087.8,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(8088,0)"><g data-mml-node="mrow" transform="translate(858.1,676)"><g data-mml-node="mi"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(570,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(642,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1142,0)" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(220,-719.9)"><g data-mml-node="msup"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,289) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtext" transform="translate(1290.1,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="62" d="M307 -11Q234 -11 168 55L158 37Q156 34 153 28T147 17T143 10L138 1L118 0H98V298Q98 599 97 603Q94 622 83 628T38 637H20V660Q20 683 22 683L32 684Q42 685 61 686T98 688Q115 689 135 690T165 693T176 694H179V543Q179 391 180 391L183 394Q186 397 192 401T207 411T228 421T254 431T286 439T323 442Q401 442 461 379T522 216Q522 115 458 52T307 -11ZM182 98Q182 97 187 90T196 79T206 67T218 55T233 44T250 35T271 29T295 26Q330 26 363 46T412 113Q424 148 424 212Q424 287 412 323Q385 405 300 405Q270 405 239 390T188 347L182 339V98Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(806,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1198,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1698,0)" style="stroke-width: 3;"></path></g></g><rect width="3744.1" height="60" x="120" y="220"></rect></g></g></g><g data-mml-node="mtr" transform="translate(0,-2001.4)"><g data-mml-node="mtd" transform="translate(8414.6,0)"></g><g data-mml-node="mtd" transform="translate(8414.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1333.6,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1778,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(2278,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(2778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(4611.6,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(5181.6,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(642,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1142,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-3893.4)"><g data-mml-node="mtd" transform="translate(8414.6,0)"></g><g data-mml-node="mtd" transform="translate(8414.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1333.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2111.6,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(3051.6,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(3621.6,0)"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(642,0)" style="stroke-width: 3;"></path><path data-c="64" d="M376 495Q376 511 376 535T377 568Q377 613 367 624T316 637H298V660Q298 683 300 683L310 684Q320 685 339 686T376 688Q393 689 413 690T443 693T454 694H457V390Q457 84 458 81Q461 61 472 55T517 46H535V0Q533 0 459 -5T380 -11H373V44L365 37Q307 -11 235 -11Q158 -11 96 50T34 215Q34 315 97 378T244 442Q319 442 376 393V495ZM373 342Q328 405 260 405Q211 405 173 369Q146 341 139 305T131 211Q131 155 138 120T173 59Q203 26 251 26Q322 26 373 103V342Z" transform="translate(1142,0)" style="stroke-width: 3;"></path></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right left" columnspacing="0em" rowspacing="3pt"><mtr><mtd><mfrac><mn>4</mn><mn>3</mn></mfrac><mi>π</mi><mtext> rad</mtext><mo>×</mo><mfrac><mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>15</mn></mrow></msup><mtext> brad</mtext></mrow><mrow><mi>π</mi><mtext> rad</mtext></mrow></mfrac></mtd><mtd><mi><mo>=</mo><mn>43691</mn><mtext> brad</mtext></mi></mtd></mtr><mtr><mtd><mtd><mi><mo>≡</mo><mo>−</mo><mn>21845</mn><mspace width="1em"><mo stretchy="false">(</mo><mi>mod</mi><mspace width="0.333em"><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>16</mn></mrow></msup><mo stretchy="false">)</mo><mtext> brad</mtext></mspace></mspace></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mo>−</mo><mn>21845</mn><mtext> brad</mtext><mo>×</mo><mfrac><mrow><mi>π</mi><mtext> rad</mtext></mrow><mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mn>15</mn></mrow></msup><mtext> brad</mtext></mrow></mfrac></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>≈</mo><mn>0.66666</mn><mi>π</mi><mtext> rad</mtext></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>≈</mo><mo>−</mo><mfrac><mn>2</mn><mn>3</mn></mfrac><mi>π</mi><mtext> rad</mtext></mi></mtd></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>Free conversions of angles to non-negative values and automatic rotation wrapping are incredibly powerful for digital computation. We can do wicked fast things like limited-precision <code>sin</code> and <code>cos</code> lookup tables:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">const</span> <span class="token keyword">int16_t</span> sin_lut<span class="token punctuation">[</span><span class="token number">4096</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// a 2^12 table of precomputed sin values</span>
<span class="token keyword">const</span> <span class="token keyword">uint16_t</span> angle<span class="token punctuation">;</span> <span class="token comment">// angle in 16-bit binary radians</span>
<span class="token comment">// right shift because there are 16x possible angles as table entries</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> sin_of_angle <span class="token operator">=</span> sin_lut<span class="token punctuation">[</span>angle <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// cos(x) = sin(x + pi / 2), pi / 2 rad = 16384 brad</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> cos_of_angle <span class="token operator">=</span> sin_lut<span class="token punctuation">[</span><span class="token punctuation">(</span>angle <span class="token operator">+</span> <span class="token number">16384</span><span class="token punctuation">)</span> <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// we can also round to the nearest entry</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> sin_of_rounded_angle <span class="token operator">=</span> sin_lut<span class="token punctuation">[</span><span class="token punctuation">(</span>angle <span class="token operator">+</span> <span class="token punctuation">(</span><span class="token number">1</span> <span class="token operator"><<</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// or linearly interpolate between them</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> lower <span class="token operator">=</span> sin_lut<span class="token punctuation">[</span>angle <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> upper <span class="token operator">=</span> sin_lut<span class="token punctuation">[</span><span class="token punctuation">(</span>angle <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> angle_fraction <span class="token operator">=</span> <span class="token punctuation">(</span>angle <span class="token operator">&</span> <span class="token number">0xF</span><span class="token punctuation">)</span> <span class="token operator"><<</span> <span class="token punctuation">(</span><span class="token number">15</span> <span class="token operator">-</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> better_sin <span class="token operator">=</span> <span class="token function">lerp</span><span class="token punctuation">(</span>lower<span class="token punctuation">,</span> upper<span class="token punctuation">,</span> angle_fraction<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Note that the contents of the <code>int16_t</code> numbers above are not bradians, but “normal” Q15 fixed point numbers representing the range <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="11.581ex" height="2.452ex" role="img" focusable="false" viewBox="0 -833.9 5118.9 1083.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1056,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1556,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2000.7,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2500.7,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="msup" transform="translate(3000.7,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(533,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mo" transform="translate(4840.9,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mn>1</mn><mo>,</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><msup><mn>2</mn><mrow data-mjx-texclass="ORD"><mo>−</mo><mn>15</mn></mrow></msup><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container>.</p>
<h2 id="implementing-atan2" tabindex="-1">Implementing <code>atan2</code> <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>Given that <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.798ex;" xmlns="http://www.w3.org/2000/svg" width="24.37ex" height="2.72ex" role="img" focusable="false" viewBox="0 -849.5 10771.4 1202.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(889,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1389,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(1945,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2445,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2834,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3406,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3850.7,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4340.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5007.4,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(6063.2,0)"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(9010.9,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(458,0)"><g data-mml-node="mi" transform="translate(249,485) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(220,-345) scale(0.707)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><rect width="604.5" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1302.5,0) translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>atan2</mtext><mo stretchy="false">(</mo><mi>x</mi><mo>,</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mtext>arctan</mtext><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mi>y</mi><mi>x</mi></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow></math></mjx-assistive-mml></mjx-container> when <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="3.409ex" height="1.464ex" role="img" focusable="false" viewBox="0 -442 1506.7 647" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(572,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1016.7,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi><mo>,</mo><mi>y</mi></math></mjx-assistive-mml></mjx-container> are in quadrants I and IV, I can implement <code>atan2</code> using arctangent near zero, where it’s smooth and easily approximated. Inputs outside of that domain can be manipulated into it, provided that the output is adjusted for those manipulations.</p>
<h2 id="derive-arctangent-approximation" tabindex="-1">“Derive” arctangent approximation <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>To implement <code>atan2</code>, I whipped out Chapter 18 from <a href="http://www.amazon.com/Streamlining-Digital-Signal-Processing-Guidebook/dp/0470131578" title="Streamlining DSP">Streamlining Digital Signal Processing</a>, which had several approximations for <code>atan</code>, including the following formula:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.933ex;" xmlns="http://www.w3.org/2000/svg" width="34.238ex" height="6.998ex" role="img" focusable="false" viewBox="0 -1796.5 15133.3 3093" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,689.5)"><g data-mml-node="mtd"><g data-mml-node="msup"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="22C6" d="M210 282Q210 284 225 381T241 480Q241 484 245 484Q249 486 251 486Q258 486 260 477T272 406Q275 390 276 380Q290 286 290 282L388 299Q484 314 487 314H488Q497 314 497 302Q497 297 434 266Q416 257 404 251L315 206L361 118Q372 98 383 75T401 40L407 28Q407 16 395 16Q394 16 392 16L390 17L250 159L110 17L108 16Q106 16 105 16Q93 16 93 28L99 40Q105 52 116 75T139 118L185 206L96 251Q6 296 4 300Q3 301 3 302Q3 314 12 314H13Q16 314 112 299L210 282Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(3217.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3606.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4178.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(4567.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1333.6,0)"><g data-mml-node="mi" transform="translate(220,676)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(255,-686)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><rect width="770" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(2343.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3137.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(4138,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(6416,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6988,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(7377,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7877,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(8377,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(8655,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9227,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9505,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-1046.5)"><g data-mml-node="mtd" transform="translate(4567.6,0)"></g><g data-mml-node="mtd" transform="translate(4567.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="2248" d="M55 319Q55 360 72 393T114 444T163 472T205 482Q207 482 213 482T223 483Q262 483 296 468T393 413L443 381Q502 346 553 346Q609 346 649 375T694 454Q694 465 698 474T708 483Q722 483 722 452Q722 386 675 338T555 289Q514 289 468 310T388 357T308 404T224 426Q164 426 125 393T83 318Q81 289 69 289Q55 289 55 319ZM55 85Q55 126 72 159T114 210T163 238T205 248Q207 248 213 248T223 249Q262 249 296 234T393 179L443 147Q502 112 553 112Q609 112 649 141T694 220Q694 249 708 249T722 217Q722 153 675 104T555 55Q514 55 468 76T388 123T308 170T224 192Q164 192 125 159T83 84Q80 55 69 55Q55 55 55 85Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(1333.6,0)"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4114.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(4503.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5075.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(5464.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path><path data-c="A0" d="" transform="translate(278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(5992.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6842.3,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(7787.1,0)"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(8065.1,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(8843.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9343.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9787.8,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10287.8,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right left" columnspacing="0em" rowspacing="3pt"><mtr><mtd><msup><mtext>arctan</mtext><mo>⋆</mo></msup><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mtd><mtd><mi><mo>=</mo><mfrac><mi>π</mi><mn>4</mn></mfrac><mi>x</mi><mo>+</mo><mn>0.273</mn><mi>x</mi><mo stretchy="false">(</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mi>x</mi><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo stretchy="false">)</mo></mi></mtd></mtr><mtr><mtd><mtd><mi><mo>≈</mo><mtext>arctan</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mtext>, </mtext><mi>x</mi><mo>∈</mo><mo stretchy="false">[</mo><mo>−</mo><mn>1</mn><mo>,</mo><mn>1</mn><mo stretchy="false">]</mo></mi></mtd></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>That’s a local polynomial<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref5">¶</a></sup> approximation good to a worst-case error of 0.22° for <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.312ex;" xmlns="http://www.w3.org/2000/svg" width="11.351ex" height="1.819ex" role="img" focusable="false" viewBox="0 -666 5017.1 804" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1555.8,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2611.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3461.3,0)"><path data-c="2264" d="M674 636Q682 636 688 630T694 615T687 601Q686 600 417 472L151 346L399 228Q687 92 691 87Q694 81 694 76Q694 58 676 56H670L382 192Q92 329 90 331Q83 336 83 348Q84 359 96 365Q104 369 382 500T665 634Q669 636 674 636ZM84 -118Q84 -108 99 -98H678Q694 -104 694 -118Q694 -130 679 -138H98Q84 -131 84 -118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(4517.1,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo>−</mo><mn>1</mn><mo>≤</mo><mi>x</mi><mo>≤</mo><mn>1</mn></math></mjx-assistive-mml></mjx-container>.</p>
<h2 id="convert-units" tabindex="-1">Convert units <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>Now this is single-operand arctangent, so its parameter <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="1.294ex" height="1.025ex" role="img" focusable="false" viewBox="0 -442 572 453" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi></math></mjx-assistive-mml></mjx-container> is really the slope <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.798ex;" xmlns="http://www.w3.org/2000/svg" width="1.911ex" height="2.602ex" role="img" focusable="false" viewBox="0 -797.5 844.5 1150.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mi" transform="translate(249,485) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(220,-345) scale(0.707)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><rect width="604.5" height="60" x="120" y="220"></rect></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mi>y</mi><mi>x</mi></mfrac></math></mjx-assistive-mml></mjx-container> as understood by <code>atan2</code>. Hence, the limited domain of the approximation function is equivalent to octants I and VIII in terms of <code>atan2</code><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref6">♠</a></sup>. The range is <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.781ex;" xmlns="http://www.w3.org/2000/svg" width="7.839ex" height="2.477ex" role="img" focusable="false" viewBox="0 -750 3464.8 1095" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mo"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(278,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1056,0)"><g data-mml-node="mi" transform="translate(220,394) scale(0.707)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(244.7,-345) scale(0.707)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><rect width="603.1" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1899.1,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2343.7,0)"><g data-mml-node="mi" transform="translate(220,394) scale(0.707)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(244.7,-345) scale(0.707)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><rect width="603.1" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(3186.8,0)"><path data-c="5D" d="M22 710V750H159V-250H22V-210H119V710H22Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mo stretchy="false">[</mo><mo>−</mo><mfrac><mi>π</mi><mn>4</mn></mfrac><mo>,</mo><mfrac><mi>π</mi><mn>4</mn></mfrac><mo stretchy="false">]</mo></math></mjx-assistive-mml></mjx-container> over that domain. We want to convert to turns, since that’s bit easier to work with:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -10.11ex;" xmlns="http://www.w3.org/2000/svg" width="39.254ex" height="21.351ex" role="img" focusable="false" viewBox="0 -4968.5 17350.2 9437" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,3626.5)"><g data-mml-node="mtd"><g data-mml-node="msubsup"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="22C6" d="M210 282Q210 284 225 381T241 480Q241 484 245 484Q249 486 251 486Q258 486 260 477T272 406Q275 390 276 380Q290 286 290 282L388 299Q484 314 487 314H488Q497 314 497 302Q497 297 434 266Q416 257 404 251L315 206L361 118Q372 98 383 75T401 40L407 28Q407 16 395 16Q394 16 392 16L390 17L250 159L110 17L108 16Q106 16 105 16Q93 16 93 28L99 40Q105 52 116 75T139 118L185 206L96 251Q6 296 4 300Q3 301 3 302Q3 314 12 314H13Q16 314 112 299L210 282Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2814,-247) scale(0.707)"><path data-c="1D70F" d="M39 284Q18 284 18 294Q18 301 45 338T99 398Q134 425 164 429Q170 431 332 431Q492 431 497 429Q517 424 517 402Q517 388 508 376T485 360Q479 358 389 358T299 356Q298 355 283 274T251 109T233 20Q228 5 215 -4T186 -13Q153 -13 153 20V30L203 192Q214 228 227 272T248 336L254 357Q254 358 208 358Q206 358 197 358T183 359Q105 359 61 295Q56 287 53 286T39 284Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(3229.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3618.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4190.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(4579.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1333.6,0)"><g data-mml-node="mn" transform="translate(505,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(220,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g><rect width="1270" height="60" x="120" y="220"></rect></g><g data-mml-node="msup" transform="translate(2843.6,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(750,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1142,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1586,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1975,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2475,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3064,413) scale(0.707)"><path data-c="22C6" d="M210 282Q210 284 225 381T241 480Q241 484 245 484Q249 486 251 486Q258 486 260 477T272 406Q275 390 276 380Q290 286 290 282L388 299Q484 314 487 314H488Q497 314 497 302Q497 297 434 266Q416 257 404 251L315 206L361 118Q372 98 383 75T401 40L407 28Q407 16 395 16Q394 16 392 16L390 17L250 159L110 17L108 16Q106 16 105 16Q93 16 93 28L99 40Q105 52 116 75T139 118L185 206L96 251Q6 296 4 300Q3 301 3 302Q3 314 12 314H13Q16 314 112 299L210 282Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(6311.1,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(6700.1,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(7272.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,1287.5)"><g data-mml-node="mtd" transform="translate(4579.6,0)"></g><g data-mml-node="mtd" transform="translate(4579.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1333.6,0)"><g data-mml-node="mn" transform="translate(505,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(220,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g><rect width="1270" height="60" x="120" y="220"></rect></g><g data-mml-node="mrow" transform="translate(2843.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M180 96T180 250T205 541T266 770T353 944T444 1069T527 1150H555Q561 1144 561 1141Q561 1137 545 1120T504 1072T447 995T386 878T330 721T288 513T272 251Q272 133 280 56Q293 -87 326 -209T399 -405T475 -531T536 -609T561 -640Q561 -643 555 -649H527Q483 -612 443 -568T353 -443T266 -270T205 -41Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(597,0)"><g data-mml-node="mi" transform="translate(220,676)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(255,-686)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><rect width="770" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(1607,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2401.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3401.4,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(5679.4,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6251.4,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(6640.4,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7140.4,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(7640.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(7918.4,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(8490.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(8768.4,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9157.4,0) translate(0 -0.5)"><path data-c="29" d="M35 1138Q35 1150 51 1150H56H69Q113 1113 153 1069T243 944T330 771T391 541T416 250T391 -40T330 -270T243 -443T152 -568T69 -649H56Q43 -649 39 -647T35 -637Q65 -607 110 -548Q283 -316 316 56Q324 133 324 251Q324 368 316 445Q278 877 48 1123Q36 1137 35 1138Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mtr" transform="translate(0,-1061.5)"><g data-mml-node="mtd" transform="translate(4579.6,0)"></g><g data-mml-node="mtd" transform="translate(4579.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1333.6,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(2273.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3067.8,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(4068,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(824,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g><rect width="2478" height="60" x="120" y="220"></rect></g><g data-mml-node="mi" transform="translate(6786,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(7358,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(7747,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(8247,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(8747,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(9025,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9597,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9875,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-3519)"><g data-mml-node="mtd" transform="translate(4579.6,0)"></g><g data-mml-node="mtd" transform="translate(4579.6,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1333.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(2072.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(736,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1898.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2898.4,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(824,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g><rect width="2478" height="60" x="120" y="220"></rect></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5616.4,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mfrac" transform="translate(6116.4,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(824,-686)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g></g><rect width="2478" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(8834.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(9112.4,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9684.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9962.4,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right left" columnspacing="0em" rowspacing="3pt"><mtr><mtd><msubsup><mtext>arctan</mtext><mi>τ</mi><mo>⋆</mo></msubsup><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mtd><mtd><mi><mo>=</mo><mfrac><mn>1</mn><mrow><mn>2</mn><mi>π</mi></mrow></mfrac><msup><mtext> arctan</mtext><mo>⋆</mo></msup><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mi></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mfrac><mn>1</mn><mrow><mn>2</mn><mi>π</mi></mrow></mfrac><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mi>π</mi><mn>4</mn></mfrac><mi>x</mi><mo>+</mo><mn>0.273</mn><mi>x</mi><mo stretchy="false">(</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mi>x</mi><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo stretchy="false">)</mo><mo data-mjx-texclass="CLOSE">)</mo></mrow></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mfrac><mn>1</mn><mn>8</mn></mfrac><mi>x</mi><mo>+</mo><mfrac><mn>0.273</mn><mrow><mn>2</mn><mi>π</mi></mrow></mfrac><mi>x</mi><mo stretchy="false">(</mo><mn>1</mn><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mi>x</mi><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo stretchy="false">)</mo></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mi>x</mi><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mn>1</mn><mn>8</mn></mfrac><mo>+</mo><mfrac><mn>0.273</mn><mrow><mn>2</mn><mi>π</mi></mrow></mfrac><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mfrac><mn>0.273</mn><mrow><mn>2</mn><mi>π</mi></mrow></mfrac><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mi>x</mi><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo data-mjx-texclass="CLOSE">)</mo></mrow></mi></mtd></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>Now the range is <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.816ex;" xmlns="http://www.w3.org/2000/svg" width="8.244ex" height="2.773ex" role="img" focusable="false" viewBox="0 -864.9 3643.8 1225.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mrow"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M202 -349V850H394V810H242V-309H394V-349H202Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(417,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1195,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"></path></g><rect width="553.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1988.6,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2433.2,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" style="stroke-width: 3;"></path></g><rect width="553.6" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(3226.8,0) translate(0 -0.5)"><path data-c="5D" d="M22 810V850H214V-349H22V-309H174V810H22Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mo>−</mo><mfrac><mn>1</mn><mn>8</mn></mfrac><mo>,</mo><mfrac><mn>1</mn><mn>8</mn></mfrac><mo data-mjx-texclass="CLOSE">]</mo></mrow></math></mjx-assistive-mml></mjx-container> in units of turns (or τ). The last form requires only two multiplications and one addition as opposed to the three multiplications and two additions required by the original form.</p>
<p>One more thing: because the final function takes in operands with a range of</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.65ex;" xmlns="http://www.w3.org/2000/svg" width="15.765ex" height="2.347ex" role="img" focusable="false" viewBox="0 -750 6968.3 1037.2" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(490,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(934.7,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1784.4,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2729.2,0)"><path data-c="5B" d="M118 -250V750H255V710H158V-210H255V-250H118Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3007.2,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3785.2,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4285.2,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(4729.9,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="msub" transform="translate(5229.9,0)"><g data-mml-node="mo"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" transform="translate(422,-150) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D444" d="M399 -80Q399 -47 400 -30T402 -11V-7L387 -11Q341 -22 303 -22Q208 -22 138 35T51 201Q50 209 50 244Q50 346 98 438T227 601Q351 704 476 704Q514 704 524 703Q621 689 680 617T740 435Q740 255 592 107Q529 47 461 16L444 8V3Q444 2 449 -24T470 -66T516 -82Q551 -82 583 -60T625 -3Q631 11 638 11Q647 11 649 2Q649 -6 639 -34T611 -100T557 -165T481 -194Q399 -194 399 -87V-80ZM636 468Q636 523 621 564T580 625T530 655T477 665Q429 665 379 640Q277 591 215 464T153 216Q153 110 207 59Q231 38 236 38V46Q236 86 269 120T347 155Q372 155 390 144T417 114T429 82T435 55L448 64Q512 108 557 185T619 334T636 468ZM314 18Q362 18 404 39L403 49Q399 104 366 115Q354 117 347 117Q344 117 341 117T337 118Q317 118 296 98T274 52Q274 18 314 18Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(791,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>y</mi><mo>,</mo><mi>x</mi><mo>∈</mo><mo stretchy="false">[</mo><mo>−</mo><mn>1</mn><mo>,</mo><mn>1</mn><msub><mo stretchy="false">)</mo><mrow data-mjx-texclass="ORD"><mi>Q</mi><mn>15</mn></mrow></msub></math></mjx-assistive-mml></mjx-container><p>in Q15 format and I want its output angle be one turn</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.249ex;" xmlns="http://www.w3.org/2000/svg" width="14.721ex" height="5.528ex" role="img" focusable="false" viewBox="0 -1449.5 6506.8 2443.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D703" d="M35 200Q35 302 74 415T180 610T319 704Q320 704 327 704T339 705Q393 701 423 656Q462 596 462 495Q462 380 417 261T302 66T168 -10H161Q125 -10 99 10T60 63T41 130T35 200ZM383 566Q383 668 330 668Q294 668 260 623T204 521T170 421T157 371Q206 370 254 370L351 371Q352 372 359 404T375 484T383 566ZM113 132Q113 26 166 26Q181 26 198 36T239 74T287 161T335 307L340 324H145Q145 321 136 286T120 208T113 132Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(746.8,0)"><path data-c="2208" d="M84 250Q84 372 166 450T360 539Q361 539 377 539T419 540T469 540H568Q583 532 583 520Q583 511 570 501L466 500Q355 499 329 494Q280 482 242 458T183 409T147 354T129 306T124 272V270H568Q583 262 583 250T568 230H124V228Q124 207 134 177T167 112T231 48T328 7Q355 1 466 0H570Q583 -10 583 -20Q583 -32 568 -40H471Q464 -40 446 -40T417 -41Q262 -41 172 45Q84 127 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="msub" transform="translate(1691.6,0)"><g data-mml-node="mrow"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(528,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(1306,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(2246,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2690.7,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(3630.7,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mi" transform="translate(4399.7,-984.9) scale(0.707)"><path data-c="1D70F" d="M39 284Q18 284 18 294Q18 301 45 338T99 398Q134 425 164 429Q170 431 332 431Q492 431 497 429Q517 424 517 402Q517 388 508 376T485 360Q479 358 389 358T299 356Q298 355 283 274T251 109T233 20Q228 5 215 -4T186 -13Q153 -13 153 20V30L203 192Q214 228 227 272T248 336L254 357Q254 358 208 358Q206 358 197 358T183 359Q105 359 61 295Q56 287 53 286T39 284Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mi>θ</mi><mo>∈</mo><msub><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mo>−</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>,</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow><mi>τ</mi></msub></math></mjx-assistive-mml></mjx-container><p>in 16-bit brads, I actually need to scale the approximation back up to deal with the 1.15→0.16 fixed point conversion:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -3.808ex;" xmlns="http://www.w3.org/2000/svg" width="39.137ex" height="8.748ex" role="img" focusable="false" viewBox="0 -2183.4 17298.6 3866.7" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,1271.8)"><g data-mml-node="mtd"><g data-mml-node="msup"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(3178,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3567,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4139,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(4528,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1333.6,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" style="stroke-width: 3;"></path></g><g data-mml-node="msubsup" transform="translate(1833.6,0)"><g data-mml-node="mtext"><path data-c="A0" d="" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(250,0)" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(750,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(1142,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1586,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1975,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2475,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3064,413) scale(0.707)"><path data-c="22C6" d="M210 282Q210 284 225 381T241 480Q241 484 245 484Q249 486 251 486Q258 486 260 477T272 406Q275 390 276 380Q290 286 290 282L388 299Q484 314 487 314H488Q497 314 497 302Q497 297 434 266Q416 257 404 251L315 206L361 118Q372 98 383 75T401 40L407 28Q407 16 395 16Q394 16 392 16L390 17L250 159L110 17L108 16Q106 16 105 16Q93 16 93 28L99 40Q105 52 116 75T139 118L185 206L96 251Q6 296 4 300Q3 301 3 302Q3 314 12 314H13Q16 314 112 299L210 282Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3064,-247) scale(0.707)"><path data-c="1D70F" d="M39 284Q18 284 18 294Q18 301 45 338T99 398Q134 425 164 429Q170 431 332 431Q492 431 497 429Q517 424 517 402Q517 388 508 376T485 360Q479 358 389 358T299 356Q298 355 283 274T251 109T233 20Q228 5 215 -4T186 -13Q153 -13 153 20V30L203 192Q214 228 227 272T248 336L254 357Q254 358 208 358Q206 358 197 358T183 359Q105 359 61 295Q56 287 53 286T39 284Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(5313.1,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(5702.1,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6274.1,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-733.9)"><g data-mml-node="mtd" transform="translate(4528,0)"></g><g data-mml-node="mtd" transform="translate(4528,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1333.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(2072.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(736,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z" style="stroke-width: 3;"></path></g><rect width="700" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1898.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(2898.4,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1074,-686)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><rect width="2478" height="60" x="120" y="220"></rect></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(5616.4,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mfrac" transform="translate(6116.4,0)"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z" transform="translate(1278,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(1778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1074,-686)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z" style="stroke-width: 3;"></path></g><rect width="2478" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(8834.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(9112.4,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9684.4,0) translate(0 -0.5)"><path data-c="7C" d="M139 -249H137Q125 -249 119 -235V251L120 737Q130 750 139 750Q152 750 159 735V-235Q151 -249 141 -249H139Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9962.4,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right left" columnspacing="0em" rowspacing="3pt"><mtr><mtd><msup><mtext>arctan</mtext><mo>†</mo></msup><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mtd><mtd><mi><mo>=</mo><mn>2</mn><msubsup><mtext> arctan</mtext><mi>τ</mi><mo>⋆</mo></msubsup><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mi></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mi>x</mi><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mn>1</mn><mn>4</mn></mfrac><mo>+</mo><mfrac><mn>0.273</mn><mi>π</mi></mfrac><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><mfrac><mn>0.273</mn><mi>π</mi></mfrac><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mi>x</mi><mo data-mjx-texclass="ORD" stretchy="false">|</mo><mo data-mjx-texclass="CLOSE">)</mo></mrow></mi></mtd></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><h2 id="exploit-function-symmetries" tabindex="-1">Exploit function symmetries <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>To handle inputs not in octant I and VIII, I chose to manipulate the coordinates and exploit the symmetries of <code>atan2</code>. For example, if our input is in octants II and III, then we rotate it by −90°:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -8.278ex;" xmlns="http://www.w3.org/2000/svg" width="35.045ex" height="17.688ex" role="img" focusable="false" viewBox="0 -4159 15489.7 7818" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,2700)"><g data-mml-node="mtd"><g data-mml-node="mrow"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(528,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(605,363) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mtr" transform="translate(0,-709)"><g data-mml-node="mtd" transform="translate(41,0)"><g data-mml-node="msup"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(523,363) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"></path></g></g></g></g></g><g data-mml-node="mo" transform="translate(1377.5,0) translate(0 -0.5)"><path data-c="5D" d="M11 1388V1450H280V-949H11V-887H218V1388H11Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtd" transform="translate(1905.5,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(1333.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(528,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(944,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1504.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2282.7,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(3282.7,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(4782.7,0)"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(944.7,0)"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(394,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(672,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2339.3,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3117.3,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(4117.3,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-700)"><g data-mml-node="mtd" transform="translate(55,0)"><g data-mml-node="mi"><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" style="stroke-width: 3;"></path><path data-c="69" d="M69 609Q69 637 87 653T131 669Q154 667 171 652T188 609Q188 579 171 564T129 549Q104 549 87 564T69 609ZM247 0Q232 3 143 3Q132 3 106 3T56 1L34 0H26V46H42Q70 46 91 49Q100 53 102 60T104 102V205V293Q104 345 102 359T88 378Q74 385 41 385H30V408Q30 431 32 431L42 432Q52 433 70 434T106 436Q123 437 142 438T171 441T182 442H185V62Q190 52 197 50T232 46H255V0H247Z" transform="translate(394,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(672,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1394.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2172.7,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(3172.7,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(5200,0)"><g data-mml-node="mi"><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" style="stroke-width: 3;"></path><path data-c="6F" d="M28 214Q28 309 93 378T250 448Q340 448 405 380T471 215Q471 120 407 55T250 -10Q153 -10 91 57T28 214ZM250 30Q372 30 372 193V225V250Q372 272 371 288T364 326T348 362T317 390T268 410Q263 411 252 411Q222 411 195 399Q152 377 139 338T126 246V226Q126 130 145 91Q177 30 250 30Z" transform="translate(444,0)" style="stroke-width: 3;"></path><path data-c="73" d="M295 316Q295 356 268 385T190 414Q154 414 128 401Q98 382 98 349Q97 344 98 336T114 312T157 287Q175 282 201 278T245 269T277 256Q294 248 310 236T342 195T359 133Q359 71 321 31T198 -10H190Q138 -10 94 26L86 19L77 10Q71 4 65 -1L54 -11H46H42Q39 -11 33 -5V74V132Q33 153 35 157T45 162H54Q66 162 70 158T75 146T82 119T101 77Q136 26 198 26Q295 26 295 104Q295 133 277 151Q257 175 194 187T111 210Q75 227 54 256T33 318Q33 357 50 384T93 424T143 442T187 447H198Q238 447 268 432L283 424L292 431Q302 440 314 448H322H326Q329 448 335 442V310L329 304H301Q295 310 295 316Z" transform="translate(944,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1504.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2282.7,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(3282.7,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(9928,0) translate(0 -0.5)"><path data-c="5D" d="M11 1388V1450H280V-949H11V-887H218V1388H11Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(11956.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(528,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-700)"><g data-mml-node="mtd" transform="translate(41,0)"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(1100,0) translate(0 -0.5)"><path data-c="5D" d="M11 1388V1450H280V-949H11V-887H218V1388H11Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mtr" transform="translate(0,-9)"><g data-mml-node="mtd" transform="translate(1905.5,0)"></g><g data-mml-node="mtd" transform="translate(1905.5,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(1333.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(528,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd" transform="translate(389,0)"><g data-mml-node="mn"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(2278,0)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-700)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(778,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(2278,0)"><g data-mml-node="mn"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(3306,0) translate(0 -0.5)"><path data-c="5D" d="M11 1388V1450H280V-949H11V-887H218V1388H11Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(5334.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(528,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-700)"><g data-mml-node="mtd" transform="translate(41,0)"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(1100,0) translate(0 -0.5)"><path data-c="5D" d="M11 1388V1450H280V-949H11V-887H218V1388H11Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mtr" transform="translate(0,-2709)"><g data-mml-node="mtd" transform="translate(1905.5,0)"></g><g data-mml-node="mtd" transform="translate(1905.5,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(1333.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="5B" d="M247 -949V1450H516V1388H309V-887H516V-949H247Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtable" transform="translate(528,0)"><g data-mml-node="mtr" transform="translate(0,700)"><g data-mml-node="mtd" transform="translate(430,0)"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-700)"><g data-mml-node="mtd"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g></g></g></g><g data-mml-node="mo" transform="translate(1878,0) translate(0 -0.5)"><path data-c="5D" d="M11 1388V1450H280V-949H11V-887H218V1388H11Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right left" columnspacing="0em" rowspacing="3pt"><mtr><mtd><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="4pt"><mtr><mtd><msup><mi>x</mi><mo data-mjx-alternate="1">′</mo></msup></mtd></mtr><mtr><mtd><msup><mi>y</mi><mo data-mjx-alternate="1">′</mo></msup></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE">]</mo></mrow></mtd><mtd><mi><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="4pt"><mtr><mtd><mi>cos</mi><mo>−</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi></mtd><mtd><mo>−</mo><mi>sin</mi><mo>−</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi></mtd></mtr><mtr><mtd><mi>sin</mi><mo>−</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi></mtd><mtd><mi>cos</mi><mo>−</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE">]</mo></mrow><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="4pt"><mtr><mtd><mi>x</mi></mtd></mtr><mtr><mtd><mi>y</mi></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE">]</mo></mrow></mi></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="4pt"><mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mo>−</mo><mn>1</mn></mtd><mtd><mn>0</mn></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE">]</mo></mrow><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="4pt"><mtr><mtd><mi>x</mi></mtd></mtr><mtr><mtd><mi>y</mi></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE">]</mo></mrow></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="4pt"><mtr><mtd><mi>y</mi></mtd></mtr><mtr><mtd><mo>−</mo><mi>x</mi></mtd></mtr></mtable><mo data-mjx-texclass="CLOSE">]</mo></mrow></mi></mtd></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>Now x′ and y′ are in octants I and VIII—as required—and we can pass them to our approximate arctangent:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -2.148ex;" xmlns="http://www.w3.org/2000/svg" width="13.815ex" height="5.428ex" role="img" focusable="false" viewBox="0 -1449.5 6106.1 2399" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(3344.6,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(736,0)"><g data-mml-node="msup" transform="translate(261,676)"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(523,363) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="msup" transform="translate(220,-686)"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(605,289) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"></path></g></g><rect width="1049.5" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(2025.5,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><msup><mtext>arctan</mtext><mo>†</mo></msup><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><msup><mi>y</mi><mo data-mjx-alternate="1">′</mo></msup><msup><mi>x</mi><mo data-mjx-alternate="1">′</mo></msup></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow></math></mjx-assistive-mml></mjx-container><p>The result then needs to be rotated 90° to put it back into octants II and III. This is easy since the result is already in angular units: just add 90°. Altogether, it looks like this:</p>
<mjx-container class="MathJax" jax="SVG" display="true" style="direction: ltr; display: block; text-align: center; margin: 1em 0; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -8.255ex;" xmlns="http://www.w3.org/2000/svg" width="34.824ex" height="17.64ex" role="img" focusable="false" viewBox="0 -4148.5 15392.3 7797" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtable"><g data-mml-node="mtr" transform="translate(0,2699)"><g data-mml-node="mtd"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(889,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(1389,0)" style="stroke-width: 3;"></path><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z" transform="translate(1945,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2445,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(2834,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3324,0)"><path data-c="2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3768.7,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4340.7,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mtd" transform="translate(4729.7,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(1333.6,0)"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(4678.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(736,0)"><g data-mml-node="msup" transform="translate(261,676)"><g data-mml-node="mi"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(523,363) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="msup" transform="translate(220,-686)"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(605,289) scale(0.707)"><path data-c="2032" d="M79 43Q73 43 52 49T30 61Q30 68 85 293T146 528Q161 560 198 560Q218 560 240 545T262 501Q262 496 260 486Q259 479 173 263T84 45T79 43Z" style="stroke-width: 3;"></path></g></g><rect width="1049.5" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(2025.5,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(7661.9,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(8662.1,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(9662.1,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,0)"><g data-mml-node="mtd" transform="translate(4729.7,0)"></g><g data-mml-node="mtd" transform="translate(4729.7,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="msup" transform="translate(1333.6,0)"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(4678.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(736,0)"><g data-mml-node="mrow" transform="translate(220,676)"><g data-mml-node="mo"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(778,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mi" transform="translate(650,-686)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><rect width="1550" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(2526,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(8162.4,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9162.6,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(10162.6,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g></g></g><g data-mml-node="mtr" transform="translate(0,-2699)"><g data-mml-node="mtd" transform="translate(4729.7,0)"></g><g data-mml-node="mtd" transform="translate(4729.7,0)"><g data-mml-node="mi"></g><g data-mml-node="mo" transform="translate(277.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(1333.6,0)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" class=" MathML-Unit" transform="translate(2333.6,0)"><path data-c="B0" d="M147 628Q147 669 179 692T244 715Q298 715 325 689T352 629Q352 592 323 567T249 542Q202 542 175 567T147 628ZM313 628Q313 660 300 669T259 678H253Q248 678 242 678T234 679Q217 679 207 674T192 659T188 644T187 629Q187 600 198 590Q210 579 250 579H265Q279 579 288 581T305 595T313 628Z" style="stroke-width: 3;"></path></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(2833.6,0)"><g data-mml-node="mo"><path data-c="2013" d="M0 248V285H499V248H0Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="msup" transform="translate(3333.6,0)"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,413) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mrow" transform="translate(6678.2,0)"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M701 -940Q701 -943 695 -949H664Q662 -947 636 -922T591 -879T537 -818T475 -737T412 -636T350 -511T295 -362T250 -186T221 17T209 251Q209 962 573 1361Q596 1386 616 1405T649 1437T664 1450H695Q701 1444 701 1441Q701 1436 681 1415T629 1356T557 1261T476 1118T400 927T340 675T308 359Q306 321 306 250Q306 -139 400 -430T690 -924Q701 -936 701 -940Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(736,0)"><g data-mml-node="mi" transform="translate(220,676)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(261,-686)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><rect width="772" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(1748,0) translate(0 -0.5)"><path data-c="29" d="M34 1438Q34 1446 37 1448T50 1450H56H71Q73 1448 99 1423T144 1380T198 1319T260 1238T323 1137T385 1013T440 864T485 688T514 485T526 251Q526 134 519 53Q472 -519 162 -860Q139 -885 119 -904T86 -936T71 -949H56Q43 -949 39 -947T34 -937Q88 -883 140 -813Q428 -430 428 251Q428 453 402 628T338 922T245 1146T145 1309T46 1425Q44 1427 42 1429T39 1433T36 1436L34 1438Z" style="stroke-width: 3;"></path></g></g></g></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="block" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; overflow: hidden; width: 100%;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><mtable displaystyle="true" columnalign="right left" columnspacing="0em" rowspacing="3pt"><mtr><mtd><mtext>atan2</mtext><mo stretchy="false">(</mo><mi>y</mi><mo>,</mo><mi>x</mi><mo stretchy="false">)</mo></mtd><mtd><mi><mo>=</mo><msup><mtext>arctan</mtext><mo>†</mo></msup><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><msup><mi>y</mi><mo data-mjx-alternate="1">′</mo></msup><msup><mi>x</mi><mo data-mjx-alternate="1">′</mo></msup></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow><mo>+</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi></mi></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><msup><mtext>arctan</mtext><mo>†</mo></msup><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mrow><mo>−</mo><mi>x</mi></mrow><mi>y</mi></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow><mo>+</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi></mi></mtd></mtd></mtr><mtr><mtd><mtd><mi><mo>=</mo><mn>90</mn><mi mathvariant="normal" class="MathML-Unit">°</mi><mrow data-mjx-texclass="ORD"><mo>–</mo></mrow><msup><mtext>arctan</mtext><mo>†</mo></msup><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mi>x</mi><mi>y</mi></mfrac><mo data-mjx-texclass="CLOSE">)</mo></mrow></mi></mtd></mtd></mtr></mtable></math></mjx-assistive-mml></mjx-container><p>I took it a step further here by using arctangent’s property as an odd function: <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.566ex;" xmlns="http://www.w3.org/2000/svg" width="25.23ex" height="2.262ex" role="img" focusable="false" viewBox="0 -750 11151.6 1000" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2781,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(3170,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(3948,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(4520,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(5186.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(6242.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mtext" transform="translate(7020.6,0)"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(9801.6,0)"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(10190.6,0)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(10762.6,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>arctan</mtext><mo stretchy="false">(</mo><mo>−</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo>−</mo><mtext>arctan</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></math></mjx-assistive-mml></mjx-container>. In terms of implementation, this means:</p>
<ol>
<li>Invert the division by swapping the two arguments<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" id="fnref7">♥</a></sup>.</li>
<li>Flip the output sign of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="7.19ex" height="1.974ex" role="img" focusable="false" viewBox="0 -861.5 3178 872.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,363) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mtext>arctan</mtext><mo>†</mo></msup></math></mjx-assistive-mml></mjx-container>.</li>
<li>Add 90° or 0.25 turns or 16384 brads to the result.</li>
</ol>
<p>For the other octants, similar transformations can be applied to put them into the valid domain of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.025ex;" xmlns="http://www.w3.org/2000/svg" width="7.19ex" height="1.974ex" role="img" focusable="false" viewBox="0 -861.5 3178 872.5" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="msup"><g data-mml-node="mtext"><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" style="stroke-width: 3;"></path><path data-c="72" d="M36 46H50Q89 46 97 60V68Q97 77 97 91T98 122T98 161T98 203Q98 234 98 269T98 328L97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 60 434T96 436Q112 437 131 438T160 441T171 442H174V373Q213 441 271 441H277Q322 441 343 419T364 373Q364 352 351 337T313 322Q288 322 276 338T263 372Q263 381 265 388T270 400T273 405Q271 407 250 401Q234 393 226 386Q179 341 179 207V154Q179 141 179 127T179 101T180 81T180 66V61Q181 59 183 57T188 54T193 51T200 49T207 48T216 47T225 47T235 46T245 46H276V0H267Q249 3 140 3Q37 3 28 0H20V46H36Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="63" d="M370 305T349 305T313 320T297 358Q297 381 312 396Q317 401 317 402T307 404Q281 408 258 408Q209 408 178 376Q131 329 131 219Q131 137 162 90Q203 29 272 29Q313 29 338 55T374 117Q376 125 379 127T395 129H409Q415 123 415 120Q415 116 411 104T395 71T366 33T318 2T249 -11Q163 -11 99 53T34 214Q34 318 99 383T250 448T370 421T404 357Q404 334 387 320Z" transform="translate(892,0)" style="stroke-width: 3;"></path><path data-c="74" d="M27 422Q80 426 109 478T141 600V615H181V431H316V385H181V241Q182 116 182 100T189 68Q203 29 238 29Q282 29 292 100Q293 108 293 146V181H333V146V134Q333 57 291 17Q264 -10 221 -10Q187 -10 162 2T124 33T105 68T98 100Q97 107 97 248V385H18V422H27Z" transform="translate(1336,0)" style="stroke-width: 3;"></path><path data-c="61" d="M137 305T115 305T78 320T63 359Q63 394 97 421T218 448Q291 448 336 416T396 340Q401 326 401 309T402 194V124Q402 76 407 58T428 40Q443 40 448 56T453 109V145H493V106Q492 66 490 59Q481 29 455 12T400 -6T353 12T329 54V58L327 55Q325 52 322 49T314 40T302 29T287 17T269 6T247 -2T221 -8T190 -11Q130 -11 82 20T34 107Q34 128 41 147T68 188T116 225T194 253T304 268H318V290Q318 324 312 340Q290 411 215 411Q197 411 181 410T156 406T148 403Q170 388 170 359Q170 334 154 320ZM126 106Q126 75 150 51T209 26Q247 26 276 49T315 109Q317 116 318 175Q318 233 317 233Q309 233 296 232T251 223T193 203T147 166T126 106Z" transform="translate(1725,0)" style="stroke-width: 3;"></path><path data-c="6E" d="M41 46H55Q94 46 102 60V68Q102 77 102 91T102 122T103 161T103 203Q103 234 103 269T102 328V351Q99 370 88 376T43 385H25V408Q25 431 27 431L37 432Q47 433 65 434T102 436Q119 437 138 438T167 441T178 442H181V402Q181 364 182 364T187 369T199 384T218 402T247 421T285 437Q305 442 336 442Q450 438 463 329Q464 322 464 190V104Q464 66 466 59T477 49Q498 46 526 46H542V0H534L510 1Q487 2 460 2T422 3Q319 3 310 0H302V46H318Q379 46 379 62Q380 64 380 200Q379 335 378 343Q372 371 358 385T334 402T308 404Q263 404 229 370Q202 343 195 315T187 232V168V108Q187 78 188 68T191 55T200 49Q221 46 249 46H265V0H257L234 1Q210 2 183 2T145 3Q42 3 33 0H25V46H41Z" transform="translate(2225,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2814,363) scale(0.707)"><path data-c="2020" d="M182 675Q195 705 222 705Q234 705 243 700T253 691T263 675L262 655Q262 620 252 549T240 454V449Q250 451 288 461T346 472T377 461T389 431Q389 417 379 404T346 390Q327 390 288 401T243 412H240V405Q245 367 250 339T258 301T261 274T263 225Q263 124 255 -41T239 -213Q236 -216 222 -216H217Q206 -216 204 -212T200 -186Q199 -175 199 -168Q181 38 181 225Q181 265 182 280T191 327T204 405V412H201Q196 412 157 401T98 390Q76 390 66 403T55 431T65 458T98 472Q116 472 155 462T205 449Q204 452 204 460T201 490T193 547Q182 619 182 655V675Z" style="stroke-width: 3;"></path></g></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mtext>arctan</mtext><mo>†</mo></msup></math></mjx-assistive-mml></mjx-container> and results can likewise be rotated back.</p>
<p>Lastly as a detail, the boundary condition <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="5.42ex" height="1.783ex" role="img" focusable="false" viewBox="0 -583 2395.6 788" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(849.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1905.6,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi><mo>=</mo><mi>y</mi></math></mjx-assistive-mml></mjx-container> needs to be tested for. This is because the result of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.798ex;" xmlns="http://www.w3.org/2000/svg" width="1.911ex" height="2.602ex" role="img" focusable="false" viewBox="0 -797.5 844.5 1150.3" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mi" transform="translate(249,485) scale(0.707)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(220,-345) scale(0.707)"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><rect width="604.5" height="60" x="120" y="220"></rect></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac><mi>y</mi><mi>x</mi></mfrac></math></mjx-assistive-mml></mjx-container>, 1, can’t be represented in the Q1.0.15 format. Fortunately, the result of <code>atan2</code> for those cases is obvious. That is, with the exception of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.464ex;" xmlns="http://www.w3.org/2000/svg" width="9.568ex" height="1.971ex" role="img" focusable="false" viewBox="0 -666 4229.1 871" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mi"><path data-c="1D465" d="M52 289Q59 331 106 386T222 442Q257 442 286 424T329 379Q371 442 430 442Q467 442 494 420T522 361Q522 332 508 314T481 292T458 288Q439 288 427 299T415 328Q415 374 465 391Q454 404 425 404Q412 404 406 402Q368 386 350 336Q290 115 290 78Q290 50 306 38T341 26Q378 26 414 59T463 140Q466 150 469 151T485 153H489Q504 153 504 145Q504 144 502 134Q486 77 440 33T333 -11Q263 -11 227 52Q186 -10 133 -10H127Q78 -10 57 16T35 71Q35 103 54 123T99 143Q142 143 142 101Q142 81 130 66T107 46T94 41L91 40Q91 39 97 36T113 29T132 26Q168 26 194 71Q203 87 217 139T245 247T261 313Q266 340 266 352Q266 380 251 392T217 404Q177 404 142 372T93 290Q91 281 88 280T72 278H58Q52 284 52 289Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(849.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(1905.6,0)"><path data-c="1D466" d="M21 287Q21 301 36 335T84 406T158 442Q199 442 224 419T250 355Q248 336 247 334Q247 331 231 288T198 191T182 105Q182 62 196 45T238 27Q261 27 281 38T312 61T339 94Q339 95 344 114T358 173T377 247Q415 397 419 404Q432 431 462 431Q475 431 483 424T494 412T496 403Q496 390 447 193T391 -23Q363 -106 294 -155T156 -205Q111 -205 77 -183T43 -117Q43 -95 50 -80T69 -58T89 -48T106 -45Q150 -45 150 -87Q150 -107 138 -122T115 -142T102 -147L99 -148Q101 -153 118 -160T152 -167H160Q177 -167 186 -165Q219 -156 247 -127T290 -65T313 -9T321 21L315 17Q309 13 296 6T270 -6Q250 -11 231 -11Q185 -11 150 11T104 82Q103 89 103 113Q103 170 138 262T173 379Q173 380 173 381Q173 390 173 393T169 400T158 404H154Q131 404 112 385T82 344T65 302T57 280Q55 278 41 278H27Q21 284 21 287Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(2673.3,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(3729.1,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi><mo>=</mo><mi>y</mi><mo>=</mo><mn>0</mn></math></mjx-assistive-mml></mjx-container>, which we just have to test for explicitly and handle as an error.</p>
<h2 id="book-mark" tabindex="-1">Book mark <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>My derivations here diverged from the four-quadrant formula in the book. I marked these as wrong in 2012, but I’m not so sure they’re different from my implementation when accounting for signed↔unsigned angular output.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Wn8qthzVrJ-690.avif 690w, https://geekshavefeelings.com/img/Wn8qthzVrJ-969.avif 969w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Wn8qthzVrJ-690.webp 690w, https://geekshavefeelings.com/img/Wn8qthzVrJ-969.webp 969w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/Wn8qthzVrJ-690.png 690w, https://geekshavefeelings.com/img/Wn8qthzVrJ-969.png 969w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Never trust a Canadian" src="https://geekshavefeelings.com/img/Wn8qthzVrJ-690.png" width="969" height="710"></picture><figcaption>Streamlining DSP table</figcaption></figure><p></p>
<p>It looks like the octants IV and V equation accounts for the sign change across the signed <code>atan2</code> discontinuity. However, since binary angle discontinuity is handled by integer overflow aligned with the output of my <code>atan2</code>, I can handle octants IV and V simply as the 180° rotated version of octants I and VII.</p>
<h2 id="nabs-rocks" tabindex="-1"><a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic"><code>nabs</code></a> rocks <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<p>So anyways, here’s the implementation. I should note that the code relies on a <code>q15_mul</code> function that perform rounding of the product from the 32-bit intermediate to 16-bit result for maximum accuracy. Also, <code>s16_nabs</code> is a function for <a href="https://geekshavefeelings.com/posts/2013/real-talk-integer-arithmetic"><em>negative absolute value</em></a>. Why use <code>nabs</code>? Well, <code>abs</code> is undefined for the most negative number, and chances are if you plug the Q15 value for −1 into <code>abs</code>, you’ll get −1 back out. <em>Negative</em> absolute value, on the other hand, is pretty easy to keep fully defined.</p>
<p>I knew how much theoretical error to expect, but I wasn't sure how to analyze my approximate arctangent's fixed-point implementation. So, I brute-force ran all 2<sup>16</sup> × 2<sup>16</sup> = 4294967296 possible inputs and computed their errors relative to the double-precision <code>atan2</code> implementation in the GNU C library. I got a worst-case error of 0.221°, which means I’m not losing much precision or introducing quantization error by using fixed-point, and there’s an root mean square (RMS) error of about 0.0004 turns.</p>
<p><code>s16_nabs</code>, <code>q15_mul</code>, <code>q15_div</code>, and of course <code>fxpt_atan2</code> are all included in this MIT-licensed source file: <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/files/fxpt_atan2.c">fxpt_atan2.c</a></p>
<p>A DSP library might have faster/better versions of some of those functions that may take advantage of your microcontroller’s DSP ALU.</p>
<h2 id="codes" tabindex="-1">Codes! <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">/**
* 16-bit fixed point four-quadrant arctangent. Given some Cartesian vector
* (x, y), find the angle subtended by the vector and the positive x-axis.
*
* The value returned is in units of 1/65536ths of one turn. This allows the use
* of the full 16-bit unsigned range to represent a turn. e.g. 0x0000 is 0
* radians, 0x8000 is pi radians, and 0xFFFF is (65535 / 32768) * pi radians.
*
* Because the magnitude of the input vector does not change the angle it
* represents, the inputs can be in any signed 16-bit fixed-point format.
*
* @param y y-coordinate in signed 16-bit
* @param x x-coordinate in signed 16-bit
* @return angle in (val / 32768) * pi radian increments from 0x0000 to 0xFFFF
*/</span>
<span class="token keyword">uint16_t</span> <span class="token function">fxpt_atan2</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int16_t</span> y<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">int16_t</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>x <span class="token operator">==</span> y<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// x/y or y/x would return -1 since 1 isn't representable</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>y <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 1/8</span>
<span class="token keyword">return</span> <span class="token number">8192</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>y <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 5/8</span>
<span class="token keyword">return</span> <span class="token number">40960</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// x = y = 0</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> nabs_y <span class="token operator">=</span> <span class="token function">s16_nabs</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span><span class="token punctuation">,</span> nabs_x <span class="token operator">=</span> <span class="token function">s16_nabs</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>nabs_x <span class="token operator"><</span> nabs_y<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// octants 1, 4, 5, 8</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> y_over_x <span class="token operator">=</span> <span class="token function">q15_div</span><span class="token punctuation">(</span>y<span class="token punctuation">,</span> x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> correction <span class="token operator">=</span> <span class="token function">q15_mul</span><span class="token punctuation">(</span><span class="token function">q15_from_double</span><span class="token punctuation">(</span><span class="token number">0.273</span> <span class="token operator">*</span> M_1_PI<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">s16_nabs</span><span class="token punctuation">(</span>y_over_x<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> unrotated <span class="token operator">=</span> <span class="token function">q15_mul</span><span class="token punctuation">(</span><span class="token function">q15_from_double</span><span class="token punctuation">(</span><span class="token number">0.25</span> <span class="token operator">+</span> <span class="token number">0.273</span> <span class="token operator">*</span> M_1_PI<span class="token punctuation">)</span> <span class="token operator">+</span> correction<span class="token punctuation">,</span> y_over_x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>x <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// octants 1, 8</span>
<span class="token keyword">return</span> unrotated<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// octants 4, 5</span>
<span class="token keyword">return</span> <span class="token number">32768</span> <span class="token operator">+</span> unrotated<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// octants 2, 3, 6, 7</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> x_over_y <span class="token operator">=</span> <span class="token function">q15_div</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> correction <span class="token operator">=</span> <span class="token function">q15_mul</span><span class="token punctuation">(</span><span class="token function">q15_from_double</span><span class="token punctuation">(</span><span class="token number">0.273</span> <span class="token operator">*</span> M_1_PI<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">s16_nabs</span><span class="token punctuation">(</span>x_over_y<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int16_t</span> unrotated <span class="token operator">=</span> <span class="token function">q15_mul</span><span class="token punctuation">(</span><span class="token function">q15_from_double</span><span class="token punctuation">(</span><span class="token number">0.25</span> <span class="token operator">+</span> <span class="token number">0.273</span> <span class="token operator">*</span> M_1_PI<span class="token punctuation">)</span> <span class="token operator">+</span> correction<span class="token punctuation">,</span> x_over_y<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>y <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// octants 2, 3</span>
<span class="token keyword">return</span> <span class="token number">16384</span> <span class="token operator">-</span> unrotated<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// octants 6, 7</span>
<span class="token keyword">return</span> <span class="token number">49152</span> <span class="token operator">-</span> unrotated<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Or a and b from a complex number, if you swing that way. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>In regular <code>atan</code>, you’d write <code>atan(y/x)</code>, which is why <code>atan2</code>'s argument order is y then x. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>If that’s confusing, look them up before continuing because it’s about to get worse. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Trust me, +1 really is missing from the range. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>Note that since we’re approximating an odd function with a quadratic, we need that absolute value in the equation to make the second-order term become even. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>Actually octants IV and V in my non-negative output <code>atan2</code>, but that’s handled by the signed↔unsigned conversion and is an implementation detail. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn7" class="footnote-item"><p>Conveniently, but not coincidentally, the swapping prevents the quotient from exceeding 1. <a href="https://geekshavefeelings.com/posts/2012/fixed-point-atan2/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
It Was Never About the Mileage
2012-12-24T06:06:42Z
https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/OeuIqpAJJJ-690.avif 690w, https://geekshavefeelings.com/img/OeuIqpAJJJ-1380.avif 1380w, https://geekshavefeelings.com/img/OeuIqpAJJJ-3000.avif 3000w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/OeuIqpAJJJ-690.webp 690w, https://geekshavefeelings.com/img/OeuIqpAJJJ-1380.webp 1380w, https://geekshavefeelings.com/img/OeuIqpAJJJ-3000.webp 3000w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/OeuIqpAJJJ-690.jpeg 690w, https://geekshavefeelings.com/img/OeuIqpAJJJ-1380.jpeg 1380w, https://geekshavefeelings.com/img/OeuIqpAJJJ-3000.jpeg 3000w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="2009 GMC Sierra Hybrid Crew Cab" src="https://geekshavefeelings.com/img/OeuIqpAJJJ-690.jpeg" width="3000" height="1839"></picture></figure><p></p>
<p>I was dismayed and slightly infuriated to find that the <a href="http://www.foxnews.com/leisure/2012/12/13/gm-to-stop-building-hybrid-pickup-trucks-next-year/" title="Fox News: GM ending hybrid pickup truck production next year">GMC Sierra Hybrid has been axed for 2014</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" id="fnref1">*</a></sup>, but wasn’t at all surprised.</p>
<p>The problem with the Sierra Hybrid, a full-size pickup truck (and its nearly identical brother, the Yukon SUV), was that it was created for Americans and appreciated only by engineers. When you think about how little pickup-needing construction work most engineers do, that already-minuscule intersection makes for an pretty nonexistent market. In fact, considering GM vehicles are designed <em>by</em> American engineers<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" id="fnref2">†</a></sup>, as any current tech school student can attest to.], I’m surprised this kind of marketing disaster doesn’t happen more often<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" id="fnref3">‡</a></sup>.</p>
<p>Let me demonstrate. What’s the question that’s been been on your mind since you found out about this <em>hybrid pickup truck</em>?</p>
<p>Yeah, “what kind of miles do you get to the gallon?”</p>
<p>But actually consider the Yukon Hybrid. Compared to a standard similarly-equipped good ol’ internal-combustion Yukon, it’s somewhere between $3000–$6000 more and weighs 262lb. On top of a ~$50,000 sticker and 5694lb curb weight, those are nothing. Here’s what you get in return:</p>
<ul>
<li>Two 60kW electric motors, which produce maximum torque at a dead stop (no clutch needed, unlike the IC engine which produces peak torque at 4100RPM)</li>
<li>A NiMH battery pack that fits under the rear seats, taking up no additional space, and which can provide enough juice to get to 30mph under pure silent electric power</li>
<li>A <a href="http://en.wikipedia.org/wiki/Continuously_variable_transmission" title="Continuously variable transmission">continuously variable transmission (CVT)</a> that juggles the torques from the motors to optimize the output of the 6.0L V8</li>
</ul>
<p>It’s an engineer’s wet dream; the hybrid system truly <a href="http://www.gmc.com/2012-yukon-hybrid-suv/features-specs/powertrain.html" title="GMC 2012 Yukon Hybrid">enhances the vehicle performance</a> in areas that matter to people who buy trucks and SUVs: acceleration (torque) and towing capacity (torque, but also power), without compromise. Heck, older versions of the Sierra even had <a href="http://www.edmunds.com/gmc/sierra-1500-hybrid/" title="Edmunds GMC Sierra 1500 Hybrid Review">120VAC outlets</a>, which is hilariously like having the reverse of a <a href="http://en.wikipedia.org/wiki/Plug-in_hybrid" title="Plug-in hybrid">plug-in hybrid</a> system, but seems genuinely useful for e.g. a contractor with corded power tools or somebody living in a remote area with flakey power.</p>
<p><a href="http://www.motortrend.com/roadtests/oneyear/112_0604lt_2004_chevrolet_silverado_hybrid/photos/"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/4Cyz3hrHja-480.avif 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/4Cyz3hrHja-480.webp 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="HEV charging a BEV... wait, what?" src="https://geekshavefeelings.com/img/4Cyz3hrHja-480.jpeg" width="480" height="300"></picture></figure></a></p>
<p>Sadly, consumers and journalists remain strapped to the myth that hybrids must be slow and small, and that their only reason to exist is to save gas, forcing carmakers to pander to that fiction. People simply don’t stop think <em>why</em> you’d build a second traction system into a car; instead, they file away hybrids as it were some expensive, heavy gadget that magically (and only) reduces the amount of gas used.</p>
<p>For example, people expect hybridizing to be appropriate only for vehicles small and light. I mean, if you’re buying a hybrid, you <em>must</em> only want to save gas, and to have extra capacity obviously <em>ruins</em> the entire vehicle. Truth is, it’s actually more difficult and less effective to hybridize a light vehicle—one of the reasons why you don’t see any motorcycles sporting extra batteries and motors—while throwing even a ton (1000 pounds) of batteries, motors, and motor controllers onto anything in our “<a href="http://en.wikipedia.org/wiki/Light_truck" title="Light truck">light truck</a>” category won’t really make a huge difference in weight and space.</p>
<p>⋮</p>
<p>My first knowledge of hybrid trucks was when I spoke to Jerry Meisel, who had advised the Georgia Tech FutureTruck team. For whatever reason, the Department of Energy (DOE) decided more than a decade ago<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" id="fnref4">§</a></sup> to invite university teams to build the most eco-friendly vehicles possible, given a toolkit consisting of a Ford Explorer<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" id="fnref5">¶</a></sup> and $10,000.</p>
<p><a href="http://editorial.autos.msn.com/article.aspx?cp-documentid=435065"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/lwnsBJkdLz-380.avif 380w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/lwnsBJkdLz-380.webp 380w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="FT03" src="https://geekshavefeelings.com/img/lwnsBJkdLz-380.jpeg" width="380" height="228"></picture></figure></a></p>
<p>Three years after the competition began, the GT team began to miss the point completely<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" id="fnref6">♠</a></sup> and <a href="http://papers.sae.org/2003-01-1270/" title="Georgia Tech's FutureTruck Split-Parallel Hybrid SUV Design">had instead crammed</a> a <a href="http://www.acpropulsion.com/datasheet/AC-150%20Motor.pdf" title="AC-150 motor">150kW motor</a> onto the front of their Explorer, then chose the “largest V6 that would fit” to power the rear axle. Although the “Future<a href="http://en.wikipedia.org/wiki/Ramblin'_Wreck" title="Ramblin' Wreck">Wreck</a>” showed it was capable of “takin’ off like greased lightnin'” at the Michigan proving grounds, it took no higher than fourth place. I’ll let Jerry himself <a href="http://www.whistle.gatech.edu/archives/03/jun/30/futuretruck.html" title="Student team finishes fourth in National FutureTruck Competition">explain why</a>:</p>
<blockquote>
<p>“Even though [our entry] really performed better than any other powertrain, [the judges] were looking for designs that had some combination of a diesel engine, the use of an alternate fuel to gasoline and some aggressive weight reduction by replacing the stock steel frame,” said Professor Jerry Meisel. “We more than met the competition’s stated goals in actual operation, but had none of these unstated approaches in our design.”</p>
</blockquote>
<p>At least it took home the award for acceleration.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/lULrzYRjEe-260.avif 260w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/lULrzYRjEe-260.webp 260w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Georgia Tech stirs up the precision portion of the off-road event" src="https://geekshavefeelings.com/img/lULrzYRjEe-260.jpeg" width="260" height="200"></picture></figure><p></p>
<p>⋮</p>
<p>Why the market remains convinced that hybrid systems are for ugly featherweight cars with rubbish names is a mystery to me. Consider this: modern electric traction systems are so powerful, <a href="http://en.wikipedia.org/wiki/Jaguar_C-X75" title="Jaguar C-X75">Jaguar built a £1 million supercar</a> where they were the only source of propulsion. <a href="http://jalopnik.com/5220219/general-dynamics-rst+v-series+hybrid-with-cool-in+wheel-motors" title="General Dynamics RST-V Series-Hybrid With Cool In-Wheel Motors">General Dynamics</a> and BAE are <a href="http://media.idtechex.com/pdfs/en/W2355M4634.pdf" title="Military Electric Vehicles - Where, Why, What Next?">building armored military vehicles</a>, including even <a href="http://www.greenbiz.com/blog/2011/10/21/bae-systems-bid-design-greener-next-gen-tank" title="BAE Systems' Bid to Design a Greener, Next-Gen 'Tank'">battle tanks</a>, propelled by electric power. Their applications in the military especially highlight the subtler auxiliary benefits of modern motors beyond their unholy torque ratings: flexible power routing, whisper-quiet operation, low parts count, and solid reliability.</p>
<p><a href="http://www.flickr.com/photos/baesystemsinc/8189488524/" title="Power Up GCV Infographic by BAESystemsInc, on Flickr"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Xb9fOuNQBp-640.avif 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Xb9fOuNQBp-640.webp 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Power Up GCV Infographic" src="https://geekshavefeelings.com/img/Xb9fOuNQBp-640.jpeg" width="640" height="402"></picture></figure></a></p>
<p>In fact, I should note that somebody involved with the General Dynamics project was who had first filled me in on the Yukon. You know who you are—thanks man and sorry for ripping you off. Doing research on this was hard!</p>
<p>⋮</p>
<p>The knee-jerk conflation between “hybrid” and “fuel efficiency,” along with “weak performance” and “sissy,” lead almost directly to the downfall of every past hybrid or electric high-performance vehicle. It even plagues <a href="http://en.wikipedia.org/wiki/Audi_R18#R18_e-tron_quattro" title="Audi R18 e-tron quattro">championship-winning Le Mans</a> cars, where the advantage of the electric half isn’t one of fuel efficiency (though increased endurance obviously helps), but is in fact an incredible advantage in any race: the ability to absorb energy otherwise lost to braking, then use it as a boost say, at the exit of a corner. This use even has a name: <a href="http://en.wikipedia.org/wiki/Kinetic_energy_recovery_system" title="Kinetic energy recovery system">kinetic energy recovery system (KERS)</a>, otherwise known as “<a href="http://en.wikipedia.org/wiki/Regenerative_brake" title="Regenerative brake">regenerative braking</a>.”</p>
<p>Yet the journalists and the media jumps on the hybrid bit like it’s all about saving the planet. <a href="http://www.websters-online-dictionary.org/definition/littorally" title="litorrally">Literally</a>:</p>
<blockquote>
<p><a href="http://www.engadget.com/2012/06/18/audi-e-tron-wins-le-mans/" title="Audi's e-Tron becomes the first hybrid to win Le Mans, saves the planet at the same time">Engadget</a>: Audi’s e-Tron becomes the first hybrid to win Le Mans, saves the planet at the same time</p>
</blockquote>
<p>Guys, I think you still missed the part where they <em>won the race with this tech</em>. They didn’t throw a motor in there to wave their engineering penis around, proving they can win “despite” using a hybrid—even if they are Audi—it was there because <em>it made their car go faster</em>.</p>
<p>⋮</p>
<p>The sooner we embrace electric as the future of auto performance, whether on the racetrack or at the worksite, the sooner their other goal can be met: actually saving the planet. No matter how parsimonious Volts are with emissions, it won’t matter if BEVs and PHEVs are only 5% of the market by 2040. We need people to drive hybrids and then electrics in every sector of the market, from people-carrier commuters to hatchback hoonmobiles to soccer mom armored child delivery systems.</p>
<p><a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/files/eo2013_presentation.pdf"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/VlNd6pRr_O-690.avif 690w, https://geekshavefeelings.com/img/VlNd6pRr_O-1380.avif 1380w, https://geekshavefeelings.com/img/VlNd6pRr_O-2880.avif 2880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/VlNd6pRr_O-690.webp 690w, https://geekshavefeelings.com/img/VlNd6pRr_O-1380.webp 1380w, https://geekshavefeelings.com/img/VlNd6pRr_O-2880.webp 2880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/VlNd6pRr_O-690.png 690w, https://geekshavefeelings.com/img/VlNd6pRr_O-1380.png 1380w, https://geekshavefeelings.com/img/VlNd6pRr_O-2880.png 2880w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Light Duty Vehicle Sales & Efficiency" src="https://geekshavefeelings.com/img/VlNd6pRr_O-690.png" width="2880" height="1800"></picture></figure></a></p>
<p>And that’s according to ExxonMobil.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>By the way, how did we get to the point where cars are announced two years ahead of their model years? <a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>A species <a href="http://www.nsf.gov/statistics/seind12/c2/c2h.htm" title="NSF Science and Engineering Indicators 2012">becoming steadily endangered</a> <a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>As an aside, the vehicles in question are not only American, but USAian too: the <a href="http://media.gm.com/media/us/en/gm/company_info/facilities/powertrain/baltimore.html" title="GM Baltimore Operations">hybrid continuously variable transmission (CVT) is produced in Baltimore</a>, the Sierra is assembled at <a href="http://media.gm.com/media/us/en/gm/company_info/facilities/assembly/ftw.html" title="GM Fort Wayne">Fort Wayne</a> and <a href="http://media.gm.com/media/us/en/gm/company_info/facilities/assembly/flint.html" title="GM Flint">Flint</a>, while the Yukon is assembled at <a href="http://media.gm.com/media/us/en/gm/company_info/facilities/assembly/arlington.html" title="GM Arlington">Arlington</a>. <a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>When Hummer, then newly owned by GM, was all the rage. <a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>At first <a href="http://helix.gatech.edu/Classes/ME4182/2001S3/FutureTruck/ProjectDescription.htm" title="DOE FutureTruck">a Chevy Suburban</a>, to be fair. By the way, I’m not really a GM fan, beyond hoping (as a taxpayer) that they do well enough in the next 12–15 months that we don’t take a full <a href="http://qz.com/37841/the-us-seems-likely-to-take-a-10-billion-hit-on-its-gm-bailout/" title="The US seems likely to take a $10 billion hit on its GM bailout">$10 billion loss on the bailout</a>. <a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>As is fitting to tradition; I’m pretty sure the whole point of the school is to miss it. I’m proud of that. <a href="https://geekshavefeelings.com/posts/2012/it-was-never-about-the-mileage/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Trayrace
2012-12-12T23:05:24Z
https://geekshavefeelings.com/posts/2012/trayrace/
<p>Trayrace is a minimal Monte Carlo renderer, created with the help of <a href="http://www.cc.gatech.edu/~turk/" title="Greg's site">Greg Turk</a> at Georgia Tech as an independent study project for my senior year.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/qEjlwFX6kL-690.avif 690w, https://geekshavefeelings.com/img/qEjlwFX6kL-1380.avif 1380w, https://geekshavefeelings.com/img/qEjlwFX6kL-2276.avif 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/qEjlwFX6kL-690.webp 690w, https://geekshavefeelings.com/img/qEjlwFX6kL-1380.webp 1380w, https://geekshavefeelings.com/img/qEjlwFX6kL-2276.webp 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/qEjlwFX6kL-690.png 690w, https://geekshavefeelings.com/img/qEjlwFX6kL-1380.png 1380w, https://geekshavefeelings.com/img/qEjlwFX6kL-2276.png 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Trayrace short" src="https://geekshavefeelings.com/img/qEjlwFX6kL-690.png" width="2276" height="2320"></picture></figure><p></p>
<p>Code available at GitHub: <a href="https://github.com/GHF/trayrace" title="Trayrace at GitHub">https://github.com/GHF/trayrace</a></p>
<p>Trayrace was designed to (eventually) have the bells and whistles of an advanced physically-based photorealistic renderer—like many renderers, it’s based loosely on <a href="http://www.pbrt.org" title="PBRT">PBRT</a>—but was implemented with uniquely little “from scratch” code, through judicious choice of off the shelf components:</p>
<ul>
<li><a href="http://software.intel.com/en-us/articles/embree-photo-realistic-ray-tracing-kernels-0" title="Intel Embree"><strong>Intel Embree</strong></a>—library that builds BVHs and traces rays. Its interface is very simple (though less so since I last visited it in summer 2011), extremely fast (it has a parallel build and the raytracing uses SIMD heavily), and it’s also mostly self-contained, once you figure out the organization of the source code.</li>
<li><a href="http://en.wikipedia.org/wiki/C%2B%2B11" title="C++11"><strong>C++11</strong></a>—newest and mostly-unadopted version of the C++ language, it’s almost a distinct tool in its own right in how much support it can provide to a new project. Asynchronous or parallel code that leapfrogged across different functions are suddenly put into neat order with functional-style <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Lambda_functions_and_expressions" title="Lambda functions">lambda closures</a>, windy templated types suddenly become a short <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Type_inference" title="Type inference"><code>auto</code></a>, and who doesn’t love <a href="http://en.cppreference.com/w/cpp/container/vector/emplace_back" title="emplace_back"><code>emplace_back</code></a>?</li>
<li><a href="http://libcxx.llvm.org" title="libc++"><strong>libc++</strong></a>—not to repeat myself, but the <em>libraries</em> in C++11 are amazing. Finally, we have <a href="http://en.cppreference.com/w/cpp/thread" title="<thread>">threads</a> and <a href="http://en.cppreference.com/w/cpp/chrono" title="<chrono>">timers</a> and <a href="http://en.cppreference.com/w/cpp/memory" title="<memory>">smart pointers</a> and <a href="http://en.cppreference.com/w/cpp/types/integer" title="<cstdint>"><code><cstdint></code></a>.</li>
<li><a href="http://eigen.tuxfamily.org"><strong>Eigen</strong></a>—excellent vector math library used to represent my geometric data and transformations. I would use lightweight wrappers around some classes, while other times I just used typedef to bring them into my code.</li>
<li><a href="http://code.google.com/p/pixeltoaster/"><strong>PixelToaster</strong></a>—great floating-point, system-native framebuffer library I use for most of my rendering projects.</li>
</ul>
<p>Here are some screenshots, where I vary the radius of the disk light used to illuminate the dragon:
</p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/r5DnPWyEHF-690.avif 690w, https://geekshavefeelings.com/img/r5DnPWyEHF-1380.avif 1380w, https://geekshavefeelings.com/img/r5DnPWyEHF-2276.avif 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/r5DnPWyEHF-690.webp 690w, https://geekshavefeelings.com/img/r5DnPWyEHF-1380.webp 1380w, https://geekshavefeelings.com/img/r5DnPWyEHF-2276.webp 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/r5DnPWyEHF-690.png 690w, https://geekshavefeelings.com/img/r5DnPWyEHF-1380.png 1380w, https://geekshavefeelings.com/img/r5DnPWyEHF-2276.png 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Screen Shot 2012-12-14 at 11.42.18" src="https://geekshavefeelings.com/img/r5DnPWyEHF-690.png" width="2276" height="2320"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/W3eR0ObAbz-690.avif 690w, https://geekshavefeelings.com/img/W3eR0ObAbz-1380.avif 1380w, https://geekshavefeelings.com/img/W3eR0ObAbz-2276.avif 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/W3eR0ObAbz-690.webp 690w, https://geekshavefeelings.com/img/W3eR0ObAbz-1380.webp 1380w, https://geekshavefeelings.com/img/W3eR0ObAbz-2276.webp 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/W3eR0ObAbz-690.png 690w, https://geekshavefeelings.com/img/W3eR0ObAbz-1380.png 1380w, https://geekshavefeelings.com/img/W3eR0ObAbz-2276.png 2276w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Screen Shot 2012-12-14 at 11.43.08" src="https://geekshavefeelings.com/img/W3eR0ObAbz-690.png" width="2276" height="2320"></picture></figure><p></p>
<p>Trayrace was also written with minimalism in mind; the goal was to get pretty results as quickly as possible, then engineer code as necessary. Each feature added would flesh out subsystems that were weak or nonexistent (I didn’t even have transformations for weeks after starting the project), so that all the code would be “battle-tested” by use as soon as it’s written. This sort of thing happens a lot when you don’t have time to write unit tests.</p>
BabyCorntrolling
2012-05-06T23:29:32Z
https://geekshavefeelings.com/posts/2012/babycorntrolling/
<p>So I totally ditched <a href="https://geekshavefeelings.com/tags/corntroller" title="Corntroller">Corntroller</a> for its hot redesigned (square!) little sibling, <a href="https://geekshavefeelings.com/tags/babycorntroller" title="BabyCorntroller">BabyCorntroller</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Kgf4pwhyLm-690.avif 690w, https://geekshavefeelings.com/img/Kgf4pwhyLm-1380.avif 1380w, https://geekshavefeelings.com/img/Kgf4pwhyLm-2612.avif 2612w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Kgf4pwhyLm-690.webp 690w, https://geekshavefeelings.com/img/Kgf4pwhyLm-1380.webp 1380w, https://geekshavefeelings.com/img/Kgf4pwhyLm-2612.webp 2612w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Kgf4pwhyLm-690.jpeg 690w, https://geekshavefeelings.com/img/Kgf4pwhyLm-1380.jpeg 1380w, https://geekshavefeelings.com/img/Kgf4pwhyLm-2612.jpeg 2612w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="BabyCorntroller!" src="https://geekshavefeelings.com/img/Kgf4pwhyLm-690.jpeg" width="2612" height="2232"></picture></figure><p></p>
<p>The control (corntrol?) logic board is called MiniCob<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/babycorntrolling/" id="fnref1">*</a></sup>. I shrunk down Corntroller’s Tassel from credit card size (3.4″ × 2.1″) to just 1.95″ × 1.95″, while adding a wireless radio, doubling the number of power stages and analog frontends (so I can <strong>control two motors</strong>), and still keeping the micro-SD card slot. Oh, and going from a four-layer to two-layer layout yet keeping all components on one side.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/y_A1SxNJdl-690.avif 690w, https://geekshavefeelings.com/img/y_A1SxNJdl-853.avif 853w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/y_A1SxNJdl-690.webp 690w, https://geekshavefeelings.com/img/y_A1SxNJdl-853.webp 853w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/y_A1SxNJdl-690.png 690w, https://geekshavefeelings.com/img/y_A1SxNJdl-853.png 853w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="MiniCob layout" src="https://geekshavefeelings.com/img/y_A1SxNJdl-690.png" width="853" height="1027"></picture></figure><p></p>
<p>To perform this miniaturization magic, I switched from the 100-pin <a href="http://www.st.com/internet/mcu/product/247492.jsp" title="STM32F103VG">STM32F103VG</a> to a 64-pin <a href="http://www.st.com/internet/mcu/product/250190.jsp" title="STM32F205RC">STM32F205RC</a>, which has more flexible pin assignments (every GPIO pin can be muxed to a variety of peripheral functions), supports bootloading on IO interfaces other than USART1, and is faster/has more SRAM for the same cost. Plus, it’s 100% pin-/code-compatible with STM32F4s which run even faster and have FPUs.</p>
<p>I actually managed to use every single pin on the STM32. Wow.</p>
<p>But why 1.95″ square? Well, so I can put the boards through <a href="http://iteadstudio.com/store/index.php?main_page=index&cPath=19_20" title="ITead Studio">dirt cheap</a> <a href="http://www.seeedstudio.com/depot/fusion-pcb-service-p-835.html?cPath=185" title="Seeed Studio">Shenzhen-direct</a> PCB services, in case I want to make like, ten of these.</p>
<p>Meanwhile, the power stage/analog frontend board (HexHusk -> TinyHusk) got a makeover as well. Though Corntroller is a blatant and outright intentional (and very poorly done) clone of <a href="http://scolton.blogspot.com/p/motor-controllers.html#duo" title="3ph Duo v2.1">3ph Duo</a>, BabyCorntroller is merely a blatant and accidental clone of <a href="http://scolton.blogspot.com/search/label/FF" title="Flying Flux v1.0">Flying Flux</a>. Shane and I had both started our boards before we realized we both had:</p>
<ul>
<li><strong><a href="http://www.ti.com/product/drv8301" title="DRV8301">TI DRV830X</a></strong> <a href="http://www.ti.com/product/drv8302" title="DRV8301">3-phase drivers/buck converters/dual low-side current differential amplifiers</a>. I chose the DRV8302, whose dead-time & over-current are set with resistors rather than with the DRV8301’s SPI interface, because I didn’t have the pins to spare for SPI.</li>
<li>D2PAK-7 FETs (mine are 60V/3.4mΩ/100nC **<a href="http://www.infineon.com/dgdl/IPB034N06N3_Rev2.5.pdf?folderId=db3a304313b8b5a60113cee8763b02d7&fileId=db3a30431b3e89eb011b457fae6c7d64" title="Infineon OptiMOS">Infineon IPB034N06N3</a>**s).</li>
<li><strong>FETs on both sides</strong> of the board, with power rails on opposite sides of the board. Unfortunately, this meant I ended up with motor terminals in the middle of the board.</li>
</ul>
<p>So of course, Shane & I declared motor control design war on Facebook, and finished our boards in record time. Think hackathons, except with hardware, less sleeping, and a whole week in length.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/9WOlq1p0CM-690.avif 690w, https://geekshavefeelings.com/img/9WOlq1p0CM-992.avif 992w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/9WOlq1p0CM-690.webp 690w, https://geekshavefeelings.com/img/9WOlq1p0CM-992.webp 992w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/9WOlq1p0CM-690.png 690w, https://geekshavefeelings.com/img/9WOlq1p0CM-992.png 992w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="TinyHusk layout" src="https://geekshavefeelings.com/img/9WOlq1p0CM-690.png" width="992" height="994"></picture></figure><p></p>
<p>It also goes without saying that I’ve stuffed TinyHusk full of advanced BLDCM/PMSM controller things:</p>
<ul>
<li><strong>Six-input PWM</strong> so I can leave phases undriven (coasting, six-step commutation, etc). MiniCob is laid out so that its 6-output TIM1/TIM8 PWM modules with deadtime push into these pins.</li>
<li><strong>Dual-phase current sense (±66A)</strong> via <a href="http://www.allegromicro.com/~/Media/Files/Datasheets/ACS714-Datasheet.ashx" title="ACS714">ACS714 bidirectional hall-effect current sensors</a> in parallel with 1mΩ jumpers, <strong>simultaneously sampled</strong> (hells yeah triple ADC) with power bus current sense provided by two low-side 1mΩ resistors in parallel.</li>
<li><strong>Voltage sense on all three phases</strong>, laid out to hit different ADCs so I can simultaneous sampling as well (not very useful, but at least I did it >.>). This is great if I want to do traditional six-step sensorless control.</li>
<li>Eighteen multi-layer <strong>ceramic 1210 50V 10μF</strong> caps. These are placed right next to the FETs and serve as the L1 cache of bus capacitance, while two low-ESR/-ESL 680μF aluminum caps chill on the side of the board as my L2.</li>
</ul>
<p>All of this should allow me to do field-oriented control (sensored or sensorless) with current (torque-mode) control. Regenerative braking, as I understand, comes with the package.</p>
<p>So all this functionality is laid out onto 16 pins on the left side of TinyHusk. So what’s the right-side 16-pin header on MiniCob for? It’s a friggin’ second motor’s worth of pins! It’s rotated 180 degrees so that I can stack two TinyHusks onto one MiniCob, and just rotate one husk board so that they use different headers.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/bD6e2DHTX--690.avif 690w, https://geekshavefeelings.com/img/bD6e2DHTX--1380.avif 1380w, https://geekshavefeelings.com/img/bD6e2DHTX--2664.avif 2664w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/bD6e2DHTX--690.webp 690w, https://geekshavefeelings.com/img/bD6e2DHTX--1380.webp 1380w, https://geekshavefeelings.com/img/bD6e2DHTX--2664.webp 2664w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/bD6e2DHTX--690.jpeg 690w, https://geekshavefeelings.com/img/bD6e2DHTX--1380.jpeg 1380w, https://geekshavefeelings.com/img/bD6e2DHTX--2664.jpeg 2664w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="DAT STACK" src="https://geekshavefeelings.com/img/bD6e2DHTX--690.jpeg" width="2664" height="2244"></picture></figure><p></p>
<p>Unfortunately because of school, I didn’t have time to test BabyCorntroller until finals week. So I had less than a week to run them in the <a href="http://inventionstudio.gatech.edu/" title="Georgia Tech Invention Studio">Invention Studio</a> before I got shipped out to <s>war</s> an internship in California.</p>
<p>However, before that, I <em>done spant a motor</em>! I implemented six-step sensored commutation with <a href="http://e2e.ti.com/group/motor/b/blog/archive/2012/04/04/so-which-pwm-technique-is-best-part-4.aspx" title="TI Motor Blog Bipolar 4Q">bipolar PWM</a> and ran it up to 32V on a pretty <a href="http://www.sciplus.com/recommend.cfm/recommendid/8348" title="Takeout Hitachis">boring BLDC motor</a>.</p>
<p>https://www.youtube.com/watch?v=v9r7dk_m11U</p>
<p>WOOO IT SPINS. By the way, notice that the motor setup isn’t actually connected to my computer. Wireless trolling opportunities abound. 😉</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/_FpcAOqE4r-480.avif 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/_FpcAOqE4r-480.webp 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Full duty commutation" src="https://geekshavefeelings.com/img/_FpcAOqE4r-480.png" width="480" height="234"></picture></figure><p></p>
<p>The phase waveforms look hot. Textbook BLDC, Shane says. I was little worried about the reverse voltage spikes when a phase goes undriven—turns out they’re inductive flyback from the field in the phase collapsing then dumping current into the controller, and not some weird PWM glitch.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/0ur5fWxlkQ-480.avif 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/0ur5fWxlkQ-480.webp 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Low duty commutation" src="https://geekshavefeelings.com/img/0ur5fWxlkQ-480.png" width="480" height="234"></picture></figure><p></p>
<p>And some more waveforms at a lower duty cycle. Still a nice slope on the undriven phase, though noisier. Now this measured at the motor terminals—my controller’s voltage sampling is buffered and low-pass filtered, so what it sees will be a lot cleaner.</p>
<p>Regen braking works brilliantly, but big current changes (like full stop or full reverse) will spike the bus on my power supply and also cause my controller to get into a trap. I thought this could be the brownout detection kicking in, so I scoped my 5V and 3.3V logic buses with the switching waveform:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/RZhpJryWM7-480.avif 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/RZhpJryWM7-480.webp 480w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Logic power noise" src="https://geekshavefeelings.com/img/RZhpJryWM7-480.png" width="480" height="234"></picture></figure><p></p>
<p>DAT NOISE. The top is 5V, the middle is 3.3V, and the bottom is PWM output going to the driver. Holy crap 3.20V peak-to-peak on my microcontroller power supply. Now granted this is relative to power ground, not logic ground near the microcontroller, so it’s a bit exaggerated, but still. I think this is my fault; there’s just 10μF of logic power capacitance coming out of my 3.3V LDO, plus a few 0.1μF caps the STM32 datasheet asked for. With a few cap upgrades I could make my logic supply a lot more stable.</p>
<p>What’s next? I’ll be implementing rotor angle extrapolation to do leading phase advance, writing a simultaneous sampling triple ADC driver for current control and sensorless six-step, and finding a nice electronics bench near Cupertino.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/babycorntrolling/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>v2.0, since it’s the second-gen board <a href="https://geekshavefeelings.com/posts/2012/babycorntrolling/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Conkers
2012-04-04T12:33:16Z
https://geekshavefeelings.com/posts/2012/conkers/
<p>Conkers is a game about hitting things.</p>
<p>With your mouse.</p>
<p>In high-quality (software rendered!) antialiased 2D graphics with framerates so smooth you’ll be able to <em>snort lines off your monitor</em> as you play.</p>
<p>https://www.youtube.com/watch?v=YaBz5E8aHlg</p>
<p>OK, so the YouTube video is at 20 FPS because my screen recorder sucks, but you get the idea.</p>
<h2 id="download" tabindex="-1">Download <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/conkers/">§</a></h2>
<p><a href="https://geekshavefeelings.com/posts/2012/conkers/files/conkers.zip" title="Win64 binaries">Download 64-bit Windows binaries (12MB)</a></p>
<p>Source code is available from my <a href="http://github.com/GHF/conkers" title="Conkers GitHub repository">GitHub repository</a></p>
<h2 id="instructions" tabindex="-1">Instructions <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/conkers/">§</a></h2>
<ol>
<li>Launch the game</li>
<li>Move your mouse</li>
<li>Press SPACE to start</li>
</ol>
<h2 id="screenshots" tabindex="-1">Screenshots <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/conkers/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/55pz_eRP7i-690.avif 690w, https://geekshavefeelings.com/img/55pz_eRP7i-1296.avif 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/55pz_eRP7i-690.webp 690w, https://geekshavefeelings.com/img/55pz_eRP7i-1296.webp 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/55pz_eRP7i-690.png 690w, https://geekshavefeelings.com/img/55pz_eRP7i-1296.png 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="conkersTitle" src="https://geekshavefeelings.com/img/55pz_eRP7i-690.png" width="1296" height="758"></picture></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ugxnxgeecy-690.avif 690w, https://geekshavefeelings.com/img/ugxnxgeecy-1296.avif 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ugxnxgeecy-690.webp 690w, https://geekshavefeelings.com/img/ugxnxgeecy-1296.webp 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/ugxnxgeecy-690.png 690w, https://geekshavefeelings.com/img/ugxnxgeecy-1296.png 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="conkersPlay0" src="https://geekshavefeelings.com/img/ugxnxgeecy-690.png" width="1296" height="758"></picture></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/zJsbXWil7z-690.avif 690w, https://geekshavefeelings.com/img/zJsbXWil7z-1296.avif 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/zJsbXWil7z-690.webp 690w, https://geekshavefeelings.com/img/zJsbXWil7z-1296.webp 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/zJsbXWil7z-690.png 690w, https://geekshavefeelings.com/img/zJsbXWil7z-1296.png 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="conkersPlay1" src="https://geekshavefeelings.com/img/zJsbXWil7z-690.png" width="1296" height="758"></picture></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/H3je9B65uT-690.avif 690w, https://geekshavefeelings.com/img/H3je9B65uT-1296.avif 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/H3je9B65uT-690.webp 690w, https://geekshavefeelings.com/img/H3je9B65uT-1296.webp 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/H3je9B65uT-690.png 690w, https://geekshavefeelings.com/img/H3je9B65uT-1296.png 1296w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="conkersOver" src="https://geekshavefeelings.com/img/H3je9B65uT-690.png" width="1296" height="758"></picture></figure><p></p>
BabyCorntroller
2012-03-15T01:17:24Z
https://geekshavefeelings.com/posts/2012/babycorntroller/
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ITZgqBx3TR-690.avif 690w, https://geekshavefeelings.com/img/ITZgqBx3TR-1380.avif 1380w, https://geekshavefeelings.com/img/ITZgqBx3TR-2748.avif 2748w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ITZgqBx3TR-690.webp 690w, https://geekshavefeelings.com/img/ITZgqBx3TR-1380.webp 1380w, https://geekshavefeelings.com/img/ITZgqBx3TR-2748.webp 2748w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ITZgqBx3TR-690.jpeg 690w, https://geekshavefeelings.com/img/ITZgqBx3TR-1380.jpeg 1380w, https://geekshavefeelings.com/img/ITZgqBx3TR-2748.jpeg 2748w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="BabyCorntroller" src="https://geekshavefeelings.com/img/ITZgqBx3TR-690.jpeg" width="2748" height="1779"></picture></figure><p></p>
Templated numerical integrators in C++
2012-03-11T01:59:08Z
https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/
<p>I find myself writing numerical integrators for physics solvers often enough<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/" id="fnref1">*</a></sup> that I wished I didn’t have to keep rewriting them every time I used a different linear algebra library or changed the dimensions what I was solving.</p>
<p>This is exactly what C++ templates are great for—writing code that works with multiple types with similar interfaces. So I whipped up Euler, midpoint, and Runge-Kutta order 4 (RK4) integrators with a generic C++ template interface.</p>
<p>Now I know templates are scary and all, but you don’t need to know them to use my code. Here’s a simple example of a physics simulator loop for solving 1D Newtonian physics with constant acceleration:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string">"Integrators.h"</span></span>
<span class="token comment">// acceleration evaluation function - just return a constant</span>
<span class="token keyword">float</span> <span class="token function">constAccel</span><span class="token punctuation">(</span><span class="token keyword">float</span> pos<span class="token punctuation">,</span> <span class="token keyword">float</span> vel<span class="token punctuation">,</span> <span class="token keyword">float</span> t<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token number">1.f</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">simLoop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
IntegratorRK4 integrator<span class="token punctuation">;</span>
<span class="token comment">// 1D particle states (positions and velocities) & buffers for next state</span>
std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span><span class="token keyword">float</span><span class="token operator">></span> poss<span class="token punctuation">,</span> vels<span class="token punctuation">,</span> nextPoss<span class="token punctuation">,</span> nextVels<span class="token punctuation">;</span>
<span class="token comment">// system time state and timestep size</span>
<span class="token keyword">float</span> t <span class="token operator">=</span> <span class="token number">0.f</span><span class="token punctuation">,</span> dt <span class="token operator">=</span> <span class="token number">1.f</span> <span class="token operator">/</span> <span class="token number">100</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// integrate accelerations to velocities & velocities to positions</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> poss<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
integrator<span class="token punctuation">.</span><span class="token function">evaluate</span><span class="token punctuation">(</span>poss<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> vels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> constAccel<span class="token punctuation">,</span> t<span class="token punctuation">,</span> dt<span class="token punctuation">,</span> nextPoss<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nextVels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// take a timestep</span>
t <span class="token operator">+=</span> dt<span class="token punctuation">;</span>
<span class="token comment">// advance state to the next state</span>
poss<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>nextPoss<span class="token punctuation">)</span><span class="token punctuation">;</span>
vels<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>nextVels<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>It’s pretty straightforward: every physics iteration, make the following call for every particle <code>i</code>: <code>integrator.evaluate(poss[i], vels[i], constAccel, t, dt, nextPoss[i], nextVels[i])</code>. Thanks to type inference, the actual templates are hidden from you. But what are those arguments?</p>
<ul>
<li><code>poss[i]</code> and <code>vels[i]</code> are the particle’s state (position and velocity)</li>
<li><code>constAccel</code> is a function that returns the acceleration for that particle (in this case a constant)</li>
<li><code>t</code> and <code>dt</code> are the system time and timestep</li>
<li><code>nextPoss[i]</code> and <code>nextVels[i]</code> are the outputs to the call—they get written with the next state of the particle</li>
</ul>
<p>Of course, those arguments don’t have to be limited to those in that example. For example, we can do:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">template</span><span class="token operator"><</span><span class="token keyword">typename</span> <span class="token class-name">Vector</span><span class="token punctuation">,</span> <span class="token keyword">typename</span> <span class="token class-name">Scalar</span><span class="token operator">></span>
<span class="token keyword">struct</span> <span class="token class-name">DragAndConstAccel</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> Vector accel<span class="token punctuation">;</span>
<span class="token keyword">const</span> Scalar drag<span class="token punctuation">;</span>
<span class="token function">DragAndConstAccel</span><span class="token punctuation">(</span><span class="token keyword">const</span> Vector <span class="token operator">&</span>accel<span class="token punctuation">,</span> <span class="token keyword">double</span> drag<span class="token punctuation">)</span> <span class="token operator">:</span>
<span class="token function">accel</span><span class="token punctuation">(</span>accel<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">drag</span><span class="token punctuation">(</span>drag<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
Vector <span class="token keyword">operator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token keyword">const</span> Vector <span class="token operator">&</span>pos<span class="token punctuation">,</span> <span class="token keyword">const</span> Vector <span class="token operator">&</span>vel<span class="token punctuation">,</span> Scalar t<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> accel <span class="token operator">-</span> vel <span class="token operator">*</span> drag<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">simLoop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
IntegratorRK4 integrator<span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>complex<span class="token operator"><</span><span class="token keyword">double</span><span class="token operator">></span> <span class="token operator">></span> poss<span class="token punctuation">,</span> vels<span class="token punctuation">,</span> nextPoss<span class="token punctuation">,</span> nextVels<span class="token punctuation">;</span>
<span class="token keyword">double</span> t <span class="token operator">=</span> <span class="token number">0.0</span><span class="token punctuation">,</span> dt <span class="token operator">=</span> <span class="token number">1.0</span> <span class="token operator">/</span> <span class="token number">100</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> poss<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
integrator<span class="token punctuation">.</span><span class="token function">evaluate</span><span class="token punctuation">(</span>poss<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span>
vels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token generic-function"><span class="token function">DragAndConstAccel</span><span class="token generic class-name"><span class="token operator"><</span>std<span class="token double-colon punctuation">::</span>complex<span class="token operator"><</span><span class="token keyword">double</span><span class="token operator">></span><span class="token punctuation">,</span> <span class="token keyword">double</span><span class="token operator">></span></span></span><span class="token punctuation">(</span><span class="token number">1.0</span><span class="token punctuation">,</span> <span class="token number">0.25</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
t<span class="token punctuation">,</span>
dt<span class="token punctuation">,</span>
nextPoss<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span>
nextVels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
t <span class="token operator">+=</span> dt<span class="token punctuation">;</span>
poss<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>nextPoss<span class="token punctuation">)</span><span class="token punctuation">;</span>
vels<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>nextVels<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Here I made our system positions and velocities be <code>std::complex<double></code>s (why would you ever do this?), the time and timestep be <code>double</code>, and replaced the constant acceleration function with a neat <a href="http://en.wikipedia.org/wiki/Function_object#In_C_and_C.2B.2B" title="Function object">functor</a> that can maintain state. In this case, the acceleration functor applies a constant acceleration with a drag acceleration that’s linear to the velocity.</p>
<p>But look how the <code>integrator.evaluate()</code> call and the simulation loop look almost the same as before: that’s the beauty of templates<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/" id="fnref2">†</a></sup>. You can change around your vector & time types and still keep the same loop code.</p>
<p>You wanna see something wild? Let’s stick in <a href="http://eigen.tuxfamily.org/" title="Eigen">Eigen</a> <code>Vector3f</code> and make our acceleration function be a <a href="http://en.wikipedia.org/wiki/C%2B%2B11#Lambda_functions_and_expressions" title="C++ lambda functions and expressions">C++11 lambda</a>:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">void</span> <span class="token function">simLoop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">using</span> <span class="token keyword">namespace</span> Eigen<span class="token punctuation">;</span>
IntegratorRK4 integrator<span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span>Vector3f<span class="token operator">></span> poss<span class="token punctuation">,</span> vels<span class="token punctuation">,</span> nextPoss<span class="token punctuation">,</span> nextVels<span class="token punctuation">;</span>
<span class="token keyword">double</span> t <span class="token operator">=</span> <span class="token number">0.0</span><span class="token punctuation">,</span> dt <span class="token operator">=</span> <span class="token number">1.0</span> <span class="token operator">/</span> <span class="token number">100</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>size_t i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> poss<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
integrator<span class="token punctuation">.</span><span class="token function">evaluate</span><span class="token punctuation">(</span>poss<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> vels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">const</span> Vector3f <span class="token operator">&</span>pos<span class="token punctuation">,</span> <span class="token keyword">const</span> Vector3f <span class="token operator">&</span>vel<span class="token punctuation">,</span> <span class="token keyword">double</span> t<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">Vector3f</span><span class="token punctuation">(</span><span class="token number">1.f</span><span class="token punctuation">,</span> <span class="token number">0.f</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1.f</span><span class="token punctuation">)</span> <span class="token operator">-</span> vel <span class="token operator">*</span> <span class="token number">0.25f</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> t<span class="token punctuation">,</span> dt<span class="token punctuation">,</span> nextPoss<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> nextVels<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
t <span class="token operator">+=</span> dt<span class="token punctuation">;</span>
poss<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>nextPoss<span class="token punctuation">)</span><span class="token punctuation">;</span>
vels<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>nextVels<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>Neat, innit? Anyways, all the integrators are available in a single header file under the MIT/X11 license. If you plan to use it, it would be nice to give me an email shout.</p>
<ul>
<li><a href="https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/files/Integrators.h">Integrators.h</a></li>
</ul>
<p>You may have noticed that the integrators don’t handle mass at all—that’s why you pass it an acceleration evaluation function rather than a force evaluation function, as it has no knowledge of mass. Extending the integrators to use mass is a trivial exercise left up to the reader. 🙂</p>
<p>Also, weathered C++ coders may notice that I specify the integrators’ interface using a <a href="http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" title="Curiously recurring template pattern">CRTP</a> base class. There’s no compelling software engineering reason for this; I actually find CRTP static polymorphism to be a mostly useless construct, as you can’t swap around your derived classes without recompiling. But it does make for a good interface spec.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Oh dear god it hurt me to write that… <a href="https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Yes, yes, I know that “the beauty of templates” is a contradiction in terms <a href="https://geekshavefeelings.com/posts/2012/templated-numerical-integrators-in-c/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Bringing up Corntroller
2011-10-22T20:36:33Z
https://geekshavefeelings.com/posts/2011/bringing-up-corntroller/
<blockquote>
<p>I compensate for my engineering mistakes with bigger engineering mistakes. -Me</p>
</blockquote>
<p>Every new board needs an “LED blink” program. It’s basically a <a href="http://en.wikipedia.org/wiki/Hello_world_program" title="Hello, World!">Hello, world!</a> for embedded engineers. Thing is, I put two seven-segment LED arrays on <a href="https://geekshavefeelings.com/tags/corntroller" title="Corntroller">Corntroller</a>, my brushless motor controller, so my LED blink program got a little bit fan-çay:</p>
<p>https://www.youtube.com/watch?v=r41xsRYGjas</p>
<p>The displays were the first things I wanted to program anyways (USB is next). Among other things, you can display hexadecimal digits on them, which is pretty straightforward from a code perspective:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">static</span> <span class="token keyword">struct</span> <span class="token class-name">SevenSegmentDisplay</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span><span class="token operator">:</span>
<span class="token function">SevenSegmentDisplay</span><span class="token punctuation">(</span>GPIO_TypeDef <span class="token operator">*</span>gpio<span class="token punctuation">,</span> <span class="token keyword">uint8_t</span> offset<span class="token punctuation">)</span> <span class="token operator">:</span>
<span class="token function">gpio</span><span class="token punctuation">(</span>gpio<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">offset</span><span class="token punctuation">(</span>offset<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">showHex</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">palClearPort</span><span class="token punctuation">(</span>gpio<span class="token punctuation">,</span> <span class="token number">0xF7</span> <span class="token operator"><<</span> offset<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">palSetPort</span><span class="token punctuation">(</span>gpio<span class="token punctuation">,</span> charLUT<span class="token punctuation">[</span>x <span class="token operator">%</span> <span class="token number">16</span><span class="token punctuation">]</span> <span class="token operator"><<</span> offset<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">void</span> <span class="token function">setDP</span><span class="token punctuation">(</span><span class="token keyword">bool</span> dp<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">palWritePad</span><span class="token punctuation">(</span>gpio<span class="token punctuation">,</span> offset <span class="token operator">+</span> <span class="token number">3</span><span class="token punctuation">,</span> dp<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">protected</span><span class="token operator">:</span>
GPIO_TypeDef <span class="token operator">*</span> <span class="token keyword">const</span> gpio<span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">uint8_t</span> offset<span class="token punctuation">;</span>
<span class="token keyword">static</span> <span class="token keyword">const</span> <span class="token keyword">uint8_t</span> charLUT<span class="token punctuation">[</span><span class="token number">16</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token function">red</span><span class="token punctuation">(</span>GPIOD<span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">green</span><span class="token punctuation">(</span>GPIOE<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">uint8_t</span> SevenSegmentDisplay<span class="token double-colon punctuation">::</span>charLUT<span class="token punctuation">[</span><span class="token number">16</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token number">0x77</span><span class="token punctuation">,</span> <span class="token number">0x14</span><span class="token punctuation">,</span> <span class="token number">0xB3</span><span class="token punctuation">,</span> <span class="token number">0xB6</span><span class="token punctuation">,</span>
<span class="token number">0xD4</span><span class="token punctuation">,</span> <span class="token number">0xE6</span><span class="token punctuation">,</span> <span class="token number">0xE7</span><span class="token punctuation">,</span> <span class="token number">0x34</span><span class="token punctuation">,</span>
<span class="token number">0xF7</span><span class="token punctuation">,</span> <span class="token number">0xF6</span><span class="token punctuation">,</span> <span class="token number">0xF5</span><span class="token punctuation">,</span> <span class="token number">0xC7</span><span class="token punctuation">,</span>
<span class="token number">0x63</span><span class="token punctuation">,</span> <span class="token number">0x97</span><span class="token punctuation">,</span> <span class="token number">0xE3</span><span class="token punctuation">,</span> <span class="token number">0xE1</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Making that lookup table was the hardest part. Most code is written for “abcdefg” bit order, but my LEDs were bit-swizzled since I rearranged my lines to have a cleaner layout. This just meant I needed different bit patterns:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">// - GFABPCDE</span>
<span class="token comment">// 0 01110111</span>
<span class="token comment">// 1 00010100</span>
<span class="token comment">// 2 10110011</span>
<span class="token comment">// 3 10110110</span>
<span class="token comment">// 4 11010100</span>
<span class="token comment">// 5 11100110</span>
<span class="token comment">// 6 11100111</span>
<span class="token comment">// 7 00110100</span>
<span class="token comment">// 8 11110111</span>
<span class="token comment">// 9 11110110</span>
<span class="token comment">// A 11110101</span>
<span class="token comment">// b 11000111</span>
<span class="token comment">// C 01100011</span>
<span class="token comment">// d 10010111</span>
<span class="token comment">// E 11100011</span>
<span class="token comment">// F 11100001</span></code></pre>
<p>For a clean layout, it’s totally worth it.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/kop_iWt3i9-690.avif 690w, https://geekshavefeelings.com/img/kop_iWt3i9-1003.avif 1003w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/kop_iWt3i9-690.webp 690w, https://geekshavefeelings.com/img/kop_iWt3i9-1003.webp 1003w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/kop_iWt3i9-690.png 690w, https://geekshavefeelings.com/img/kop_iWt3i9-1003.png 1003w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Lines of awesome" src="https://geekshavefeelings.com/img/kop_iWt3i9-690.png" width="1003" height="791"></picture></figure><p></p>
Assembly-izing Tassel
2011-10-20T07:19:30Z
https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/
<blockquote>
<p>Tasssel: the extra ‘s’ is for “scattering”</p>
</blockquote>
<p>Work continues on <a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel" title="Corn-Troller: Tassel">Corntroller</a>, my sneaky copy of <a href="http://scolton.blogspot.com/search/label/3ph" title="Shane's 3ph duo v3">Shane’s sweet brushless motor controller</a>.</p>
<p>I got my Digi-Key order last week and started assembling the board at the <a href="https://wiki.cc.gatech.edu/gvu/index.php/PrototypingLab" title="GVU Prototyping Lab">Graphics/Visualization/Usability (GVU) Prototyping Lab</a>, the sister lab to the <a href="http://inventionstudio.gatech.edu/" title="Invention Studio">Georgia Tech Invention Studio</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref1">*</a></sup>, and home to my favorite hot-air reflow station on campus for prototyping.</p>
<p>Now the thing about reflow soldering is that it perfectly captures the sights, sounds, and smells of hell.</p>
<p>What else but hell would make you sit in place, hunched over for hours, as electric fire brings tears to your eyes and solder paste brimstone pierces your nostrils? Bright incandescent lighting, smoldering soldering irons, and in the case of the GVU reflow station, a 50-decibel electric pump all magnify the feeling of burning alive in invidious flames of divine wrath.</p>
<p>https://www.youtube.com/watch?v=fyt_DEAbSOU</p>
<p>But the GVU version of surface mount hell is actually pretty legit. The aforementioned electric pump is hooked up to a precision solenoid valve gas dispenser (controlled by a foot pedal), which in turn feeds pressurized air into a hand-held tube of leaded solder paste. Hit the foot pedal, and a small and carefully controlled bit of gray goop flows out.</p>
<p>The setup basically lets you do manual pick and place assembly. Less efficient for small and medium runs than <a href="http://www.sparkfun.com/tutorials/58" title="Sparkfun Solder Paste Stenciling tutorial">solder paste stenciling</a>, but way less setup time and a lot more fun<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref2">†</a></sup>. It’s perfect for prototyping a new board.</p>
<p>Now I ended up shooting video instead of taking too many pictures, so bear with my video screenshots here.</p>
<p>To make life easier, I assemble components under a 10×/30× stereo microscope with tweezers in one hand, solder paste dispenser in the other, and foot on the foot pedal.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/e0R2UMDwQw-690.avif 690w, https://geekshavefeelings.com/img/e0R2UMDwQw-1380.avif 1380w, https://geekshavefeelings.com/img/e0R2UMDwQw-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/e0R2UMDwQw-690.webp 690w, https://geekshavefeelings.com/img/e0R2UMDwQw-1380.webp 1380w, https://geekshavefeelings.com/img/e0R2UMDwQw-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/e0R2UMDwQw-690.jpeg 690w, https://geekshavefeelings.com/img/e0R2UMDwQw-1380.jpeg 1380w, https://geekshavefeelings.com/img/e0R2UMDwQw-1920.jpeg 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Microscope pick'n'place (you totally can't see my new faux hawk in this photo)" src="https://geekshavefeelings.com/img/e0R2UMDwQw-690.jpeg" width="1920" height="1080"></picture></figure><p></p>
<p>At 10× you can see the particles in the solder paste.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/CqOVCMznWD-690.avif 690w, https://geekshavefeelings.com/img/CqOVCMznWD-1380.avif 1380w, https://geekshavefeelings.com/img/CqOVCMznWD-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/CqOVCMznWD-690.webp 690w, https://geekshavefeelings.com/img/CqOVCMznWD-1380.webp 1380w, https://geekshavefeelings.com/img/CqOVCMznWD-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/CqOVCMznWD-690.jpeg 690w, https://geekshavefeelings.com/img/CqOVCMznWD-1380.jpeg 1380w, https://geekshavefeelings.com/img/CqOVCMznWD-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="7-segment closeup, unreflown" src="https://geekshavefeelings.com/img/CqOVCMznWD-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>After assembly, I preheat the board over a <a href="http://www.zeph.com/smdpreheater.htm" title="No One Knows More About Preheating PCB's Than Zephyrtronics!">Zephyrtronics… board preheater</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/IHyX4-xQ3X-690.avif 690w, https://geekshavefeelings.com/img/IHyX4-xQ3X-1380.avif 1380w, https://geekshavefeelings.com/img/IHyX4-xQ3X-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/IHyX4-xQ3X-690.webp 690w, https://geekshavefeelings.com/img/IHyX4-xQ3X-1380.webp 1380w, https://geekshavefeelings.com/img/IHyX4-xQ3X-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/IHyX4-xQ3X-690.jpeg 690w, https://geekshavefeelings.com/img/IHyX4-xQ3X-1380.jpeg 1380w, https://geekshavefeelings.com/img/IHyX4-xQ3X-1920.jpeg 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Its uses include, and is limited to, board preheating" src="https://geekshavefeelings.com/img/IHyX4-xQ3X-690.jpeg" width="1920" height="1080"></picture></figure><p></p>
<p>I’m not even making this up. This thing emulates the flat “warm-up” period of the reflow temperature profile you’d use in a full reflow oven. In addition, it has a <em>genius</em> “cool” mode during which it draws air down (instead of blowing hot air up), using ambient air to cool the board (“ramp-down”). No more blowing on the board until your face is red and your tongue is covered with flakes of solder.</p>
<p><a href="http://www.allegromicro.com/en/corporate/environment/faqs.asp#Q14"><figure><picture><source type="image/webp" srcset="https://geekshavefeelings.com/img/R7sK7vEirW-508.webp 508w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Allegro's recommended reflow profile" src="https://geekshavefeelings.com/img/R7sK7vEirW-508.gif" width="508" height="283"></picture></figure></a></p>
<p>It even comes with a sweet PCB jig to hold your board at just the right height above the pre-heater.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Ls7BmYLq_q-690.avif 690w, https://geekshavefeelings.com/img/Ls7BmYLq_q-1380.avif 1380w, https://geekshavefeelings.com/img/Ls7BmYLq_q-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Ls7BmYLq_q-690.webp 690w, https://geekshavefeelings.com/img/Ls7BmYLq_q-1380.webp 1380w, https://geekshavefeelings.com/img/Ls7BmYLq_q-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Ls7BmYLq_q-690.jpeg 690w, https://geekshavefeelings.com/img/Ls7BmYLq_q-1380.jpeg 1380w, https://geekshavefeelings.com/img/Ls7BmYLq_q-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Preheat" src="https://geekshavefeelings.com/img/Ls7BmYLq_q-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>After that, you pretty much just apply heat like a normal person.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/73pL4Xlao2-690.avif 690w, https://geekshavefeelings.com/img/73pL4Xlao2-1380.avif 1380w, https://geekshavefeelings.com/img/73pL4Xlao2-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/73pL4Xlao2-690.webp 690w, https://geekshavefeelings.com/img/73pL4Xlao2-1380.webp 1380w, https://geekshavefeelings.com/img/73pL4Xlao2-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/73pL4Xlao2-690.jpeg 690w, https://geekshavefeelings.com/img/73pL4Xlao2-1380.jpeg 1380w, https://geekshavefeelings.com/img/73pL4Xlao2-1920.jpeg 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Lefrowing" src="https://geekshavefeelings.com/img/73pL4Xlao2-690.jpeg" width="1920" height="1080"></picture></figure><p></p>
<p>You may notice that in addition to unpopulated inertial sensors, there are also two funny-looking solder bridges.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/5ntKPjgohj-690.avif 690w, https://geekshavefeelings.com/img/5ntKPjgohj-1380.avif 1380w, https://geekshavefeelings.com/img/5ntKPjgohj-2104.avif 2104w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/5ntKPjgohj-690.webp 690w, https://geekshavefeelings.com/img/5ntKPjgohj-1380.webp 1380w, https://geekshavefeelings.com/img/5ntKPjgohj-2104.webp 2104w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/5ntKPjgohj-690.jpeg 690w, https://geekshavefeelings.com/img/5ntKPjgohj-1380.jpeg 1380w, https://geekshavefeelings.com/img/5ntKPjgohj-2104.jpeg 2104w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Laßt uns froh sein!" src="https://geekshavefeelings.com/img/5ntKPjgohj-690.jpeg" width="2104" height="1400"></picture></figure><p></p>
<p>You have ze Germans to blame for that. Had I the European-styled schematic symbols für a <a href="http://en.wikipedia.org/wiki/Choke_(electronics)#Common-mode_choke" title="Common mode choke">common-mode choke</a> ge-used, which had I the wrong orientation for the part ge-using. I think.</p>
<p>In other words, I managed to short my input power leads across a pair of inductors.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/pZlO70wU20-690.avif 690w, https://geekshavefeelings.com/img/pZlO70wU20-1380.avif 1380w, https://geekshavefeelings.com/img/pZlO70wU20-1769.avif 1769w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/pZlO70wU20-690.webp 690w, https://geekshavefeelings.com/img/pZlO70wU20-1380.webp 1380w, https://geekshavefeelings.com/img/pZlO70wU20-1769.webp 1769w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/pZlO70wU20-690.png 690w, https://geekshavefeelings.com/img/pZlO70wU20-1380.png 1380w, https://geekshavefeelings.com/img/pZlO70wU20-1769.png 1769w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="eurotraschematic" src="https://geekshavefeelings.com/img/pZlO70wU20-690.png" width="1769" height="1033"></picture></figure><p></p>
<p>Not that that surprises me in the least; I’ve managed to build almost every circuit I’ve ever designed to have a short from power to ground. Heck, this is the probably the highest impedance short I’ve gotten on a first-try board in the past two years.</p>
<p>Actually, maybe the footprint I was using for my <a href="http://katalog.we-online.de/kataloge/eisos/media/pdf/744232261.pdf" title="WE-CNS_1206">Würth-Elektronik common-mode choke</a> just had a mistake in pin assignments. But I like to chalk it up to cultural differences, since it’s 34% more hilarious that way.</p>
<p>At any rate, I ended up skipping the choke completely using solder bridges; I get less noise immunity, but hey, nobody’s perfect and I’m not sure if it would’ve even helped at all.</p>
<p>At this point, it was time to try out the logic power supply. With fingers crossed, I hook up the bench power supply to the <em>V+</em> and <em>V−</em> power pads and hit the switch.</p>
<p>Nothing.</p>
<p>Turns out when soldering leads to the V− pad while “e-testing” the board, I had broken one of the traces from the pad.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/IL2mD8C8lf-690.avif 690w, https://geekshavefeelings.com/img/IL2mD8C8lf-1380.avif 1380w, https://geekshavefeelings.com/img/IL2mD8C8lf-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/IL2mD8C8lf-690.webp 690w, https://geekshavefeelings.com/img/IL2mD8C8lf-1380.webp 1380w, https://geekshavefeelings.com/img/IL2mD8C8lf-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/IL2mD8C8lf-690.jpeg 690w, https://geekshavefeelings.com/img/IL2mD8C8lf-1380.jpeg 1380w, https://geekshavefeelings.com/img/IL2mD8C8lf-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Oops" src="https://geekshavefeelings.com/img/IL2mD8C8lf-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>Oops.</p>
<p>I haven’t made a soldering boo-boo this bad in years, but whatever. I briefly considered running a little green wire over the trace<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref3">‡</a></sup>, but then realized that I tented over all my vias with soldermask<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref4">§</a></sup> and couldn’t airwire even if I wanted to.</p>
<p>Instead I just ripped up the soldermask with an X-acto knife under 30× magnification and then solder bridged the shorn copper. <em>Like a boss.</em></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/qV6fSDU6qP-690.avif 690w, https://geekshavefeelings.com/img/qV6fSDU6qP-1380.avif 1380w, https://geekshavefeelings.com/img/qV6fSDU6qP-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/qV6fSDU6qP-690.webp 690w, https://geekshavefeelings.com/img/qV6fSDU6qP-1380.webp 1380w, https://geekshavefeelings.com/img/qV6fSDU6qP-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/qV6fSDU6qP-690.jpeg 690w, https://geekshavefeelings.com/img/qV6fSDU6qP-1380.jpeg 1380w, https://geekshavefeelings.com/img/qV6fSDU6qP-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Scrape scrape scrape" src="https://geekshavefeelings.com/img/qV6fSDU6qP-690.jpeg" width="4912" height="3264"></picture></figure> <figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/MgPhIDRkcS-690.avif 690w, https://geekshavefeelings.com/img/MgPhIDRkcS-1380.avif 1380w, https://geekshavefeelings.com/img/MgPhIDRkcS-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/MgPhIDRkcS-690.webp 690w, https://geekshavefeelings.com/img/MgPhIDRkcS-1380.webp 1380w, https://geekshavefeelings.com/img/MgPhIDRkcS-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/MgPhIDRkcS-690.jpeg 690w, https://geekshavefeelings.com/img/MgPhIDRkcS-1380.jpeg 1380w, https://geekshavefeelings.com/img/MgPhIDRkcS-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Solder solder solder" src="https://geekshavefeelings.com/img/MgPhIDRkcS-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>Now I was getting a sweet 3.304V out of my LT3970 circuit from an input of 4V all the way up to 31V, which was as high as the power supply could go. Not really sure why this mattered, since I’ll always be putting 5V into the board, but whatever.</p>
<p>But why the heck am I posting about such minor minutiae as fixing a broken trace when I should be plopping down code like a pro? Well, because performing board bringup<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref5">¶</a></sup> on an STM32-based board like this is an (necessary) act of distilled masochism, and I avoid it like a plague even when I’m already <em>working on the board to begin with</em>. I mean, hell, the software you use with the popular GCC/GDB ARM toolchain is called <a href="http://openocd.sourceforge.net/" title="OpenOCD">OpenOCD</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/jCzDxf0DWZ-690.avif 690w, https://geekshavefeelings.com/img/jCzDxf0DWZ-997.avif 997w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/jCzDxf0DWZ-690.webp 690w, https://geekshavefeelings.com/img/jCzDxf0DWZ-997.webp 997w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/jCzDxf0DWZ-690.png 690w, https://geekshavefeelings.com/img/jCzDxf0DWZ-997.png 997w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Open... OCD?" src="https://geekshavefeelings.com/img/jCzDxf0DWZ-690.png" width="997" height="522"></picture></figure><p></p>
<p>So I plug my board into my <a href="http://www.olimex.com/dev/arm-usb-tiny-h.html" title="ARM-USB-TINY-H">Olimex ARM-USB-TINY-H</a> and then pray to Tony Stark to guide my board to a successful JTAG interrogation.</p>
<pre><code> # See STM Document RM0008
# Section 29.6.2
# Low density devices, Rev A
set _BSTAPID1 0x06412041
# Medium density devices, Rev A
set _BSTAPID2 0x06410041
# Medium density devices, Rev B and Rev Z
set _BSTAPID3 0x16410041
# High density devices, Rev A
set _BSTAPID4 0x06414041
# Connectivity line devices, Rev A and Rev Z
set _BSTAPID5 0x06418041
</code></pre>
<p>Oops, my STM32F103VG XL-density microcontroller isn’t in there. The comments mention Section 29.6.2 of RM0008, the STM32F1x Family Reference Manual. In section 31.6.2 (dotdotdot) of the <a href="http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00171190.pdf" title="Reference manual">newest version of RM0008</a><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref6">♠</a></sup>, we see that <code>0x06430041</code> is Revision A of XL-density devices.</p>
<p>So I need a more recent version of OpenOCD that has the newer STM32 devices. Crap.</p>
<p>See, I use the default vanilla FTDI drivers for my Olimex, presumably so I can use the Virtual COM Port driver for the broken-out UART the ARM-USB-TINY-H doesn’t have. Yeah, I’m dumb. But OpenOCD doesn’t support those drivers out of the box; licensing issues prevent binary distributors like <a href="http://www.freddiechopin.info/index.php/en/download/category/4-openocd" title="Freddie Chopin's OpenOCD builds">Freddie Chopin</a> from making available binaries compatible with regular FTDI drivers. Instead most people use <a href="http://www.intra2net.com/en/developer/libftdi/" title="libftdi">libftdi</a> and <a href="http://www.libusb.org/wiki/libusb-win32" title="libusb-win32">libusb-win32</a> for hardware interfacing on Windows.</p>
<p>So I gotta build OpenOCD myself to make it work? God damn it; what is this, Linux?</p>
<p>Let’s just say <code>$ ./configure --prefix=/cygdrive/c/Users/Xo/Desktop/ocd-build/out --enable-maintainer-mode --disable-werror --disable-shared --enable-ft2232_ftd2xx --with-ftd2xx-win32-zipdir=/cygdrive/c/Users/Xo/Desktop/ocd-build/ftd2xx CC="gcc -mno-cygwin"</code><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" id="fnref7">♥</a></sup></p>
<p>With my new OpenOCD <code>0.6.0-dev</code> build, I got a fully successful JTAG scan, and the OpenOCD GDB server is now open for business:</p>
<pre class="language-shell-session" tabindex="0"><code class="language-shell-session"><span class="token output">C:\Users\Xo>openocd -c "gdb_port 2222" -c "telnet_port 4444" -f "C:/Progra~2/OpenOCD/interface/olimex-arm-usb-tiny-h.cfg" -f "C:/Progra~2/OpenOCD/target/stm32f1x.cfg"
Open On-Chip Debugger 0.6.0-dev (2011-10-19-22:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
cortex_m3 reset_config sysresetreq
Info : device: 6 "2232H"
Info : deviceID: 364511274
Info : SerialNumber: OLTQ5QMÖA
Info : Description: Olimex OpenOCD JTAG ARM-USB-TINY-H A
Info : max TCK change to: 30000 kHz
Info : clock speed 1000 kHz
Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32.bs tap/device found: 0x06430041 (mfg: 0x020, part: 0x6430, ver: 0x0)
Info : stm32.cpu: hardware has 6 breakpoints, 4 watchpoints
</span></code></pre>
<p>lol @ <code>C:/Progra~2</code>. Because this thing <em>f—ing breaks</em> if I don’t.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>At least in sweet, sweet <a href="http://support.cc.gatech.edu/resources/technology-fees/tech-fee.inventionlab.2.pdf" title="Tech Fee request">funding</a> <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>No, not really <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>I hear in some Asian electrical engineering <s>tria-</s> circles, using more than 三 (3) little green wires is a shame to the engineer’s family and results in ritual <s>disassocia-</s> de-accreditation <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Yeah. On a first-version prototype. <em>Balls</em>, suckas. <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>“Performing board bringup” sounds way cooler than “bringing up” <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>As of 2011/10/19 <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn7" class="footnote-item"><p>Yeah, that really is for my benefit only. How did you guess? <a href="https://geekshavefeelings.com/posts/2011/assembly-izing-tassel/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Corn-Troller: Tassel
2011-10-12T11:23:33Z
https://geekshavefeelings.com/posts/2011/corn-troller-tassel/
<p>Looking around at the <a href="http://www.youtube.com/watch?v=b4W3iYRPeX4?hd=1">hoppin’ electric vehicle scene</a> happening at <a href="http://inventionstudio.gatech.edu/" title="GT Invention Studio">certain</a> <a href="http://miters.mit.edu/" title="MITERS">institutions</a>, I realized that pretty soon I’d be playing catch-up to more than just <a href="http://thevariableconstant.blogspot.com/">Jamo</a> when it comes stuff-strutting unless I started building something ridiculous, and quickly too.</p>
<p>So in typical son-of-an-accountant behavior, instead of building my own scooter, I decided to go the manic whacky sneaky route and build something to sell to the scooter builders. So now I’m announcing the corniest, trolliest brushless motor controller of them all: <em>Corntroller</em>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/TTWeOl07KC-690.avif 690w, https://geekshavefeelings.com/img/TTWeOl07KC-1380.avif 1380w, https://geekshavefeelings.com/img/TTWeOl07KC-3726.avif 3726w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/TTWeOl07KC-690.webp 690w, https://geekshavefeelings.com/img/TTWeOl07KC-1380.webp 1380w, https://geekshavefeelings.com/img/TTWeOl07KC-3726.webp 3726w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/TTWeOl07KC-690.jpeg 690w, https://geekshavefeelings.com/img/TTWeOl07KC-1380.jpeg 1380w, https://geekshavefeelings.com/img/TTWeOl07KC-3726.jpeg 3726w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Corntroller" src="https://geekshavefeelings.com/img/TTWeOl07KC-690.jpeg" width="3726" height="2480"></picture></figure><p></p>
<p>Corntroller is a result of me completely ripping off <a href="http://scolton.blogspot.com/p/motor-controllers.html" title="Shane's motor controllers">Shane Colton</a> and <a href="http://danstrother.com/2011/01/12/brushless-dc-motor-controller-board/" title="Dan's Brushless DC motor controller board">Dan Strother</a> to build an extremely feature-bloated brushless motor controller. All of the following will be devoted to driving just a single motor:</p>
<ul>
<li>Modular corn-inspired design, stacking a logic board (called <em>Tassel</em>) onto a power board (called <em>HexHusk</em>)</li>
<li>10V–45V operation with two switching regulators for logic power (<a href="http://www.linear.com/product/LT3991" title="LT3991">LT3991-5</a>, <a href="http://www.linear.com/product/LT3970" title="LT3970">LT3970-3.3</a>)</li>
<li>At least 40A of current capacity through <a href="http://ixdev.ixys.com/DataSheet/GWM160-0055X1.pdf" title="GWM160-0055X1">IXYS GWM160-0055X1</a> 3-phase MOSFET power modules</li>
<li>Way too much processing power from a 100-pin <a href="http://www.st.com/internet/mcu/product/247492.jsp" title="STM32F103VG">STM32F103VG</a>, one of the top parts in the STM32 F1 series of ARM Cortex M3 microcontrollers</li>
<li>Full voltage and current sensing on everything (motor phases and power bus), so I can implement vector control or sensorlessness</li>
<li>Compact three-phase N-channel FET driving through dedicated gate driver IC (<a href="http://www.allegromicro.com/en/Products/Part_Numbers/4935/">A4935</a>)</li>
<li>Motor hall sensor inputs to microcontroller capture timer</li>
<li>microSD card slot interfaced through SDIO (not MMC over SPI) for <a href="http://scolton.blogspot.com/2010/09/midi-for-your-motor.html" title="*cough*">datalogging</a></li>
<li>Full speed USB interface… just because</li>
<li>Two 7-segment LED displays… also just because</li>
<li>Full 9-degrees-of-measure IMU (accelerometer, gyroscope, magnetometer) with the some of the best dumb<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/" id="fnref1">*</a></sup> MEMS sensors (<a href="http://www.bosch-sensortec.com/content/language1/downloads/BST-BMA180-FL000-03.pdf" title="BMA180">BMA180</a>, <a href="http://invensense.com/mems/gyro/tripleaxis.html" title="IMU3000">IMU3000</a>, <a href="http://www.magneticsensors.com/three-axis-digital-compass.php" title="HMC5883L">HMC5883L</a>) available… just $@#%ing because</li>
</ul>
<p>I’m only half-joking about that last one; I designed <em>Tassel</em>, the logic board on Corntroller, as a replacement for my (yet to be written up) <em>Maizure</em> Cortex M3/MEMS sensors board. Maizure has served as my general dev board, and its successor is so full featured and has such overspec’d components because of that. But, I can choose to not populate components for unused features. So when Tassel is used as a part of Corntroller, it will not have its 3-axis MEMS sensor footprints populated<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/" id="fnref2">†</a></sup>.</p>
<p>By the way, I started naming my projects after corn. Just—you guessed it—because.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/EfLmQl6YPp-690.avif 690w, https://geekshavefeelings.com/img/EfLmQl6YPp-1380.avif 1380w, https://geekshavefeelings.com/img/EfLmQl6YPp-1639.avif 1639w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/EfLmQl6YPp-690.webp 690w, https://geekshavefeelings.com/img/EfLmQl6YPp-1380.webp 1380w, https://geekshavefeelings.com/img/EfLmQl6YPp-1639.webp 1639w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/EfLmQl6YPp-690.jpeg 690w, https://geekshavefeelings.com/img/EfLmQl6YPp-1380.jpeg 1380w, https://geekshavefeelings.com/img/EfLmQl6YPp-1639.jpeg 1639w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Tassel" src="https://geekshavefeelings.com/img/EfLmQl6YPp-690.jpeg" width="1639" height="1091"></picture></figure><p></p>
<p>Tassel was laid out with only surface mount components (preferring 0603<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/" id="fnref3">‡</a></sup> chip resistors and capacitors), all on the top side. Layout was actually fairly straightforward, since a lot of the work required just routing directly from STM32 pins to headers (which I could reassign anyways).</p>
<p>The hard part was figuring out which peripherals I could route <em>out of the STM32</em>. The original plan was to use a 48-pin device; this grew to 64-pin and then 100-pin as I realized that all the “good” peripherals I wanted in the STM32 were actually sharing the same pins.</p>
<p>For example, USART1 and TIM1 (with its useful three-phase complemented PWM with software deadtime insertion) shared the same pins. I had to spend a solid week assigning pins to their functionalities, restarting all over each time I had to up the pin count and move to a bigger device. Through all of this I also had to make sure to fan everything out properly so wires route cleanly from μC pin to headers and devices.</p>
<p>That’s really how I ended up with 7-segment displays; switching to 100 pins meant I had a lot of I/O pins left over that I didn’t want to go to waste. With the decimal point, each <a href="http://www.kingbrightusa.com/category.asp?catalog%5Fname=LED&category%5Fname=KC0%2E2in+1%2DDigit" title="Kingbright 10-SMD ACS 7-segment LED display">Kingbright 0.2″ display</a> fills up 8 pins: perfect for half a GPIO port, and thus nice to control in software.</p>
<p>Plus, 7-segment displays and resistor arrays are way easier to solder than individual 0805 LEDs and 0603 resistors.</p>
<p>So I ended up with a long list of nets to route well before even starting a schematic in <a href="http://www.cadsoftusa.com/" title="CadSoft - EAGLE">EAGLE</a> (see appendix)!</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/HjnxvuEZjY-690.avif 690w, https://geekshavefeelings.com/img/HjnxvuEZjY-1380.avif 1380w, https://geekshavefeelings.com/img/HjnxvuEZjY-1764.avif 1764w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/HjnxvuEZjY-690.webp 690w, https://geekshavefeelings.com/img/HjnxvuEZjY-1380.webp 1380w, https://geekshavefeelings.com/img/HjnxvuEZjY-1764.webp 1764w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/HjnxvuEZjY-690.png 690w, https://geekshavefeelings.com/img/HjnxvuEZjY-1380.png 1380w, https://geekshavefeelings.com/img/HjnxvuEZjY-1764.png 1764w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Tassel layout" src="https://geekshavefeelings.com/img/HjnxvuEZjY-690.png" width="1764" height="1056"></picture></figure><p></p>
<p>Since Maizure had a bit of problems with noise and stability, I made Tassel a four-layer design. This means extra layers of copper on which to route signals, but more importantly to serve as ground planes for surface signals. This isn’t necessarily <em>needed</em>, but it certainly lends me extra noise immunity I figure I’d want on such a densely routed board.</p>
<p>A four-layer design meant I had way fewer choices in PCB fabrication: I went with <a href="http://www.dorkbotpdx.org/wiki/pcb_order" title="Laen's group order">Dorkbot Portland’s group PCB order</a>, but also considered <a href="http://www.4pcb.com/index.php?load=content&page_id=131" title="4PCB $66 each">4PCB’s/Advanced Circuits’s $66 each service</a> and <a href="http://batchpcb.com/index.php/Faq#what_are_the_pcb_rules" title="BatchPCB 4-layer">BatchPCB’s 4-layer group order</a>. For me, DorkbotPDX just turned out to be the best bang for the buck.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/imtEO-FKds-690.avif 690w, https://geekshavefeelings.com/img/imtEO-FKds-1380.avif 1380w, https://geekshavefeelings.com/img/imtEO-FKds-4912.avif 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/imtEO-FKds-690.webp 690w, https://geekshavefeelings.com/img/imtEO-FKds-1380.webp 1380w, https://geekshavefeelings.com/img/imtEO-FKds-4912.webp 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/imtEO-FKds-690.jpeg 690w, https://geekshavefeelings.com/img/imtEO-FKds-1380.jpeg 1380w, https://geekshavefeelings.com/img/imtEO-FKds-4912.jpeg 4912w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Tassel in the wind" src="https://geekshavefeelings.com/img/imtEO-FKds-690.jpeg" width="4912" height="3264"></picture></figure><p></p>
<p>Why do I just have photos of unpopulated boards? Because (a) they’re pretty and (b) I sent these out before I finished designing the power stage, in an attempt to pipeline the prototyping process. I wanted to send these out, complete HexHusk, order parts for both from Digi-Key, and have the components before Tassel’s boards arrived. That didn’t happen… the Digi-Key order is just now in the mail. Guess I failed at pipelining.</p>
<p>Design files for everything and a HexHusk post are coming. I promise.</p>
<p><strong>Appendix</strong>
Partial pin assignments:</p>
<pre><code>Outputs
=======
# Q1
15 PC0 V_P
16 PC1 V_A
17 PC2 V_B
18 PC3 V_C
23 PA0 I_A
24 PA1 I_B
25 PA2 I_P
# Q2
26 PA3 AN_0
29 PA4 SPI1_NSS
30 PA5 SPI1_SCK
31 PA6 SPI1_MISO
32 PA7 SPI1_MOSI
- V+
- V-
- 3.3V
39 PE8 PWM1~ # remap
40 PE9 PWM1 # remap
41 PE10 PWM2~ # remap
42 PE11 PWM2 # remap
43 PE12 PWM3~ # remap
44 PE13 PWM3 # remap
# Q3
68 PA9 USART1_TX
69 PA10 USART1_RX
# Q4
86 PD5 H1 # 5V
87 PD6 H2 # 5V
88 PD7 H3 # 5V
92 PB6 I2C1_SCL
93 PB7 I2C1_SDA
JTAG
====
- 3.3V
PB4 JTRST
PA15 JTDI
PA13 JTMS
PA14 JTCK
PB3 JTDO
NRST RESET
- V-
USB
===
PA11 USB_D-
PA12 USB_D+
- V+
- V-
SDIO
====
PC8 SDIO_D0
PC9 SDIO_D1
PC10 SDIO_D2
PC11 SDIO_D3
PC12 SDIO_CK
PD2 SDIO_CMD
MEMS
====
PB10 I2C2_SCL
PB11 I2C2_SDA
PB12 SPI2_NSS
PB13 SPI2_SCK
PB14 SPI2_MISO
PB15 SPI2_MOSI
</code></pre>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Read: non-intelligent, where “intelligent” is a <a href="http://en.wikipedia.org/wiki/Intelligent_sensor" title="WP: Intelligent sensor">technical term</a> <a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Or maybe it will… what electric vehicle could use an IMU? ;) <a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>That’s 63 mils by 31 mils or 0.063″×0.031″ <a href="https://geekshavefeelings.com/posts/2011/corn-troller-tassel/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
5 V to 3.3 V with Preferred Resistors
2011-10-02T02:33:26Z
https://geekshavefeelings.com/posts/2011/5v-to-3-3v-with-preferred-resistors/
<p>What do you do when you want to scale a 5 V analog signal to 3.3 V? You build a resistor divider, possibly with an op amp-based voltage follower to drive low impedance loads.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/V33JGc_waK-690.avif 690w, https://geekshavefeelings.com/img/V33JGc_waK-1380.avif 1380w, https://geekshavefeelings.com/img/V33JGc_waK-1593.avif 1593w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/V33JGc_waK-690.webp 690w, https://geekshavefeelings.com/img/V33JGc_waK-1380.webp 1380w, https://geekshavefeelings.com/img/V33JGc_waK-1593.webp 1593w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/V33JGc_waK-690.png 690w, https://geekshavefeelings.com/img/V33JGc_waK-1380.png 1380w, https://geekshavefeelings.com/img/V33JGc_waK-1593.png 1593w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="microchip_en026368.pdf" src="https://geekshavefeelings.com/img/V33JGc_waK-690.png" width="1593" height="810"></picture></figure><p></p>
<p>But what resistors do you buy for your resistor bridge? You <em>want</em> resistance values of some multiple of 1.7 to 3.3, but resistors come in <a href="http://www.logwell.com/tech/components/resistor_values.html" title="Resistor decades">preferred values</a>, which are mathemagicatically spaced out resistance scales.</p>
<p>None of the “nice” E24 values that are multiples of 170 or 330 really work (330 exists, but not 170; there’s a 510 but no 990; and 680 but no 1320).</p>
<p>There’s gotta be some kind of ideal combination of preferred-value resistors that give me either the perfect 5 V to 3.3 V divider, or at least minimizes the error. Well, I wasn’t about to do all 24² combinations of upper/lower resistors by hand and for some reason Google couldn’t find it for me, so I wrote a <a href="https://geekshavefeelings.com/posts/2011/5v-to-3-3v-with-preferred-resistors/"><s>script</s> C++0x program</a> to uh… do it for me (although the code runs in O(N * log N) time rather than O(N²) time, so it doesn’t even do the full 24² search).</p>
<p>So what are the results for each EIA resistor value series?</p>
<table>
<thead>
<tr>
<th style="text-align:center">Resistor series</th>
<th style="text-align:left">R<sub>1</sub> (Ω)</th>
<th style="text-align:left">R<sub>2</sub> (Ω)</th>
<th style="text-align:left">Divider Error</th>
<th style="text-align:left">Tolerance Error (max)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">E12</td>
<td style="text-align:left">180 ± 10 %</td>
<td style="text-align:left">330 ± 10 %</td>
<td style="text-align:left">−2.6 %</td>
<td style="text-align:left">± 21 %</td>
</tr>
<tr>
<td style="text-align:center">E24</td>
<td style="text-align:left">470 ± 5 %</td>
<td style="text-align:left">910 ± 5 %</td>
<td style="text-align:left">−0.15 %</td>
<td style="text-align:left">± 10.25 %</td>
</tr>
<tr>
<td style="text-align:center">E48</td>
<td style="text-align:left">825 ± 2 %</td>
<td style="text-align:left">1600 ± 2 %</td>
<td style="text-align:left">−0.0342 %</td>
<td style="text-align:left">± 4.04 %</td>
</tr>
<tr>
<td style="text-align:center">E96</td>
<td style="text-align:left">491 ± 1 %</td>
<td style="text-align:left">953 ± 1 %</td>
<td style="text-align:left">−0.00420 %</td>
<td style="text-align:left">± 2.01 %</td>
</tr>
<tr>
<td style="text-align:center">E192</td>
<td style="text-align:left">102 ± 0.5 %</td>
<td style="text-align:left">198 ± 0.5 %</td>
<td style="text-align:left">0 %</td>
<td style="text-align:left">± 1.0025 %</td>
</tr>
</tbody>
</table>
<p>Those error percentages are for the resulting voltages. For example, the 180 & 330 combo would have an error of <mjx-container class="MathJax" jax="SVG" style="direction: ltr; position: relative;"><svg style="overflow: visible; min-height: 1px; min-width: 1px; vertical-align: -0.912ex;" xmlns="http://www.w3.org/2000/svg" width="37.543ex" height="2.869ex" role="img" focusable="false" viewBox="0 -864.9 16594 1267.9" aria-hidden="true"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mrow"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(458,0)"><g data-mml-node="mn" transform="translate(1025.4,394) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mrow" transform="translate(220,-345) scale(0.707)"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(1500,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(2278,0)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"></path></g></g><rect width="2871.4" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(3791.7,0)"><path data-c="F7" d="M318 466Q318 500 339 518T386 537Q418 537 438 517T458 466Q458 438 440 417T388 396Q355 396 337 417T318 466ZM56 237T56 250T70 270H706Q721 262 721 250T706 230H70Q56 237 56 250ZM318 34Q318 68 339 86T386 105Q418 105 438 85T458 34Q458 6 440 -15T388 -36Q355 -36 337 -15T318 34Z" style="stroke-width: 3;"></path></g><g data-mml-node="mfrac" transform="translate(4791.9,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z" transform="translate(778,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(495.1,-345) scale(0.707)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z" style="stroke-width: 3;"></path></g><rect width="1103.7" height="60" x="120" y="220"></rect></g><g data-mml-node="mo" transform="translate(6357.8,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(7358,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(7858,0) translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z" style="stroke-width: 3;"></path></g></g><g data-mml-node="mo" transform="translate(8538.2,0)"><path data-c="D7" d="M630 29Q630 9 609 9Q604 9 587 25T493 118L389 222L284 117Q178 13 175 11Q171 9 168 9Q160 9 154 15T147 29Q147 36 161 51T255 146L359 250L255 354Q174 435 161 449T147 471Q147 480 153 485T168 490Q173 490 175 489Q178 487 284 383L389 278L493 382Q570 459 587 475T609 491Q630 491 630 471Q630 464 620 453T522 355L418 250L522 145Q606 61 618 48T630 29Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(9538.5,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z" transform="translate(1000,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(11038.5,0)"><path data-c="25" d="M465 605Q428 605 394 614T340 632T319 641Q332 608 332 548Q332 458 293 403T202 347Q145 347 101 402T56 548Q56 637 101 693T202 750Q241 750 272 719Q359 642 464 642Q580 642 650 732Q662 748 668 749Q670 750 673 750Q682 750 688 743T693 726Q178 -47 170 -52Q166 -56 160 -56Q147 -56 142 -45Q137 -36 142 -27Q143 -24 363 304Q469 462 525 546T581 630Q528 605 465 605ZM207 385Q235 385 263 427T292 548Q292 617 267 664T200 712Q193 712 186 709T167 698T147 668T134 615Q132 595 132 548V527Q132 436 165 403Q183 385 203 385H207ZM500 146Q500 234 544 290T647 347Q699 347 737 292T776 146T737 0T646 -56Q590 -56 545 0T500 146ZM651 -18Q679 -18 707 24T736 146Q736 215 711 262T644 309Q637 309 630 306T611 295T591 265T578 212Q577 200 577 146V124Q577 -18 647 -18H651Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(12149.2,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z" style="stroke-width: 3;"></path></g><g data-mml-node="mo" transform="translate(13205,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z" style="stroke-width: 3;"></path></g><g data-mml-node="mn" transform="translate(13983,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" style="stroke-width: 3;"></path><path data-c="2E" d="M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z" transform="translate(500,0)" style="stroke-width: 3;"></path><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z" transform="translate(778,0)" style="stroke-width: 3;"></path><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z" transform="translate(1278,0)" style="stroke-width: 3;"></path></g><g data-mml-node="mi" transform="translate(15761,0)"><path data-c="25" d="M465 605Q428 605 394 614T340 632T319 641Q332 608 332 548Q332 458 293 403T202 347Q145 347 101 402T56 548Q56 637 101 693T202 750Q241 750 272 719Q359 642 464 642Q580 642 650 732Q662 748 668 749Q670 750 673 750Q682 750 688 743T693 726Q178 -47 170 -52Q166 -56 160 -56Q147 -56 142 -45Q137 -36 142 -27Q143 -24 363 304Q469 462 525 546T581 630Q528 605 465 605ZM207 385Q235 385 263 427T292 548Q292 617 267 664T200 712Q193 712 186 709T167 698T147 668T134 615Q132 595 132 548V527Q132 436 165 403Q183 385 203 385H207ZM500 146Q500 234 544 290T647 347Q699 347 737 292T776 146T737 0T646 -56Q590 -56 545 0T500 146ZM651 -18Q679 -18 707 24T736 146Q736 215 711 262T644 309Q637 309 630 306T611 295T591 265T578 212Q577 200 577 146V124Q577 -18 647 -18H651Z" style="stroke-width: 3;"></path></g></g></g></svg><mjx-assistive-mml unselectable="on" display="inline" style="top: 0px; left: 0px; clip: rect(1px, 1px, 1px, 1px); -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; position: absolute; padding: 1px 0px 0px 0px; border: 0px; display: block; width: auto; overflow: hidden;"><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow data-mjx-texclass="INNER"><mo data-mjx-texclass="OPEN">(</mo><mfrac><mn>330</mn><mrow><mn>180</mn><mo>+</mo><mn>330</mn></mrow></mfrac><mo>÷</mo><mfrac><mn>3.3</mn><mn>5</mn></mfrac><mo>−</mo><mn>1</mn><mo data-mjx-texclass="CLOSE">)</mo></mrow><mo>×</mo><mn>100</mn><mi mathvariant="normal">%</mi><mo>=</mo><mo>−</mo><mn>1.96</mn><mi mathvariant="normal">%</mi></math></mjx-assistive-mml></mjx-container>. Not bad for parts you can get at RadioShack.</p>
<p>It turns E192 does have a perfect combo, but it’s not like E192-series resistors are available in just any kit. However, you can get E96 resistors to build a divider with only −4.20 ppm nominal (not total) error.</p>
<p>However, keep in mind that most resistors are exactly as wrong as their tolerances due to <a href="http://www.edn.com/article/509250-7_solution.php">the bimodal distribution of binned resistor values</a>. So, it’s clear that in each resistor series that the error due to tolerance far outweighs the divider ratio being off due to less than ideal nominal values. All that the time I’ve spent on making it “correct” was completely wasted, because what my search <em>really</em> should have keyed on is the expected value of each resistor, not its nominal value.</p>
<p>Oh well.</p>
<h2 id="appendix" tabindex="-1">Appendix <a class="header-anchor" href="https://geekshavefeelings.com/posts/2011/5v-to-3-3v-with-preferred-resistors/">§</a></h2>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">// (C) Copyright 2011 Xo Wang <xo@geekshavefeelings.com></span>
<span class="token comment">// SPDX-License-Identifier: Apache-2.0</span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><algorithm></span> <span class="token comment">// <3 lower_bound, <3 set_union</span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><iostream></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><limits></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><string></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><vector></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><cmath></span></span>
<span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><cstdlib></span></span>
<span class="token keyword">static</span> <span class="token keyword">double</span> <span class="token function">error</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">double</span> r1<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">double</span> r2<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>r2 <span class="token operator">*</span> <span class="token number">1.7</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token punctuation">(</span>r1 <span class="token operator">*</span> <span class="token number">3.3</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1.0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> <span class="token keyword">double</span> <span class="token function">true_error</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">double</span> r1<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">double</span> r2<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>r2 <span class="token operator">*</span> <span class="token number">5.0</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>r1 <span class="token operator">+</span> r2<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">3.3</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1.0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">process_series</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&</span> name<span class="token punctuation">,</span>
<span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> series<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">using</span> <span class="token keyword">namespace</span> std<span class="token punctuation">;</span>
<span class="token keyword">int</span> min_error_r1 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> min_error_r2 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">double</span> min_error <span class="token operator">=</span> <span class="token class-name">numeric_limits</span><span class="token operator"><</span><span class="token keyword">double</span><span class="token operator">></span><span class="token double-colon punctuation">::</span><span class="token function">max</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">for_each</span><span class="token punctuation">(</span>series<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> series<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token operator">&</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span> r1<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// find nearest resistance</span>
<span class="token keyword">const</span> <span class="token keyword">double</span> r2_wanted <span class="token operator">=</span> r1 <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token number">3.3</span> <span class="token operator">/</span> <span class="token number">1.7</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// r_wanted is too large, so scale it down by ten when searching</span>
<span class="token keyword">const</span> <span class="token keyword">bool</span> r2_wanted_10x <span class="token operator">=</span> r2_wanted <span class="token operator">></span> series<span class="token punctuation">.</span><span class="token function">back</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">auto</span> r2_higher_iter <span class="token operator">=</span>
<span class="token function">lower_bound</span><span class="token punctuation">(</span>series<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> series<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
r2_wanted_10x <span class="token operator">?</span> r2_wanted <span class="token operator">*</span> <span class="token number">0.1</span> <span class="token operator">:</span> r2_wanted<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// nearest two resistance values</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> r2_higher <span class="token operator">=</span>
r2_wanted_10x <span class="token operator">?</span> <span class="token operator">*</span>r2_higher_iter <span class="token operator">*</span> <span class="token number">10</span> <span class="token operator">:</span> <span class="token operator">*</span>r2_higher_iter<span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">int</span> r2_lower <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">=</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-></span> <span class="token keyword">int</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>r2_higher <span class="token operator">==</span> series<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">*</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> series<span class="token punctuation">.</span><span class="token function">back</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> r2_wanted_10x <span class="token operator">?</span> <span class="token operator">*</span><span class="token punctuation">(</span>r2_higher_iter <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">10</span> <span class="token operator">:</span> <span class="token operator">*</span><span class="token punctuation">(</span>r2_higher_iter <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">fabs</span><span class="token punctuation">(</span>min_error<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token function">fabs</span><span class="token punctuation">(</span><span class="token function">error</span><span class="token punctuation">(</span>r1<span class="token punctuation">,</span> r2_lower<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
min_error <span class="token operator">=</span> <span class="token function">true_error</span><span class="token punctuation">(</span>r1<span class="token punctuation">,</span> r2_lower<span class="token punctuation">)</span><span class="token punctuation">;</span>
min_error_r1 <span class="token operator">=</span> r1<span class="token punctuation">;</span>
min_error_r2 <span class="token operator">=</span> r2_lower<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">fabs</span><span class="token punctuation">(</span>min_error<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token function">fabs</span><span class="token punctuation">(</span><span class="token function">error</span><span class="token punctuation">(</span>r1<span class="token punctuation">,</span> r2_higher<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
min_error <span class="token operator">=</span> <span class="token function">true_error</span><span class="token punctuation">(</span>r1<span class="token punctuation">,</span> r2_higher<span class="token punctuation">)</span><span class="token punctuation">;</span>
min_error_r1 <span class="token operator">=</span> r1<span class="token punctuation">;</span>
min_error_r2 <span class="token operator">=</span> r2_higher<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
cout <span class="token operator"><<</span> name <span class="token operator"><<</span> <span class="token string">" best: r1 = "</span> <span class="token operator"><<</span> min_error_r1 <span class="token operator"><<</span> <span class="token string">", r2 = "</span> <span class="token operator"><<</span> min_error_r2
<span class="token operator"><<</span> <span class="token string">" ("</span> <span class="token operator"><<</span> <span class="token punctuation">(</span>min_error <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">?</span> <span class="token string">"+"</span> <span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">)</span> <span class="token operator"><<</span> min_error <span class="token operator">*</span> <span class="token number">100</span> <span class="token operator"><<</span> <span class="token string">"%)\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> <span class="token function">merge_series</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span><span class="token operator">&</span> s1<span class="token punctuation">,</span>
<span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span><span class="token operator">&</span> s2<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">using</span> <span class="token keyword">namespace</span> std<span class="token punctuation">;</span>
vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> <span class="token function">out_series</span><span class="token punctuation">(</span>s1<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> s2<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">auto</span> last <span class="token operator">=</span>
<span class="token function">set_union</span><span class="token punctuation">(</span>s1<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> s1<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> s2<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> s2<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> out_series<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
out_series<span class="token punctuation">.</span><span class="token function">resize</span><span class="token punctuation">(</span><span class="token function">distance</span><span class="token punctuation">(</span>out_series<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> last<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> out_series<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">using</span> <span class="token keyword">namespace</span> std<span class="token punctuation">;</span>
<span class="token keyword">const</span> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> E12 <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">120</span><span class="token punctuation">,</span> <span class="token number">150</span><span class="token punctuation">,</span> <span class="token number">180</span><span class="token punctuation">,</span> <span class="token number">220</span><span class="token punctuation">,</span> <span class="token number">270</span><span class="token punctuation">,</span>
<span class="token number">330</span><span class="token punctuation">,</span> <span class="token number">390</span><span class="token punctuation">,</span> <span class="token number">470</span><span class="token punctuation">,</span> <span class="token number">560</span><span class="token punctuation">,</span> <span class="token number">680</span><span class="token punctuation">,</span> <span class="token number">820</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> E24 <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">,</span> <span class="token number">120</span><span class="token punctuation">,</span> <span class="token number">130</span><span class="token punctuation">,</span> <span class="token number">150</span><span class="token punctuation">,</span> <span class="token number">160</span><span class="token punctuation">,</span> <span class="token number">180</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span>
<span class="token number">220</span><span class="token punctuation">,</span> <span class="token number">240</span><span class="token punctuation">,</span> <span class="token number">270</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">,</span> <span class="token number">330</span><span class="token punctuation">,</span> <span class="token number">360</span><span class="token punctuation">,</span> <span class="token number">390</span><span class="token punctuation">,</span> <span class="token number">430</span><span class="token punctuation">,</span>
<span class="token number">470</span><span class="token punctuation">,</span> <span class="token number">510</span><span class="token punctuation">,</span> <span class="token number">560</span><span class="token punctuation">,</span> <span class="token number">620</span><span class="token punctuation">,</span> <span class="token number">680</span><span class="token punctuation">,</span> <span class="token number">750</span><span class="token punctuation">,</span> <span class="token number">820</span><span class="token punctuation">,</span> <span class="token number">910</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> E48 <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">105</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">,</span> <span class="token number">115</span><span class="token punctuation">,</span> <span class="token number">121</span><span class="token punctuation">,</span> <span class="token number">127</span><span class="token punctuation">,</span> <span class="token number">133</span><span class="token punctuation">,</span> <span class="token number">140</span><span class="token punctuation">,</span> <span class="token number">147</span><span class="token punctuation">,</span> <span class="token number">154</span><span class="token punctuation">,</span>
<span class="token number">162</span><span class="token punctuation">,</span> <span class="token number">169</span><span class="token punctuation">,</span> <span class="token number">178</span><span class="token punctuation">,</span> <span class="token number">187</span><span class="token punctuation">,</span> <span class="token number">196</span><span class="token punctuation">,</span> <span class="token number">205</span><span class="token punctuation">,</span> <span class="token number">215</span><span class="token punctuation">,</span> <span class="token number">226</span><span class="token punctuation">,</span> <span class="token number">237</span><span class="token punctuation">,</span> <span class="token number">249</span><span class="token punctuation">,</span>
<span class="token number">261</span><span class="token punctuation">,</span> <span class="token number">274</span><span class="token punctuation">,</span> <span class="token number">287</span><span class="token punctuation">,</span> <span class="token number">301</span><span class="token punctuation">,</span> <span class="token number">316</span><span class="token punctuation">,</span> <span class="token number">332</span><span class="token punctuation">,</span> <span class="token number">348</span><span class="token punctuation">,</span> <span class="token number">365</span><span class="token punctuation">,</span> <span class="token number">383</span><span class="token punctuation">,</span> <span class="token number">402</span><span class="token punctuation">,</span>
<span class="token number">422</span><span class="token punctuation">,</span> <span class="token number">442</span><span class="token punctuation">,</span> <span class="token number">464</span><span class="token punctuation">,</span> <span class="token number">487</span><span class="token punctuation">,</span> <span class="token number">511</span><span class="token punctuation">,</span> <span class="token number">536</span><span class="token punctuation">,</span> <span class="token number">562</span><span class="token punctuation">,</span> <span class="token number">590</span><span class="token punctuation">,</span> <span class="token number">619</span><span class="token punctuation">,</span> <span class="token number">649</span><span class="token punctuation">,</span>
<span class="token number">681</span><span class="token punctuation">,</span> <span class="token number">715</span><span class="token punctuation">,</span> <span class="token number">750</span><span class="token punctuation">,</span> <span class="token number">787</span><span class="token punctuation">,</span> <span class="token number">825</span><span class="token punctuation">,</span> <span class="token number">866</span><span class="token punctuation">,</span> <span class="token number">909</span><span class="token punctuation">,</span> <span class="token number">953</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> E96 <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">102</span><span class="token punctuation">,</span> <span class="token number">105</span><span class="token punctuation">,</span> <span class="token number">107</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">,</span> <span class="token number">113</span><span class="token punctuation">,</span> <span class="token number">115</span><span class="token punctuation">,</span> <span class="token number">118</span><span class="token punctuation">,</span> <span class="token number">121</span><span class="token punctuation">,</span> <span class="token number">124</span><span class="token punctuation">,</span> <span class="token number">127</span><span class="token punctuation">,</span> <span class="token number">130</span><span class="token punctuation">,</span> <span class="token number">133</span><span class="token punctuation">,</span> <span class="token number">137</span><span class="token punctuation">,</span>
<span class="token number">140</span><span class="token punctuation">,</span> <span class="token number">143</span><span class="token punctuation">,</span> <span class="token number">147</span><span class="token punctuation">,</span> <span class="token number">150</span><span class="token punctuation">,</span> <span class="token number">154</span><span class="token punctuation">,</span> <span class="token number">158</span><span class="token punctuation">,</span> <span class="token number">162</span><span class="token punctuation">,</span> <span class="token number">165</span><span class="token punctuation">,</span> <span class="token number">169</span><span class="token punctuation">,</span> <span class="token number">174</span><span class="token punctuation">,</span> <span class="token number">178</span><span class="token punctuation">,</span> <span class="token number">182</span><span class="token punctuation">,</span> <span class="token number">187</span><span class="token punctuation">,</span> <span class="token number">191</span><span class="token punctuation">,</span>
<span class="token number">196</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token number">205</span><span class="token punctuation">,</span> <span class="token number">210</span><span class="token punctuation">,</span> <span class="token number">215</span><span class="token punctuation">,</span> <span class="token number">221</span><span class="token punctuation">,</span> <span class="token number">226</span><span class="token punctuation">,</span> <span class="token number">232</span><span class="token punctuation">,</span> <span class="token number">237</span><span class="token punctuation">,</span> <span class="token number">243</span><span class="token punctuation">,</span> <span class="token number">249</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">261</span><span class="token punctuation">,</span> <span class="token number">267</span><span class="token punctuation">,</span>
<span class="token number">274</span><span class="token punctuation">,</span> <span class="token number">280</span><span class="token punctuation">,</span> <span class="token number">287</span><span class="token punctuation">,</span> <span class="token number">294</span><span class="token punctuation">,</span> <span class="token number">301</span><span class="token punctuation">,</span> <span class="token number">309</span><span class="token punctuation">,</span> <span class="token number">316</span><span class="token punctuation">,</span> <span class="token number">324</span><span class="token punctuation">,</span> <span class="token number">332</span><span class="token punctuation">,</span> <span class="token number">340</span><span class="token punctuation">,</span> <span class="token number">348</span><span class="token punctuation">,</span> <span class="token number">357</span><span class="token punctuation">,</span> <span class="token number">365</span><span class="token punctuation">,</span> <span class="token number">374</span><span class="token punctuation">,</span>
<span class="token number">383</span><span class="token punctuation">,</span> <span class="token number">392</span><span class="token punctuation">,</span> <span class="token number">402</span><span class="token punctuation">,</span> <span class="token number">412</span><span class="token punctuation">,</span> <span class="token number">422</span><span class="token punctuation">,</span> <span class="token number">432</span><span class="token punctuation">,</span> <span class="token number">442</span><span class="token punctuation">,</span> <span class="token number">453</span><span class="token punctuation">,</span> <span class="token number">464</span><span class="token punctuation">,</span> <span class="token number">475</span><span class="token punctuation">,</span> <span class="token number">487</span><span class="token punctuation">,</span> <span class="token number">491</span><span class="token punctuation">,</span> <span class="token number">511</span><span class="token punctuation">,</span> <span class="token number">523</span><span class="token punctuation">,</span>
<span class="token number">536</span><span class="token punctuation">,</span> <span class="token number">549</span><span class="token punctuation">,</span> <span class="token number">562</span><span class="token punctuation">,</span> <span class="token number">576</span><span class="token punctuation">,</span> <span class="token number">590</span><span class="token punctuation">,</span> <span class="token number">604</span><span class="token punctuation">,</span> <span class="token number">619</span><span class="token punctuation">,</span> <span class="token number">634</span><span class="token punctuation">,</span> <span class="token number">649</span><span class="token punctuation">,</span> <span class="token number">665</span><span class="token punctuation">,</span> <span class="token number">681</span><span class="token punctuation">,</span> <span class="token number">698</span><span class="token punctuation">,</span> <span class="token number">715</span><span class="token punctuation">,</span> <span class="token number">732</span><span class="token punctuation">,</span>
<span class="token number">750</span><span class="token punctuation">,</span> <span class="token number">768</span><span class="token punctuation">,</span> <span class="token number">787</span><span class="token punctuation">,</span> <span class="token number">806</span><span class="token punctuation">,</span> <span class="token number">825</span><span class="token punctuation">,</span> <span class="token number">845</span><span class="token punctuation">,</span> <span class="token number">866</span><span class="token punctuation">,</span> <span class="token number">887</span><span class="token punctuation">,</span> <span class="token number">909</span><span class="token punctuation">,</span> <span class="token number">931</span><span class="token punctuation">,</span> <span class="token number">959</span><span class="token punctuation">,</span> <span class="token number">976</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> E192 <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">101</span><span class="token punctuation">,</span> <span class="token number">102</span><span class="token punctuation">,</span> <span class="token number">104</span><span class="token punctuation">,</span> <span class="token number">105</span><span class="token punctuation">,</span> <span class="token number">106</span><span class="token punctuation">,</span> <span class="token number">107</span><span class="token punctuation">,</span> <span class="token number">109</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">,</span> <span class="token number">111</span><span class="token punctuation">,</span> <span class="token number">113</span><span class="token punctuation">,</span> <span class="token number">114</span><span class="token punctuation">,</span> <span class="token number">115</span><span class="token punctuation">,</span> <span class="token number">117</span><span class="token punctuation">,</span> <span class="token number">118</span><span class="token punctuation">,</span>
<span class="token number">120</span><span class="token punctuation">,</span> <span class="token number">121</span><span class="token punctuation">,</span> <span class="token number">123</span><span class="token punctuation">,</span> <span class="token number">124</span><span class="token punctuation">,</span> <span class="token number">126</span><span class="token punctuation">,</span> <span class="token number">127</span><span class="token punctuation">,</span> <span class="token number">129</span><span class="token punctuation">,</span> <span class="token number">130</span><span class="token punctuation">,</span> <span class="token number">132</span><span class="token punctuation">,</span> <span class="token number">133</span><span class="token punctuation">,</span> <span class="token number">135</span><span class="token punctuation">,</span> <span class="token number">137</span><span class="token punctuation">,</span> <span class="token number">138</span><span class="token punctuation">,</span> <span class="token number">140</span><span class="token punctuation">,</span> <span class="token number">142</span><span class="token punctuation">,</span>
<span class="token number">143</span><span class="token punctuation">,</span> <span class="token number">145</span><span class="token punctuation">,</span> <span class="token number">147</span><span class="token punctuation">,</span> <span class="token number">149</span><span class="token punctuation">,</span> <span class="token number">150</span><span class="token punctuation">,</span> <span class="token number">152</span><span class="token punctuation">,</span> <span class="token number">154</span><span class="token punctuation">,</span> <span class="token number">156</span><span class="token punctuation">,</span> <span class="token number">158</span><span class="token punctuation">,</span> <span class="token number">160</span><span class="token punctuation">,</span> <span class="token number">162</span><span class="token punctuation">,</span> <span class="token number">164</span><span class="token punctuation">,</span> <span class="token number">165</span><span class="token punctuation">,</span> <span class="token number">167</span><span class="token punctuation">,</span> <span class="token number">169</span><span class="token punctuation">,</span>
<span class="token number">172</span><span class="token punctuation">,</span> <span class="token number">174</span><span class="token punctuation">,</span> <span class="token number">176</span><span class="token punctuation">,</span> <span class="token number">178</span><span class="token punctuation">,</span> <span class="token number">180</span><span class="token punctuation">,</span> <span class="token number">182</span><span class="token punctuation">,</span> <span class="token number">184</span><span class="token punctuation">,</span> <span class="token number">187</span><span class="token punctuation">,</span> <span class="token number">189</span><span class="token punctuation">,</span> <span class="token number">191</span><span class="token punctuation">,</span> <span class="token number">193</span><span class="token punctuation">,</span> <span class="token number">196</span><span class="token punctuation">,</span> <span class="token number">198</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token number">203</span><span class="token punctuation">,</span>
<span class="token number">205</span><span class="token punctuation">,</span> <span class="token number">208</span><span class="token punctuation">,</span> <span class="token number">210</span><span class="token punctuation">,</span> <span class="token number">213</span><span class="token punctuation">,</span> <span class="token number">215</span><span class="token punctuation">,</span> <span class="token number">218</span><span class="token punctuation">,</span> <span class="token number">221</span><span class="token punctuation">,</span> <span class="token number">223</span><span class="token punctuation">,</span> <span class="token number">226</span><span class="token punctuation">,</span> <span class="token number">229</span><span class="token punctuation">,</span> <span class="token number">232</span><span class="token punctuation">,</span> <span class="token number">234</span><span class="token punctuation">,</span> <span class="token number">237</span><span class="token punctuation">,</span> <span class="token number">240</span><span class="token punctuation">,</span> <span class="token number">243</span><span class="token punctuation">,</span>
<span class="token number">246</span><span class="token punctuation">,</span> <span class="token number">249</span><span class="token punctuation">,</span> <span class="token number">252</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">258</span><span class="token punctuation">,</span> <span class="token number">261</span><span class="token punctuation">,</span> <span class="token number">264</span><span class="token punctuation">,</span> <span class="token number">267</span><span class="token punctuation">,</span> <span class="token number">271</span><span class="token punctuation">,</span> <span class="token number">274</span><span class="token punctuation">,</span> <span class="token number">277</span><span class="token punctuation">,</span> <span class="token number">280</span><span class="token punctuation">,</span> <span class="token number">284</span><span class="token punctuation">,</span> <span class="token number">287</span><span class="token punctuation">,</span> <span class="token number">291</span><span class="token punctuation">,</span>
<span class="token number">294</span><span class="token punctuation">,</span> <span class="token number">298</span><span class="token punctuation">,</span> <span class="token number">301</span><span class="token punctuation">,</span> <span class="token number">305</span><span class="token punctuation">,</span> <span class="token number">309</span><span class="token punctuation">,</span> <span class="token number">312</span><span class="token punctuation">,</span> <span class="token number">316</span><span class="token punctuation">,</span> <span class="token number">320</span><span class="token punctuation">,</span> <span class="token number">324</span><span class="token punctuation">,</span> <span class="token number">328</span><span class="token punctuation">,</span> <span class="token number">332</span><span class="token punctuation">,</span> <span class="token number">336</span><span class="token punctuation">,</span> <span class="token number">340</span><span class="token punctuation">,</span> <span class="token number">344</span><span class="token punctuation">,</span> <span class="token number">348</span><span class="token punctuation">,</span>
<span class="token number">352</span><span class="token punctuation">,</span> <span class="token number">357</span><span class="token punctuation">,</span> <span class="token number">361</span><span class="token punctuation">,</span> <span class="token number">365</span><span class="token punctuation">,</span> <span class="token number">370</span><span class="token punctuation">,</span> <span class="token number">374</span><span class="token punctuation">,</span> <span class="token number">379</span><span class="token punctuation">,</span> <span class="token number">383</span><span class="token punctuation">,</span> <span class="token number">388</span><span class="token punctuation">,</span> <span class="token number">392</span><span class="token punctuation">,</span> <span class="token number">397</span><span class="token punctuation">,</span> <span class="token number">402</span><span class="token punctuation">,</span> <span class="token number">407</span><span class="token punctuation">,</span> <span class="token number">412</span><span class="token punctuation">,</span> <span class="token number">417</span><span class="token punctuation">,</span>
<span class="token number">422</span><span class="token punctuation">,</span> <span class="token number">427</span><span class="token punctuation">,</span> <span class="token number">432</span><span class="token punctuation">,</span> <span class="token number">437</span><span class="token punctuation">,</span> <span class="token number">442</span><span class="token punctuation">,</span> <span class="token number">448</span><span class="token punctuation">,</span> <span class="token number">453</span><span class="token punctuation">,</span> <span class="token number">459</span><span class="token punctuation">,</span> <span class="token number">464</span><span class="token punctuation">,</span> <span class="token number">470</span><span class="token punctuation">,</span> <span class="token number">475</span><span class="token punctuation">,</span> <span class="token number">481</span><span class="token punctuation">,</span> <span class="token number">487</span><span class="token punctuation">,</span> <span class="token number">493</span><span class="token punctuation">,</span> <span class="token number">499</span><span class="token punctuation">,</span>
<span class="token number">505</span><span class="token punctuation">,</span> <span class="token number">511</span><span class="token punctuation">,</span> <span class="token number">517</span><span class="token punctuation">,</span> <span class="token number">523</span><span class="token punctuation">,</span> <span class="token number">530</span><span class="token punctuation">,</span> <span class="token number">536</span><span class="token punctuation">,</span> <span class="token number">542</span><span class="token punctuation">,</span> <span class="token number">549</span><span class="token punctuation">,</span> <span class="token number">556</span><span class="token punctuation">,</span> <span class="token number">562</span><span class="token punctuation">,</span> <span class="token number">569</span><span class="token punctuation">,</span> <span class="token number">576</span><span class="token punctuation">,</span> <span class="token number">583</span><span class="token punctuation">,</span> <span class="token number">590</span><span class="token punctuation">,</span> <span class="token number">597</span><span class="token punctuation">,</span>
<span class="token number">604</span><span class="token punctuation">,</span> <span class="token number">612</span><span class="token punctuation">,</span> <span class="token number">619</span><span class="token punctuation">,</span> <span class="token number">626</span><span class="token punctuation">,</span> <span class="token number">634</span><span class="token punctuation">,</span> <span class="token number">642</span><span class="token punctuation">,</span> <span class="token number">649</span><span class="token punctuation">,</span> <span class="token number">657</span><span class="token punctuation">,</span> <span class="token number">665</span><span class="token punctuation">,</span> <span class="token number">673</span><span class="token punctuation">,</span> <span class="token number">681</span><span class="token punctuation">,</span> <span class="token number">690</span><span class="token punctuation">,</span> <span class="token number">698</span><span class="token punctuation">,</span> <span class="token number">706</span><span class="token punctuation">,</span> <span class="token number">715</span><span class="token punctuation">,</span>
<span class="token number">723</span><span class="token punctuation">,</span> <span class="token number">732</span><span class="token punctuation">,</span> <span class="token number">741</span><span class="token punctuation">,</span> <span class="token number">750</span><span class="token punctuation">,</span> <span class="token number">759</span><span class="token punctuation">,</span> <span class="token number">768</span><span class="token punctuation">,</span> <span class="token number">777</span><span class="token punctuation">,</span> <span class="token number">787</span><span class="token punctuation">,</span> <span class="token number">796</span><span class="token punctuation">,</span> <span class="token number">806</span><span class="token punctuation">,</span> <span class="token number">816</span><span class="token punctuation">,</span> <span class="token number">825</span><span class="token punctuation">,</span> <span class="token number">835</span><span class="token punctuation">,</span> <span class="token number">845</span><span class="token punctuation">,</span> <span class="token number">856</span><span class="token punctuation">,</span>
<span class="token number">866</span><span class="token punctuation">,</span> <span class="token number">876</span><span class="token punctuation">,</span> <span class="token number">887</span><span class="token punctuation">,</span> <span class="token number">898</span><span class="token punctuation">,</span> <span class="token number">909</span><span class="token punctuation">,</span> <span class="token number">920</span><span class="token punctuation">,</span> <span class="token number">931</span><span class="token punctuation">,</span> <span class="token number">942</span><span class="token punctuation">,</span> <span class="token number">953</span><span class="token punctuation">,</span> <span class="token number">965</span><span class="token punctuation">,</span> <span class="token number">976</span><span class="token punctuation">,</span> <span class="token number">988</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
cout<span class="token punctuation">.</span><span class="token function">setf</span><span class="token punctuation">(</span>ios<span class="token double-colon punctuation">::</span>fixed<span class="token punctuation">,</span> ios<span class="token double-colon punctuation">::</span>floatfield<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">process_series</span><span class="token punctuation">(</span><span class="token string">"E12"</span><span class="token punctuation">,</span> E12<span class="token punctuation">)</span><span class="token punctuation">;</span>
vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> series <span class="token operator">=</span> <span class="token function">merge_series</span><span class="token punctuation">(</span>E12<span class="token punctuation">,</span> E24<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">process_series</span><span class="token punctuation">(</span><span class="token string">"E24"</span><span class="token punctuation">,</span> series<span class="token punctuation">)</span><span class="token punctuation">;</span>
series <span class="token operator">=</span> <span class="token function">merge_series</span><span class="token punctuation">(</span>series<span class="token punctuation">,</span> E48<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">process_series</span><span class="token punctuation">(</span><span class="token string">"E48"</span><span class="token punctuation">,</span> series<span class="token punctuation">)</span><span class="token punctuation">;</span>
series <span class="token operator">=</span> <span class="token function">merge_series</span><span class="token punctuation">(</span>series<span class="token punctuation">,</span> E96<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">process_series</span><span class="token punctuation">(</span><span class="token string">"E96"</span><span class="token punctuation">,</span> series<span class="token punctuation">)</span><span class="token punctuation">;</span>
series <span class="token operator">=</span> <span class="token function">merge_series</span><span class="token punctuation">(</span>series<span class="token punctuation">,</span> E192<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">process_series</span><span class="token punctuation">(</span><span class="token string">"E192"</span><span class="token punctuation">,</span> series<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> EXIT_SUCCESS<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
HÄRDBÖRD: Interesting Bits
2010-10-25T04:05:26Z
https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/
<p><strong>Update <time datetime="2023-10-24">2023/10/24</time>:</strong> See follow-up post <a href="https://geekshavefeelings.com/posts/2023/c-corrections">C++ Corrections</a>.</p>
<p>OK, so I need to get better at blogging on caffeine. I spent about four times the amount of time writing the last blog post on HÄRDBÖRD than I did working on the stuff described in it. And let’s face it, what I described were my personal insecurities about electronics hacking becoming more popular & accessible, making my own talents less sexy to the laypeople. That, and a shady DAC with three passive components hooked up. Big whoop. So here’s the next part, with actual interesting stuff.</p>
<h2 id="transmitten" tabindex="-1">Transmitten <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<p>would be a great name if my setup involved some sort of sensory glove and HÄRDBÖRD were some sorta German name, but it doesn’t and I have…</p>
<h2 id="the-transmitter" tabindex="-1">The transmitter <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<p>I could explain the design, but I think this video is more helpful (though not <em>very</em> helpful):</p>
<p>https://www.youtube.com/watch?v=kVccBTCpcYI</p>
<p>I think it’s fairly obvious what I was trying to do here, though poor camerawork kind of obscured how moving the joystick on the Nunchuk controlled Jamison’s three-pound battlebot, Cake. Wirelessly. Anyways, a series of dysconscious design decisions led to the following desired specs:</p>
<ul>
<li>Wireless control of the BÖRDs</li>
<li>Wii Nunchuk as the human interface</li>
<li>Some sort of reliable 2.4GHz link (radio hardware with a protocol stack built in)</li>
</ul>
<p>Everything else fell into place right after that. I grabbed two pairs of the lowest-end Xbee radio transceivers as well as the cheapest USB adapters and breakout boards I could find for them. “O Captain,” you cry, “that’ll be from Sparkfun, right?”</p>
<p>Yeah no, Sparkfun is for tools, man. They were so much better when they were underground. </hípster></p>
<p>Surprisingly enough, <a href="http://www.parallax.com/">Parallax</a> has Xbees at the same price as Digi-Key/Mouser, $3 breakout adapter boards<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" id="fnref1">*</a></sup>, and a $20 USB breakout<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" id="fnref2">†</a></sup>. And you thought they’re those overpriced backwards BASIC Stamp kids who supposedly got superseded by the Arduino clusterfugue<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" id="fnref3">‡</a></sup>.</p>
<p>The rest of the article is about the technical hacks I used in software to reduce complexity, part count, cost, etc. Boring stuff.</p>
<h2 id="nunchuk" tabindex="-1">Nunchuk <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<p>First off, it’s “<em>nunchuk</em>.” Not “nunchuck,” which requires a convent.</p>
<p>Secondly, these things are an awesome addition to any project requiring an analog joystick, two buttons, and a three axis gyro, mounted in an overly ergonomic housing with Apple aesthetics and Nintendo unbreakability. Take care not to drop them though—you might break the floor. Nunchuks can be accessed through a simple I²C interface, exposed physically through six spring contacts in the connector for which <a href="http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/">simple adapters</a> are available.</p>
<p>Keep in mind that the Nunchuks have gold-plated spring contacts and there is a tin finish on those adapters. This causes some sort of galvanic reaction and you get a lot of streaky black residue on both after a few months of use. Ew.</p>
<p>Now, I haven’t written straight C for a while now, so I wondered what sort of twisted interface code I’d come up with to grab data off of these things. Oddly enough I didn’t screw up the external interface that badly:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span>
uint8 joyX<span class="token punctuation">;</span>
uint8 joyY<span class="token punctuation">;</span>
uint16 accelX<span class="token punctuation">;</span>
uint16 accelY<span class="token punctuation">;</span>
uint16 accelZ<span class="token punctuation">;</span>
uint8 buttonZ<span class="token punctuation">;</span>
uint8 buttonC<span class="token punctuation">;</span>
<span class="token punctuation">}</span> NunchukData_t<span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">nunchukInit</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> <span class="token function">nunchukReadData</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
NunchukData_t <span class="token function">nunchukGetData</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token function">nunchukPrintData</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Yeah, so if you were to use my code, you’d see a C struct for the data output and four self-explanatory functions. Clean and simple.</p>
<p>However, my implementation in the source file (attached) is way shakier, involving GCC attributes, bitfields, and anonymous union-nested anonymous structs. But hey, that’s how I roll when I want to decode binary data. First I define this… <em>thing</em>:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token class-name">__attribute__</span><span class="token punctuation">(</span><span class="token punctuation">(</span>__packed__<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token keyword">struct</span> <span class="token punctuation">{</span>
uint8 joyX<span class="token punctuation">;</span>
uint8 joyY<span class="token punctuation">;</span>
uint8 accelX_HI<span class="token punctuation">;</span>
uint8 accelY_HI<span class="token punctuation">;</span>
uint8 accelZ_HI<span class="token punctuation">;</span>
uint8 buttonZ <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
uint8 buttonC <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
uint8 accelX_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
uint8 accelY_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
uint8 accelZ_LO <span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
uint8 buffer<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> NunchukRegisters_t<span class="token punctuation">;</span></code></pre>
<p>What is that supposed to achieve? Well, it’s basically a 6-byte long C struct which corresponds to the bit patterns read off of the Nunchuk. Based on <a href="http://www.windmeadow.com/node/42">reading materials</a>, I know that the data is encoded/ciphered by the byte, and all the decoded data is swizzled together to save bandwidth.</p>
<p>Thus, I have a <a href="http://en.wikipedia.org/wiki/Union_(computer_science)">union</a> between the aforementioned struct and a size 6 byte array so I can fill up and decode the struct in a per-byte fashion, just by looping over the unioned array. The <code>__attribute__((__packed__))</code> is just an futile, unnecessary hint to my compiler to make sure it doesn’t pad out my struct with extraneous bytes.</p>
<p>How do I use this struct? Now this is the beautiful part:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">int</span> <span class="token function">nunchukReadData</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
NunchukRegisters_t nunchukRegs<span class="token punctuation">;</span> <span class="token comment">// allocate space</span>
<span class="token function">readNI2C1</span><span class="token punctuation">(</span>NUNCHUK_ADDR<span class="token punctuation">,</span> nunchukRegs<span class="token punctuation">.</span>buffer<span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// read from nunchuk</span>
<span class="token keyword">int</span> i<span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">6</span> <span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// decode by byte</span>
nunchukRegs<span class="token punctuation">.</span>buffer<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">nunchukByteDecode</span><span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>buffer<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// assemble raw data</span>
nunchukData<span class="token punctuation">.</span>joyX <span class="token operator">=</span> nunchukRegs<span class="token punctuation">.</span>joyX<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>joyY <span class="token operator">=</span> nunchukRegs<span class="token punctuation">.</span>joyY<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>accelX <span class="token operator">=</span> <span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>accelX_HI <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> nunchukRegs<span class="token punctuation">.</span>accelX_LO<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>accelY <span class="token operator">=</span> <span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>accelY_HI <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> nunchukRegs<span class="token punctuation">.</span>accelY_LO<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>accelZ <span class="token operator">=</span> <span class="token punctuation">(</span>nunchukRegs<span class="token punctuation">.</span>accelZ_HI <span class="token operator"><<</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">|</span> nunchukRegs<span class="token punctuation">.</span>accelZ_LO<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>buttonZ <span class="token operator">=</span> <span class="token operator">!</span>nunchukRegs<span class="token punctuation">.</span>buttonZ<span class="token punctuation">;</span>
nunchukData<span class="token punctuation">.</span>buttonC <span class="token operator">=</span> <span class="token operator">!</span>nunchukRegs<span class="token punctuation">.</span>buttonC<span class="token punctuation">;</span>
<span class="token function">DELAY_US</span><span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// comm delay so nunchuk doesn't complain</span>
<span class="token function">nunchukRequestData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// signal nunchuk to read sensors again</span>
<span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<p>Notice how the unioning lets me fill up the registers without janky casting, and the bitfields in the nested anonymous prevents me from having to shift or mask off bits in order to decode the Nunchuk registers into my output data struct. For <a href="http://www.atom.com/funny_videos/haha_america/">comparative delta</a>, this is how the “<a href="http://todbot.com/arduino/sketches/WiichuckDemo/nunchuck_funcs.h">reference implementation</a>” looks on the Arduino:</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token comment">// from http://todbot.com/arduino/sketches/WiichuckDemo/nunchuck_funcs.h</span>
<span class="token keyword">int</span> joy_x_axis <span class="token operator">=</span> nunchuck_buf<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> joy_y_axis <span class="token operator">=</span> nunchuck_buf<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> accel_x_axis <span class="token operator">=</span> nunchuck_buf<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// * 2 * 2;</span>
<span class="token keyword">int</span> accel_y_axis <span class="token operator">=</span> nunchuck_buf<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// * 2 * 2;</span>
<span class="token keyword">int</span> accel_z_axis <span class="token operator">=</span> nunchuck_buf<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// * 2 * 2;</span>
<span class="token keyword">int</span> z_button <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> c_button <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token comment">// byte nunchuck_buf[5] contains bits for z and c buttons</span>
<span class="token comment">// it also contains the least significant bits for the accelerometer data</span>
<span class="token comment">// so we have to check each bit of byte outbuf[5]</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
z_button <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
c_button <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
accel_x_axis <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
accel_x_axis <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
accel_y_axis <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
accel_y_axis <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">6</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
accel_z_axis <span class="token operator">+=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span>nunchuck_buf<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">>></span> <span class="token number">7</span><span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span>
accel_z_axis <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span></code></pre>
<p>Yeah… I’d rather have nested anonymous structs than line after line of nasty bit twiddling. Let’s ignore the fact that the above example is a snippet of application code, while my decoding was library code, making it instantly superior from a software engineering standpoint. That is, the programmer who uses my code can pick up and run with an interface which is decoupled from how bits are swizzled by the Nunchuk. But, the coder above would have to reference a couple of websites to write their own decoding routines before <code>printf</code>'ing the data, for example.</p>
<h2 id="non-volatile-storage" tabindex="-1">Non-volatile storage <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<p>If there’s one thing I’m unhappy about with my choice of microcontroller, it’s that it doesn’t have built-in data EEPROM. EEPROM is flash memory, which is non-volatile—its contents are retained even when powered off. Most decent PICs have, in addition to RAM and program memory flash (where all your code is stored), a piece of data EEPROM acting as a memory-mapped peripheral which you can use as if it were an external EEPROM chip over SPI or I²C. The dsPIC33 family does not have this<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" id="fnref4">§</a></sup>.</p>
<p>But I still want my non-volatile storage, so I can store Nunchuk calibration data in the transmitter. How? We write it to the program flash. To make a long story short, this is a fairly complicated procedure which was achieved by using Microchip’s <a href="http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en538000">Data EEPROM Emulation library</a>, which turns unused program flash space into software-addressable EEPROM blocks. It even spreads writes over different blocks of allocated program flash in order to reduce wear on the EEPROM cells.</p>
<p>Trouble was, this library had some fairly odd software engineering practices, like putting way too much internals in a public header. It also used a separate unit of assembly language routines so the library could use specific instructions for flash reads and writes, when they could have been done in inline assembly, or even better, compiler built-in functions. It’s not like your assembly is more portable when you put it in a separate file, Microchip. :\</p>
<p>My modifications and simplifications to the library are attached to this post.</p>
<h2 id="the-protocol" tabindex="-1">The protocol <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<p>RC control is essentially packeted data; each piece of data you send is a full state of what motors/LEDs should be doing what, with no dependence on past or future data. Xbees provide you with a bidirectional stream (yes, I know it’s packets underneath) rather than a packet interface like <a href="http://www.sparkfun.com/commerce/categories.php?c=114">Nordic radios</a>. For those who grok teh nets, it’s more TCP and less UDP.</p>
<p>So, I hacked up a protocol that took advantage of both: use escape characters and base64 encoding to represent binary packets, and human-readable ASCII which is ignored by the receiver.</p>
<p>First I define a data structure. Starting to see a pattern?</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">typedef</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span>
<span class="token keyword">union</span> <span class="token punctuation">{</span>
<span class="token keyword">struct</span> <span class="token punctuation">{</span>
uint16 speed<span class="token punctuation">;</span>
uint8 reversed<span class="token punctuation">;</span>
uint8 brake<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
uint8 buffer<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> FluffyData_t<span class="token punctuation">;</span></code></pre>
<p><code>FluffyData_t</code><sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" id="fnref5">¶</a></sup> is the information the receiver cares about: speed, direction, and whether to brake. This is put through a base64 encode<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" id="fnref6">♠</a></sup>, and surrounded with non-base64 escape characters, ^ and $, into a 10-byte ASCII string.</p>
<p>Now, everything outside of those escape chars can be easily parsed out on the receiving end. So, now we have easily-decoded binary data represented as ASCII so it doesn’t screw with our terminals, and we can stick “comments” into the stream so we can peek in and read debug output.</p>
<p>For example, this is what actually goes through my Xbees:</p>
<pre class="language-plain" tabindex="0"><code class="language-plain">(Accel) x: 664, y: 450, z: 612 (Joystick) x: 148, y: 196 (Button) z: 1, c: 0
(fluffy) speed: 46260, reversed: 0, brake: 0
^tLQAAA==$
(Accel) x: 664, y: 450, z: 614 (Joystick) x: 148, y: 197 (Button) z: 1, c: 0
(fluffy) speed: 47031, reversed: 0, brake: 0
^t7cAAA==$</code></pre>
<p>That’s right, most of it is human readable. Only a tiny fraction of it is for the machine. This is called taking advantage of the bandwidth.</p>
<p>On the receiver end, it’s trivial to listen for a ^ character, start decoding base64 into another FluffyData_t struct, and then stop decoding upon receiving a $ character. Of course I am oversimplifying data integrity issues here, which are remedied in my design with a few simple checks and CRC16 checksums.</p>
<h2 id="code-listings" tabindex="-1">Code listings <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<ul>
<li><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/files/nunchuk.c">nunchuk.c</a></li>
<li><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/files/nunchuk.h">nunchuk.h</a></li>
<li><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/files/DEE-Emulation-16-bit.c">DEE Emulation 16-bit.c</a></li>
<li><a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/files/DEE-Emulation-16-bit.h">DEE Emulation 16-bit.h</a></li>
</ul>
<p>Note that I use the excellent <a href="http://www.reesemicro.com/Home/pic24-software-library-collection">Reese/Jones/Bruce library for PIC24 & dsPIC33</a> as my hardware interface library, which is referenced in the nunchuk.c code for I²C routines.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>With pin headers, Montresor! Sparkfun sells <em>only</em> headers at the same cost. <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Really a USB to serial adapter + LDO regulator with an Xbee footprint. <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>OK, they are. But still. <em>SUPPLIES!</em> <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Though dsPIC30 does, for some reason. <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>HÄRDBÖRD used to be called Fluffy, in case you’re wondering about the name. <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn6" class="footnote-item"><p>Note the byte array union again, which is great for doing binary transforms like b64 encoding. <a href="https://geekshavefeelings.com/posts/2010/hardbord-interesting-bits/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
HÄRDBÖRD: Hardcore Electric Longboard
2010-10-18T06:06:22Z
https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/
<p>So I’m going to start using my blog as a build log for projects. All the <a href="http://www.etotheipiplusone.net/">cool</a> <a href="http://thevariableconstant.blogspot.com/">kids</a> are doing it.</p>
<h2 id="introducing-haerdboerd-the-new-reason-for-my-keyboard-layout" tabindex="-1">Introducing HÄRDBÖRD, the new reason for my keyboard layout <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/">§</a></h2>
<p>Today, I want to turn your attention to HÄRDBÖRD<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" id="fnref1">*</a></sup>, this wireless, all-aluminum electric longboard/deathtrap project I got myself involved in. My roommate <a href="http://thevariableconstant.blogspot.com/">Jamison</a> and I are the principal designers (engineers? build slaves?) on a pair of these for fun and… leverage against The Man? The idea here is to get some learning done, but we do end up with ridiculously cool looking, possibly overpowered boards to ride around campus on:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Shbru4OtvU-690.avif 690w, https://geekshavefeelings.com/img/Shbru4OtvU-1200.avif 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Shbru4OtvU-690.webp 690w, https://geekshavefeelings.com/img/Shbru4OtvU-1200.webp 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Shbru4OtvU-690.jpeg 690w, https://geekshavefeelings.com/img/Shbru4OtvU-1200.jpeg 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="HÄRDBÖRD (Unpowered)" src="https://geekshavefeelings.com/img/Shbru4OtvU-690.jpeg" width="1200" height="1600"></picture><figcaption>Take that, campus shuttle!</figcaption></figure><p></p>
<p>I’m mostly in charge of the electronics, which are pretty simple compared to the all the other stuff. Most of it was done in about a week<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" id="fnref2">†</a></sup>. The plan is to use a Wii Nunchuk to wirelessly control the motor controllers. Why a Nunchuk? Why wireless? These transcendental questions of painful gravity are endless, but I can not answer them.</p>
<p>Jamison has done much of the mechanical design and machining, though I’ve been able to contribute a bit in the shop by learning the trade (i.e. the OMAX waterjet cutter in the Invention Studio at Georgia Tech). The boards are almost all waterjet-cut 6061 aluminum, with custom trucks, wheel hangers, deck—the whole shebang. We’ve run into a few snags where the wheel hangers don’t center with as much force as we’d like (in fact, not enough to be rideable); I have an elegant solution involving one spring and a cam, but it’s unmachineable and apparently patented or licensed by <a href="http://www.originalskateboards.com/longboard-trucks">Original</a>.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/-Uux8N5Tm3-690.avif 690w, https://geekshavefeelings.com/img/-Uux8N5Tm3-1380.avif 1380w, https://geekshavefeelings.com/img/-Uux8N5Tm3-1600.avif 1600w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/-Uux8N5Tm3-690.webp 690w, https://geekshavefeelings.com/img/-Uux8N5Tm3-1380.webp 1380w, https://geekshavefeelings.com/img/-Uux8N5Tm3-1600.webp 1600w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/-Uux8N5Tm3-690.jpeg 690w, https://geekshavefeelings.com/img/-Uux8N5Tm3-1380.jpeg 1380w, https://geekshavefeelings.com/img/-Uux8N5Tm3-1600.jpeg 1600w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Trucks and batteries" src="https://geekshavefeelings.com/img/-Uux8N5Tm3-690.jpeg" width="1600" height="1200"></picture></figure><p></p>
<p>Power runs from <em>huge</em> 4000mAh 6S1P pack lithium-polymer batteries (22.2V nominal, 25.2V max). They’re really not that big, but I haven’t built large bots for a long while so their size still surprises me. This juice runs to a pair of Turnigy brushless motors mounted within 4-inch 30A durometer polymer-core wheels, though what goes in between the motors and the batteries is still up for debate with the bean counters—no motor control solution for the pair of the boards costs less than $300.</p>
<p>For more information on “getting the boards to move,” see <a href="http://thevariableconstant.blogspot.com/search/label/HardBord">Jamo’s posts on Härdbörd</a>.</p>
<p>Meanwhile, we’re thinking of using a pair of <a href="https://downloads.maxonmotor.com/Katalog_neu/eshop/Downloads/maxon_motor_control/1-Q-EC-Verstaerker/DEC_Module_50_5/380200/380200_Operating_Instruction_E.pdf">Maxon DEC 50/5 (PDF)</a> sensored brushless control modules. Now I’d personally prefer to build my own brushless controllers, but we really want to see this on the road. These take in a few digital signals and a 0–5V analog signal for speed. Unfortunately, everything electronic I covet and hold dear (including my low-MIPS microcontroller of choice, the Microchip dsPIC33FJ128GP802) use 3.3V, and I hate analog like that flat watered-down Sprite you get from really stingy restaurants in NYC’s Chinatown. No sir, no op-amps in my design; I’d rather drink diet.</p>
<h2 id="an-aside-on-my-choice-of-mc" tabindex="-1">An aside on my choice of μC <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/">§</a></h2>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/KW2rVc4P2W-690.avif 690w, https://geekshavefeelings.com/img/KW2rVc4P2W-1380.avif 1380w, https://geekshavefeelings.com/img/KW2rVc4P2W-1448.avif 1448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/KW2rVc4P2W-690.webp 690w, https://geekshavefeelings.com/img/KW2rVc4P2W-1380.webp 1380w, https://geekshavefeelings.com/img/KW2rVc4P2W-1448.webp 1448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/KW2rVc4P2W-690.png 690w, https://geekshavefeelings.com/img/KW2rVc4P2W-1380.png 1380w, https://geekshavefeelings.com/img/KW2rVc4P2W-1448.png 1448w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="dsPIC pinout" src="https://geekshavefeelings.com/img/KW2rVc4P2W-690.png" width="1448" height="680"></picture></figure><p></p>
<p>The nice thing about the <a href="http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en532298">dsPIC33FJ128GP802</a> is that it’s chock-full of every sort of peripheral, as described in its <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/70292D.pdf">386-page datasheet</a>. If you don’t have a software solution, <em>it has a hardware solution</em>. If you don’t have a hardware solution, <em>it has a hardware solution</em>. If you already have a solution, <em>IT HAS A HARDWARE SOLUTION</em>.</p>
<p>In my computer architecture class, the professor was talking about the DEC VAX having a POLYD instruction to evaluate polynomials and everyone laughed at the ridiculously complex ISA co-designed by two Stuy alums. Then I realized, “dang, the dsPIC has a polynomial evaluator for CRC calculations!” Hardware bloat is not fastest in Intel’s newest SIMD floating point SSE6.8d extension, but in these little 8- and 16-bit nuggets by means of the memory-mapped peripheral.</p>
<p>I mean seriously, in addition to the usual timers, ADCs, I²C, SPI, U(S)ARTs, CAN, and other junk, it’s got freaking DMA and multi-priority interrupt system for all of those. Then they decide that wasn’t enough and crammed an extra ALU and barrel shifter in there with 40-bit accumulators and called it a DSP engine. But wait, there’s more! There’s more space on the die! Let’s shove a comparator and a real-time clock in there! Now they had more hardware than they had pins, so what do they do? STICK MUXES AND TRISTATE DRIVERS EVERYWHERE. Yeah, that’s right, <em>almost every peripheral on this thing can be mapped to any pin</em>. This thing even solves your PCB layout issues because you can <em>reconfigure your pinout in software</em>.</p>
<p>Oh yeah, this thing also doesn’t need a crystal to run at its full 40MIPS, has a free official GCC compiler, and comes in 28-pin breadboadable through hole (as free samples!). Life doesn’t get more perfect.</p>
<h2 id="the-receiver" tabindex="-1">The receiver <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/">§</a></h2>
<p>Aside aside, I wanted to output 0–5V analog from my dsPIC33F. Well, first thing I see is that it’s got this DAC peripheral. Everything is fine and dandy unti—AUGH IT OUTPUTS A DIFFERENTIAL SIGNAL. In other words, not only is it not 0–5V, it’s not even 0–3.3V. It’s some janky 0.8–2.8V (-ish. Don’t quote me.) swing for audio use. Darn, now I have to ghetto-hack a DAC from the PWM hardware.</p>
<p>Fortunately, this is extremely straightforward. The Output Compare module, as the “PWM” module is called in the dsPIC33F/PIC24H lines, is one of the most pleasant hardware peripherals I’ve ever used, on any computer, ever. Put it like this: <em>it’s easier than the software way</em>. You set up a timer with some prescaler values against system clock, as well as a period match register for when it should reset the timer counter to 0. That’s right: not only can you set the frequency of the timer tick, but also the period by which it resets. Awsm.</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token keyword">void</span> <span class="token function">configTimer2</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
T2CON <span class="token operator">=</span> T2_OFF <span class="token operator">|</span> T2_IDLE_CON <span class="token operator">|</span> T2_GATE_OFF <span class="token operator">|</span> T2_32BIT_MODE_OFF <span class="token operator">|</span> T2_SOURCE_INT <span class="token operator">|</span> T2_PS_1_1<span class="token punctuation">;</span>
PR2 <span class="token operator">=</span> <span class="token function">usToU16Ticks</span><span class="token punctuation">(</span>PWM_PERIOD<span class="token punctuation">,</span> <span class="token function">getTimerPrescale</span><span class="token punctuation">(</span>T2CONbits<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
TMR2 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">//clear timer2 value</span>
_T2IF <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
_T2IP <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
_T2IE <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">//enable the Timer2 interrupt</span>
<span class="token punctuation">}</span></code></pre>
<p>Anyways, next you just set up the output compare module to use that timer.</p>
<pre class="language-cpp" tabindex="0"><code class="language-cpp"><span class="token keyword">static</span> <span class="token keyword">inline</span> <span class="token keyword">void</span> <span class="token function">configOutputCompare1</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
T2CONbits<span class="token punctuation">.</span>TON <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">//disable Timer when configuring Output compare</span>
<span class="token function">CONFIG_RB14_AS_DIG_OUTPUT</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">CONFIG_OC1_TO_RP</span><span class="token punctuation">(</span><span class="token number">14</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//map OC1 to RP14/RB14</span>
<span class="token comment">//assumes TIMER2 initialized before OC1 so PRE bits are set</span>
OC1RS <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">//initially off</span>
<span class="token comment">//turn on the compare toggle mode using Timer2</span>
OC1CON <span class="token operator">=</span> OC_TIMER2_SRC <span class="token operator">|</span> <span class="token comment">//Timer2 source</span>
OC_PWM_FAULT_PIN_DISABLE<span class="token punctuation">;</span> <span class="token comment">//PWM, no fault detection</span>
<span class="token punctuation">}</span></code></pre>
<p>The way this work is basically described by this timing diagram:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/tE4KyK1gpN-690.avif 690w, https://geekshavefeelings.com/img/tE4KyK1gpN-1248.avif 1248w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/tE4KyK1gpN-690.webp 690w, https://geekshavefeelings.com/img/tE4KyK1gpN-1248.webp 1248w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/tE4KyK1gpN-690.png 690w, https://geekshavefeelings.com/img/tE4KyK1gpN-1248.png 1248w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Output Compare" src="https://geekshavefeelings.com/img/tE4KyK1gpN-690.png" width="1248" height="1014"></picture></figure><p></p>
<p>When the timer counter is less than register <code>OC1RS</code>, the OC1 pin (reconfigured by software as described above, to RP14) is output high. Otherwise, it’s output low. The period of rollover is defined by the timer’s period register <code>PR2</code>. In other words, the duty cycle (and thus average voltage) is exactly<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" id="fnref3">‡</a></sup> OC1RS/PR2.</p>
<p>Aside: you know why this would be useless on your ATMEGATRON9000KFLASH4BYTERAM AVRDUINO CAPPUCCINO2001 device? It’s 8-bit. All of these registers would be 8-bit, and you’d either have crappy 8-bit timers that can’t do straightforward PWM like this or some janky concatenated 2×8-bit monster with terrible latency and 40 pages in errata. End aside.</p>
<p>OK, so now we know how the PWM works. But how do we get 5V output? Surely we’ll need an op amp to up our range to fiv—CATSLAP. <em>We don’t like your kind here.</em></p>
<p>Yeah, so there’s a dsPIC peripheral solution here. The digital pins on the dsPIC have an open-drain operation mode<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" id="fnref4">§</a></sup>. A pin in open-drain output mode is hard pull to low (drain) when its port register bit is 0, and tristated (high-impedance, Z, floating) when its bit is 1. This means you can hook up 5V pull-up resistor to it, and get 5V output from a 3.3V device.</p>
<p>Now all I need to do is feed that 5V signal to a RC filter tuned to attenuate the PWM frequency, and I’ll have a clean 5V DAC output. I feel like freaking 诸葛亮 right here.</p>
<h2 id="the-test" tabindex="-1">The test <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/">§</a></h2>
<p>I’m working on all of this in the Invention Studio because I want an oscilloscope for this. Now the Invention Studio is an Mechanical Engineering shop, so the o-scope is a bit dinky, but hey, it’s digital, there are working probes around, and it works… for the most part.</p>
<p>![Oscope warning](images/IMG_0486.jpg ""Try a USB flash drive which has a smaller memory size." OK, what?")</p>
<p>Anyways, I don’t have real o-scope captures, so bear with my cellphone camera photos of the various test cases. So here’s the circuit under test:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/xJOuP3d_NF-690.avif 690w, https://geekshavefeelings.com/img/xJOuP3d_NF-1200.avif 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/xJOuP3d_NF-690.webp 690w, https://geekshavefeelings.com/img/xJOuP3d_NF-1200.webp 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/xJOuP3d_NF-690.jpeg 690w, https://geekshavefeelings.com/img/xJOuP3d_NF-1200.jpeg 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Circuit under test" src="https://geekshavefeelings.com/img/xJOuP3d_NF-690.jpeg" width="1200" height="1600"></picture><figcaption>The transmitter and receiver ghettoed up to a power supply and scope</figcaption></figure><p></p>
<p>Now let’s get some data:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/BBYGDkofcE-690.avif 690w, https://geekshavefeelings.com/img/BBYGDkofcE-1200.avif 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/BBYGDkofcE-690.webp 690w, https://geekshavefeelings.com/img/BBYGDkofcE-1200.webp 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/BBYGDkofcE-690.jpeg 690w, https://geekshavefeelings.com/img/BBYGDkofcE-1200.jpeg 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="PWM DAC 2.47V" src="https://geekshavefeelings.com/img/BBYGDkofcE-690.jpeg" width="1200" height="1600"></picture><figcaption>This is the PWM output from the dsPIC, without open-drain</figcaption></figure><p></p>
<p>Being able to adjust the duty cycle of the waveform with a joystick is some hot stuff, especially if you fiddle with the trigger settings a bit. Now let’s hook up a 100KOhm×0.1μF RC filter on that. This has a cutoff frequency of about 16Hz, at which point half the signal is attenuated. Higher frequency signals are attenuated at 20dB per decade, so the 3.28kHz PWM frequency is attenuated by at least 40dB. Good enough for me to play Etch-A-Sketch on the scope with my Nunchuk:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/tF9TAlrdaF-690.avif 690w, https://geekshavefeelings.com/img/tF9TAlrdaF-1200.avif 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/tF9TAlrdaF-690.webp 690w, https://geekshavefeelings.com/img/tF9TAlrdaF-1200.webp 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/tF9TAlrdaF-690.jpeg 690w, https://geekshavefeelings.com/img/tF9TAlrdaF-1200.jpeg 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="ETCH A SKETCH" src="https://geekshavefeelings.com/img/tF9TAlrdaF-690.jpeg" width="1200" height="1600"></picture><figcaption>With RC filter and slooow sweep scope samples</figcaption></figure><p></p>
<p>And just for the hell of it, I measured the ripple of the analog:</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/r5RmRW-FJy-690.avif 690w, https://geekshavefeelings.com/img/r5RmRW-FJy-1200.avif 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/r5RmRW-FJy-690.webp 690w, https://geekshavefeelings.com/img/r5RmRW-FJy-1200.webp 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/r5RmRW-FJy-690.jpeg 690w, https://geekshavefeelings.com/img/r5RmRW-FJy-1200.jpeg 1200w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="oscope ripple voltage measurement" src="https://geekshavefeelings.com/img/r5RmRW-FJy-690.jpeg" width="1200" height="1600"></picture></figure><p></p>
<p>About 30mV. Not bad. Taking this measurement was a real pain: I had to keep my joystick finger steady while zooming/panning on a tiny sliver of the vertical scale, throw in measurements, and praying that a little twitch won’t throw the waveform off the triggering level.</p>
<p>So, that concludes this really boring part of “reducing part count of everything to just a dsPIC.” Next time, I’ll show how I did this with the transmitter side.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Credit goes to <a href="http://www.etotheipiplusone.net/">Charles</a> for this awesome name. Note that the Umlauts are metal umlauts, not actual German. <a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Much of that time was spent coding with my shirt off while Rammstein blasted from my workstation. <a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Actually, there’s a fencepost error here I’m glossing over, but which is covered by my code snippet. <a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Well, all of the I/O pins on the equivalent PIC24H do, but you’re not supposed to use the dsPIC analog pins in open-drain since they’re not 5V tolerant. Yes, it does work, but this puts your app outside of spec. <a href="https://geekshavefeelings.com/posts/2010/hardbord-hardcore-electric-longboard/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
Mistakes to Make on a Raytracer
2010-03-25T21:10:11Z
https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/
<p>Writing your first classical ray tracer was at one point a big deal. Now I don’t see what’s so difficult about the dark side of computer graphics. <a href="http://www.youtube.com/watch?v=5J8pI8jobMo">Tray racing</a>, as I call it, is a remarkably entertaining exercise that will become the future of gaming and 3D visualization as computing hardware catch up with our ambitions<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" id="fnref1">*</a></sup>.</p>
<p>Simply put, ray tracing’s generating computer images through a physical simulation of light, by “shooting” <em>rays</em> from a viewpoint in 3D space and then “tracing” them along their paths for objects to draw on screen. Shoot a lot of them and you will have enough information for the screen.</p>
<p>This is far superior in quality and correctness, though also very much less efficient, than our current method of <em>rasterization</em>: gathering up all the objects we put into the virtual space, deciding what they should look like given a few arbitrary parameters, and then drawing them on the screen where we think they should go. Ray tracers produce such good-looking images, in fact, because they are <em>accurate</em>.</p>
<p>For an example, see Wikipedia’s exemplar specimen of ray traced work:
<a href="http://en.wikipedia.org/wiki/File:Glasses_800_edit.png"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/125ZMhAPlN-690.avif 690w, https://geekshavefeelings.com/img/125ZMhAPlN-1380.avif 1380w, https://geekshavefeelings.com/img/125ZMhAPlN-2048.avif 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/125ZMhAPlN-690.webp 690w, https://geekshavefeelings.com/img/125ZMhAPlN-1380.webp 1380w, https://geekshavefeelings.com/img/125ZMhAPlN-2048.webp 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/125ZMhAPlN-690.png 690w, https://geekshavefeelings.com/img/125ZMhAPlN-1380.png 1380w, https://geekshavefeelings.com/img/125ZMhAPlN-2048.png 2048w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Glasses_800_edit.png from Wikipedia" src="https://geekshavefeelings.com/img/125ZMhAPlN-690.png" width="2048" height="1536"></picture></figure></a></p>
<p>If you need more convincing, check out a small company in California called <a href="http://en.wikipedia.org/wiki/Pixar" title="Pixar at Wikipedia">Pixar</a>. I believe they make these moving pictures or something.</p>
<p>“Now Xo,” you ask, “why did you call this wonderful ‘tray racing’ technique the ‘dark side’ of computer graphics? Surely it would be the ‘light side (no pun intended)?’”</p>
<p>No, it’s not. I learned rasterization first, I worked hard at some very pointless but very fast <a href="https://geekshavefeelings.com/posts/2009/raxo" title="Raxo project page">software rasterizers</a>, and I just like it more. Shoot me (no pun intended).</p>
<p>Anyways, I wrote a simple “classical” (properly known as <a href="http://en.wikipedia.org/wiki/Ray_tracing_(graphics)#Ray_tracing_algorithm" title="Turner Whitted on Wikipedia (there's no page for him?)">Whitted</a>) ray tracer for CS3451<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" id="fnref2">†</a></sup> as an assignment. To my surprise, it took only eight hours of marathon coding to write, none of them daytime. The work consisted primarily of making and fixing simple mistakes that, once I had worked out the math, were <em>physically</em> incorrect.</p>
<p>That was the nice bit of it all; if you had a rendering error, you can just look at your model of the world and see if you did something in a way that makes no sense in the real world. Once I fixed those mistakes, I had a pretty nice ray tracer, if trivial by today’s standards.
</p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/5FEMnTXiaV-690.avif 690w, https://geekshavefeelings.com/img/5FEMnTXiaV-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/5FEMnTXiaV-690.webp 690w, https://geekshavefeelings.com/img/5FEMnTXiaV-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/5FEMnTXiaV-690.png 690w, https://geekshavefeelings.com/img/5FEMnTXiaV-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="A pretty standard image to be racin' trays for" src="https://geekshavefeelings.com/img/5FEMnTXiaV-690.png" width="768" height="768"></picture></figure> <figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/KLtxB_gNTR-690.avif 690w, https://geekshavefeelings.com/img/KLtxB_gNTR-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/KLtxB_gNTR-690.webp 690w, https://geekshavefeelings.com/img/KLtxB_gNTR-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/KLtxB_gNTR-690.png 690w, https://geekshavefeelings.com/img/KLtxB_gNTR-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Lots of inter-reflections and shadows. My friend TH said this didn't look right. I said to suck it." src="https://geekshavefeelings.com/img/KLtxB_gNTR-690.png" width="768" height="768"></picture></figure><p></p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/QXLyitJrp_-690.avif 690w, https://geekshavefeelings.com/img/QXLyitJrp_-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/QXLyitJrp_-690.webp 690w, https://geekshavefeelings.com/img/QXLyitJrp_-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/QXLyitJrp_-690.png 690w, https://geekshavefeelings.com/img/QXLyitJrp_-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Pretty colors!" src="https://geekshavefeelings.com/img/QXLyitJrp_-690.png" width="768" height="768"></picture></figure> <figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Kv86NPFxke-690.avif 690w, https://geekshavefeelings.com/img/Kv86NPFxke-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Kv86NPFxke-690.webp 690w, https://geekshavefeelings.com/img/Kv86NPFxke-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/Kv86NPFxke-690.png 690w, https://geekshavefeelings.com/img/Kv86NPFxke-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="If you stare real hard, you can see your own face in a hall of mirrors. Spherical mirrors." src="https://geekshavefeelings.com/img/Kv86NPFxke-690.png" width="768" height="768"></picture></figure><p></p>
<p>These are the technical issues I stumbled on (and have stumbled on before; I don’t learn too well from my mistakes<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" id="fnref3">‡</a></sup>), and ones you probably should watch out for:</p>
<ul>
<li>
<p><strong>Normalize your unit vectors!</strong>
Rays have directions representing their straight line path through space. These are usually represented with unit vectors. If you don’t keep them normal, then the distances you get through ray-object intersections will be inaccurate. This will cause issues if you actually depend on distances at some point, like when you do shadowing or light attenuation.</p>
</li>
<li>
<p><strong>Check for negative intersections!</strong>
When checking for ray-object intersections. Make sure you discard intersections that are <em>behind</em> the rays origin. Say that you parameterize your ray as <strong>o</strong> + <em>t</em><strong>d</strong>, where <strong>o</strong> is the ray’s origin, <strong>d</strong> is the direction (uuunit veeector!), and <em>t</em> is the scalar parameter indicating distance along the path given by <strong>o</strong> and <strong>d</strong>. If you get an intersection of <em>t</em> < 0, discard the intersection.</p>
<p>Don’t do this:
</p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/uUhWs46fiV-690.avif 690w, https://geekshavefeelings.com/img/uUhWs46fiV-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/uUhWs46fiV-690.webp 690w, https://geekshavefeelings.com/img/uUhWs46fiV-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/uUhWs46fiV-690.png 690w, https://geekshavefeelings.com/img/uUhWs46fiV-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Negative intersections" src="https://geekshavefeelings.com/img/uUhWs46fiV-690.png" width="768" height="768"></picture></figure><p></p>
</li>
<li>
<p><strong>Terminate your reflection rays by contribution!</strong>
When doing lots of bounces around shiny objects, that is, objects of constant of reflection <em>K<sub>refl</sub></em> > 0, make sure to stop doing more bounces when additional bounces will contribute no visible difference to the image. My measuring stick here is by recursive descent along reflection rays: with each bounce, I multiply the contribution factor (which starts out at 1) by the <em>K<sub>refl</sub></em> of the intersected object. If the contribution of the next recursive level is less than 0.5/255, which is half the value of least significance for an 8-bit/channel output buffer, then I consider further bounces to be useless and terminate further recursion. It’s just a performance thing.</p>
</li>
<li>
<p><strong>Don’t let your reflection rays check against its own origin!</strong>
When bouncing reflection rays, be sure to <em>not</em> check for intersections against the object you just bounced it off of. It’s a simple way to avoid a rendering artifact known as surface acne<sup class="footnote-ref"><a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" id="fnref4">§</a></sup>. However, this technique will prevent objects from casting <em>self shadows</em>, which are exactly what they sound like. Therefore, omit the reflection intersection check for the biggest thing in an object that does not self-shadow, e.g. spheres, triangles, planar polygons, etc. So if you are reflecting off an object composed of many triangles, <em>don’t</em> intersect the reflection ray against the triangle it bounced off of, but <em>do</em> check against the other triangles in the object.</p>
</li>
<li>
<p><strong>Intersect your shadow rays with geometry <em>and</em> lights!</strong>
OK, this is hard to describe, but it’s important. You check for shadowing by shooting a shadow ray towards the light you’re trying to err, check for shadowing against, right? If there is an intersection with another object, then there’s something blocking the light, right? Non monsieur! What if the light is between the two objects? For a shadow to be cast, the distance to the intersection must be <em>less than</em> the distance to the light.</p>
<p>Example: There is a light smack dab in between two spheres. It should look like this:
</p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ets0GadvWQ-690.avif 690w, https://geekshavefeelings.com/img/ets0GadvWQ-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ets0GadvWQ-690.webp 690w, https://geekshavefeelings.com/img/ets0GadvWQ-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/ets0GadvWQ-690.png 690w, https://geekshavefeelings.com/img/ets0GadvWQ-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Shadowing done right" src="https://geekshavefeelings.com/img/ets0GadvWQ-690.png" width="768" height="768"></picture></figure><p></p>
<p>Except when it doesn’t:
</p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/njEjyOXwHR-690.avif 690w, https://geekshavefeelings.com/img/njEjyOXwHR-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/njEjyOXwHR-690.webp 690w, https://geekshavefeelings.com/img/njEjyOXwHR-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/njEjyOXwHR-690.png 690w, https://geekshavefeelings.com/img/njEjyOXwHR-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Shadowing done wrong annotated" src="https://geekshavefeelings.com/img/njEjyOXwHR-690.png" width="768" height="768"></picture></figure><p></p>
<p>Just for the heck of it, let’s add more magic:
</p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/zbqTxFRudw-690.avif 690w, https://geekshavefeelings.com/img/zbqTxFRudw-768.avif 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/zbqTxFRudw-690.webp 690w, https://geekshavefeelings.com/img/zbqTxFRudw-768.webp 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/zbqTxFRudw-690.png 690w, https://geekshavefeelings.com/img/zbqTxFRudw-768.png 768w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="More magic" src="https://geekshavefeelings.com/img/zbqTxFRudw-690.png" width="768" height="768"></picture></figure><p></p>
</li>
</ul>
<p>So there you have it. Hopefully the technical bits in this post will help some poor uni student out there struggling to race their first tray, the writing has entertained you, and at the very least the pretty pictures got you all excited.</p>
<aside class="footnotes">
<h2 id="feetnote">Feetnote <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/">§</a></h2>
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>Not meaning computers will get fast enough to simulate light realistically in real time; meaning they will make dining trays big enough to support my weight <a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>Computer Graphics at Georgia Tech <a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>Unless I write it down with lots of parentheticals and footnotes like this <a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" class="footnote-backref">⏎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>See this article: <a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/files/Its-Really-Not-a-Rendering-Bug-You-see....pdf">It’s Really Not a Rendering Bug, You see…</a> <a href="https://geekshavefeelings.com/posts/2010/mistakes-to-make-on-a-raytracer/" class="footnote-backref">⏎</a></p>
</li>
</ol>
</aside>
US International Dvorak
2010-01-30T02:16:45Z
https://geekshavefeelings.com/posts/2010/us-international-dvorak/
<p>Windows (and many other operating systems) include by default an interesting keyboard layout called <a href="http://en.wikipedia.org/wiki/Keyboard_layout#US-International" title="Wiki: US-International Keyboard layout">United States-International</a>. It is essentially a version of the prolific American QWERTY keyboard layout, with many popular symbols and characters not found in English accessible through the <a href="http://en.wikipedia.org/wiki/AltGr_key" title="Wiki: AltGr Key">AltGr key</a> (or its Windows substitute, the right Alt key or Ctrl + Left Alt) and through <a href="http://en.wikipedia.org/wiki/Dead_key" title="Wiki: Dead key">dead keys</a>.</p>
<p>I saw fit to create a Dvorak version of US-International, with the same deadkeys and combinations, but with the three touch-type rows rearranged to fit ANSI Dvorak. It should be an easy switch for existing Dvorak users and great if you’re starting out learning Dvorak.</p>
<p><strong>Keyboard layout installer for Windows 2000/XP/2003/Vista/7 (x86, x64, and Itanium):</strong> <a href="https://geekshavefeelings.com/posts/2010/us-international-dvorak/files/intldvrk.zip" title="intldvrk.zip">intldvrk.zip</a>
<strong>Microsoft Keyboard Layout Creator</strong> <strong>source file:</strong> <a href="https://geekshavefeelings.com/posts/2010/us-international-dvorak/files/intldvrk.klc" title="intldvrk.klc">intldvrk.klc</a></p>
<p>The installer will add the layout to the Windows regional settings list of keyboard layouts, and is not some sort of driver, background service, or registry hack. It was made in <a href="http://msdn.microsoft.com/en-us/goglobal/bb964665.aspx" title="Microsoft Keyboard Layout Creator">Microsoft Keyboard Layout Creator</a>.</p>
<p>Anyways, with the US-International keyboard layout, nobody should have any excuse to type “u” or “ue” instead of “ü,” “2 x 4” instead of “2 × 4,” or “General Xo's Chicken” instead of “General Xo’s Chicken.” Heck, maybe we could have prevented the creation of the English neologism “<a href="http://en.wikipedia.org/wiki/%C3%9Cber#Spelling" title="Wiki: Uber">uber</a>.”</p>
<p>Of course, I do take issue with its lack of distinction between the hyphen (-), the en dash (–), and the em dash (—), and its lack of the prime marks (′, ″, and ‴) and the ditto symbol (〃). However, its existing variety of punctuation, accents, and other typographical symbols, including separate key combinations for the single closing quote (’), the typewriter apostrophe ('), and the acute accent (´), are easily enough to overwhelm anyone new to smugly elitist typographical pedantry (the sort I enjoy).</p>
<p>Also, the dead keys themselves do get annoying. For example, Ubuntu Linux includes a layout called “USA International (AltGr dead keys).” That moves the dead keys to their AltGr combinations, so hitting the ' key would produce a ' straightaway, but to get the á (acute a) symbol, which is encountered far less frequently than the apostrophe, one would need to hit AltGr+’ and then A. Also of note is Ubuntu’s “USA Dvorak International,” which is not to be confused with my US-Internation Dvorak layout. It is simply the ANSI Dvorak layout with a few symbols available by AltGr; it is not, like my layout, a Dvorak remapping of the full US-International layout.</p>
<p>With that said, I’m not even a Dvorak typist. Heh.</p>
<h2 id="edit-10-1284-2006" tabindex="-1">Edit (10/1284/2006): <a class="header-anchor" href="https://geekshavefeelings.com/posts/2010/us-international-dvorak/">§</a></h2>
<p>I did some extremely cursory Googling, and came up with these two more Dvorak layouts based on US-International (created by others):</p>
<ul>
<li><a href="http://keyboards.jargon-file.org/#USID" title="United States-Dvorak International at Jargon File">USID at Jargon File</a> – Pretty much the same as my keyboard layout, except it came before mine. 🙁 <em>Update:</em> it appears that the layout’s apostrophe deadkey produces an acute accent (´) instead of an apostrophe ('); haven’t noticed anything else wrong though.</li>
<li><a href="http://arjenvankol.com/dvorak.php" title="Dvorak international extended keyboard at Arjen van Kol">Dvorak international extended keyboard at Arjen van Kol</a> – Instead of using an exactly key-to-key mapping from US-International to ANSI Dvorak, this layout moves many of the AltGr-accessed special characters to be adjacent to other similar characters.</li>
</ul>
<p><em>Edit (12/26/2012, which I guess is 10/2279/2006. Ha!):</em>
So here’s the layout I use, which is the regular US International—QWERTY and all—but you need to hold AltGr to hit deadkeys.</p>
<p><strong>Keyboard layout installer for Windows 2000/XP/2003/Vista/7 (x86, x64, and Itanium):</strong> <a href="https://geekshavefeelings.com/posts/2010/us-international-dvorak/files/usintalt.zip" title="usintalt.zip">usintalt.zip</a></p>
<p>I kept a list of symbols I meant to add to it but never did, and probably never will now that I dislike customization:</p>
<ul>
<li>Prime marks, en & em dash, ditto sign (′, ″, ‴, –, —, 〃)</li>
<li>Solidus, bullet (⁄, •)</li>
<li><=, >=, !=, and =~ (≤, ≥, ≠, ≈)</li>
<li>Dot, sqrt, XOR (·, √, ⊕)</li>
<li>+/-, -/+ (±, ∓)</li>
<li>Sum of, integral of (∑, ∫)</li>
<li>Ellipsis, therefore (…, ∴)</li>
</ul>
<p>I still wish I had these. 🙁</p>
Raxo
2009-12-10T01:49:45Z
https://geekshavefeelings.com/posts/2009/raxo/
<p>Raxo is a work-in-progress real-time rasterizing software renderer with a highly flexible, full-precision floating-point pipeline. This means that it draws animated objects and scenes using software running on the CPU instead of with hardware on the graphics card.</p>
<p>Raxo is written in templated C++, and I am working on using just-in-time (JIT) compilation of assembly routines to accelerate rendering, by eliminating costly conditionals in inner loops.</p>
<p><strong>GitHub project:</strong> <a href="http://github.com/GHF/Raxo">http://github.com/GHF/Raxo</a> (git source repository)</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/qxaQXssRIl-656.avif 656w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/qxaQXssRIl-656.webp 656w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Lighting sphere" src="https://geekshavefeelings.com/img/qxaQXssRIl-656.png" width="656" height="438"></picture><figcaption>If you can animate a ball, you can render a wrench photorealistically at interactive rates (à la [Dodgeball](http://www.imdb.com/title/tt0364725/quotes “Dodgeball: A True Underdog Story”)).</figcaption></figure><p></p>
<p>Raxo, currently in heavy development, is a continuation of my work for Stuyvesant’s <a href="http://wiki.stuy.edu/cs/zamansky/ML6">ML6: Computer Graphics</a> course, taught by Michael Zamansky. While I may later write games or demos with it, it is currently a way for me to fully explore both the “classical” and novel rendering techniques used by and developed by computer graphics researchers and game programmers. I will do so by implementing those techniques myself, in the most badass, impressive, mind-numbingly fast ways I can devise.</p>
<h2 id="goals" tabindex="-1">Goals <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/raxo/">§</a></h2>
<ul>
<li>Raxo is, above all, a learning tool for myself. It’ll probably become the biggest project I’ve worked on alone. Though this is a rewrite of a bigger group project and I’ve worked on much bigger software projects outside of an academic setting, I have to say that design and architecture is <em>hard</em>.</li>
<li>This is how it’ll work: I’m going to learn what it is I’m trying to learn (still figuring this out) by deriving and implementing. I’ll gobble up blog posts, research papers, and textbooks, but in the end I have to turn it into code.</li>
<li>It’s got to be fast. What is computer graphics research if not a never-ending expedient tradeoff between speed and trickery of the eye?</li>
<li>It’s going to be done right; more right (err, rightly?) than the hardware we have now. I want proper fill rules, subpixel precision where needed, a full floating-point pipeline (that’s right, textures, color buffers, lights—all 128-bit color), the whole works.</li>
<li>I want to explore techniques published in papers but never implemented in modern hard. I have a flex-function pipeline and no need to release a product, so why not go ahead and play with <a href="http://en.wikipedia.org/wiki/Irregular_Z-buffer">irregular Z-buffers</a> for shadow mapping or <a href="http://graphics.stanford.edu/papers/silmap/">silhouette maps</a>?</li>
</ul>
<h2 id="implemented-features" tabindex="-1">Implemented features <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/raxo/">§</a></h2>
<ul>
<li>A sensible C++ architecture and pipeline. Raxo is a library; it’s a collection of loosely-linked classes that form a rendering pipeline, like OpenGL or Direct3D. It takes in geometric data and draws it, but without an animation application or 3D models, it can’t do much</li>
<li>Coordinate systems with homogeneous coordinates</li>
<li>4×4 Matrices and transformations (including a SSE/SSE2 implementation with an amortized cost of about 17 instruction cycles per vector on modern Intel CPUs)</li>
<li>Full coordinate transformation pipeline as in the OpenGL fixed-function pipeline, from eye space coordinates to viewport coordinates</li>
<li>Quaternion representation of rotations, including conversions to and from rotation matrices, linear interpolation in spherical space, and linear interpolation in linear space with normalization</li>
<li>Arbitrary vertex and pixel shaders, with arbitrary number of interpolants (specified at compile time with template parameters)</li>
<li>OpenGL-style materials/lighting properties</li>
</ul>
<p><em>I really hate <a href="https://geekshavefeelings.com/posts/2009/better-spheres-fewer-triangles">this sphere</a> now. Its render screw-ups has become a blooper reel for my life.</em></p>
<h2 id="work-in-progress" tabindex="-1">Work-in-progress <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/raxo/">§</a></h2>
<ul>
<li>A “default” rasterizer that supports most of the features in OpenGL</li>
<li>Classical Blinn-Phong lighting, with point, directional, and spot lights</li>
<li>Geometry generators and file loaders (I’ve been staring at the same darn spinning tesselated sphere for more than a year now as a reference model)</li>
<li>Run-time specified render buffers—Raxo can render to screen using <a href="http://code.google.com/p/pixeltoaster/">PixelToaster</a>, to file, or to a null target for headless testing</li>
<li>Converting some inner loops to assembly so they can be generated by AsmJit</li>
<li>Hand-coded SSE/SSE2/SSE3/SSSE3/SSE4.1 (list would be longer if I had a newer computer) intrinsics to accelerate some key parts</li>
<li>Camera system</li>
</ul>
<h2 id="planned-features" tabindex="-1">Planned features <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/raxo/">§</a></h2>
<ul>
<li>Perspective correction for interpolants</li>
<li>Shadow maps and shadow volumes</li>
<li>External asset loading from files</li>
<li>Different mesh storage methods</li>
<li>Precomputed mapped ambient occlusion</li>
<li>Screen space ambient occlusion</li>
<li>Tone mapping and gamma correction of output image onto screen</li>
<li>Depth of field</li>
</ul>
<h2 id="and-beyond" tabindex="-1">And beyond… <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/raxo/">§</a></h2>
<ul>
<li>Postprocessing filters (also JIT compiled)</li>
<li>Image quality (multi-sampling, texture filtering, etc.)</li>
<li>Things I find in research papers</li>
<li>???</li>
<li>PROFIT! (maybe this will help me find a job?)</li>
</ul>
<h2 id="links" tabindex="-1">Links <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/raxo/">§</a></h2>
<ul>
<li><a href="http://chrishecker.com/Miscellaneous_Technical_Articles">Chris Hecker’s perspective texture mapping articles</a> – Great for learning proper rasterization rules, subpixel and subtexel precision, linear interpolation of variables, and of course, perspective-correct texturing.</li>
<li><a href="http://code.google.com/p/asmjit/">AsmJit</a> – Terrific runtime assembler. Generates executable functions from assembly, and does higher-level things too, like register allocation/memory spilling for variables. Since the death of <a href="https://gna.org/projects/softwire">SoftWire</a>, this is the best choice for JIT assembly. Google Chromes’s <a href="http://code.google.com/p/v8/">V8</a> and Safari’s <a href="http://webkit.org/blog/214/introducing-squirrelfish-extreme/">SquirrelFish Extreme</a> JavaScript engines have JIT components as well that can be extracted for use, but of course they are not designed for the same tasks.</li>
<li><a href="http://code.google.com/p/pixeltoaster/">PixelToaster</a> – Cross-platform framebuffer library of champions.</li>
<li><a href="http://ompf.org/forum/">ompf.org forum</a> – Community for real-time ray tracing enthusiasts. Full of wizardry in assembly, approximations, hardware hacks and of course, floating point color.</li>
<li><a href="http://www.gamasutra.com/view/feature/4190/sponsored_feature_rasterization_.php">Rasterization on Larrabee</a> – Reading Mike Abrash (author of the <a href="http://www.gamedev.net/reference/articles/article1698.asp">Black Book</a>, developer for Quake and <a href="http://www.radgametools.com/pixomain.htm">Pixomatic</a>) is always inspirational and a bit humbling. Even when he talks about doing things you’ve no desire of ever trying, you can appreciate the effort and ingenuity that goes into it all. Also, Larrabee. Sweet.</li>
<li><a href="http://www.realtimerendering.com/">Real Time Rendering</a> – Nice book to have.</li>
<li><a href="http://calvados.di.unipi.it/dokuwiki/doku.php?id=ffnamespace:about">FastFlow</a> – Interesting C++ parallel programming library with different abstraction layers for describing computing problems and solving each in parallel.</li>
<li><a href="http://www.cs.brown.edu/courses/cs123/lectures.htm">Brown CS123 slides</a> – Slides from course taught by van Dam of Foley and van Dam. The 2009 course supposedly uses an unpublished version of said book.</li>
<li><a href="http://concatenative.org/wiki/view/SSE">SSE Idioms</a></li>
</ul>
Better Spheres, Fewer Triangles
2009-07-26T00:55:11Z
https://geekshavefeelings.com/posts/2009/better-spheres-fewer-triangles/
<p><strong>Generating spheres through recursive subdivision of icosahedrons</strong></p>
<p>UV spheres are one of the easiest and most commmon ways to generate a sphere for computer graphics.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/XiXXY-U8Fx-640.avif 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/XiXXY-U8Fx-640.webp 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="UV sphere generated by revolving a circle about an axis planar to itself" src="https://geekshavefeelings.com/img/XiXXY-U8Fx-640.png" width="640" height="400"></picture><figcaption>UV sphere</figcaption></figure>
<em>UV sphere generated by revolving a circle about an axis planar to itself</em><p></p>
<p>It has its charms: it looks kind of like a globe, with its clear longitudinals and latitudinals, it’s ridiculously easy to imagine and create, and it works well with UV texture mapping. Still, its uneven distribution of points can cause wasted texture resolution as well as computation time at best, funny-looking bunching of points near the “poles” at slightly worse, and disgusting visual artifacts at worst due to having to render many slivers of triangles often of widths less than a pixel.</p>
<p>A far better solution is the geodesic sphere, created by dividing up the faces of a platonic solid and then projecting the vertices onto a sphere*.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/CgEv97o4u2-690.avif 690w, https://geekshavefeelings.com/img/CgEv97o4u2-1380.avif 1380w, https://geekshavefeelings.com/img/CgEv97o4u2-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/CgEv97o4u2-690.webp 690w, https://geekshavefeelings.com/img/CgEv97o4u2-1380.webp 1380w, https://geekshavefeelings.com/img/CgEv97o4u2-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/CgEv97o4u2-690.png 690w, https://geekshavefeelings.com/img/CgEv97o4u2-1380.png 1380w, https://geekshavefeelings.com/img/CgEv97o4u2-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Icosphere" src="https://geekshavefeelings.com/img/CgEv97o4u2-690.png" width="1920" height="1200"></picture><figcaption>Icosphere</figcaption></figure>
<em>Icosahedron after two iterations of subdivision</em><p></p>
<p><em>To be completed…</em></p>
<p>*Of course, following this logic, you could make a spherical looking mesh by basically taking any convex mesh and projecting its points onto a sphere. But then its points wouldn’t really be even distributed. That’s why we subdivide an icosahedron.</p>
Donald Knuth Finally Sells Out
2009-04-21T05:56:25Z
https://geekshavefeelings.com/posts/2009/donald-knuth-finally-sells-out/
<p><a href="http://www.ibiblio.org/Dave/Dr-Fun/df200002/df20000210.jpg"><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/89M3i9FRyK-640.avif 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/89M3i9FRyK-640.webp 640w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Donald Knuth finally sells out" src="https://geekshavefeelings.com/img/89M3i9FRyK-640.jpeg" width="640" height="480"></picture></figure></a></p>
Harpy – Sumo Bots 2009
2009-02-09T05:26:46Z
https://geekshavefeelings.com/posts/2009/harpy-sumo-bots-2009/
<p>This will be a collection of design information, videos, and photos of Harpy, the robotic sumo platform I built for the Science Olympiad tournaments in New York State.</p>
<p>Harpy’s drivetrain uses the motors that were used in La Cucaracha, only paired with larger, stickier wheels. It also has more capable, robust 4-cell 2.3Ah A123 lithium-iron-phosphate batteries capable of 70A continuous, but has a motor controller (Dimension Engineering Sabertooth 2×25A) that is akin to complete crap.</p>
<p>Harpy took a lot of cues from lessons learned building and competing with previous sumo bots. Its design goals were to be as simple and compact as possible, minimizing especially height and the length between the wheels and the front edge of the scoop. The first is to allow the bot to fit inside a foam-lined <a href="http://www.plasticase.com/productdetails.asp?node=40&lang=en">Plasticase 628 procase</a>, which were offered at a discount to Techtonics, and to lower the center of gravity. The second was to maximize robot maneuverability—Harpy does not have swing around a large front “head” like many other robots do, but instead pivots about a point relatively fore to be bot. Its overall length was reduced, but if more length was require for space, it would have been added to the rear.</p>
<p>Harpy’s weight distribution (which is to place a maximal amount of weight upon tires and to minimize weight on ground contact points that do not contribute to pushing force) was heavily considered during design, but it was not a major design goal. Simplicity and robustness of the chassis were seen as more important and could not be compromised by design choices that improved weight distribution. Thus, a four-wheel design (driven by belts or gears from the two motors) was rejected, as well as a scoop with adjustable “ride height.”</p>
<p>Pursuing the goal of robustness and simplicity, Harpy features no flat horizontal load-bearing structures in its chassis. That is, contrary to most “standard” robot designs, there is no “base plate” or platform on which other components are mounted. Instead, Harpy has four one-quarter inch PETG plates standing vertically. They clamp onto the motors and clip onto the ends of the battery pack. In this way, the sturdy gearmotors and “shotgun barrel” style A123 pack (built from kit from the now-defunct Model Electronics Corp.) serve as the primary structural elements of the chassis.</p>
<p>These vertical plates are also connected to another vertical piece running left-to-right and to the scoop. That is more or less the entire chassis, and it is exceptionally sturdy and rigid compared to a traditional (and easy to build) platform-style design robot. In fact, even at the tournaments, Harpy uses no glue to hold its plastic parts together.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/zPNrjiboCX-690.avif 690w, https://geekshavefeelings.com/img/zPNrjiboCX-1380.avif 1380w, https://geekshavefeelings.com/img/zPNrjiboCX-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/zPNrjiboCX-690.webp 690w, https://geekshavefeelings.com/img/zPNrjiboCX-1380.webp 1380w, https://geekshavefeelings.com/img/zPNrjiboCX-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/zPNrjiboCX-690.jpeg 690w, https://geekshavefeelings.com/img/zPNrjiboCX-1380.jpeg 1380w, https://geekshavefeelings.com/img/zPNrjiboCX-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/zPNrjiboCX-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/AZeCoC33Gb-690.avif 690w, https://geekshavefeelings.com/img/AZeCoC33Gb-1380.avif 1380w, https://geekshavefeelings.com/img/AZeCoC33Gb-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/AZeCoC33Gb-690.webp 690w, https://geekshavefeelings.com/img/AZeCoC33Gb-1380.webp 1380w, https://geekshavefeelings.com/img/AZeCoC33Gb-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/AZeCoC33Gb-690.jpeg 690w, https://geekshavefeelings.com/img/AZeCoC33Gb-1380.jpeg 1380w, https://geekshavefeelings.com/img/AZeCoC33Gb-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/AZeCoC33Gb-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/huVuaqvlEt-690.avif 690w, https://geekshavefeelings.com/img/huVuaqvlEt-800.avif 800w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/huVuaqvlEt-690.webp 690w, https://geekshavefeelings.com/img/huVuaqvlEt-800.webp 800w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/huVuaqvlEt-690.jpeg 690w, https://geekshavefeelings.com/img/huVuaqvlEt-800.jpeg 800w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/huVuaqvlEt-690.jpeg" width="800" height="600"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/6LPK5QIQxM-690.avif 690w, https://geekshavefeelings.com/img/6LPK5QIQxM-1380.avif 1380w, https://geekshavefeelings.com/img/6LPK5QIQxM-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/6LPK5QIQxM-690.webp 690w, https://geekshavefeelings.com/img/6LPK5QIQxM-1380.webp 1380w, https://geekshavefeelings.com/img/6LPK5QIQxM-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/6LPK5QIQxM-690.jpeg 690w, https://geekshavefeelings.com/img/6LPK5QIQxM-1380.jpeg 1380w, https://geekshavefeelings.com/img/6LPK5QIQxM-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/6LPK5QIQxM-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/ggf8vrco50-690.avif 690w, https://geekshavefeelings.com/img/ggf8vrco50-1380.avif 1380w, https://geekshavefeelings.com/img/ggf8vrco50-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/ggf8vrco50-690.webp 690w, https://geekshavefeelings.com/img/ggf8vrco50-1380.webp 1380w, https://geekshavefeelings.com/img/ggf8vrco50-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/ggf8vrco50-690.jpeg 690w, https://geekshavefeelings.com/img/ggf8vrco50-1380.jpeg 1380w, https://geekshavefeelings.com/img/ggf8vrco50-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/ggf8vrco50-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/zrlpAqtYEj-690.avif 690w, https://geekshavefeelings.com/img/zrlpAqtYEj-1380.avif 1380w, https://geekshavefeelings.com/img/zrlpAqtYEj-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/zrlpAqtYEj-690.webp 690w, https://geekshavefeelings.com/img/zrlpAqtYEj-1380.webp 1380w, https://geekshavefeelings.com/img/zrlpAqtYEj-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/zrlpAqtYEj-690.jpeg 690w, https://geekshavefeelings.com/img/zrlpAqtYEj-1380.jpeg 1380w, https://geekshavefeelings.com/img/zrlpAqtYEj-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/zrlpAqtYEj-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/erZcxJwpdI-690.avif 690w, https://geekshavefeelings.com/img/erZcxJwpdI-1380.avif 1380w, https://geekshavefeelings.com/img/erZcxJwpdI-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/erZcxJwpdI-690.webp 690w, https://geekshavefeelings.com/img/erZcxJwpdI-1380.webp 1380w, https://geekshavefeelings.com/img/erZcxJwpdI-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/erZcxJwpdI-690.jpeg 690w, https://geekshavefeelings.com/img/erZcxJwpdI-1380.jpeg 1380w, https://geekshavefeelings.com/img/erZcxJwpdI-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/erZcxJwpdI-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/HVmwTVTrqU-690.avif 690w, https://geekshavefeelings.com/img/HVmwTVTrqU-1380.avif 1380w, https://geekshavefeelings.com/img/HVmwTVTrqU-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/HVmwTVTrqU-690.webp 690w, https://geekshavefeelings.com/img/HVmwTVTrqU-1380.webp 1380w, https://geekshavefeelings.com/img/HVmwTVTrqU-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/HVmwTVTrqU-690.jpeg 690w, https://geekshavefeelings.com/img/HVmwTVTrqU-1380.jpeg 1380w, https://geekshavefeelings.com/img/HVmwTVTrqU-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/HVmwTVTrqU-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/c8kTVIi1Sg-690.avif 690w, https://geekshavefeelings.com/img/c8kTVIi1Sg-1380.avif 1380w, https://geekshavefeelings.com/img/c8kTVIi1Sg-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/c8kTVIi1Sg-690.webp 690w, https://geekshavefeelings.com/img/c8kTVIi1Sg-1380.webp 1380w, https://geekshavefeelings.com/img/c8kTVIi1Sg-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/c8kTVIi1Sg-690.jpeg 690w, https://geekshavefeelings.com/img/c8kTVIi1Sg-1380.jpeg 1380w, https://geekshavefeelings.com/img/c8kTVIi1Sg-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/c8kTVIi1Sg-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/I6zPm3YGrm-690.avif 690w, https://geekshavefeelings.com/img/I6zPm3YGrm-1380.avif 1380w, https://geekshavefeelings.com/img/I6zPm3YGrm-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/I6zPm3YGrm-690.webp 690w, https://geekshavefeelings.com/img/I6zPm3YGrm-1380.webp 1380w, https://geekshavefeelings.com/img/I6zPm3YGrm-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/I6zPm3YGrm-690.jpeg 690w, https://geekshavefeelings.com/img/I6zPm3YGrm-1380.jpeg 1380w, https://geekshavefeelings.com/img/I6zPm3YGrm-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/I6zPm3YGrm-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/VvmjFnFYS8-690.avif 690w, https://geekshavefeelings.com/img/VvmjFnFYS8-1380.avif 1380w, https://geekshavefeelings.com/img/VvmjFnFYS8-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/VvmjFnFYS8-690.webp 690w, https://geekshavefeelings.com/img/VvmjFnFYS8-1380.webp 1380w, https://geekshavefeelings.com/img/VvmjFnFYS8-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/VvmjFnFYS8-690.jpeg 690w, https://geekshavefeelings.com/img/VvmjFnFYS8-1380.jpeg 1380w, https://geekshavefeelings.com/img/VvmjFnFYS8-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/VvmjFnFYS8-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/eUtVSs-sny-690.avif 690w, https://geekshavefeelings.com/img/eUtVSs-sny-1380.avif 1380w, https://geekshavefeelings.com/img/eUtVSs-sny-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/eUtVSs-sny-690.webp 690w, https://geekshavefeelings.com/img/eUtVSs-sny-1380.webp 1380w, https://geekshavefeelings.com/img/eUtVSs-sny-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/eUtVSs-sny-690.jpeg 690w, https://geekshavefeelings.com/img/eUtVSs-sny-1380.jpeg 1380w, https://geekshavefeelings.com/img/eUtVSs-sny-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/eUtVSs-sny-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/2WCszeX5Ey-690.avif 690w, https://geekshavefeelings.com/img/2WCszeX5Ey-1380.avif 1380w, https://geekshavefeelings.com/img/2WCszeX5Ey-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/2WCszeX5Ey-690.webp 690w, https://geekshavefeelings.com/img/2WCszeX5Ey-1380.webp 1380w, https://geekshavefeelings.com/img/2WCszeX5Ey-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/2WCszeX5Ey-690.jpeg 690w, https://geekshavefeelings.com/img/2WCszeX5Ey-1380.jpeg 1380w, https://geekshavefeelings.com/img/2WCszeX5Ey-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/2WCszeX5Ey-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/e5wA9Xo-Au-690.avif 690w, https://geekshavefeelings.com/img/e5wA9Xo-Au-1380.avif 1380w, https://geekshavefeelings.com/img/e5wA9Xo-Au-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/e5wA9Xo-Au-690.webp 690w, https://geekshavefeelings.com/img/e5wA9Xo-Au-1380.webp 1380w, https://geekshavefeelings.com/img/e5wA9Xo-Au-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/e5wA9Xo-Au-690.jpeg 690w, https://geekshavefeelings.com/img/e5wA9Xo-Au-1380.jpeg 1380w, https://geekshavefeelings.com/img/e5wA9Xo-Au-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/e5wA9Xo-Au-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/FeCkqnb6P3-690.avif 690w, https://geekshavefeelings.com/img/FeCkqnb6P3-1380.avif 1380w, https://geekshavefeelings.com/img/FeCkqnb6P3-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/FeCkqnb6P3-690.webp 690w, https://geekshavefeelings.com/img/FeCkqnb6P3-1380.webp 1380w, https://geekshavefeelings.com/img/FeCkqnb6P3-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/FeCkqnb6P3-690.jpeg 690w, https://geekshavefeelings.com/img/FeCkqnb6P3-1380.jpeg 1380w, https://geekshavefeelings.com/img/FeCkqnb6P3-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/FeCkqnb6P3-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/yh3yj4XMzt-690.avif 690w, https://geekshavefeelings.com/img/yh3yj4XMzt-1380.avif 1380w, https://geekshavefeelings.com/img/yh3yj4XMzt-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/yh3yj4XMzt-690.webp 690w, https://geekshavefeelings.com/img/yh3yj4XMzt-1380.webp 1380w, https://geekshavefeelings.com/img/yh3yj4XMzt-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/yh3yj4XMzt-690.jpeg 690w, https://geekshavefeelings.com/img/yh3yj4XMzt-1380.jpeg 1380w, https://geekshavefeelings.com/img/yh3yj4XMzt-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/yh3yj4XMzt-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/3-3o00Kna7-690.avif 690w, https://geekshavefeelings.com/img/3-3o00Kna7-1380.avif 1380w, https://geekshavefeelings.com/img/3-3o00Kna7-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/3-3o00Kna7-690.webp 690w, https://geekshavefeelings.com/img/3-3o00Kna7-1380.webp 1380w, https://geekshavefeelings.com/img/3-3o00Kna7-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/3-3o00Kna7-690.jpeg 690w, https://geekshavefeelings.com/img/3-3o00Kna7-1380.jpeg 1380w, https://geekshavefeelings.com/img/3-3o00Kna7-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/3-3o00Kna7-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/DHMxHzlxrX-690.avif 690w, https://geekshavefeelings.com/img/DHMxHzlxrX-1380.avif 1380w, https://geekshavefeelings.com/img/DHMxHzlxrX-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/DHMxHzlxrX-690.webp 690w, https://geekshavefeelings.com/img/DHMxHzlxrX-1380.webp 1380w, https://geekshavefeelings.com/img/DHMxHzlxrX-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/DHMxHzlxrX-690.jpeg 690w, https://geekshavefeelings.com/img/DHMxHzlxrX-1380.jpeg 1380w, https://geekshavefeelings.com/img/DHMxHzlxrX-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/DHMxHzlxrX-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/SYcfRuyt8t-690.avif 690w, https://geekshavefeelings.com/img/SYcfRuyt8t-1380.avif 1380w, https://geekshavefeelings.com/img/SYcfRuyt8t-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/SYcfRuyt8t-690.webp 690w, https://geekshavefeelings.com/img/SYcfRuyt8t-1380.webp 1380w, https://geekshavefeelings.com/img/SYcfRuyt8t-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/SYcfRuyt8t-690.jpeg 690w, https://geekshavefeelings.com/img/SYcfRuyt8t-1380.jpeg 1380w, https://geekshavefeelings.com/img/SYcfRuyt8t-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/SYcfRuyt8t-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/XGD-Gv9QaU-690.avif 690w, https://geekshavefeelings.com/img/XGD-Gv9QaU-1380.avif 1380w, https://geekshavefeelings.com/img/XGD-Gv9QaU-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/XGD-Gv9QaU-690.webp 690w, https://geekshavefeelings.com/img/XGD-Gv9QaU-1380.webp 1380w, https://geekshavefeelings.com/img/XGD-Gv9QaU-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/XGD-Gv9QaU-690.jpeg 690w, https://geekshavefeelings.com/img/XGD-Gv9QaU-1380.jpeg 1380w, https://geekshavefeelings.com/img/XGD-Gv9QaU-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/XGD-Gv9QaU-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/aiC865lRZL-690.avif 690w, https://geekshavefeelings.com/img/aiC865lRZL-1380.avif 1380w, https://geekshavefeelings.com/img/aiC865lRZL-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/aiC865lRZL-690.webp 690w, https://geekshavefeelings.com/img/aiC865lRZL-1380.webp 1380w, https://geekshavefeelings.com/img/aiC865lRZL-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/aiC865lRZL-690.jpeg 690w, https://geekshavefeelings.com/img/aiC865lRZL-1380.jpeg 1380w, https://geekshavefeelings.com/img/aiC865lRZL-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/aiC865lRZL-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/Tidl4AMeU--690.avif 690w, https://geekshavefeelings.com/img/Tidl4AMeU--1380.avif 1380w, https://geekshavefeelings.com/img/Tidl4AMeU--2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/Tidl4AMeU--690.webp 690w, https://geekshavefeelings.com/img/Tidl4AMeU--1380.webp 1380w, https://geekshavefeelings.com/img/Tidl4AMeU--2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/Tidl4AMeU--690.jpeg 690w, https://geekshavefeelings.com/img/Tidl4AMeU--1380.jpeg 1380w, https://geekshavefeelings.com/img/Tidl4AMeU--2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/Tidl4AMeU--690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/IWgnjpSaiz-690.avif 690w, https://geekshavefeelings.com/img/IWgnjpSaiz-1380.avif 1380w, https://geekshavefeelings.com/img/IWgnjpSaiz-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/IWgnjpSaiz-690.webp 690w, https://geekshavefeelings.com/img/IWgnjpSaiz-1380.webp 1380w, https://geekshavefeelings.com/img/IWgnjpSaiz-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/IWgnjpSaiz-690.jpeg 690w, https://geekshavefeelings.com/img/IWgnjpSaiz-1380.jpeg 1380w, https://geekshavefeelings.com/img/IWgnjpSaiz-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/IWgnjpSaiz-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/LOSVVA3_ka-690.avif 690w, https://geekshavefeelings.com/img/LOSVVA3_ka-1380.avif 1380w, https://geekshavefeelings.com/img/LOSVVA3_ka-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/LOSVVA3_ka-690.webp 690w, https://geekshavefeelings.com/img/LOSVVA3_ka-1380.webp 1380w, https://geekshavefeelings.com/img/LOSVVA3_ka-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/LOSVVA3_ka-690.jpeg 690w, https://geekshavefeelings.com/img/LOSVVA3_ka-1380.jpeg 1380w, https://geekshavefeelings.com/img/LOSVVA3_ka-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/LOSVVA3_ka-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/AIZ0CqEwQX-690.avif 690w, https://geekshavefeelings.com/img/AIZ0CqEwQX-1380.avif 1380w, https://geekshavefeelings.com/img/AIZ0CqEwQX-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/AIZ0CqEwQX-690.webp 690w, https://geekshavefeelings.com/img/AIZ0CqEwQX-1380.webp 1380w, https://geekshavefeelings.com/img/AIZ0CqEwQX-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/AIZ0CqEwQX-690.jpeg 690w, https://geekshavefeelings.com/img/AIZ0CqEwQX-1380.jpeg 1380w, https://geekshavefeelings.com/img/AIZ0CqEwQX-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/AIZ0CqEwQX-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/dv1-KKNL_w-690.avif 690w, https://geekshavefeelings.com/img/dv1-KKNL_w-1380.avif 1380w, https://geekshavefeelings.com/img/dv1-KKNL_w-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/dv1-KKNL_w-690.webp 690w, https://geekshavefeelings.com/img/dv1-KKNL_w-1380.webp 1380w, https://geekshavefeelings.com/img/dv1-KKNL_w-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/dv1-KKNL_w-690.jpeg 690w, https://geekshavefeelings.com/img/dv1-KKNL_w-1380.jpeg 1380w, https://geekshavefeelings.com/img/dv1-KKNL_w-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/dv1-KKNL_w-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/-DUWYb0Hx7-690.avif 690w, https://geekshavefeelings.com/img/-DUWYb0Hx7-1380.avif 1380w, https://geekshavefeelings.com/img/-DUWYb0Hx7-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/-DUWYb0Hx7-690.webp 690w, https://geekshavefeelings.com/img/-DUWYb0Hx7-1380.webp 1380w, https://geekshavefeelings.com/img/-DUWYb0Hx7-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/-DUWYb0Hx7-690.jpeg 690w, https://geekshavefeelings.com/img/-DUWYb0Hx7-1380.jpeg 1380w, https://geekshavefeelings.com/img/-DUWYb0Hx7-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/-DUWYb0Hx7-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/L1aXKCwYcH-690.avif 690w, https://geekshavefeelings.com/img/L1aXKCwYcH-1380.avif 1380w, https://geekshavefeelings.com/img/L1aXKCwYcH-2592.avif 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/L1aXKCwYcH-690.webp 690w, https://geekshavefeelings.com/img/L1aXKCwYcH-1380.webp 1380w, https://geekshavefeelings.com/img/L1aXKCwYcH-2592.webp 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/jpeg" srcset="https://geekshavefeelings.com/img/L1aXKCwYcH-690.jpeg 690w, https://geekshavefeelings.com/img/L1aXKCwYcH-1380.jpeg 1380w, https://geekshavefeelings.com/img/L1aXKCwYcH-2592.jpeg 2592w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/L1aXKCwYcH-690.jpeg" width="2592" height="1944"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/vZatSd-rme-690.avif 690w, https://geekshavefeelings.com/img/vZatSd-rme-1380.avif 1380w, https://geekshavefeelings.com/img/vZatSd-rme-1648.avif 1648w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/vZatSd-rme-690.webp 690w, https://geekshavefeelings.com/img/vZatSd-rme-1380.webp 1380w, https://geekshavefeelings.com/img/vZatSd-rme-1648.webp 1648w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/vZatSd-rme-690.png 690w, https://geekshavefeelings.com/img/vZatSd-rme-1380.png 1380w, https://geekshavefeelings.com/img/vZatSd-rme-1648.png 1648w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/vZatSd-rme-690.png" width="1648" height="887"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/BJzvCeG3MD-690.avif 690w, https://geekshavefeelings.com/img/BJzvCeG3MD-1380.avif 1380w, https://geekshavefeelings.com/img/BJzvCeG3MD-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/BJzvCeG3MD-690.webp 690w, https://geekshavefeelings.com/img/BJzvCeG3MD-1380.webp 1380w, https://geekshavefeelings.com/img/BJzvCeG3MD-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/BJzvCeG3MD-690.png 690w, https://geekshavefeelings.com/img/BJzvCeG3MD-1380.png 1380w, https://geekshavefeelings.com/img/BJzvCeG3MD-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/BJzvCeG3MD-690.png" width="1920" height="1200"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/w5OUTKmu5k-690.avif 690w, https://geekshavefeelings.com/img/w5OUTKmu5k-1380.avif 1380w, https://geekshavefeelings.com/img/w5OUTKmu5k-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/w5OUTKmu5k-690.webp 690w, https://geekshavefeelings.com/img/w5OUTKmu5k-1380.webp 1380w, https://geekshavefeelings.com/img/w5OUTKmu5k-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/w5OUTKmu5k-690.png 690w, https://geekshavefeelings.com/img/w5OUTKmu5k-1380.png 1380w, https://geekshavefeelings.com/img/w5OUTKmu5k-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/w5OUTKmu5k-690.png" width="1920" height="1200"></picture></figure>
<figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/HrBxD4othG-690.avif 690w, https://geekshavefeelings.com/img/HrBxD4othG-1380.avif 1380w, https://geekshavefeelings.com/img/HrBxD4othG-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/HrBxD4othG-690.webp 690w, https://geekshavefeelings.com/img/HrBxD4othG-1380.webp 1380w, https://geekshavefeelings.com/img/HrBxD4othG-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/HrBxD4othG-690.png 690w, https://geekshavefeelings.com/img/HrBxD4othG-1380.png 1380w, https://geekshavefeelings.com/img/HrBxD4othG-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="" src="https://geekshavefeelings.com/img/HrBxD4othG-690.png" width="1920" height="1200"></picture></figure><p></p>
<p>Harpy has <em>immense</em> pushing power, due to its 550-size gearmotors and custom-molded wheels. Thanks to cylindrical gearheads over the gearmotors that are flush and inline to the motor cans, Harpy has wheels that fit <em>over</em> the gearhead casing, rather than protruding out from the side of the gearmotors. The wheel forms are made from polycarbonate tubing (razor-sawed by hand) with inserts laser-cut from PETG. They are then placed inside a mold of similar construction. Pathway Polymers Por-A-Mold S-111 (which has a cured hardness of Shore A 20) was then mixed and poured into the mold.</p>
<p>The wheel and tire assembly was then broken out of the mold by cutting away the outer mold tubing on two sides, breaking the tube along one of the cuts, and folding the tube along the other cut. Think opening up a wrist shackle.</p>
<p>The resulting wheel and tire assembly were <em>extremely</em> sticky. After the wheel was mounted to the gearmotor, each of which is about a pound, it was found that the assembly could stick to vertical painted drywall indefinitely, and even upside-down to the ceiling. The robot, with clean wheels, can push more than 2 to 3 times its weight, depending on the condition of the wheels, alignment, etc. In fact, if the robot were to drive into a wall from a standstill, it can actually pop apart all of its plastic parts at the tab-and-slot joints, and essentially disintegrate. That is why it does not use any glue or plastic weld cement—if the structure can not relieve stress by popping apart at Lego-like joints, then it will crack and cleave.</p>
<h2 id="new-york-city-regionals" tabindex="-1">New York City Regionals <a class="header-anchor" href="https://geekshavefeelings.com/posts/2009/harpy-sumo-bots-2009/">§</a></h2>
<p>Match 1 – Stuyvesant Team C vs. Townsend Harris Team B</p>
<p>https://www.youtube.com/watch?v=tcK_pTSACFo</p>
<p>Match 2 – Stuyvesant Team C vs. Townsend Harris Team A</p>
<p>https://www.youtube.com/watch?v=rr2dlnZYKis</p>
<p>Match 3 – Stuyvesant Team C vs. Unknown Team</p>
<p>https://www.youtube.com/watch?v=PVBH9pTa3HQ</p>
<p>Match 4 – Stuyvesant Team C vs. Cardozo Team A</p>
<p>https://www.youtube.com/watch?v=hlN-aRDRF44</p>
<p>Match 5 – Stuyvesant Team C vs. Unknown Team</p>
<p>https://www.youtube.com/watch?v=wFQoIJLK6aY</p>
<p>Match 6 – Stuyvesant Team C vs. Cardozo Team A</p>
<p>https://www.youtube.com/watch?v=UXaveu4_Iuk</p>
<p>Match 6 – Stuyvesant Team C vs. Cardozo Team A (<em>Redo</em>)</p>
<p>https://www.youtube.com/watch?v=I6-ogTGIw2c</p>
<p>Match 7 – Stuyvesant Team C vs. Cardozo Team A</p>
<p>https://www.youtube.com/watch?v=A8sT3dksMMQ</p>
<p>All in all, Harpy’s mechanical design was extremely satisfactory, except that it has nowhere to mount the motor controller. Also, if the scoop is just a bit lifted up, then the rear rests on the batteries rather than the wheels, and it begins to lose traction, which can be seen in the video for Match 7. The motor controller is unacceptably unresponsive and underpowered, and a decision was made to replace them with Victor 883s, from La Cucaracha. These and other deficiencies resulted in Harpy II, which has not yet seen battle, but is a clear improvement upon Harpy I.</p>
<p></p><figure><picture><source type="image/avif" srcset="https://geekshavefeelings.com/img/BJzvCeG3MD-690.avif 690w, https://geekshavefeelings.com/img/BJzvCeG3MD-1380.avif 1380w, https://geekshavefeelings.com/img/BJzvCeG3MD-1920.avif 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/webp" srcset="https://geekshavefeelings.com/img/BJzvCeG3MD-690.webp 690w, https://geekshavefeelings.com/img/BJzvCeG3MD-1380.webp 1380w, https://geekshavefeelings.com/img/BJzvCeG3MD-1920.webp 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><source type="image/png" srcset="https://geekshavefeelings.com/img/BJzvCeG3MD-690.png 690w, https://geekshavefeelings.com/img/BJzvCeG3MD-1380.png 1380w, https://geekshavefeelings.com/img/BJzvCeG3MD-1920.png 1920w" sizes="(max-width: calc(690px + 2rem)) calc(100vw - 2rem), 690px"><img loading="lazy" decoding="async" alt="Harpy II" src="https://geekshavefeelings.com/img/BJzvCeG3MD-690.png" width="1920" height="1200"></picture><figcaption>Harpy II</figcaption></figure><p></p>