tag:blogger.com,1999:blog-167934652024-03-13T19:06:04.957+01:00Read the source Luke!Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-16793465.post-45056551063007547442014-12-21T23:02:00.001+01:002014-12-21T23:07:42.069+01:00FTP and WebDAV Plugins for Pharo's FileSystem<h2 id="project-info">Project info</h2>
<p>The “FileSystemNetwork” project is a small library which adds WebDAV and FTP support to Pharo’s FileSystem framework. This allows you to use remote WebDAV and FTP locations with the same (FileSystem) API that’s used for disk access.</p>
<h2 id="project-location">Project location</h2>
<p>The project is located on STHub at <a href="http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork">http://smalltalkhub.com/#!/~UdoSchneider/FileSystemNetwork</a></p>
<h2 id="screenshot">Screenshot</h2>
<p>Because the Pharo Tools use FileSystem as their underlying framework even those built-in tools are now able to use remote WebDAV and FTP locations. <br>
<img src="http://udos.s3.amazonaws.com/blog/nfs/releases.png" alt="Pharo FileList browser on mozilla.org FTP Server" title=""></p>
<h2 id="installation">Installation</h2>
<p>To install everything (WebDAV, FTP and tests) simply use:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">Gofer</span><span class="pln"> it
smalltalkhubUser</span><span class="pun">:</span><span class="pln"> </span><span class="str">'UdoSchneider'</span><span class="pln"> project</span><span class="pun">:</span><span class="pln"> </span><span class="str">'FileSystemNetwork'</span><span class="pun">;</span><span class="pln">
configuration</span><span class="pun">;</span><span class="pln">
loadStable</span><span class="pun">.</span></code></pre>
<p>If you don’t want to load everything the configuration provides (two) three groups:</p>
<ul>
<li><code>Webdav</code>: (Only WebDav - no tests)</li>
<li><code>FTP</code>: (Only FTP - no tests)</li>
<li><code>Tests</code>: (All tests - loads everything)</li>
</ul>
<p>E.g. to only load WebDAV support use</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">Gofer</span><span class="pln"> it
smalltalkhubUser</span><span class="pun">:</span><span class="pln"> </span><span class="str">'UdoSchneider'</span><span class="pln"> project</span><span class="pun">:</span><span class="pln"> </span><span class="str">'FileSystemNetwork'</span><span class="pun">;</span><span class="pln">
configuration</span><span class="pun">;</span><span class="pln">
load</span><span class="pun">.</span><span class="pln">
</span><span class="com">#ConfigurationOfFileSystemNetwork asClass project stableVersion load: 'Webdav'</span></code></pre>
<h2 id="use-in-your-own-application">Use in your own application</h2>
<p>Once loaded the <code>FileSystem</code> class provides additional methods (<code>#webdav:</code> and <code>#ftp:</code>) which return a Network filesystem. Both methods take a <code>String</code> or <code>(Zn)Url</code> argument which allows you to specify username, password, host, port and initial working directory (e.g. <code>[scheme]://[username]:[password]@[hostname]:[port][workingdirectory]</code>. Once you obtained the <code>FileSystem</code> you can use the usual <code>FileSystem</code> API (see <a href="http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/PBE2.pdf#page=23">Files with FileSystem</a> for examples).</p>
<blockquote>
<p><strong>NOTE:</strong> Please remember to always <code>#close</code> the <code>FileSystem</code> instance. There might be dangling/open instances otherwise!</p>
</blockquote>
<h3 id="ftp">FTP</h3>
<pre class="prettyprint prettyprinted"><code><span class="str">"Obtain a FTP FileSystem"</span><span class="pln">
fs </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">FileSystem</span><span class="pln"> ftp</span><span class="pun">:</span><span class="pln"> </span><span class="str">'ftp://ftp.mozilla.org'</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Get working directory"</span><span class="pln">
wd </span><span class="pun">:=</span><span class="pln"> fs workingDirectory </span><span class="pun">.</span><span class="pln">
</span><span class="str">"Print the following expression!"</span><span class="pln">
</span><span class="pun">(</span><span class="pln">wd </span><span class="pun">/</span><span class="pln"> </span><span class="str">'pub'</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'firefox'</span><span class="pun">)</span><span class="pln"> children</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Open a FileList on the FileSystem"</span><span class="pln">
</span><span class="typ">FileList</span><span class="pln"> openOn</span><span class="pun">:</span><span class="pln"> wd</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Remember to close if you are finished!"</span><span class="pln">
fs close</span><span class="pun">.</span></code></pre>
<h3 id="webdav">WebDAV</h3>
<pre class="prettyprint prettyprinted"><code><span class="str">"Obtain a WebDAV FileSystem"</span><span class="pln">
fs </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">FileSystem</span><span class="pln"> webdav</span><span class="pun">:</span><span class="pln"> </span><span class="str">'https://udoschneider:PASSWORD@webdav.hidrive.strato.com/users/udoschneider/'</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Get working directory"</span><span class="pln">
wd </span><span class="pun">:=</span><span class="pln"> fs workingDirectory</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Open a FileList on the FileSystem"</span><span class="pln">
</span><span class="typ">FileList</span><span class="pln"> openOn</span><span class="pun">:</span><span class="pln"> wd</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Remember to close if you are finished!"</span><span class="pln">
fs close</span><span class="pun">.</span></code></pre>
<h2 id="packages">Packages</h2>
<ul>
<li><code>FileSystem-Network-Core</code> - package with core/protocol independent functionality</li>
<li><code>FileSystem-Tests-Network-Core</code> - package with core tests</li>
<li><code>FileSystem-Network-FTP</code> - package with FTP functionality</li>
<li><code>FileSystem-Tests-Network-FTP</code> - package with FTP tests</li>
<li><code>FileSystem-Network-Webdav</code> - package with WebDAV functionality</li>
<li><code>FileSystem-Tests-Network-Webdav</code> - package with WebDAV tests</li>
</ul>
<h2 id="testing">Testing</h2>
<p>The package comes with 156 tests in the test packages (most of them inherited from <code>FileSystem</code> tests). All tests are green on the clients/servers I used.</p>
<blockquote>
<p><strong>NOTE</strong> If you want to verify that a certain server works correctly simply run the tests against this server. Please remember that you need write access for the tests to be successful.</p>
<p><strong>NOTE</strong> The server URLs for WebDAV and FTP are not hardcoded in the tests. You will be requested to provide FTP and WebDAV URLs on first run. If you want to reset the cached URLs use <code>FTPFileSystemTest reset.</code>and <code>WebdavFileSystemTest reset.</code>.</p>
</blockquote>
<h2 id="to-do">To Do</h2>
<h3 id="enhanced-ftp-server-support">Enhanced FTP Server Support</h3>
<p>Currently only FTP Servers running on *nix or Windows are supported. Support for NetWare and Rumpus are on the way.</p>
<h3 id="s3-support">S3 Support</h3>
<p>Amazon S3 Support will be integrated soon as most of the functionality is already there due to the WebDAV/HTTP support.</p>
<h2 id="license">License</h2>
<p>The code is under <a href="http://opensource.org/licenses/mit-license.html">MIT License</a>.</p>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com6tag:blogger.com,1999:blog-16793465.post-52867313352440065622014-11-26T11:14:00.001+01:002014-11-26T11:17:15.682+01:00PaymentFont for Seaside<h2 id="project-info">Project info</h2>
<p>The “PaymentFont for Seaside” project is a small <a href="http://seaside.st/">Seaside</a> wrapper for the <a href="http://paymentfont.io/">PaymentFont project</a>. FontPayment is a “sleek SVG webfont containing 74 icons of all main payment operators and methods”.</p>
<h2 id="project-location">Project location</h2>
<p>The project is located on STHub at <a href="http://smalltalkhub.com/#!/~UdoSchneider/PaymentFont/">http://smalltalkhub.com/#!/~UdoSchneider/PaymentFont/</a></p>
<h2 id="screenshot">Screenshot</h2>
<p><img src="http://udos.s3.amazonaws.com/smalltalkhub/PaymentFont/PaymentFontExamplesBrowser.png" alt="PaymentFont for Seaside Examples Browser" title=""></p>
<h2 id="license">License</h2>
<p>PaymentFont is licensed under <a href="http://scripts.sil.org/OFL">SIL OFL 1.1</a>. The CSS files are licensed under the <a href="http://opensource.org/licenses/mit-license.html">MIT License</a>. The Pharo Smalltalk wrapper code is under <a href="http://opensource.org/licenses/mit-license.html">MIT License</a>.</p>
<h2 id="installation">Installation</h2>
<pre class="prettyprint prettyprinted"><code><span class="typ">Gofer</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
url</span><span class="pun">:</span><span class="pln"> </span><span class="str">'http://smalltalkhub.com/mc/UdoSchneider/PaymentFont/main'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">package</span><span class="pun">:</span><span class="pln"> </span><span class="str">'ConfigurationOfPaymentFont'</span><span class="pun">;</span><span class="pln">
load</span><span class="pun">.</span><span class="pln">
</span><span class="pun">((</span><span class="typ">Smalltalk</span><span class="pln"> at</span><span class="pun">:</span><span class="pln"> </span><span class="com">#ConfigurationOfPaymentFont) project stableVersion) load.</span></code></pre>
<h3 id="run-the-demo-locally">Run the Demo locally</h3>
<p>Start the web server for Seaside - for instance with Zinc evaluate:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">ZnZincServerAdaptor</span><span class="pln"> startOn</span><span class="pun">:</span><span class="pln"> </span><span class="lit">8080</span></code></pre>
<p>Now point your browser to <a href="http://127.0.0.1:8080/paymentfont">http://127.0.0.1:8080/paymentfont</a></p>
<h2 id="use-in-your-own-application">Use in your own application</h2>
<h3 id="necessary-seaside-libraries">Necessary Seaside libraries</h3>
<p>To add PaymentFont to your Seaside application you just have to add the appropriate seaside file libraries containing the CSS and fonts to your Seaside application.</p>
<p>Depending on the scenario there is a <code>PFDeploymentLibrary</code> and a <code>PFDevelopmentLibrary</code> that you will find in the package <code>PaymentFont-Core</code> in the category <code>PaymentFont-Core-Libraries</code>.</p>
<p>Have a look at the <code>#register</code> method in the <code>PFExamplesHome</code> class for an example.</p>
<h3 id="use-in-your-code">Use in your code</h3>
<p>If the PaymentFont library is registered with your Seaside application you can use the <code>#pfPaymentIcon</code> selectors in your usual rendering methods (like <code>#renderContentOn:</code>):</p>
<pre class="prettyprint prettyprinted"><code><span class="pln">renderContentOn</span><span class="pun">:</span><span class="pln"> html
html pfPaymentIcon amazon</span></code></pre>
<h2 id="packages">Packages</h2>
<ul>
<li><code>PaymentFont-Core</code> - package with the core, contains anything you need in an own app</li>
<li><code>PaymentFont-Tests</code> - package with the SUnit tests</li>
<li><code>PaymentFont-Examples</code> - example package for the demo</li>
</ul>
<h2 id="testing">Testing</h2>
<p>The package comes with 74 tests in the package <code>PaymentFont-Tests</code>. Just use the SUnit TestRunner to run them.</p>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-24853499770047910212014-09-22T20:23:00.001+02:002014-09-23T18:23:25.710+02:00Block Translators - parsing magic<h2 id="introduction">Introduction</h2>
<p>I have to admit I do love parsers, BNF grammars and similar stuff. I don’t really understand all this stuff in detail but I love working with it. After being exposed to lex/yacc in a previous life I simply loved using <a href="http://wiki.squeak.org/squeak/1419">T-Gen</a>, <a href="http://www.refactoryworkers.com/SmaCC.html">SmallCC</a> from within Smalltalk and now finally settled with <a href="http://pharobooks.gforge.inria.fr/PharoByExampleTwo-Eng/latest/PetitParser.pdf">PetitParser</a>.</p>
<p>All these parser generators are great if you need to parse a given textual input. In some cases however this is complete overkill. Especially if you need to (dynamically) translate a Smalltalk expression into something “different”.</p>
<p>Translating Smalltalk expressions into “something different” is exactly the usecase for what I call “Block Translators”.</p>
<h2 id="block-translators">Block Translators</h2>
<p>During this Blog Entry I’ll develop a simple Parser/Translator which is able to translate Smalltalk expressions like <code>(customer joinDate year is: Date today year)</code> into an equivalent SQL-like Expression like <code>(YEAR(customers.joinDate) = 2014)</code>. <br>
Please note that this Translator will neither be complete in terms of operations nor neatly refactored like you would expect for production code. But it should be able to show the general idea how to create <em>translators</em> which translate a Smalltalk expression into something different.</p>
<h2 id="smalltalk-collection-messages-as-sql-expression">Smalltalk collection messages as SQL Expression</h2>
<p>Smalltalk’s collection messages like <code>#do:</code>, <code>#select:</code> or <code>#detect:ifNone</code> are IMHO one of the biggest features of the class library. Most SQL libraries for Smalltalk also include the feature to express SQL expressions as Smalltalk code. So something like this …</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">(</span><span class="pln">
</span><span class="pun">(</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">and</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">
</span><span class="pun">(</span><span class="pln">customer bonusPoints gt</span><span class="pun">:</span><span class="pln"> customer joinDate year</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer joinDate year </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pln"> today year</span><span class="pun">)</span><span class="pln">
</span><span class="pun">)</span></code></pre>
<p>… should be translated into something SQL-like like this:</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">(((</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">surname </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">surname </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">&</span><span class="pln"> </span><span class="pun">((</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">bonusPoints </span><span class="pun">></span><span class="pln"> YEAR</span><span class="pun">(</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">joinDate</span><span class="pun">))</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">YEAR</span><span class="pun">(</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">joinDate</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2014</span><span class="pun">)))</span></code></pre>
<p>One way would be to hook into the Smalltalk compiler and build the SQL-like expression from the AST. Another would be to ignore the Smalltalk side completely and parse Strings via a Parsers into those expressions (again using graphs/ASTs). But in some cases a simpler approach with “Message Recording” objects is more than sufficient.</p>
<h2 id="blocks-as-parserstranslators">Blocks as Parsers/Translators</h2>
<p>Let’s start with the block from above. What happens if we call <code>#value:</code> with an arbitrary value? Let’s try <code>nil</code> for now:</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">|</span><span class="pln"> selectBlock </span><span class="pun">|</span><span class="pln">
selectBlock </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln">
</span><span class="pun">((</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">and</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">customer bonusPoints gt</span><span class="pun">:</span><span class="pln"> customer joinDate year</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer joinDate year </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pln"> today year</span><span class="pun">))</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
expression </span><span class="pun">:=</span><span class="pln"> selectBlock value</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">nil</span><span class="pun">.</span><span class="pln"> </span><span class="str">"Inspect-it"</span></code></pre>
<p>If we execute this snippet we’ll get an error message “<code>MessageNotUnderstood: UndefinedObject>>surname</code>“. And it’s clear why: Executing the block binds <code>nil</code> to <code>customer</code>. And the first message sent to <code>customer</code> is <code>#surname</code>. This of course raises an error because <code>UndefinedObject</code> does not understand <code>#surname</code>.</p>
<p>But what happens if we use another object (let’s call it a <code>SQLTable</code>) instead? This <code>SQLTable</code> does understand <code>#surname</code> and responds with something useful - a <code>SQLColumn</code> named accordingly in this case. If we keep up resolving to “useful” objects we’ll end up with a graph of objects expressing the original expression!</p>
<p>The “hard” parsing work is done by the Smalltalk compiler itself. Our job is only to record any (useful) message sent to our objects and respond with other useful objects to continue the proccess. Once we’re finished we can then use this graph of objects to create our “translated” language.</p>
<h2 id="sql-translator">SQL Translator</h2>
<blockquote>
<p><strong>NOTE:</strong> The following code snippets should be enough to build some working code (Copy&Paste from the blog should work). If you want to see the complete code you can find it here: <a href="http://www.smalltalkhub.com/#!/~UdoSchneider/BlockParser">BlockParsers on SmalltalkHub</a>.</p>
</blockquote>
<h3 id="sql-tables">SQL tables</h3>
<p>We’ll add bits and pieces of code along with the blog entry. Always just enough to hit the next Debugger. This will give us enough clues about how to proceed: <br>
The first class we need to create is <code>SQLTable</code> to bind to the <code>customer</code> Variable. Make it a subclass of <code>SQLComponent</code>. It also needs to store the table name in an instance variable:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">Object</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLComponent</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span></code></pre>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLComponent</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLTable</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">'name'</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span></code></pre>
<p>Add (instance creation) methods to set the table name:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTable</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">>>#</span><span class="pln">named</span><span class="pun">:</span><span class="pln"> aString
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
setName</span><span class="pun">:</span><span class="pln"> aString</span><span class="pun">;</span><span class="pln">
yourself
</span><span class="typ">SQLTable</span><span class="pun">>>#</span><span class="pln">setName</span><span class="pun">:</span><span class="pln"> aString
name </span><span class="pun">:=</span><span class="pln"> aString</span></code></pre>
<p>Try our new class and call the block with it:</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">|</span><span class="pln"> selectBlock table </span><span class="pun">|</span><span class="pln">
selectBlock </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln">
</span><span class="pun">((</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">and</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">customer bonusPoints gt</span><span class="pun">:</span><span class="pln"> customer joinDate year</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer joinDate year </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pln"> today year</span><span class="pun">))</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
table </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">SQLTable</span><span class="pln"> named</span><span class="pun">:</span><span class="pln"> </span><span class="str">'customers'</span><span class="pun">.</span><span class="pln">
selectBlock value</span><span class="pun">:</span><span class="pln"> table</span><span class="pun">.</span><span class="pln"> </span><span class="str">"Inspect-it"</span></code></pre>
<p>Executing this snippet will result in an error because (again) <code>#surname</code> is not understood: <br>
<img src="http://udos.s3.amazonaws.com/blog/block_parsing_magic/MessageNotUnderstood_SQLTable_surname.png" alt="Wallback: <code>MessageNotUnderstood: SQLTable>>surname</code>" title=""></p>
<p>If <code>customer</code> in the block is an <code>SQLTable</code> instance (or to be more specific a table row) then the semantic meaning of <code>customer surname</code> is to get its <code>surname</code> property - or to stick with SQL to get a column with that name.</p>
<h3 id="sql-columns">SQL columns</h3>
<p>To make things easier we’ll intercept each unary message sent to a <code>SQLTable</code> instance and return an <code>SQLColumn</code> instance which knows its originating table and its name. Because columns can participate in relations we’ll create an <code>SQLColumn</code> class as subclass of <code>SQLTerm</code>:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLComponent</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLTerm</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span><span class="pln">
</span><span class="typ">SQLTerm</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLColumn</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">'table name'</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span></code></pre>
<p>We also add methods to set the owning table and name:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLColumn</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">>>#</span><span class="pln">table</span><span class="pun">:</span><span class="pln"> aSQLTable name</span><span class="pun">:</span><span class="pln"> aString
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
setTable</span><span class="pun">:</span><span class="pln"> aSQLTable name</span><span class="pun">:</span><span class="pln"> aString</span><span class="pun">;</span><span class="pln">
yourself
</span><span class="typ">SQLColumn</span><span class="pun">>>#</span><span class="pln">setTable</span><span class="pun">:</span><span class="pln"> aSQLTable name</span><span class="pun">:</span><span class="pln"> aString
table </span><span class="pun">:=</span><span class="pln"> aSQLTable</span><span class="pun">.</span><span class="pln">
name </span><span class="pun">:=</span><span class="pln"> aString</span></code></pre>
<p>We also need to add behaviour to <code>SQLTable</code> to return an <code>SQLColumn</code> instance when it recieves an unknown unary message. So we’ll add that behavior do <code>#doesNotUnderstand</code>:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTable</span><span class="pun">>>#</span><span class="pln">doesNotUnderstand</span><span class="pun">:</span><span class="pln"> aMessage
</span><span class="pun">|</span><span class="pln"> selector </span><span class="pun">|</span><span class="pln">
selector </span><span class="pun">:=</span><span class="pln"> aMessage selector</span><span class="pun">.</span><span class="pln">
selector isUnary
ifTrue</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLColumn</span><span class="pln"> table</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> selector asString </span><span class="pun">].</span><span class="pln">
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">super</span><span class="pln"> doesNotUnderstand</span><span class="pun">:</span><span class="pln"> aMessage</span></code></pre>
<blockquote>
<p><strong>NOTE:</strong> In a “real” implementation you might want to check the selector name. If its a known column name (you have the schema? Don’t you?) you’d return the column. Otherwise forward <code>#doesNotUnderstand:</code> to <code>super</code>.</p>
</blockquote>
<h3 id="sql-expressions">SQL expressions</h3>
<p>Running the snippet now yields an “<code>SQLColumn(Object)>>doesNotUnderstand: #is:</code>” error: <br>
<img src="http://udos.s3.amazonaws.com/blog/block_parsing_magic/MessageNotUnderstood_SQLColumn_is.png" alt="Wallback: <code>MessageNotUnderstood: SQLColumn>>is:</code>" title=""></p>
<p>We’ll implement <code>#is:</code> as an comparison operator in an <code>SQLTerm</code>. Every SQL term (columns included) might be combined with a constant or to another term by using an operator. An <code>SQLExpression</code> stores a left and right term as well as the operand (like <code>=</code>, <code><</code>, <code>></code>, <code>+</code>, <code>-</code>, <code>*</code>, …):</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLExpression</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">'left operand right'</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span><span class="pln">
</span><span class="typ">SQLExpression</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">>>#</span><span class="pln">left</span><span class="pun">:</span><span class="pln"> leftTerm operand</span><span class="pun">:</span><span class="pln"> aSymbol right</span><span class="pun">:</span><span class="pln"> rightTerm
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
setLeft</span><span class="pun">:</span><span class="pln"> leftTerm operand</span><span class="pun">:</span><span class="pln"> aSymbol right</span><span class="pun">:</span><span class="pln"> rightTerm</span><span class="pun">;</span><span class="pln">
yourself
</span><span class="typ">SQLExpression</span><span class="pun">>>#</span><span class="pln">setLeft</span><span class="pun">:</span><span class="pln"> leftTerm operand</span><span class="pun">:</span><span class="pln"> aSymbol right</span><span class="pun">:</span><span class="pln"> rightTerm
left </span><span class="pun">:=</span><span class="pln"> leftTerm asSQLComponent</span><span class="pun">.</span><span class="pln">
operand </span><span class="pun">:=</span><span class="pln"> aSymbol</span><span class="pun">.</span><span class="pln">
right </span><span class="pun">:=</span><span class="pln"> rightTerm asSQLComponent</span></code></pre>
<blockquote>
<p><strong>NOTE:</strong> Please note that we are sending <code>#asSQLComponent</code> to both terms here. The left term should always be a subclass of <code>SQLComponent</code> already. The right side however might also be a constant (originating from Smalltalk code). So sending <code>#asSQLComponent</code> provides the possibility to wrap constants in a <code>SQLConstant</code> (sub-)class.</p>
</blockquote>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLConstant</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">'value'</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span><span class="pln">
</span><span class="typ">SQLConstant</span><span class="pun">>>#</span><span class="pln">value</span><span class="pun">:</span><span class="pln"> aValue
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
setValue</span><span class="pun">:</span><span class="pln"> aValue</span><span class="pun">;</span><span class="pln">
yourself
</span><span class="typ">SQLConstant</span><span class="pun">>>#</span><span class="pln">setValue</span><span class="pun">:</span><span class="pln"> aValue
value </span><span class="pun">:=</span><span class="pln"> aValue</span></code></pre>
<p>Now we need to implement <code>#asSQLComponent</code> in some classes which might appear in expressions:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLComponent</span><span class="pun">>>#</span><span class="pln">asSQLComponent
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln">
</span><span class="typ">Object</span><span class="pun">>>#</span><span class="pln">asSQLComponent
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLConstant</span><span class="pln"> value</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span></code></pre>
<blockquote>
<p><strong>NOTE:</strong> For now we only implement <code>#asSQLComponent</code> in <code>Object</code> and <code>SQLComponent</code>. In production you might want to use different <code>SQLConstant</code> subclasses for different kind of constants like <code>String</code>s, <code>Number</code>s, <code>Date</code>s to deal with the target expressions formatting. </p>
</blockquote>
<h3 id="equality-is">Equality (<code>#is:</code>)</h3>
<p>We’ll implement <code>#is:</code> in <code>SQLTerm</code> to return an <code>SQLExpression</code>.</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#= right: anObject</span></code></pre>
<blockquote>
<p><strong>NOTE:</strong> Why do we use <code>#is:</code> instead of <code>#=</code>? Overriding <code>#=</code> instead of implementing <code>#is:</code> is a double edged sword. Especially in our case because we’d change the semantics of the message. We won’t return a <code>Boolean</code> any longer - we’ll return something different! Overwriting <code>#=</code> to answer a non-<code>Boolean</code> leads to <em>interesting</em> effects down the line … you have been warned …</p>
</blockquote>
<h3 id="boolean-operators">Boolean Operators</h3>
<p>Next try: Let’s see how far we get now. <br>
<img src="https://udos.s3.amazonaws.com/blog/block_parsing_magic/MessageNotUnderstood_SQLExpression_or.png" alt="Wallback; <code>MessageNotUnderstood: SQLExpression>>or:</code>" title=""></p>
<p>We’ll get an Error message “<code>MessageNotUnderstood: SQLExpression>>or:</code>“. So let’s implement <code>SQLTerm>>#or:</code> and <code>SQLTerm>>#and:</code>. </p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pun">>></span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#| right: anObject</span><span class="pln">
</span><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="kwd">and</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#& right: anObject</span></code></pre>
<blockquote>
<p><strong>NOTE:</strong> Our implementation does not use regular blocks as arguments. You can use blocks in your implementation though. Just be warned that the compiler/VM might inline sends of <code>#and:</code>, <code>#or:</code> … if the argument is a block!</p>
<p><strong>NOTE:</strong> Logical <code>#not</code> is not an expression - not an operator “between” to terms. It’s an Operator applied to <em>one term</em>. So it’s best expressed as a <em>function</em>!</p>
</blockquote>
<h3 id="sql-functions">SQL functions</h3>
<p>Running the code snippet complains about an <code>SQLColumn</code> instance not understanding <code>#year</code>. Semantically I’d say that something like <code>tableName columnName year</code> is like calling a function: <code>YEAR(tableName.column)</code>. <br>
So every unary message sent to an <code>SQLTerm</code> should result in a <code>SQLFunction</code> wrapping it:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pln"> subclass</span><span class="pun">:</span><span class="pln"> </span><span class="com">#SQLFunction</span><span class="pln">
instanceVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">'name term'</span><span class="pln">
classVariableNames</span><span class="pun">:</span><span class="pln"> </span><span class="str">''</span><span class="pln">
category</span><span class="pun">:</span><span class="pln"> </span><span class="str">'BlockParser-SQL'</span><span class="pln">
</span><span class="typ">SQLFunction</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">>>#</span><span class="pln">name</span><span class="pun">:</span><span class="pln"> aString term</span><span class="pun">:</span><span class="pln"> anSQLTerm
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> </span><span class="kwd">new</span><span class="pln">
setName</span><span class="pun">:</span><span class="pln"> aString term</span><span class="pun">:</span><span class="pln"> anSQLTerm</span><span class="pun">;</span><span class="pln">
yourself
</span><span class="typ">SQLFunction</span><span class="pun">>>#</span><span class="pln">setName</span><span class="pun">:</span><span class="pln"> aString term</span><span class="pun">:</span><span class="pln"> anSQLTerm
name </span><span class="pun">:=</span><span class="pln"> aString</span><span class="pun">.</span><span class="pln">
term </span><span class="pun">:=</span><span class="pln"> anSQLTerm</span></code></pre>
<p>We’ll also implement <code>SQLTerm>>#doesNotUnderstand:</code> to return <code>SQLFunction</code>s.</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="pln">doesNotUnderstand</span><span class="pun">:</span><span class="pln"> aMessage
</span><span class="pun">|</span><span class="pln"> selector </span><span class="pun">|</span><span class="pln">
selector </span><span class="pun">:=</span><span class="pln"> aMessage selector</span><span class="pun">.</span><span class="pln">
selector isUnary
ifTrue</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLFunction</span><span class="pln"> name</span><span class="pun">:</span><span class="pln"> selector asString asUppercase term</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">super</span><span class="pln"> doesNotUnderstand</span><span class="pun">:</span><span class="pln"> aMessage</span></code></pre>
<blockquote>
<p><strong>NOTE:</strong> <code>#doesNotUnderstand:</code> is the quick and dirty solution here. If you have a limited number of functions you can also implement them as methods directly.</p>
</blockquote>
<h3 id="comparisons">Comparisons</h3>
<p>And again: <br>
<img src="http://udos.s3.amazonaws.com/blog/block_parsing_magic/MessageNotUnderstood_SQLColumn_gt.png" alt="Wallback; <code>MessageNotUnderstood: SQLExpression>>gt:</code>" title=""></p>
<p>We’ll get an Error message “<code>MessageNotUnderstood: SQLExpression>>gt:</code>“. So the next method we need is greater than. We’ll implement these using similar to <code>SQLTerm>>#is:</code>:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="pln">gt</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#> right: anObject</span><span class="pln">
</span><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="pln">gte</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#>= right: anObject</span><span class="pln">
</span><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="pln">lt</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#< right: anObject</span><span class="pln">
</span><span class="typ">SQLTerm</span><span class="pun">>>#</span><span class="pln">lte</span><span class="pun">:</span><span class="pln"> anObject
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">SQLExpression</span><span class="pln"> left</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> operand</span><span class="pun">:</span><span class="pln"> </span><span class="com">#<= right: anObject</span></code></pre>
<h3 id="done-1st-half">DONE! (1st half …)</h3>
<p>We made it! Our expression parses! Inspecting the result of our snippet in the inspector shows a nice graph of objects which we’ll use in the next step to create the SQL String. <br>
<img src="http://udos.s3.amazonaws.com/blog/block_parsing_magic/SQLExpression.png" alt="Parsed <code>SQLExpression</code>: Look Ma! Without any grammar!" title=""></p>
<h2 id="sql-generator">SQL Generator</h2>
<p>Now that we have a nice graph of objects let’s try to create the SQL string from it: Implement the messages <code>#sqlString</code> and <code>#printSqlOn:</code> in <code>SQLComponent</code> which should be implemented by all subclasses:</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLComponent</span><span class="pun">>#</span><span class="pln">sqlString
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> streamContents</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">stream </span><span class="pun">|</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> printSqlOn</span><span class="pun">:</span><span class="pln"> stream </span><span class="pun">]</span><span class="pln">
</span><span class="typ">SQLComponent</span><span class="pun">>#</span><span class="pln">printSqlOn</span><span class="pun">:</span><span class="pln"> aStream
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> subclassResponsibility</span></code></pre>
<p>Now let’s try our “implement until next error” approach again using the following code:</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">|</span><span class="pln"> selectBlock table expression </span><span class="pun">|</span><span class="pln">
selectBlock </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln">
</span><span class="pun">((</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">and</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">customer bonusPoints gt</span><span class="pun">:</span><span class="pln"> customer joinDate year</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customer joinDate year </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pln"> today year</span><span class="pun">))</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
table </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">SQLTable</span><span class="pln"> named</span><span class="pun">:</span><span class="pln"> </span><span class="str">'customers'</span><span class="pun">.</span><span class="pln">
expression </span><span class="pun">:=</span><span class="pln"> selectBlock value</span><span class="pun">:</span><span class="pln"> table</span><span class="pun">.</span><span class="pln"> </span><span class="str">"Inspect-it"</span><span class="pln">
expression sqlString </span><span class="str">"Inspect-It"</span></code></pre>
<p>We’ll get an error “<code>SubclassResponsibility: SQLExpression had the subclass responsibility to implement #printSqlOn:</code>“: <br>
<img src="http://udos.s3.amazonaws.com/blog/block_parsing_magic/SubclassResponsibility%20SQLExpression%20had%20the%20subclass%20responsibility%20to%20implement_printSqlOn.png" alt="<code>SubclassResponsibility: SQLExpression had the subclass responsibility to implement #printSqlOn:</code>" title=""></p>
<p><em>So Pharo is telling us <strong>exactly</strong> what to do next</em>. From now on we’ll simply implement <code>#printSqlOn:</code> in all the classes until we finally get the string without error.</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLExpression</span><span class="pun">>>#</span><span class="pln">printSqlOn</span><span class="pun">:</span><span class="pln"> aStream
aStream nextPut</span><span class="pun">:</span><span class="pln"> $</span><span class="pun">(.</span><span class="pln">
left printSqlOn</span><span class="pun">:</span><span class="pln"> aStream</span><span class="pun">.</span><span class="pln">
aStream
space</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln"> operand</span><span class="pun">;</span><span class="pln">
space</span><span class="pun">.</span><span class="pln">
right printSqlOn</span><span class="pun">:</span><span class="pln"> aStream</span><span class="pun">.</span><span class="pln">
aStream nextPut</span><span class="pun">:</span><span class="pln"> $</span><span class="pun">)</span></code></pre>
<p>As you can see we simply output the information either directly or by delegating <code>#printSqlOn:</code> to child nodes.</p>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLColumn</span><span class="pun">>>#</span><span class="pln">printSqlOn</span><span class="pun">:</span><span class="pln"> aStream
table printSqlOn</span><span class="pun">:</span><span class="pln"> aStream</span><span class="pun">.</span><span class="pln">
aStream
nextPut</span><span class="pun">:</span><span class="pln"> $</span><span class="pun">.;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln"> name</span></code></pre>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLTable</span><span class="pun">>>#</span><span class="pln">printSqlOn</span><span class="pun">:</span><span class="pln"> aStream
aStream nextPutAll</span><span class="pun">:</span><span class="pln"> name</span></code></pre>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLConstant</span><span class="pun">>>#</span><span class="pln">printSqlOn</span><span class="pun">:</span><span class="pln"> aStream
aStream </span><span class="kwd">print</span><span class="pun">:</span><span class="pln"> value</span></code></pre>
<pre class="prettyprint prettyprinted"><code><span class="typ">SQLFunction</span><span class="pun">>>#</span><span class="pln">printSqlOn</span><span class="pun">:</span><span class="pln"> aStream
aStream
nextPutAll</span><span class="pun">:</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
nextPut</span><span class="pun">:</span><span class="pln"> $</span><span class="pun">(.</span><span class="pln">
term printSqlOn</span><span class="pun">:</span><span class="pln"> aStream</span><span class="pun">.</span><span class="pln">
aStream nextPut</span><span class="pun">:</span><span class="pln"> $</span><span class="pun">)</span></code></pre>
<h3 id="done">Done!</h3>
<p>Finally our translator works and yields</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">(((</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">surname </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">surname </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">((</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">bonusPoints </span><span class="pun">></span><span class="pln"> YEAR</span><span class="pun">(</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">joinDate</span><span class="pun">))</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">YEAR</span><span class="pun">(</span><span class="pln">customers</span><span class="pun">.</span><span class="pln">joinDate</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2014</span><span class="pun">)))</span></code></pre>
<p>Cool, eh?</p>
<h2 id="summary">Summary</h2>
<p>I hope I was able to show you (in an understandable way?) how to use “Block Parsers/Translators” to parse Smalltalk expressions and translate them into something “different”. I know that this example is neither comprehensive nor production ready. In a production setup you’d have to think a lot more about different subclasses e.g. for constants, functions … even if it’s “just” for printing constants correctly. But the skeleton should be the same.</p>
<h2 id="limitationsnotes">Limitations/Notes</h2>
<h3 id="method-names">Method names</h3>
<p>Overriding some methods (esp. <code>#=</code>) is a pretty bad idea. I agree that <code>customer name = 'Schneider'</code>is easier to read and write than <code>customer name is: 'Schneider'</code> - but trust me. Overriding <code>#=</code> with different semantics is a sure recipe for disaster!</p>
<p>You should also be careful with “<code>Boolean</code>-ish” methods like <code>#and:</code>, <code>#or:</code>, <code>#ifTrue:</code>. These methods are sometimes inlined by the compiler and you’ll get warnings about one of the operands being a non-<code>Boolean</code>. </p>
<h3 id="order-of-expressions">Order of expressions</h3>
<p>The whole approach bases on the idea of intercepting messages sent <em>to</em> an object (to be able to respond with “another” intercepting object). So make sure that in each and every expression the objects you put into the block (or derivates thereof) are always the recieving objects (left side in operations). Everything else will fail.</p>
<p>Two expressions might be semantically identical/equal in Smalltalk yet yield different results when used with Block Parsers. E.g.:</p>
<pre class="prettyprint prettyprinted"><code><span class="pln">table </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">SQLTable</span><span class="pln"> named</span><span class="pun">:</span><span class="pln"> </span><span class="str">'customers'</span><span class="pun">.</span><span class="pln">
</span><span class="str">"Both blocks are semantically equal in Smalltalk ..."</span><span class="pln">
block1 </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln"> customer age </span><span class="pun">></span><span class="pln"> </span><span class="lit">23</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
block2 </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln"> </span><span class="lit">23</span><span class="pln"> </span><span class="pun">></span><span class="pln"> customer age </span><span class="pun">].</span><span class="pln">
</span><span class="str">"But not when used to parse!"</span><span class="pln">
</span><span class="typ">String</span><span class="pln"> streamContents</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">stream </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">block1 value</span><span class="pun">:</span><span class="pln"> table</span><span class="pun">)</span><span class="pln"> printSqlOn</span><span class="pun">:</span><span class="pln"> stream </span><span class="pun">].</span><span class="pln"> </span><span class="str">'(customers.age > 23)'</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="typ">String</span><span class="pln"> streamContents</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">stream </span><span class="pun">|</span><span class="pln"> </span><span class="pun">(</span><span class="pln">block2 value</span><span class="pun">:</span><span class="pln"> table</span><span class="pun">)</span><span class="pln"> printSqlOn</span><span class="pun">:</span><span class="pln"> stream </span><span class="pun">].</span><span class="pln"> </span><span class="str">"Error: SQLColumn(Object)>>doesNotUnderstand: #adaptToNumber:andSend:"</span></code></pre>
<h3 id="expressions-only-mostly">Expressions only! … mostly …</h3>
<p>This approach does work fine if you want to translate an expression - even a compound one. Expressions (e.g. for filtering) are traditionally used for Collection messages like <code>#select:</code>. So something like this works fine (note the temporal variables):</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">|</span><span class="pln"> selectBlock table expression </span><span class="pun">|</span><span class="pln">
selectBlock </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> surname joinDate </span><span class="pun">|</span><span class="pln">
surname </span><span class="pun">:=</span><span class="pln"> customer surname</span><span class="pun">.</span><span class="pln">
joinDate </span><span class="pun">:=</span><span class="pln"> customer joinDate</span><span class="pun">.</span><span class="pln">
</span><span class="pun">((</span><span class="pln">surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pun">))</span><span class="pln">
</span><span class="kwd">and</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">customer bonusPoints gt</span><span class="pun">:</span><span class="pln"> joinDate year</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="pln">joinDate year </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Date</span><span class="pln"> today year</span><span class="pun">))</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
table </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">SQLTable</span><span class="pln"> named</span><span class="pun">:</span><span class="pln"> </span><span class="str">'customers'</span><span class="pun">.</span><span class="pln">
expression </span><span class="pun">:=</span><span class="pln"> selectBlock value</span><span class="pun">:</span><span class="pln"> table</span><span class="pun">.</span><span class="pln"> </span><span class="str">"Inspect-it"</span><span class="pln">
expression sqlString </span><span class="str">"Inspect-It"</span></code></pre>
<p>Something like this won’t work (as expected?):</p>
<pre class="prettyprint prettyprinted"><code><span class="pun">|</span><span class="pln"> selectBlock table expression </span><span class="pun">|</span><span class="pln">
selectBlock </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">customer </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> surname </span><span class="pun">|</span><span class="pln">
surname </span><span class="pun">:=</span><span class="pln"> customer surname</span><span class="pun">.</span><span class="pln">
surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Schneider'</span><span class="pun">.</span><span class="pln">
surname </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Mueller'</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
table </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">SQLTable</span><span class="pln"> named</span><span class="pun">:</span><span class="pln"> </span><span class="str">'customers'</span><span class="pun">.</span><span class="pln">
expression </span><span class="pun">:=</span><span class="pln"> selectBlock value</span><span class="pun">:</span><span class="pln"> table</span><span class="pun">.</span><span class="pln"> </span><span class="str">"Inspect-it"</span><span class="pln">
expression sqlString </span><span class="str">"Inspect-It"</span><span class="pln"> </span><span class="str">" (customers.surname = 'Mueller')'"</span></code></pre>
<p>Only the expression for the second use <code>surname is: 'Mueller'</code> is returned an can be translated. You can of course use a builder in the background and record “new” expressions - i.e. if the initial object passed in receives a message. But that’s not 100% safe - especially if you didn’t refactor all temp variables.</p>
<p>But if you stick to expressions in Blocks (although it also works fine for expressions in methods!) it’s more likely to not hit that limitation.</p>
<h3 id="priort-art">Priort Art</h3>
<p>By no means did I invent this stuff! … that’s at least what I think. Based on frameworks I worked with and some feedback I got I’m aware of at least two places, where this approach has been used before:</p>
<ul>
<li><a href="http://glorpwiki.wikispaces.com/home">GLORP</a></li>
<li><a href="http://www.solutionsoft.co.uk/restore/manual/querying1.htm">ReStore</a></li>
</ul>
<p>AFAIK both frameworks use a similar approach to create SQL queries from Smalltalk blocks.</p>
<blockquote>
<p>Written with <a href="https://stackedit.io/">StackEdit</a>.</p>
</blockquote>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-81718889122719790292014-08-08T23:50:00.001+02:002014-08-11T17:58:44.852+02:00Replacing Floating Point multiplication with Integer shifting (or ... "optimization witchcraft")<p><strong>Updated 2014/08/09 <a href="#Update">(see update)</a></strong></p>
<blockquote>
<p><strong>NOTE:</strong> Throughout this article I try to use lowercase names (i.e. <code>float</code> or <code>integer</code>) for the types and uppercase names (i.e. <code>Float</code> or <code>Integer</code>) for class names.</p>
</blockquote>
<p>I’m currently working with some professional vision mixers and one of the tasks is loading & saving image from and to the mixer. And the mixer expects all in 8-bit (4:2:2) encoded YCbCr. Converting between RGB and YCbCr is pretty straight forward using some transformation matrices:</p>
<p><span class="MathJax_Preview"></span><div class="MathJax_Display" role="textbox" aria-readonly="true" style="text-align: center;"><span class="MathJax" id="MathJax-Element-91-Frame"><nobr><span class="math" id="MathJax-Span-1827" style="width: 25.446em; display: inline-block;"><span style="display: inline-block; position: relative; width: 21.018em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(2.187em 1000.003em 5.965em -0.528em); top: -4.306em; left: 0.003em;"><span class="mrow" id="MathJax-Span-1828"><span class="mrow" id="MathJax-Span-1829"><span class="mo" id="MathJax-Span-1830" style="vertical-align: 1.951em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; font-family: STIXSizeOneSym; top: -3.303em; left: 0.003em;">⎡<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; font-family: STIXSizeOneSym; top: -0.942em; left: 0.003em;">⎣<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -2.535em; left: 0.003em;">⎢<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -1.709em; left: 0.003em;">⎢<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span></span><span class="mtable" id="MathJax-Span-1831" style="padding-right: 0.18em; padding-left: 0.18em;"><span style="display: inline-block; position: relative; width: 0.77em; height: 0px;"><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.528em); top: -4.07em; left: 0.003em;"><span style="display: inline-block; position: relative; width: 0.77em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -3.657em; left: 50%; margin-left: -0.292em;"><span class="mtd" id="MathJax-Span-1832"><span class="mrow" id="MathJax-Span-1833"><span class="mi" id="MathJax-Span-1834" style="font-family: STIXGeneral-Italic;">R</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -2.476em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-1835"><span class="mrow" id="MathJax-Span-1836"><span class="mi" id="MathJax-Span-1837" style="font-family: STIXGeneral-Italic;">G</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -1.296em; left: 50%; margin-left: -0.292em;"><span class="mtd" id="MathJax-Span-1838"><span class="mrow" id="MathJax-Span-1839"><span class="mi" id="MathJax-Span-1840" style="font-family: STIXGeneral-Italic;">B</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span></span></span><span class="mo" id="MathJax-Span-1841" style="vertical-align: 1.951em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; font-family: STIXSizeOneSym; top: -3.303em; left: 0.003em;">⎤<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; font-family: STIXSizeOneSym; top: -0.942em; left: 0.003em;">⎦<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -2.535em; left: 0.003em;">⎥<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -1.709em; left: 0.003em;">⎥<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span></span></span><span class="mo" id="MathJax-Span-1842" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mrow" id="MathJax-Span-1843" style="padding-left: 0.298em;"><span class="mo" id="MathJax-Span-1844" style="vertical-align: 1.951em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; font-family: STIXSizeOneSym; top: -3.303em; left: 0.003em;">⎡<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; font-family: STIXSizeOneSym; top: -0.942em; left: 0.003em;">⎣<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -2.535em; left: 0.003em;">⎢<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -1.709em; left: 0.003em;">⎢<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span></span><span class="mtable" id="MathJax-Span-1845" style="padding-right: 0.18em; padding-left: 0.18em;"><span style="display: inline-block; position: relative; width: 10.452em; height: 0px;"><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.41em); top: -4.07em; left: 0.003em;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -3.657em; left: 50%; margin-left: -1.119em;"><span class="mtd" id="MathJax-Span-1846"><span class="mrow" id="MathJax-Span-1847"><span class="mn" id="MathJax-Span-1848" style="font-family: STIXGeneral-Regular;">1.164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.476em; left: 50%; margin-left: -1.119em;"><span class="mtd" id="MathJax-Span-1855"><span class="mrow" id="MathJax-Span-1856"><span class="mn" id="MathJax-Span-1857" style="font-family: STIXGeneral-Regular;">1.164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -1.296em; left: 50%; margin-left: -1.119em;"><span class="mtd" id="MathJax-Span-1866"><span class="mrow" id="MathJax-Span-1867"><span class="mn" id="MathJax-Span-1868" style="font-family: STIXGeneral-Regular;">1.164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.528em); top: -4.07em; left: 3.427em;"><span style="display: inline-block; position: relative; width: 2.955em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -3.657em; left: 50%; margin-left: -0.233em;"><span class="mtd" id="MathJax-Span-1849"><span class="mrow" id="MathJax-Span-1850"><span class="mn" id="MathJax-Span-1851" style="font-family: STIXGeneral-Regular;">0</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -2.476em; left: 50%; margin-left: -1.473em;"><span class="mtd" id="MathJax-Span-1858"><span class="mrow" id="MathJax-Span-1859"><span class="mo" id="MathJax-Span-1860" style="font-family: STIXGeneral-Regular;">−</span><span class="mn" id="MathJax-Span-1861" style="font-family: STIXGeneral-Regular;">0.392</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -1.296em; left: 50%; margin-left: -1.119em;"><span class="mtd" id="MathJax-Span-1869"><span class="mrow" id="MathJax-Span-1870"><span class="mn" id="MathJax-Span-1871" style="font-family: STIXGeneral-Regular;">2.017</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.528em); top: -4.07em; left: 7.5em;"><span style="display: inline-block; position: relative; width: 2.955em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -3.657em; left: 50%; margin-left: -1.119em;"><span class="mtd" id="MathJax-Span-1852"><span class="mrow" id="MathJax-Span-1853"><span class="mn" id="MathJax-Span-1854" style="font-family: STIXGeneral-Regular;">1.596</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -2.476em; left: 50%; margin-left: -1.473em;"><span class="mtd" id="MathJax-Span-1862"><span class="mrow" id="MathJax-Span-1863"><span class="mo" id="MathJax-Span-1864" style="font-family: STIXGeneral-Regular;">−</span><span class="mn" id="MathJax-Span-1865" style="font-family: STIXGeneral-Regular;">0.813</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -1.296em; left: 50%; margin-left: -0.233em;"><span class="mtd" id="MathJax-Span-1872"><span class="mrow" id="MathJax-Span-1873"><span class="mn" id="MathJax-Span-1874" style="font-family: STIXGeneral-Regular;">0</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span></span></span><span class="mo" id="MathJax-Span-1875" style="vertical-align: 1.951em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; font-family: STIXSizeOneSym; top: -3.303em; left: 0.003em;">⎤<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; font-family: STIXSizeOneSym; top: -0.942em; left: 0.003em;">⎦<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -2.535em; left: 0.003em;">⎥<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -1.709em; left: 0.003em;">⎥<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span></span></span><span class="mo" id="MathJax-Span-1876" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mrow" id="MathJax-Span-1877" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-1878" style="vertical-align: 1.951em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; font-family: STIXSizeOneSym; top: -3.303em; left: 0.003em;">⎡<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; font-family: STIXSizeOneSym; top: -0.942em; left: 0.003em;">⎣<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -2.535em; left: 0.003em;">⎢<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -1.709em; left: 0.003em;">⎢<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span></span><span class="mtable" id="MathJax-Span-1879" style="padding-right: 0.18em; padding-left: 0.18em;"><span style="display: inline-block; position: relative; width: 3.84em; height: 0px;"><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.469em); top: -4.07em; left: 0.003em;"><span style="display: inline-block; position: relative; width: 3.84em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -3.657em; left: 50%; margin-left: -1.414em;"><span class="mtd" id="MathJax-Span-1880"><span class="mrow" id="MathJax-Span-1881"><span class="mi" id="MathJax-Span-1882" style="font-family: STIXGeneral-Italic;">Y<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.062em;"></span></span><span class="mo" id="MathJax-Span-1883" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">−</span><span class="mn" id="MathJax-Span-1884" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">16</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -2.476em; left: 50%; margin-left: -1.886em;"><span class="mtd" id="MathJax-Span-1885"><span class="mrow" id="MathJax-Span-1886"><span class="mi" id="MathJax-Span-1887" style="font-family: STIXGeneral-Italic;">C<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mi" id="MathJax-Span-1888" style="font-family: STIXGeneral-Italic;">b</span><span class="mo" id="MathJax-Span-1889" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">−</span><span class="mn" id="MathJax-Span-1890" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">128</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -1.296em; left: 50%; margin-left: -1.827em;"><span class="mtd" id="MathJax-Span-1891"><span class="mrow" id="MathJax-Span-1892"><span class="mi" id="MathJax-Span-1893" style="font-family: STIXGeneral-Italic;">C<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mi" id="MathJax-Span-1894" style="font-family: STIXGeneral-Italic;">r<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1895" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">−</span><span class="mn" id="MathJax-Span-1896" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">128</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span></span></span><span class="mo" id="MathJax-Span-1897" style="vertical-align: 1.951em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; font-family: STIXSizeOneSym; top: -3.303em; left: 0.003em;">⎤<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; font-family: STIXSizeOneSym; top: -0.942em; left: 0.003em;">⎦<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -2.535em; left: 0.003em;">⎥<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="font-family: STIXSizeOneSym; position: absolute; top: -1.709em; left: 0.003em;">⎥<span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.312em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 4.289em; vertical-align: -1.854em;"></span></span></nobr></span></div><script type="math/tex; mode=display" id="MathJax-Element-91">
\left[ \begin{matrix}
R \\ G \\ B
\end{matrix} \right] =
\left[ \begin{matrix}
1.164 & 0 & 1.596 \\
1.164 & -0.392 & -0.813 \\
1.164 & 2.017 & 0 \\
\end{matrix} \right] \cdot
\left[ \begin{matrix}
Y-16 \\
Cb -128 \\
Cr-128 \end{matrix} \right]
</script></p><div class="se-section-delimiter"></div>
<pre class="prettyprint prettyprinted"><code><span class="pln">floatRgbFromY</span><span class="pun">:</span><span class="pln"> y </span><span class="typ">Cb</span><span class="pun">:</span><span class="pln"> cb </span><span class="typ">Cr</span><span class="pun">:</span><span class="pln"> cr
</span><span class="str">"YCrCb to RGB
RGB 0-255
Y 16-235
CbCr 16-240"</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> r g b </span><span class="pun">|</span><span class="pln">
r </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y </span><span class="pun">-</span><span class="pln"> </span><span class="lit">16</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.164</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">((</span><span class="pln">cr </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.793</span><span class="pun">).</span><span class="pln">
g </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y </span><span class="pun">-</span><span class="pln"> </span><span class="lit">16</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.164</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">((</span><span class="pln">cb </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.213</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">((</span><span class="pln">cr </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.533</span><span class="pun">).</span><span class="pln">
b </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y </span><span class="pun">-</span><span class="pln"> </span><span class="lit">16</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.164</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">((</span><span class="pln">cb </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2.112</span><span class="pun">).</span><span class="pln">
</span><span class="pun">^</span><span class="pln"> </span><span class="pun">{</span><span class="pln">r</span><span class="pun">.</span><span class="pln">g</span><span class="pun">.</span><span class="pln">b</span><span class="pun">}</span></code></pre>
<p>However using this code to convert a 1280x720 image from YCbCr takes around 20 seconds on my machine … not really fast. After some surfing I found a two different ways to convert the data - both of which where a bit and much faster:</p>
<pre class="prettyprint prettyprinted"><code><span class="pln">integerRgbFromY</span><span class="pun">:</span><span class="pln"> y </span><span class="typ">Cb</span><span class="pun">:</span><span class="pln"> cb </span><span class="typ">Cr</span><span class="pun">:</span><span class="pln"> cr
</span><span class="str">"YCrCb to RGB
RGB 0-255
Y 16-235
CbCr 16-240"</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ym cbm crm r g b </span><span class="pun">|</span><span class="pln">
ym </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">y </span><span class="pun">-</span><span class="pln"> </span><span class="lit">16</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">149</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">128.</span><span class="pln">
cbm </span><span class="pun">:=</span><span class="pln"> cb </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128.</span><span class="pln">
crm </span><span class="pun">:=</span><span class="pln"> cr </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128.</span><span class="pln">
r </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">crm </span><span class="pun">*</span><span class="pln"> </span><span class="lit">459</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">256</span><span class="pun">).</span><span class="pln">
g </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">*</span><span class="pln"> </span><span class="lit">109</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">512</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="pln">crm </span><span class="pun">*</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">32</span><span class="pun">).</span><span class="pln">
b </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">*</span><span class="pln"> </span><span class="lit">135</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">64</span><span class="pun">).</span><span class="pln">
</span><span class="pun">^</span><span class="pln"> </span><span class="pun">{</span><span class="pln">r</span><span class="pun">.</span><span class="pln">g</span><span class="pun">.</span><span class="pln">b</span><span class="pun">}</span></code></pre>
<pre class="prettyprint prettyprinted"><code><span class="pln">shiftRgbFromY</span><span class="pun">:</span><span class="pln"> y </span><span class="typ">Cb</span><span class="pun">:</span><span class="pln"> cb </span><span class="typ">Cr</span><span class="pun">:</span><span class="pln"> cr
</span><span class="str">"YCrCb to RGB
RGB 0-255
Y 16-235
CbCr 16-240"</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> ym r g b cbm crm </span><span class="pun">|</span><span class="pln">
ym </span><span class="pun">:=</span><span class="pln"> y </span><span class="pun">-</span><span class="pln"> </span><span class="lit">16.</span><span class="pln">
ym </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ym </span><span class="pun">>></span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ym </span><span class="pun">>></span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ym </span><span class="pun">>></span><span class="pln"> </span><span class="lit">7</span><span class="pun">).</span><span class="pln">
cbm </span><span class="pun">:=</span><span class="pln"> cb </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128.</span><span class="pln">
crm </span><span class="pun">:=</span><span class="pln"> cr </span><span class="pun">-</span><span class="pln"> </span><span class="lit">128.</span><span class="pln">
r </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">+</span><span class="pln"> crm </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">crm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">crm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">4</span><span class="pun">).</span><span class="pln">
g </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">-</span><span class="pln"> </span><span class="pun">((</span><span class="pln">cbm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">5</span><span class="pun">))</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">((</span><span class="pln">crm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">crm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">5</span><span class="pun">)).</span><span class="pln">
b </span><span class="pun">:=</span><span class="pln"> ym </span><span class="pun">+</span><span class="pln"> </span><span class="pun">((</span><span class="pln">cbm </span><span class="pun"><<</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cbm </span><span class="pun">>></span><span class="pln"> </span><span class="lit">6</span><span class="pun">)).</span><span class="pln">
</span><span class="pun">^</span><span class="pln"> </span><span class="pun">{</span><span class="pln">r</span><span class="pun">.</span><span class="pln">g</span><span class="pun">.</span><span class="pln">b</span><span class="pun">}</span></code></pre>
<p>To be honest I thought I understood the integer approach but had no idea how the shift approach worked. Still the results were the same numerically - just a lot faster. So I my adventure into “Integer witchcraft” started and I decided to keep my findings here in the blog.</p>
<p>I’ll start with a simple example. Lets take the term <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-69-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-999" style="width: 4.253em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.486em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-1000"><span class="mi" id="MathJax-Span-1001" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1002" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-1003" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-69"> x \cdot 1.164</script>. This is obviously a term which requires floating point operations. Lets try to convert it into an <code>integer</code>shift(s) expression step by step.</p>
<h2 id="eliminate-floating-point-numbers-using-powers-of-10">Eliminate floating point numbers (using powers of 10)</h2>
<p>The <code>float</code> <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-70-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-1004" style="width: 2.777em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-1005"><span class="mn" id="MathJax-Span-1006" style="font-family: STIXGeneral-Regular;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-70">1.164</script> is something we want to eliminate. Because it has a limited number of decimal places it’s easy to rewrite it as a combination of one multiplication and one division. I.e. </p>
<p><span class="MathJax_Preview"></span><div class="MathJax_Display" role="textbox" aria-readonly="true" style="text-align: center;"><span class="MathJax" id="MathJax-Element-71-Frame"><nobr><span class="math" id="MathJax-Span-1007" style="width: 28.279em; display: inline-block;"><span style="display: inline-block; position: relative; width: 23.38em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.006em 1000.003em 3.427em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-1008"><span class="mi" id="MathJax-Span-1009" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1010" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-1011" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span><span class="mo" id="MathJax-Span-1012" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mi" id="MathJax-Span-1013" style="font-family: STIXGeneral-Italic; padding-left: 0.298em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1014" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mfrac" id="MathJax-Span-1015" style="padding-left: 0.357em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 2.128em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -3.185em; left: 50%; margin-left: -1.001em;"><span class="mn" id="MathJax-Span-1016" style="font-family: STIXGeneral-Regular;">1164</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.41em); top: -1.827em; left: 50%; margin-left: -1.001em;"><span class="mn" id="MathJax-Span-1017" style="font-family: STIXGeneral-Regular;">1000</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 2.128em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-1018" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mi" id="MathJax-Span-1019" style="font-family: STIXGeneral-Italic; padding-left: 0.298em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1020" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-1021" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1164</span><span class="mo" id="MathJax-Span-1022" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-1023" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1000</span><span class="mo" id="MathJax-Span-1024" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mi" id="MathJax-Span-1025" style="font-family: STIXGeneral-Italic; padding-left: 0.298em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1026" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-1027" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1000</span><span class="mo" id="MathJax-Span-1028" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-1029" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 2.646em; vertical-align: -0.925em;"></span></span></nobr></span></div><script type="math/tex; mode=display" id="MathJax-Element-71">
x \cdot 1.164 = x \cdot \frac{1164}{1000} = x \cdot 1164 \div 1000 = x \div 1000 \cdot 1164
</script></p>
<p>The last two terms are mathematically equal – however if you work in a language where <code>integer</code>operations do not coerce to floats “automagically” (e.g. C or Ruby) you my want to multiply first. Why? Let’s assume <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-72-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-1030" style="width: 3.368em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.777em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-1031"><span class="mi" id="MathJax-Span-1032" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1033" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mn" id="MathJax-Span-1034" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">10</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-72">x=10</script> then <br>
<span class="MathJax_Preview"></span><div class="MathJax_Display" role="textbox" aria-readonly="true" style="text-align: center;"><span class="MathJax" id="MathJax-Element-73-Frame"><nobr><span class="math" id="MathJax-Span-1035" style="width: 31.172em; display: inline-block;"><span style="display: inline-block; position: relative; width: 25.741em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(-0.587em 1000.003em 4.371em -0.292em); top: -2.122em; left: 0.003em;"><span class="mrow" id="MathJax-Span-1036"><span class="mtable" id="MathJax-Span-1037" style="padding-right: 0.18em; padding-left: 0.18em;"><span style="display: inline-block; position: relative; width: 25.328em; height: 0px;"><span style="position: absolute; clip: rect(2.896em 1000.003em 7.677em -0.469em); top: -5.487em; left: 0.003em;"><span style="display: inline-block; position: relative; width: 11.986em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -4.306em; right: 0.003em;"><span class="mtd" id="MathJax-Span-1038"><span class="mrow" id="MathJax-Span-1039"><span class="mo" id="MathJax-Span-1040" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1041" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1042" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1043" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1044" style="font-family: STIXGeneral-Regular;">)</span><span class="mi" id="MathJax-Span-1045" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1046" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mo" id="MathJax-Span-1047" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1048" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1049" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1050" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1051" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1052" style="font-family: STIXGeneral-Regular;">1000</span><span class="mo" id="MathJax-Span-1053" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-1054" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1055" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1056" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1057" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1058" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1059" style="font-family: STIXGeneral-Regular;">1164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -3.067em; right: 0.003em;"><span class="mtd" id="MathJax-Span-1085"><span class="mrow" id="MathJax-Span-1086"><span class="mo" id="MathJax-Span-1087" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1088" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1089" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1090" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1091" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1092" style="font-family: STIXGeneral-Regular;">10</span><span class="mo" id="MathJax-Span-1093" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mo" id="MathJax-Span-1094" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1095" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1096" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1097" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1098" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1099" style="font-family: STIXGeneral-Regular;">1000</span><span class="mo" id="MathJax-Span-1100" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-1101" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1102" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1103" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1104" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1105" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1106" style="font-family: STIXGeneral-Regular;">1164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -1.886em; right: 0.003em;"><span class="mtd" id="MathJax-Span-1132"><span class="mrow" id="MathJax-Span-1133"><span class="mo" id="MathJax-Span-1134" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1135" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1136" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1137" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1138" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1139" style="font-family: STIXGeneral-Regular;">0</span><span class="mo" id="MathJax-Span-1140" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-1141" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1142" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1143" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1144" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1145" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1146" style="font-family: STIXGeneral-Regular;">1164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.469em); top: -0.705em; right: 0.003em;"><span class="mtd" id="MathJax-Span-1165"><span class="mrow" id="MathJax-Span-1166"><span class="mo" id="MathJax-Span-1167" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1168" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1169" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1170" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1171" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1172" style="font-family: STIXGeneral-Regular;">0</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 5.493em;"></span></span><span style="position: absolute; clip: rect(2.836em 1000.003em 7.618em -0.469em); top: -5.428em; left: 12.282em;"><span style="display: inline-block; position: relative; width: 0.711em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.469em); top: -4.306em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-1060"><span class="mrow" id="MathJax-Span-1061"><span class="mo" id="MathJax-Span-1062" style="font-family: STIXGeneral-Regular;">≠</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.469em); top: -3.067em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-1107"><span class="mrow" id="MathJax-Span-1108"><span class="mo" id="MathJax-Span-1109" style="font-family: STIXGeneral-Regular;">≠</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.469em); top: -1.886em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-1147"><span class="mrow" id="MathJax-Span-1148"><span class="mo" id="MathJax-Span-1149" style="font-family: STIXGeneral-Regular;">≠</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.469em); top: -0.705em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-1173"><span class="mrow" id="MathJax-Span-1174"><span class="mo" id="MathJax-Span-1175" style="font-family: STIXGeneral-Regular;">≠</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 5.434em;"></span></span><span style="position: absolute; clip: rect(2.896em 1000.003em 7.677em -0.469em); top: -5.487em; left: 13.344em;"><span style="display: inline-block; position: relative; width: 11.986em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -4.306em; left: 0.003em;"><span class="mtd" id="MathJax-Span-1063"><span class="mrow" id="MathJax-Span-1064"><span class="mo" id="MathJax-Span-1065" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1066" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1067" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1068" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1069" style="font-family: STIXGeneral-Regular;">)</span><span class="mi" id="MathJax-Span-1070" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1071" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-1072" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1073" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1074" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1075" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1076" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1077" style="font-family: STIXGeneral-Regular;">1164</span><span class="mo" id="MathJax-Span-1078" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mo" id="MathJax-Span-1079" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1080" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1081" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1082" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1083" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1084" style="font-family: STIXGeneral-Regular;">1000</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -3.067em; left: 0.003em;"><span class="mtd" id="MathJax-Span-1110"><span class="mrow" id="MathJax-Span-1111"><span class="mo" id="MathJax-Span-1112" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1113" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1114" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1115" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1116" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1117" style="font-family: STIXGeneral-Regular;">10</span><span class="mo" id="MathJax-Span-1118" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-1119" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1120" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1121" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1122" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1123" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1124" style="font-family: STIXGeneral-Regular;">1164</span><span class="mo" id="MathJax-Span-1125" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mo" id="MathJax-Span-1126" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1127" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1128" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1129" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1130" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1131" style="font-family: STIXGeneral-Regular;">1000</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -1.886em; left: 0.003em;"><span class="mtd" id="MathJax-Span-1150"><span class="mrow" id="MathJax-Span-1151"><span class="mo" id="MathJax-Span-1152" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1153" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1154" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1155" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1156" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1157" style="font-family: STIXGeneral-Regular;">11640</span><span class="mo" id="MathJax-Span-1158" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mo" id="MathJax-Span-1159" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-1160" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1161" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1162" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1163" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1164" style="font-family: STIXGeneral-Regular;">1000</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.469em); top: -0.705em; left: 0.003em;"><span class="mtd" id="MathJax-Span-1176"><span class="mrow" id="MathJax-Span-1177"><span class="mo" id="MathJax-Span-1178" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-1179" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-1180" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-1181" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-1182" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-1183" style="font-family: STIXGeneral-Regular;">11</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 5.493em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.128em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 5.718em; vertical-align: -2.568em;"></span></span></nobr></span></div><script type="math/tex; mode=display" id="MathJax-Element-73">
\begin{eqnarray}
(int)x \div (int)1000 \cdot (int)1164 & \neq & (int)x \cdot (int)1164 \div (int)1000 \\
(int)10 \div (int)1000 \cdot (int)1164 & \neq & (int)10 \cdot (int)1164 \div (int)1000 \\
(int)0 \cdot (int)1164 & \neq & (int)11640 \div (int)1000 \\
(int)0 & \neq & (int)11 \\
\end{eqnarray}
</script></p>
<p>So multiplying first doesn’t hurt in Smalltalk (unless you sprinkle in a lot of <code>asInteger</code> calls) or other languages which automatically coerce to <code>float</code>s if needed … but might safe your bu.. in C, Ruby and maybe a few others.</p><div class="se-section-delimiter"></div>
<h2 id="eliminate-floating-point-numbers-using-powers-of-2">Eliminate floating point numbers (using powers of 2)</h2>
<p>Instead of using powers of 10 we can also use powers of 2. This will allow us to convert the expression <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-7-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-188" style="width: 4.253em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.486em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-189"><span class="mi" id="MathJax-Span-190" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-191" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-192" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-7">x \cdot 1.164</script> into an Integer-only/shifting expression.</p>
<blockquote>
<p>We can use any power of 2 – but let’s just use 32 (<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-8-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-193" style="width: 1.245em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.059em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.059em 1000.003em 2.301em -0.556em); top: -2.109em; left: 0.003em;"><span class="mrow" id="MathJax-Span-194"><span class="msubsup" id="MathJax-Span-195"><span style="display: inline-block; position: relative; width: 0.997em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-196" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="mn" id="MathJax-Span-197" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.115em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.146em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-8">2^5</script>) for now. We can/will/should/must use others as well; but that’s discussed later.</p>
</blockquote>
<p><span class="MathJax_Preview"></span><div class="MathJax_Display" role="textbox" aria-readonly="true" style="text-align: center;"><span class="MathJax" id="MathJax-Element-9-Frame"><nobr><span class="math" id="MathJax-Span-198" style="width: 30.109em; display: inline-block;"><span style="display: inline-block; position: relative; width: 24.855em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.006em 1000.003em 3.427em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-199"><span class="mi" id="MathJax-Span-200" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-201" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-202" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span><span class="mo" id="MathJax-Span-203" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mi" id="MathJax-Span-204" style="font-family: STIXGeneral-Italic; padding-left: 0.298em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-205" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-206" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span><span class="mo" id="MathJax-Span-207" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-208" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1</span><span class="mo" id="MathJax-Span-209" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mi" id="MathJax-Span-210" style="font-family: STIXGeneral-Italic; padding-left: 0.298em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-211" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-212" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span><span class="mo" id="MathJax-Span-213" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mfrac" id="MathJax-Span-214" style="padding-left: 0.357em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.125em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -3.185em; left: 50%; margin-left: -0.469em;"><span class="mn" id="MathJax-Span-215" style="font-family: STIXGeneral-Regular;">32</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -1.827em; left: 50%; margin-left: -0.469em;"><span class="mn" id="MathJax-Span-216" style="font-family: STIXGeneral-Regular;">32</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.125em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-217" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mi" id="MathJax-Span-218" style="font-family: STIXGeneral-Italic; padding-left: 0.298em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-219" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-220" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span><span class="mo" id="MathJax-Span-221" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-222" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span><span class="mo" id="MathJax-Span-223" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-224" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 2.646em; vertical-align: -0.925em;"></span></span></nobr></span></div><script type="math/tex; mode=display" id="MathJax-Element-9">
x \cdot 1.164 = x \cdot 1.164 \cdot 1 = x \cdot 1.164 \cdot \frac{32}{32} = x \cdot 1.164 \cdot 32 \div 32
</script></p>
<p><span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-10-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-225" style="width: 2.777em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-226"><span class="mn" id="MathJax-Span-227" style="font-family: STIXGeneral-Regular;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-10">1.164</script> is equal to <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-11-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-228" style="width: 7.382em; display: inline-block;"><span style="display: inline-block; position: relative; width: 6.083em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-229"><span class="mn" id="MathJax-Span-230" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-231" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-232" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span><span class="mo" id="MathJax-Span-233" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-234" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-11">1.164 \cdot 32 \div 32</script> and with a bit of integer magic we can come up with an <strong><code>integer</code></strong> expression which is “kind of” equal:</p>
<p><span class="MathJax_Preview"></span><div class="MathJax_Display" role="textbox" aria-readonly="true" style="text-align: center;"><span class="MathJax" id="MathJax-Element-12-Frame"><nobr><span class="math" id="MathJax-Span-235" style="width: 17.299em; display: inline-block;"><span style="display: inline-block; position: relative; width: 14.289em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(0.003em 1000.003em 3.781em -0.351em); top: -2.122em; left: 0.003em;"><span class="mrow" id="MathJax-Span-236"><span class="mtable" id="MathJax-Span-237" style="padding-right: 0.18em; padding-left: 0.18em;"><span style="display: inline-block; position: relative; width: 13.875em; height: 0px;"><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.528em); top: -4.07em; left: 0.003em;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -3.716em; right: 0.003em;"><span class="mtd" id="MathJax-Span-238"><span class="mrow" id="MathJax-Span-239"><span class="mn" id="MathJax-Span-240" style="font-family: STIXGeneral-Regular;">1.164</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: -3.952em; right: 0.003em;"><span class="mtd" id="MathJax-Span-251"><span class="mrow" id="MathJax-Span-252"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: -2.772em; right: 0.003em;"><span class="mtd" id="MathJax-Span-275"><span class="mrow" id="MathJax-Span-276"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span><span style="position: absolute; clip: rect(2.305em 1000.003em 5.434em -0.469em); top: -4.011em; left: 2.6em;"><span style="display: inline-block; position: relative; width: 0.711em; height: 0px;"><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: -3.716em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-241"><span class="mrow" id="MathJax-Span-242"><span class="mo" id="MathJax-Span-243" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.892em 1000.003em 2.718em -0.469em); top: -2.476em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-253"><span class="mrow" id="MathJax-Span-254"><span class="mo" id="MathJax-Span-255" style="font-family: STIXGeneral-Regular;">≈</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.892em 1000.003em 2.718em -0.469em); top: -1.296em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-277"><span class="mrow" id="MathJax-Span-278"><span class="mo" id="MathJax-Span-279" style="font-family: STIXGeneral-Regular;">≈</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(2.069em 1000.003em 5.493em -0.469em); top: -4.07em; left: 3.663em;"><span style="display: inline-block; position: relative; width: 10.215em; height: 0px;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -3.716em; left: 0.003em;"><span class="mtd" id="MathJax-Span-244"><span class="mrow" id="MathJax-Span-245"><span class="mn" id="MathJax-Span-246" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-247" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-248" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span><span class="mo" id="MathJax-Span-249" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-250" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: -2.476em; left: 0.003em;"><span class="mtd" id="MathJax-Span-256"><span class="mrow" id="MathJax-Span-257"><span class="mo" id="MathJax-Span-258" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-259" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-260" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-261" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-262" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-263" style="font-family: STIXGeneral-Regular;">(</span><span class="mn" id="MathJax-Span-264" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-265" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-266" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span><span class="mo" id="MathJax-Span-267" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-268" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mo" id="MathJax-Span-269" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-270" style="font-family: STIXGeneral-Italic;">i</span><span class="mi" id="MathJax-Span-271" style="font-family: STIXGeneral-Italic;">n</span><span class="mi" id="MathJax-Span-272" style="font-family: STIXGeneral-Italic;">t<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-273" style="font-family: STIXGeneral-Regular;">)</span><span class="mn" id="MathJax-Span-274" style="font-family: STIXGeneral-Regular;">32</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -1.296em; left: 0.003em;"><span class="mtd" id="MathJax-Span-280"><span class="mrow" id="MathJax-Span-281"><span class="mn" id="MathJax-Span-282" style="font-family: STIXGeneral-Regular;">37</span><span class="mo" id="MathJax-Span-283" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-284" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span><span class="mo" id="MathJax-Span-285" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mn" id="MathJax-Span-286" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">1.15625</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.128em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 4.289em; vertical-align: -1.854em;"></span></span></nobr></span></div><script type="math/tex; mode=display" id="MathJax-Element-12">
\begin{eqnarray}
1.164 & = & 1.164 \cdot 32 \div 32 \\
& \approx & (int)(1.164 \cdot 32) \div (int)32\\
& \approx & 37 \div 32 = 1.15625
\end{eqnarray}
</script></p>
<p>As you can see the difference between the <code>float</code> value <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-13-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-287" style="width: 2.777em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-288"><span class="mn" id="MathJax-Span-289" style="font-family: STIXGeneral-Regular;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-13">1.164</script> and our approximate “equivalent” expression value <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-14-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-290" style="width: 4.017em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.309em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-291"><span class="mn" id="MathJax-Span-292" style="font-family: STIXGeneral-Regular;">1.15625</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-14">1.15625</script> is quite small. But it’s a lot easier (and faster) to calculate <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-15-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-293" style="width: 5.139em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-294"><span class="mi" id="MathJax-Span-295" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-296" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-297" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">37</span><span class="mo" id="MathJax-Span-298" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-299" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-15">x \cdot 37 \div 32</script> than <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-16-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-300" style="width: 4.253em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.486em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-301"><span class="mi" id="MathJax-Span-302" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-303" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-304" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-16">x \cdot 1.164</script>.</p>
<blockquote>
<p>When working in languages which to not automatically coerce the result of <code>integer</code> operations to <code>float</code>s when needed your can stop reading here. Integer arithmetic is on of the most heavily optimized areas in today’s compilers and CPUs. <br>
It’s different in Smalltalk though: A simple expression like <code>3 * 4 / 5</code> (which would be <code>2</code>with integer arithmetic and <code>2.4</code>with floating points) might result in a <code>Fraction</code> (<code>(12/5)</code>)!!! Although great from a “keep the precision” standpoint it’s a speed nightmare. Sprinkling in some <code>asFloat</code>calls might speed up the thing a bit … but for soeme calculations it can even be faster … just read on.</p>
</blockquote>
<h2 id="replace-multiplication-of-floating-point-numbers-with-integer-shifts">Replace multiplication of floating point numbers with integer shifts</h2>
<p>So how to convert the expression <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-17-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-305" style="width: 5.139em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-306"><span class="mi" id="MathJax-Span-307" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-308" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-309" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">37</span><span class="mo" id="MathJax-Span-310" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-311" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-17">x \cdot 37 \div 32</script> into something which only uses <code>integer</code> shifts? The “trick” is to replace the numerator <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-18-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-312" style="width: 1.243em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.006em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-313"><span class="mn" id="MathJax-Span-314" style="font-family: STIXGeneral-Regular;">37</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-18">37</script> with expressions which are powers of <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-19-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-315" style="width: 0.652em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.534em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-316"><span class="mn" id="MathJax-Span-317" style="font-family: STIXGeneral-Regular;">2</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.932em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-19">2</script> (the denominator is already a power of <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-20-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-318" style="width: 0.652em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.534em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-319"><span class="mn" id="MathJax-Span-320" style="font-family: STIXGeneral-Regular;">2</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.932em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-20">2</script>). Each of these expressions is either a multiplication or division with a power of <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-21-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-321" style="width: 0.652em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.534em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-322"><span class="mn" id="MathJax-Span-323" style="font-family: STIXGeneral-Regular;">2</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.932em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-21">2</script>.</p>
<blockquote>
<p><strong>QUICK REFRESH</strong> <br>
<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-22-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-324" style="width: 6.835em; display: inline-block;"><span style="display: inline-block; position: relative; width: 5.904em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.556em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-325"><span class="mi" id="MathJax-Span-326" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-327" style="font-family: STIXGeneral-Regular; padding-left: 0.314em;">≪</span><span class="mi" id="MathJax-Span-328" style="font-family: STIXGeneral-Italic; padding-left: 0.314em;">s</span><span class="mo" id="MathJax-Span-329" style="font-family: STIXGeneral-Regular; padding-left: 0.314em;">=</span><span class="mi" id="MathJax-Span-330" style="font-family: STIXGeneral-Italic; padding-left: 0.314em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-331" style="font-family: STIXGeneral-Regular; padding-left: 0.252em;">⋅</span><span class="msubsup" id="MathJax-Span-332" style="padding-left: 0.252em;"><span style="display: inline-block; position: relative; width: 0.935em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-333" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="mi" id="MathJax-Span-334" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">s</span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-22"> x \ll s = x \cdot 2^s </script>: Shifting an integer <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-23-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-335" style="width: 0.562em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.5em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.866em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-336"><span class="mi" id="MathJax-Span-337" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.646em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-23">x</script> by <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-24-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-338" style="width: 0.5em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.438em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.866em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-339"><span class="mi" id="MathJax-Span-340" style="font-family: STIXGeneral-Italic;">s</span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.646em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-24">s</script> bits to the left is equal to multiplying <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-25-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-341" style="width: 0.562em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.5em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.866em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-342"><span class="mi" id="MathJax-Span-343" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.646em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-25">x</script> with <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-26-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-344" style="width: 1.183em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.997em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.183em 1000.003em 2.301em -0.556em); top: -2.109em; left: 0.003em;"><span class="mrow" id="MathJax-Span-345"><span class="msubsup" id="MathJax-Span-346"><span style="display: inline-block; position: relative; width: 0.935em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-347" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="mi" id="MathJax-Span-348" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">s</span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.115em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-26">2^s</script>. <br>
<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-27-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-349" style="width: 11.929em; display: inline-block;"><span style="display: inline-block; position: relative; width: 10.376em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.556em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-350"><span class="mi" id="MathJax-Span-351" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-352" style="font-family: STIXGeneral-Regular; padding-left: 0.314em;">≫</span><span class="mi" id="MathJax-Span-353" style="font-family: STIXGeneral-Italic; padding-left: 0.314em;">s</span><span class="mo" id="MathJax-Span-354" style="font-family: STIXGeneral-Regular; padding-left: 0.314em;">=</span><span class="mi" id="MathJax-Span-355" style="font-family: STIXGeneral-Italic; padding-left: 0.314em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-356" style="font-family: STIXGeneral-Regular; padding-left: 0.252em;">∗</span><span class="msubsup" id="MathJax-Span-357" style="padding-left: 0.252em;"><span style="display: inline-block; position: relative; width: 1.432em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-358" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="texatom" id="MathJax-Span-359"><span class="mrow" id="MathJax-Span-360"><span class="mo" id="MathJax-Span-361" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">−</span><span class="mi" id="MathJax-Span-362" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">s</span></span></span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span><span class="mo" id="MathJax-Span-363" style="font-family: STIXGeneral-Regular; padding-left: 0.314em;">=</span><span class="mi" id="MathJax-Span-364" style="font-family: STIXGeneral-Italic; padding-left: 0.314em;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-365" style="font-family: STIXGeneral-Regular; padding-left: 0.252em;">÷</span><span class="msubsup" id="MathJax-Span-366" style="padding-left: 0.252em;"><span style="display: inline-block; position: relative; width: 0.935em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-367" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="mi" id="MathJax-Span-368" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">s</span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-27"> x \gg s = x * 2^{-s} = x \div 2^s </script>: Shifting an integer <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-28-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-369" style="width: 0.562em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.5em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.866em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-370"><span class="mi" id="MathJax-Span-371" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.646em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-28">x</script> by <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-29-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-372" style="width: 0.5em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.438em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.866em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-373"><span class="mi" id="MathJax-Span-374" style="font-family: STIXGeneral-Italic;">s</span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.646em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-29">s</script> bits to the left is equal to multiplying <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-30-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-375" style="width: 0.562em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.5em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.866em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mrow" id="MathJax-Span-376"><span class="mi" id="MathJax-Span-377" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.646em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-30">x</script> with <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-31-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-378" style="width: 1.742em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.494em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.183em 1000.003em 2.301em -0.556em); top: -2.109em; left: 0.003em;"><span class="mrow" id="MathJax-Span-379"><span class="msubsup" id="MathJax-Span-380"><span style="display: inline-block; position: relative; width: 1.432em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-381" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="texatom" id="MathJax-Span-382"><span class="mrow" id="MathJax-Span-383"><span class="mo" id="MathJax-Span-384" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">−</span><span class="mi" id="MathJax-Span-385" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">s</span></span></span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.115em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-31">2^{-s}</script> or dividing by <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-32-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-386" style="width: 1.183em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.997em; height: 0px; font-size: 115%;"><span style="position: absolute; clip: rect(1.183em 1000.003em 2.301em -0.556em); top: -2.109em; left: 0.003em;"><span class="mrow" id="MathJax-Span-387"><span class="msubsup" id="MathJax-Span-388"><span style="display: inline-block; position: relative; width: 0.935em; height: 0px;"><span style="position: absolute; clip: rect(1.618em 1000.003em 2.674em -0.556em); top: -2.481em; left: 0.003em;"><span class="mn" id="MathJax-Span-389" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.488em;"></span></span><span style="position: absolute; top: -2.543em; left: 0.562em;"><span class="mi" id="MathJax-Span-390" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">s</span><span style="display: inline-block; width: 0px; height: 2.177em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.115em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-32">2^s</script>.</p>
</blockquote>
<p><span class="MathJax_Preview"></span><div class="MathJax_Display" role="textbox" aria-readonly="true" style="text-align: center;"><span class="MathJax" id="MathJax-Element-33-Frame"><nobr><span class="math" id="MathJax-Span-391" style="width: 22.966em; display: inline-block;"><span style="display: inline-block; position: relative; width: 18.952em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(-7.199em 1000.003em 10.983em -0.351em); top: -2.122em; left: 0.003em;"><span class="mrow" id="MathJax-Span-392"><span class="mtable" id="MathJax-Span-393" style="padding-right: 0.18em; padding-left: 0.18em;"><span style="display: inline-block; position: relative; width: 18.539em; height: 0px;"><span style="position: absolute; clip: rect(9.271em 1000.003em 27.099em -0.528em); top: -18.474em; left: 0.003em;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -10.918em; right: 0.003em;"><span class="mtd" id="MathJax-Span-394"><span class="mrow" id="MathJax-Span-395"><span class="mi" id="MathJax-Span-396" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-397" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-398" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">37</span><span class="mo" id="MathJax-Span-399" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-400" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: -10.977em; right: 0.003em;"><span class="mtd" id="MathJax-Span-417"><span class="mrow" id="MathJax-Span-418"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: -8.675em; right: 0.003em;"><span class="mtd" id="MathJax-Span-443"><span class="mrow" id="MathJax-Span-444"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: -5.251em; right: 0.003em;"><span class="mtd" id="MathJax-Span-471"><span class="mrow" id="MathJax-Span-472"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: -2.122em; right: 0.003em;"><span class="mtd" id="MathJax-Span-506"><span class="mrow" id="MathJax-Span-507"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: 0.121em; right: 0.003em;"><span class="mtd" id="MathJax-Span-531"><span class="mrow" id="MathJax-Span-532"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: 1.774em; right: 0.003em;"><span class="mtd" id="MathJax-Span-560"><span class="mrow" id="MathJax-Span-561"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: 3.25em; right: 0.003em;"><span class="mtd" id="MathJax-Span-599"><span class="mrow" id="MathJax-Span-600"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(3.84em 1000.003em 4.194em -0.528em); top: 4.43em; right: 0.003em;"><span class="mtd" id="MathJax-Span-623"><span class="mrow" id="MathJax-Span-624"></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span></span><span style="display: inline-block; width: 0px; height: 18.48em;"></span></span><span style="position: absolute; clip: rect(9.271em 1000.003em 26.803em -0.469em); top: -18.179em; left: 4.548em;"><span style="display: inline-block; position: relative; width: 0.711em; height: 0px;"><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: -10.918em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-401"><span class="mrow" id="MathJax-Span-402"><span class="mo" id="MathJax-Span-403" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: -9.501em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-419"><span class="mrow" id="MathJax-Span-420"><span class="mo" id="MathJax-Span-421" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: -7.199em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-445"><span class="mrow" id="MathJax-Span-446"><span class="mo" id="MathJax-Span-447" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: -3.775em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-473"><span class="mrow" id="MathJax-Span-474"><span class="mo" id="MathJax-Span-475" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: -0.646em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-508"><span class="mrow" id="MathJax-Span-509"><span class="mo" id="MathJax-Span-510" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: 1.597em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-533"><span class="mrow" id="MathJax-Span-534"><span class="mo" id="MathJax-Span-535" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: 3.25em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-562"><span class="mrow" id="MathJax-Span-563"><span class="mo" id="MathJax-Span-564" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: 4.726em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-601"><span class="mrow" id="MathJax-Span-602"><span class="mo" id="MathJax-Span-603" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.469em); top: 5.906em; left: 50%; margin-left: -0.351em;"><span class="mtd" id="MathJax-Span-625"><span class="mrow" id="MathJax-Span-626"><span class="mo" id="MathJax-Span-627" style="font-family: STIXGeneral-Regular;">=</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 18.185em;"></span></span><span style="position: absolute; clip: rect(9.448em 1000.003em 27.453em -0.528em); top: -18.651em; left: 5.611em;"><span style="display: inline-block; position: relative; width: 12.931em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.896em -0.528em); top: -10.918em; left: 0.003em;"><span class="mtd" id="MathJax-Span-404"><span class="mrow" id="MathJax-Span-405"><span class="mi" id="MathJax-Span-406" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-407" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-408" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mn" id="MathJax-Span-409" style="font-family: STIXGeneral-Regular;">32</span><span class="mo" id="MathJax-Span-410" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mn" id="MathJax-Span-411" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">4</span><span class="mo" id="MathJax-Span-412" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mn" id="MathJax-Span-413" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1</span><span class="mo" id="MathJax-Span-414" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-415" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="mn" id="MathJax-Span-416" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">32</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.479em 1000.003em 2.896em -0.528em); top: -9.501em; left: 0.003em;"><span class="mtd" id="MathJax-Span-422"><span class="mrow" id="MathJax-Span-423"><span class="mi" id="MathJax-Span-424" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-425" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mo" id="MathJax-Span-426" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="msubsup" id="MathJax-Span-427"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-428" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-429" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-430" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="msubsup" id="MathJax-Span-431" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-432" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-433" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-434" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="msubsup" id="MathJax-Span-435" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-436" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-437" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">0</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-438" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-439" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">÷</span><span class="msubsup" id="MathJax-Span-440" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-441" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-442" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(2.128em 1000.003em 5.552em -0.528em); top: -8.734em; left: 0.003em;"><span class="mtd" id="MathJax-Span-448"><span class="mrow" id="MathJax-Span-449"><span class="mi" id="MathJax-Span-450" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-451" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mrow" id="MathJax-Span-452" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-453" style="vertical-align: -0.764em;"><span style="font-family: STIXSizeFourSym;">(</span></span><span class="mfrac" id="MathJax-Span-454" style="padding-left: 0.121em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 5.316em; height: 0px;"><span style="position: absolute; clip: rect(1.479em 1000.003em 2.777em -0.528em); top: -3.185em; left: 50%; margin-left: -2.594em;"><span class="mrow" id="MathJax-Span-455"><span class="msubsup" id="MathJax-Span-456"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-457" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-458" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-459" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="msubsup" id="MathJax-Span-460" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-461" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-462" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-463" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="msubsup" id="MathJax-Span-464" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-465" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-466" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">0</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -3.126em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-467"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-468" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-469" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 5.316em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-470" style="vertical-align: -0.764em;"><span style="font-family: STIXSizeFourSym;">)</span></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span><span style="position: absolute; clip: rect(2.128em 1000.003em 5.552em -0.528em); top: -5.31em; left: 0.003em;"><span class="mtd" id="MathJax-Span-476"><span class="mrow" id="MathJax-Span-477"><span class="mi" id="MathJax-Span-478" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-479" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mrow" id="MathJax-Span-480" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-481" style="vertical-align: -0.764em;"><span style="font-family: STIXSizeFourSym;">(</span></span><span class="mfrac" id="MathJax-Span-482" style="padding-left: 0.121em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.066em; height: 0px;"><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -4.661em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-483"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-484" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-485" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -3.126em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-486"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-487" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-488" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.066em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-489" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mfrac" id="MathJax-Span-490" style="padding-left: 0.357em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.066em; height: 0px;"><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -4.661em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-491"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-492" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-493" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -3.126em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-494"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-495" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-496" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.066em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-497" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mfrac" id="MathJax-Span-498" style="padding-left: 0.357em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.066em; height: 0px;"><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -4.661em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-499"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-500" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-501" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">0</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -3.126em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-502"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-503" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-504" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.066em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-505" style="vertical-align: -0.764em;"><span style="font-family: STIXSizeFourSym;">)</span></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span><span style="position: absolute; clip: rect(2.423em 1000.003em 5.257em -0.528em); top: -2.181em; left: 0.003em;"><span class="mtd" id="MathJax-Span-511"><span class="mrow" id="MathJax-Span-512"><span class="mi" id="MathJax-Span-513" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-514" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mrow" id="MathJax-Span-515" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-516" style="vertical-align: -0.587em;"><span style="font-family: STIXSizeThreeSym;">(</span></span><span class="mn" id="MathJax-Span-517" style="font-family: STIXGeneral-Regular;">1</span><span class="mo" id="MathJax-Span-518" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mfrac" id="MathJax-Span-519" style="padding-left: 0.357em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.066em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.41em); top: -3.185em; left: 50%; margin-left: -0.233em;"><span class="mn" id="MathJax-Span-520" style="font-family: STIXGeneral-Regular;">1</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -3.126em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-521"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-522" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-523" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">3</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.066em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-524" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mfrac" id="MathJax-Span-525" style="padding-left: 0.357em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.066em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.41em); top: -3.185em; left: 50%; margin-left: -0.233em;"><span class="mn" id="MathJax-Span-526" style="font-family: STIXGeneral-Regular;">1</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(2.955em 1000.003em 4.194em -0.528em); top: -3.126em; left: 50%; margin-left: -0.469em;"><span class="msubsup" id="MathJax-Span-527"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-528" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-529" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.017em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.066em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-530" style="vertical-align: -0.587em;"><span style="font-family: STIXSizeThreeSym;">)</span></span></span></span></span><span style="display: inline-block; width: 0px; height: 4.076em;"></span></span><span style="position: absolute; clip: rect(2.01em 1000.003em 3.722em -0.528em); top: 1.006em; left: 0.003em;"><span class="mtd" id="MathJax-Span-536"><span class="mrow" id="MathJax-Span-537"><span class="mi" id="MathJax-Span-538" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-539" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mrow" id="MathJax-Span-540" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-541" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">(</span></span></span><span class="msubsup" id="MathJax-Span-542"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-543" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-544" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">0</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-545" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="msubsup" id="MathJax-Span-546" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 1.479em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-547" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="texatom" id="MathJax-Span-548"><span class="mrow" id="MathJax-Span-549"><span class="mo" id="MathJax-Span-550" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">−</span><span class="mn" id="MathJax-Span-551" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">3</span></span></span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-552" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="msubsup" id="MathJax-Span-553" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 1.479em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-554" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="texatom" id="MathJax-Span-555"><span class="mrow" id="MathJax-Span-556"><span class="mo" id="MathJax-Span-557" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">−</span><span class="mn" id="MathJax-Span-558" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span></span></span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-559" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">)</span></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 3.132em;"></span></span><span style="position: absolute; clip: rect(2.01em 1000.003em 3.722em -0.351em); top: 2.659em; left: 0.003em;"><span class="mtd" id="MathJax-Span-565"><span class="mrow" id="MathJax-Span-566"><span class="mrow" id="MathJax-Span-567"><span class="mo" id="MathJax-Span-568" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">(</span></span></span><span class="mi" id="MathJax-Span-569" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-570" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="msubsup" id="MathJax-Span-571" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 0.947em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-572" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="mn" id="MathJax-Span-573" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">0</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-574" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">)</span></span></span></span><span class="mo" id="MathJax-Span-575" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mrow" id="MathJax-Span-576" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-577" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">(</span></span></span><span class="mi" id="MathJax-Span-578" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-579" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="msubsup" id="MathJax-Span-580" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 1.479em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-581" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="texatom" id="MathJax-Span-582"><span class="mrow" id="MathJax-Span-583"><span class="mo" id="MathJax-Span-584" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">−</span><span class="mn" id="MathJax-Span-585" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">3</span></span></span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-586" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">)</span></span></span></span><span class="mo" id="MathJax-Span-587" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mrow" id="MathJax-Span-588" style="padding-left: 0.239em;"><span class="mo" id="MathJax-Span-589" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">(</span></span></span><span class="mi" id="MathJax-Span-590" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-591" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="msubsup" id="MathJax-Span-592" style="padding-left: 0.239em;"><span style="display: inline-block; position: relative; width: 1.479em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mn" id="MathJax-Span-593" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; top: -2.594em; left: 0.534em;"><span class="texatom" id="MathJax-Span-594"><span class="mrow" id="MathJax-Span-595"><span class="mo" id="MathJax-Span-596" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">−</span><span class="mn" id="MathJax-Span-597" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span></span></span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span></span></span><span class="mo" id="MathJax-Span-598" style="vertical-align: -0.233em;"><span><span style="font-size: 110%; font-family: STIXSizeOneSym;">)</span></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 3.132em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.469em); top: 4.726em; left: 0.003em;"><span class="mtd" id="MathJax-Span-604"><span class="mrow" id="MathJax-Span-605"><span class="mo" id="MathJax-Span-606" style="font-family: STIXGeneral-Regular;">(</span><span class="mi" id="MathJax-Span-607" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-608" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-609" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">0</span><span class="mo" id="MathJax-Span-610" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-611" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-612" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-613" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-614" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-615" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">3</span><span class="mo" id="MathJax-Span-616" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-617" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-618" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-619" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-620" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-621" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">5</span><span class="mo" id="MathJax-Span-622" style="font-family: STIXGeneral-Regular;">)</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.528em); top: 5.906em; left: 0.003em;"><span class="mtd" id="MathJax-Span-628"><span class="mrow" id="MathJax-Span-629"><span class="mi" id="MathJax-Span-630" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-631" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-632" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-633" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-634" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-635" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">3</span><span class="mo" id="MathJax-Span-636" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-637" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-638" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-639" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-640" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-641" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">5</span><span class="mo" id="MathJax-Span-642" style="font-family: STIXGeneral-Regular;">)</span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="display: inline-block; width: 0px; height: 18.657em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.128em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 21.718em; vertical-align: -10.568em;"></span></span></nobr></span></div><script type="math/tex; mode=display" id="MathJax-Element-33">
\begin{eqnarray}
x \cdot 37 \div 32 & = & x \cdot (32 + 4 + 1 ) \div 32 \\
& = & x \cdot (2^5 +2^2 + 2^0) \div 2^5 \\
& = & x \cdot \left( \frac{2^5 +2^2 + 2^0}{2^5} \right) \\
& = & x \cdot \left( \frac{2^5}{2^5} + \frac{2^2}{2^5} + \frac{2^0}{2^5} \right) \\
& = & x \cdot \left( 1 + \frac{1}{2^3} + \frac{1}{2^5} \right) \\
& = & x \cdot \left( 2^0 + 2^{-3} + 2^{-5} \right) \\
& = & \left(x \cdot 2^0\right) + \left(x \cdot 2^{-3}\right) + \left(x \cdot 2^{-5}\right) \\
& = & (x \gg 0) + (x \gg 3) + (x \gg 5) \\
& = & x + (x \gg 3) + (x \gg 5) \\
\end{eqnarray}
</script></p>
<p>So we can replace the expression <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-34-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-643" style="width: 4.253em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.486em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-644"><span class="mi" id="MathJax-Span-645" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-646" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-647" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-34">x \cdot 1.164</script> (which “forces” <code>float</code> values&operations) with <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-35-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-648" style="width: 11.042em; display: inline-block;"><span style="display: inline-block; position: relative; width: 9.094em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-649"><span class="mi" id="MathJax-Span-650" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-651" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-652" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-653" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-654" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-655" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">3</span><span class="mo" id="MathJax-Span-656" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-657" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-658" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-659" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-660" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-661" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">5</span><span class="mo" id="MathJax-Span-662" style="font-family: STIXGeneral-Regular;">)</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.218em; vertical-align: -0.282em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-35">x + (x \gg 3) + (x \gg 5)</script> (which only uses <code>integer</code> values&operations).</p>
<h2 id="conclusion">Conclusion</h2>
<p>Maybe everybody knew this “trick” and I have simply been living under a rock for the last decades. If this is the case this blog still server of a reminder for myself. If you indeed learned something that’s even better!</p>
<h2 id="limitations">Limitations</h2>
<h3 id="it-only-works-for-integer-values">IT ONLY WORKS FOR INTEGER VALUES!!</h3>
<p>An expression like <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-36-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-663" style="width: 4.253em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.486em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-664"><span class="mi" id="MathJax-Span-665" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-666" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">⋅</span><span class="mn" id="MathJax-Span-667" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-36">x \cdot 1.164</script> can only be converted to <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-37-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-668" style="width: 11.042em; display: inline-block;"><span style="display: inline-block; position: relative; width: 9.094em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.896em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-669"><span class="mi" id="MathJax-Span-670" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-671" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-672" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-673" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-674" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-675" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">3</span><span class="mo" id="MathJax-Span-676" style="font-family: STIXGeneral-Regular;">)</span><span class="mo" id="MathJax-Span-677" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">+</span><span class="mo" id="MathJax-Span-678" style="font-family: STIXGeneral-Regular; padding-left: 0.239em;">(</span><span class="mi" id="MathJax-Span-679" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-680" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≫</span><span class="mn" id="MathJax-Span-681" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">5</span><span class="mo" id="MathJax-Span-682" style="font-family: STIXGeneral-Regular;">)</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.218em; vertical-align: -0.282em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-37">x + (x \gg 3) + (x \gg 5)</script> if any only if <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-38-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-683" style="width: 0.593em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-684"><span class="mi" id="MathJax-Span-685" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.718em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-38">x</script> is an <code>integer</code>!</p>
<h3 id="precision">PRECISION</h3>
<p><code>Float</code> values (<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-39-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-686" style="width: 3.073em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.541em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.777em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-687"><span class="mi" id="MathJax-Span-688" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-689" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">∈</span><span class="texatom" id="MathJax-Span-690" style="padding-left: 0.298em;"><span class="mrow" id="MathJax-Span-691"><span class="mi" id="MathJax-Span-692" style="font-family: STIXGeneral-Regular;">ℚ</span></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.075em; vertical-align: -0.139em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-39">x \in \mathbb{Q}</script>) can be represented as a fraction (<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-40-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-693" style="width: 0.947em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.77em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.184em 1000.003em 2.718em -0.41em); top: -2.122em; left: 0.003em;"><span class="mrow" id="MathJax-Span-694"><span class="mfrac" id="MathJax-Span-695" style="padding-left: 0.121em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.364em -0.528em); top: -2.594em; left: 50%; margin-left: -0.174em;"><span class="mi" id="MathJax-Span-696" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">a</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.528em); top: -1.768em; left: 50%; margin-left: -0.174em;"><span class="mi" id="MathJax-Span-697" style="font-size: 70.7%; font-family: STIXGeneral-Italic;">b</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 0.475em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.128em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.575em; vertical-align: -0.568em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-40">\frac{a}{b}</script>). Other <code>float</code>s (e.g. <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-41-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-698" style="width: 0.711em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.593em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-699"><span class="mi" id="MathJax-Span-700" style="font-family: STIXGeneral-Italic;">π<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.062em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.718em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-41">\pi</script>) cannot be represented as a fraction. The method presented above however will always try to approximate the <code>float</code> value <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-42-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-701" style="width: 0.593em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.475em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.951em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-702"><span class="mi" id="MathJax-Span-703" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.718em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-42">x</script> with a fraction. Even if the value can be represented as a fraction (<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-43-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-704" style="width: 3.073em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.541em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.777em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-705"><span class="mi" id="MathJax-Span-706" style="font-family: STIXGeneral-Italic;">x<span style="display: inline-block; overflow: hidden; height: 1px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-707" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">∈</span><span class="texatom" id="MathJax-Span-708" style="padding-left: 0.298em;"><span class="mrow" id="MathJax-Span-709"><span class="mi" id="MathJax-Span-710" style="font-family: STIXGeneral-Regular;">ℚ</span></span></span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.075em; vertical-align: -0.139em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-43">x \in \mathbb{Q}</script>) you might loose precision – due to the denominator always being a power of <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-44-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-711" style="width: 0.652em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.534em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-712"><span class="mn" id="MathJax-Span-713" style="font-family: STIXGeneral-Regular;">2</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.932em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-44">2</script> and because the <em>achievable</em> precision depends on the used exponent:</p>
<p><strong>Denominator <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-45-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-714" style="width: 4.427em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.308em; height: 0px; font-size: 134%;"><span style="position: absolute; clip: rect(1.495em 1000.003em 2.721em -0.37em); top: -2.556em; left: 0.003em;"><span class="mrow" id="MathJax-Span-715"><span class="mn" id="MathJax-Span-716" style="font-family: STIXGeneral-Regular;">16</span><span class="mo" id="MathJax-Span-717" style="font-family: STIXGeneral-Regular; padding-left: 0.322em;">=</span><span class="msubsup" id="MathJax-Span-718" style="padding-left: 0.322em;"><span style="display: inline-block; position: relative; width: 0.962em; height: 0px;"><span style="position: absolute; clip: rect(1.708em 1000.003em 2.721em -0.424em); top: -2.556em; left: 0.003em;"><span class="mn" id="MathJax-Span-719" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span><span style="position: absolute; top: -2.609em; left: 0.536em;"><span class="mn" id="MathJax-Span-720" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">4</span><span style="display: inline-block; width: 0px; height: 2.188em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.361em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-45">16 = 2^4</script></strong></p>
<ul>
<li>Approximated fraction: <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-46-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-721" style="width: 10.452em; display: inline-block;"><span style="display: inline-block; position: relative; width: 8.622em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.479em 1000.003em 3.132em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-722"><span class="mn" id="MathJax-Span-723" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-724" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≈</span><span class="mfrac" id="MathJax-Span-725" style="padding-left: 0.416em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 0.829em; height: 0px;"><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.469em); top: -2.594em; left: 50%; margin-left: -0.351em;"><span class="mn" id="MathJax-Span-726" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">19</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.469em); top: -1.768em; left: 50%; margin-left: -0.351em;"><span class="mn" id="MathJax-Span-727" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">16</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 0.829em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-728" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mn" id="MathJax-Span-729" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">1.1875</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.789em; vertical-align: -0.568em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-46">1.164 \approx \frac{19}{16} = 1.1875</script>; Error <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-47-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-730" style="width: 5.139em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-731"><span class="mo" id="MathJax-Span-732" style="font-family: STIXGeneral-Regular;">≈</span><span class="mn" id="MathJax-Span-733" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">0.02350</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-47">\approx 0.02350</script></li>
<li>Shift Expression: <code>x + (x >> 3) + (x >> 4)</code></li>
</ul>
<p><strong>Denominator <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-48-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-734" style="width: 4.427em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.308em; height: 0px; font-size: 134%;"><span style="position: absolute; clip: rect(1.495em 1000.003em 2.721em -0.424em); top: -2.556em; left: 0.003em;"><span class="mrow" id="MathJax-Span-735"><span class="mn" id="MathJax-Span-736" style="font-family: STIXGeneral-Regular;">32</span><span class="mo" id="MathJax-Span-737" style="font-family: STIXGeneral-Regular; padding-left: 0.322em;">=</span><span class="msubsup" id="MathJax-Span-738" style="padding-left: 0.322em;"><span style="display: inline-block; position: relative; width: 0.962em; height: 0px;"><span style="position: absolute; clip: rect(1.708em 1000.003em 2.721em -0.424em); top: -2.556em; left: 0.003em;"><span class="mn" id="MathJax-Span-739" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span><span style="position: absolute; top: -2.609em; left: 0.536em;"><span class="mn" id="MathJax-Span-740" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">5</span><span style="display: inline-block; width: 0px; height: 2.188em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.361em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-48">32 = 2^5</script></strong></p>
<ul>
<li>Approximated fraction: <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-49-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-741" style="width: 11.101em; display: inline-block;"><span style="display: inline-block; position: relative; width: 9.153em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.479em 1000.003em 3.132em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-742"><span class="mn" id="MathJax-Span-743" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-744" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≈</span><span class="mfrac" id="MathJax-Span-745" style="padding-left: 0.416em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 0.829em; height: 0px;"><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.528em); top: -2.594em; left: 50%; margin-left: -0.351em;"><span class="mn" id="MathJax-Span-746" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">37</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.528em); top: -1.768em; left: 50%; margin-left: -0.351em;"><span class="mn" id="MathJax-Span-747" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">32</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 0.829em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-748" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mn" id="MathJax-Span-749" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">1.15625</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.718em; vertical-align: -0.568em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-49">1.164 \approx \frac{37}{32} = 1.15625</script>; Error <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-50-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-750" style="width: 5.139em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-751"><span class="mo" id="MathJax-Span-752" style="font-family: STIXGeneral-Regular;">≈</span><span class="mn" id="MathJax-Span-753" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">0.00775</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-50">\approx 0.00775</script></li>
<li>Shift Expression: <code>x + (x >> 3) + (x >> 5)</code></li>
</ul>
<p><strong>Denominator <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-51-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-754" style="width: 4.427em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.308em; height: 0px; font-size: 134%;"><span style="position: absolute; clip: rect(1.495em 1000.003em 2.721em -0.424em); top: -2.556em; left: 0.003em;"><span class="mrow" id="MathJax-Span-755"><span class="mn" id="MathJax-Span-756" style="font-family: STIXGeneral-Regular;">64</span><span class="mo" id="MathJax-Span-757" style="font-family: STIXGeneral-Regular; padding-left: 0.322em;">=</span><span class="msubsup" id="MathJax-Span-758" style="padding-left: 0.322em;"><span style="display: inline-block; position: relative; width: 0.962em; height: 0px;"><span style="position: absolute; clip: rect(1.708em 1000.003em 2.721em -0.424em); top: -2.556em; left: 0.003em;"><span class="mn" id="MathJax-Span-759" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span><span style="position: absolute; top: -2.609em; left: 0.536em;"><span class="mn" id="MathJax-Span-760" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">6</span><span style="display: inline-block; width: 0px; height: 2.188em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.361em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-51">64 = 2^6</script></strong></p>
<ul>
<li>Approximated fraction: <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-52-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-761" style="width: 11.101em; display: inline-block;"><span style="display: inline-block; position: relative; width: 9.153em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.479em 1000.003em 3.132em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-762"><span class="mn" id="MathJax-Span-763" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-764" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≈</span><span class="mfrac" id="MathJax-Span-765" style="padding-left: 0.416em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 0.829em; height: 0px;"><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.528em); top: -2.594em; left: 50%; margin-left: -0.351em;"><span class="mn" id="MathJax-Span-766" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">74</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.528em); top: -1.768em; left: 50%; margin-left: -0.351em;"><span class="mn" id="MathJax-Span-767" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">64</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 0.829em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-768" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mn" id="MathJax-Span-769" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">1.15625</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.718em; vertical-align: -0.568em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-52">1.164 \approx \frac{74}{64} = 1.15625</script>; Error <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-53-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-770" style="width: 5.139em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-771"><span class="mo" id="MathJax-Span-772" style="font-family: STIXGeneral-Regular;">≈</span><span class="mn" id="MathJax-Span-773" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">0.00775</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-53">\approx 0.00775</script></li>
<li>Shift Expression: <code>x + (x >> 3) + (x >> 5)</code></li>
</ul>
<p><strong>Denominator <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-54-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-774" style="width: 5.173em; display: inline-block;"><span style="display: inline-block; position: relative; width: 3.841em; height: 0px; font-size: 134%;"><span style="position: absolute; clip: rect(1.549em 1000.003em 2.721em -0.37em); top: -2.556em; left: 0.003em;"><span class="mrow" id="MathJax-Span-775"><span class="mn" id="MathJax-Span-776" style="font-family: STIXGeneral-Regular;">128</span><span class="mo" id="MathJax-Span-777" style="font-family: STIXGeneral-Regular; padding-left: 0.322em;">=</span><span class="msubsup" id="MathJax-Span-778" style="padding-left: 0.322em;"><span style="display: inline-block; position: relative; width: 0.962em; height: 0px;"><span style="position: absolute; clip: rect(1.708em 1000.003em 2.721em -0.424em); top: -2.556em; left: 0.003em;"><span class="mn" id="MathJax-Span-779" style="font-family: STIXGeneral-Regular;">2</span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span><span style="position: absolute; top: -2.609em; left: 0.536em;"><span class="mn" id="MathJax-Span-780" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">7</span><span style="display: inline-block; width: 0px; height: 2.188em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 2.561em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.361em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-54">128 = 2^7</script></strong></p>
<ul>
<li>Approximated fraction: <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-55-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-781" style="width: 12.754em; display: inline-block;"><span style="display: inline-block; position: relative; width: 10.511em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.479em 1000.003em 3.132em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-782"><span class="mn" id="MathJax-Span-783" style="font-family: STIXGeneral-Regular;">1.164</span><span class="mo" id="MathJax-Span-784" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">≈</span><span class="mfrac" id="MathJax-Span-785" style="padding-left: 0.416em; padding-right: 0.121em;"><span style="display: inline-block; position: relative; width: 1.184em; height: 0px;"><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.469em); top: -2.594em; left: 50%; margin-left: -0.528em;"><span class="mn" id="MathJax-Span-786" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">149</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(1.538em 1000.003em 2.364em -0.469em); top: -1.768em; left: 50%; margin-left: -0.528em;"><span class="mn" id="MathJax-Span-787" style="font-size: 70.7%; font-family: STIXGeneral-Regular;">128</span><span style="display: inline-block; width: 0px; height: 2.187em;"></span></span><span style="position: absolute; clip: rect(0.829em 1000.003em 1.243em -0.528em); top: -1.296em; left: 0.003em;"><span style="border-left-width: 1.184em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.25px; vertical-align: 0.003em;"></span><span style="display: inline-block; width: 0px; height: 1.066em;"></span></span></span></span><span class="mo" id="MathJax-Span-788" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">=</span><span class="mn" id="MathJax-Span-789" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">1.1640625</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.718em; vertical-align: -0.568em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-55">1.164 \approx \frac{149}{128} = 1.1640625</script>; Error <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-56-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-790" style="width: 5.139em; display: inline-block;"><span style="display: inline-block; position: relative; width: 4.253em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-791"><span class="mo" id="MathJax-Span-792" style="font-family: STIXGeneral-Regular;">≈</span><span class="mn" id="MathJax-Span-793" style="font-family: STIXGeneral-Regular; padding-left: 0.298em;">0.00006</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-56">\approx 0.00006</script></li>
<li>Shift Expression: <code>x + (x >> 3) + (x >> 5) + (x >> 7)</code></li>
</ul>
<p>So in theory the bigger the denominator the higher the precision – although not every step means more precision (compare 32 and 64). Another limiting factor is the numeric range of the variable. If the variable is an <code>unsigned byte</code> (<code>0-255</code>) it’s pointless to shift it more than 8 bits to the right.</p>
<p>So given the example above (<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-57-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-794" style="width: 2.777em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-795"><span class="mn" id="MathJax-Span-796" style="font-family: STIXGeneral-Regular;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-57">1.164</script>) using <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-58-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-797" style="width: 1.892em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.538em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-798"><span class="mn" id="MathJax-Span-799" style="font-family: STIXGeneral-Regular;">128</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-58">128</script> for byte-sized values is pointless: The largest shift is 7 bits – so only values with the highest bit set (128+) will “survive” and result in a value different than <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-59-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-800" style="width: 0.652em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.534em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.528em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-801"><span class="mn" id="MathJax-Span-802" style="font-family: STIXGeneral-Regular;">0</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-59">0</script>. Using <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-60-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-803" style="width: 1.243em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.006em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-804"><span class="mn" id="MathJax-Span-805" style="font-family: STIXGeneral-Regular;">64</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-60">64</script> or <span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-61-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-806" style="width: 1.243em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.006em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.715em 1000.003em 2.718em -0.469em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-807"><span class="mn" id="MathJax-Span-808" style="font-family: STIXGeneral-Regular;">32</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-61">32</script> will result in the same shift operations with a maximum shift of 5 bits - so the highest 3 bits will “survive”. That’s quite usable for most cases.</p>
<p>Finding the best compromise between precision and number of shifts is the actual hard decision you have to make. Check the code below to make an informed decision.</p>
<h2 id="code">Code</h2>
<blockquote>
<p><strong>NOTE:</strong> The code below is neither nice nor fast. But it does it’s job :-)</p>
</blockquote>
<pre class="prettyprint prettyprinted"><code><span class="typ">Number</span><span class="pun">>>#</span><span class="pln">multiplyAsShiftReportWith
</span><span class="pun">^</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> multiplyAsShiftReportWith</span><span class="pun">:</span><span class="pln"> </span><span class="str">'x'</span></code></pre>
<pre class="prettyprint prettyprinted"><code><span class="typ">Number</span><span class="pun">>>#</span><span class="pln">multiplyAsShiftReportWith</span><span class="pun">:</span><span class="pln"> variableName
</span><span class="pun">^</span><span class="pln"> </span><span class="typ">String</span><span class="pln">
streamContents</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">report </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> denominator numerator aproximatedFloat bitString numberOfSetBits currentShiftOffset shiftPositions </span><span class="pun">|</span><span class="pln">
report
nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Float: '</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pln"> printString</span><span class="pun">;</span><span class="pln">
cr</span><span class="pun">.</span><span class="pln">
</span><span class="lit">4</span><span class="pln"> to</span><span class="pun">:</span><span class="pln"> </span><span class="lit">9</span><span class="pln"> </span><span class="kwd">do</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">denominatorExponent </span><span class="pun">|</span><span class="pln">
denominator </span><span class="pun">:=</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> raisedTo</span><span class="pun">:</span><span class="pln"> denominatorExponent</span><span class="pun">.</span><span class="pln">
numerator </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">self</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> denominator</span><span class="pun">)</span><span class="pln"> rounded</span><span class="pun">.</span><span class="pln">
aproximatedFloat </span><span class="pun">:=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">numerator </span><span class="pun">/</span><span class="pln"> denominator</span><span class="pun">)</span><span class="pln"> asFloat</span><span class="pun">.</span><span class="pln">
bitString </span><span class="pun">:=</span><span class="pln"> numerator bitString </span><span class="kwd">last</span><span class="pun">:</span><span class="pln"> </span><span class="lit">16.</span><span class="pln">
numberOfSetBits </span><span class="pun">:=</span><span class="pln"> bitString asBag occurrencesOf</span><span class="pun">:</span><span class="pln"> $1</span><span class="pun">.</span><span class="pln">
report
cr</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="str">'<1p> / <2p> = <3p>'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> numerator </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> denominator </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> aproximatedFloat</span><span class="pun">);</span><span class="pln">
cr</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="str">'|Error| = <1s>; (log10 |Error| = <2s>)'</span><span class="pln">
expandMacrosWith</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">aproximatedFloat </span><span class="pun">-</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">)</span><span class="pln"> abs printShowingDecimalPlaces</span><span class="pun">:</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">aproximatedFloat </span><span class="pun">-</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">)</span><span class="pln"> abs log printShowingDecimalPlaces</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">));</span><span class="pln">
cr</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="str">'<1p> = Binary <2s>'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> numerator </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> bitString</span><span class="pun">);</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="str">'; required shifts: <1p>'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> numberOfSetBits</span><span class="pun">);</span><span class="pln">
cr</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="str">'Precision/Shifts Ratio: <1s>'</span><span class="pln">
expandMacrosWith</span><span class="pun">:</span><span class="pln"> </span><span class="pun">((</span><span class="pln">aproximatedFloat </span><span class="pun">-</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">)</span><span class="pln"> abs log abs </span><span class="pun">/</span><span class="pln"> numberOfSetBits printShowingDecimalPlaces</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">));</span><span class="pln">
cr</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Orignal Expression: <1s> * <2p>'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> variableName </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">);</span><span class="pln">
cr</span><span class="pun">;</span><span class="pln">
nextPutAll</span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="str">'Integer Expression: <1s> * <2p> / <3p>'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> variableName </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> numerator </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> denominator</span><span class="pun">);</span><span class="pln">
cr</span><span class="pun">.</span><span class="pln">
currentShiftOffset </span><span class="pun">:=</span><span class="pln"> denominatorExponent </span><span class="pun">-</span><span class="pln"> bitString size</span><span class="pun">.</span><span class="pln">
shiftPositions </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">OrderedCollection</span><span class="pln"> </span><span class="kwd">new</span><span class="pun">.</span><span class="pln">
bitString asArray
</span><span class="kwd">do</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">bit </span><span class="pun">|</span><span class="pln">
currentShiftOffset </span><span class="pun">:=</span><span class="pln"> currentShiftOffset </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1.</span><span class="pln">
bit </span><span class="pun">=</span><span class="pln"> $1
ifTrue</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> shiftPositions add</span><span class="pun">:</span><span class="pln"> currentShiftOffset </span><span class="pun">]</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
report nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Shift Expression: '</span><span class="pun">.</span><span class="pln">
shiftPositions
</span><span class="kwd">do</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="pun">:</span><span class="pln">position </span><span class="pun">|</span><span class="pln">
position </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
ifTrue</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> report nextPutAll</span><span class="pun">:</span><span class="pln"> variableName </span><span class="pun">]</span><span class="pln">
ifFalse</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
position negative
ifTrue</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> report nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="str">'(<1s> %<%< <2p>)'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> variableName </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> position negated</span><span class="pun">)</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
ifFalse</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> report nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="str">'(<1s> >> <2p>)'</span><span class="pln"> expandMacrosWith</span><span class="pun">:</span><span class="pln"> variableName </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> position</span><span class="pun">)</span><span class="pln"> </span><span class="pun">]</span><span class="pln"> </span><span class="pun">]</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
separatedBy</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> report nextPutAll</span><span class="pun">:</span><span class="pln"> </span><span class="str">' + '</span><span class="pln"> </span><span class="pun">].</span><span class="pln">
report cr </span><span class="pun">]</span><span class="pln"> </span><span class="pun">]</span></code></pre>
<h3 id="code-usage">Code (Usage)</h3>
<p>I using the same <code>float</code> (<span class="MathJax_Preview"></span><span class="MathJax" id="MathJax-Element-62-Frame" role="textbox" aria-readonly="true"><nobr><span class="math" id="MathJax-Span-809" style="width: 2.777em; display: inline-block;"><span style="display: inline-block; position: relative; width: 2.305em; height: 0px; font-size: 121%;"><span style="position: absolute; clip: rect(1.656em 1000.003em 2.718em -0.41em); top: -2.535em; left: 0.003em;"><span class="mrow" id="MathJax-Span-810"><span class="mn" id="MathJax-Span-811" style="font-family: STIXGeneral-Regular;">1.164</span></span><span style="display: inline-block; width: 0px; height: 2.541em;"></span></span></span><span style="border-left-width: 0.004em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.004em; vertical-align: -0.068em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-62">1.164</script>) I used throughout this article to demonstrate the functionality. The report shows the different values incl. their precision, number of shifts and expressions which can be directly copy&pasted.</p>
<pre class="prettyprint prettyprinted"><code><span class="lit">1.164</span><span class="pln"> multiplyAsShiftReportWith</span><span class="pun">:</span><span class="pln"> </span><span class="str">'x'</span><span class="pun">.</span><span class="pln"> </span><span class="str">"print-it"</span><span class="pln">
</span><span class="str">'Float: 1.164
19 / 16 = 1.1875
|Error| = 0.02350; (log10 |Error| = -1.629)
19 = Binary 0000000000010011; required shifts: 3
Precision/Shifts Ratio: 0.543
Orignal Expression: x * 1.164
Integer Expression: x * 19 / 16
Shift Expression: x + (x >> 3) + (x >> 4)
37 / 32 = 1.15625
|Error| = 0.00775; (log10 |Error| = -2.111)
37 = Binary 0000000000100101; required shifts: 3
Precision/Shifts Ratio: 0.704
Orignal Expression: x * 1.164
Integer Expression: x * 37 / 32
Shift Expression: x + (x >> 3) + (x >> 5)
74 / 64 = 1.15625
|Error| = 0.00775; (log10 |Error| = -2.111)
74 = Binary 0000000001001010; required shifts: 3
Precision/Shifts Ratio: 0.704
Orignal Expression: x * 1.164
Integer Expression: x * 74 / 64
Shift Expression: x + (x >> 3) + (x >> 5)
149 / 128 = 1.1640625
|Error| = 0.00006; (log10 |Error| = -4.204)
149 = Binary 0000000010010101; required shifts: 4
Precision/Shifts Ratio: 1.051
Orignal Expression: x * 1.164
Integer Expression: x * 149 / 128
Shift Expression: x + (x >> 3) + (x >> 5) + (x >> 7)
298 / 256 = 1.1640625
|Error| = 0.00006; (log10 |Error| = -4.204)
298 = Binary 0000000100101010; required shifts: 4
Precision/Shifts Ratio: 1.051
Orignal Expression: x * 1.164
Integer Expression: x * 298 / 256
Shift Expression: x + (x >> 3) + (x >> 5) + (x >> 7)
596 / 512 = 1.1640625
|Error| = 0.00006; (log10 |Error| = -4.204)
596 = Binary 0000001001010100; required shifts: 4
Precision/Shifts Ratio: 1.051
Orignal Expression: x * 1.164
Integer Expression: x * 596 / 512
Shift Expression: x + (x >> 3) + (x >> 5) + (x >> 7)
'</span></code></pre>
<h2 id="update-1"><a name="Update">Update 1</a></h2>
<p>This approach of course works for every kind of <code>Number</code>, <code>ScaledDecimal</code>s included (thanks Tobias!). So I moved the method to class <code>Number</code>and updated the code.</p>
<h2 id="update-2">Update 2</h2>
<p>Thanks to a Twitter conversation with Hwa Jong Oh there is now a <code>FastConstantMultiplier</code>. So if you need to multiply an <code>Integer</code> with a constant quite often this might be interesting for you:</p>
<h3 id="load-package">Load package</h3>
<pre class="prettyprint prettyprinted"><code><span class="typ">Gofer</span><span class="pln"> it
smalltalkhubUser</span><span class="pun">:</span><span class="pln"> </span><span class="str">'UdoSchneider'</span><span class="pln"> project</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Playground'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">package</span><span class="pun">:</span><span class="pln"> </span><span class="str">'FastConstantMultiplier'</span><span class="pun">;</span><span class="pln">
load</span><span class="pun">.</span></code></pre>
<h3 id="using-the-package">Using the package</h3>
<pre class="prettyprint prettyprinted"><code class="language-`"><span class="pln">m </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">FastConstantMultiplier</span><span class="pln"> constant</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.123456789</span><span class="pln"> significantDigits</span><span class="pun">:</span><span class="pln"> </span><span class="lit">11.</span><span class="pln">
m </span><span class="pun">*</span><span class="pln"> </span><span class="lit">10000.</span><span class="pln"> </span><span class="str">"1232 "</span><span class="pln">
m </span><span class="pun">*</span><span class="pln"> </span><span class="lit">10000000000000.</span><span class="str">" 1234567890054"</span><span class="pln"> </span></code></pre>
<blockquote>
<p>Written with <a href="https://stackedit.io/">StackEdit</a>.</p>
</blockquote>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-55121074216400846932014-07-09T15:51:00.000+02:002014-10-13T14:34:30.109+02:00PBKDF2 (Password-Based Key Derivation Function 2) for Pharo<h2 id="introduction">Introduction</h2>
<p>I just extracted some PBKDF2 code I’m using in a project to it’s own package. The implementation is directly based on <a href="http://tools.ietf.org/html/rfc2898">RFC 2898</a>. The only requirement is the Cryptography package. I’m using this code to store hashed+salted passwords. Simply using “hash-only” approaches isn’t secure anymore (and maybe never was). Some pretty good articles do outline this in greater detail:</p>
<ul>
<li>3 Wrong Ways to Store a Password</li>
<li>Salted Password Hashing - Doing it Right</li>
</ul>
<p>The package is hosted on SmalltalkHub at <a href="http://smalltalkhub.com/#!/~udos/PBKDF2">http://smalltalkhub.com/#!/~udos/PBKDF2</a>. You can install the package using</p>
<pre class="prettyprint"><code class=" hljs lua">Gofer new
url: <span class="hljs-string">'http://smalltalkhub.com/mc/UdoSchneider/PBKDF2/main'</span>;
<span class="hljs-built_in">package</span>: <span class="hljs-string">'ConfigurationOfPBKDF2'</span>;
<span class="hljs-built_in">load</span>.
(Smalltalk at: #ConfigurationOfPBKDF2) project stableVersion <span class="hljs-built_in">load</span>.</code></pre>
<p>If you want to load the tests as well use:</p>
<pre class="prettyprint"><code class=" hljs ruleslanguage">(Smalltalk at: <span class="hljs-array">#ConfigurationOfPBKDF</span>2) project stableVersion load: <span class="hljs-string">'Tests'</span>.</code></pre>
<h2 id="usage">Usage</h2>
<pre class="prettyprint"><code class=" hljs scss">derivedKey <span class="hljs-value">:= PBKDF2 new
hashFunction: SHA1;</span>
password<span class="hljs-value">: <span class="hljs-string">'password'</span>;</span>
salt<span class="hljs-value">: <span class="hljs-string">'salt'</span>;</span>
iterations<span class="hljs-value">: <span class="hljs-number">4096</span>;</span>
length<span class="hljs-value">: <span class="hljs-number">256</span>;</span>
deriveKey.</code></pre>
<p>You can also use some convenience class methods. E.g.:</p>
<pre class="prettyprint"><code class=" hljs fix"><span class="hljs-attribute"> derivedKey :</span>=<span class="hljs-string"> PBKDF2 derivedKeySHA1Password: password salt: salt.</span></code></pre>
<p>Some settings are using defaults unless otherwise specified:</p>
<h3 id="defaults">Defaults</h3>
<ul>
<li><strong>prf:</strong> <code>HMAC-SHA-1</code></li>
<li><strong>iterations:</strong> 1000</li>
<li><strong>length:</strong> 16 Bytes</li>
</ul>
<h2 id="security">Security</h2>
<p>My current rule of thumb is to “1 second per hash”: So I configure the hash-function/iterations to consume about 1 second of time on the deployment server. So when a user logs on the server needs 1 second to validate the password. That’s no big deal - neither for the user nor for the server (unless you have hundreds of logins per second). On the other hand this also means that an attacker will need about the same time to check the password.</p>
<p>Of course the rate of passwords for PBKDF2 on a GPU is much higher than the Smalltalk implementation. But even if the GPU based approach is faster by a factor of let’s say one million this means 1.000.000 passwords per second. Using a 16 bytes derived key size this still means around 1*10<sup>25</sup> years (<code>((2 raisedTo: (16*8)) / 1000000) seconds asDays / 365</code>) to crack the password.</p>
<p>Even if we only assume simple passwords (8 characters, only letters and numbers) we get around 6 years (<code>(((26+26+10) raisedTo: 8) / 1000000) seconds asDays / 365</code>) …</p>
<h2 id="conclusion">Conclusion</h2>
<p>Configuring PBKDF2 to use 1 second per check on the deployment platform provides “enough” security for my needs … and the next deployment platform will be faster and use more iterations. </p>
<h3 id="how-to-not-do-it">How to not do it …</h3>
<p>Last but not least: Even “just” one second is much more secure than simply hashing passwords (let’s say with SHA-1 or MD5, especially w/o salts) … those can be broken instantly using rainbow tables. Just try the following with your favorite password:</p>
<pre class="prettyprint"><code class=" hljs bash">(MD5 <span class="hljs-built_in">hash</span>Message: <span class="hljs-string">'admin123'</span>) hex. <span class="hljs-string">"print-it"</span> <span class="hljs-string">'0192023a7bbd73250516f069df18b500'</span></code></pre>
<p>Google for <code>0192023a7bbd73250516f069df18b500</code>, first hit and bingo! You just broke an MD5 hashed password …</p>
<h2 id="benchmarks">Benchmarks</h2>
<p>All Benchmarks were done on an old Windows 7 Laptop (Core2Duo, 2.54GHz, 8GB):</p>
<pre class="prettyprint"><code class=" hljs profile">SystemVersion current. <span class="hljs-string">"print-it"</span> <span class="hljs-filename">Pharo3.0 of 18 March 2013 update 30851
Smalltalk vm version. "print-it" 'NBCoInterpreter NativeBoost-CogPlugin-GuillermoPolito.19 uuid</span>: acc98e51-<span class="hljs-number">2</span>fba-<span class="hljs-number">4841</span>-a965-<span class="hljs-number">2975997</span>bba66 Dec <span class="hljs-number">7</span> <span class="hljs-number">2013</span>
NBCogit NativeBoost-CogPlugin-<span class="hljs-filename">GuillermoPolito.19 uuid</span>: acc98e51-<span class="hljs-number">2</span>fba-<span class="hljs-number">4841</span>-a965-<span class="hljs-number">2975997</span>bba66 Dec <span class="hljs-number">7</span> <span class="hljs-number">2013</span>
https://<span class="hljs-filename">github.com/pharo-project/pharo-vm.git Commit</span>: <span class="hljs-number">71</span>adca113a9aff2876288927e5c1c86bf7ac13e2 Date: <span class="hljs-number">2013</span>-<span class="hljs-number">12</span>-<span class="hljs-number">07</span> <span class="hljs-number">05</span>:<span class="hljs-number">00</span>:<span class="hljs-number">47</span> -<span class="hljs-number">0800</span> By: Philippe Back <philippeback@<span class="hljs-filename">gmail.com> Jenkins build #14776
' </span></code></pre>
<h3 id="derived-key-size-16-bytes-sha1-10000-iterations">Derived Key Size 16 Bytes, SHA1, 10.000 iterations</h3>
<pre class="prettyprint"><code class=" hljs vbnet">[PBKDF2 derivedKeyHashFunction: SHA1
password: <span class="hljs-comment">'aSimplePassword'</span>
salt: <span class="hljs-number">16</span>rFEDCA9876543210
iterations: <span class="hljs-number">10000</span>
length: <span class="hljs-number">16</span>] timeToRun. <span class="hljs-string">"print-it"</span> <span class="hljs-number">0</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00.902</span>
Derived <span class="hljs-keyword">Key</span> Size <span class="hljs-number">256</span> Bytes, SHA1, <span class="hljs-number">4.096</span> iterations (<span class="hljs-keyword">as</span> used <span class="hljs-keyword">by</span> WPA2)</code></pre>
<h3 id="derived-key-size-256-bytes-sha1-4096-iterations-as-used-by-wpa2">Derived Key Size 256 Bytes, SHA1, 4.096 iterations (as used by WPA2)</h3>
<pre class="prettyprint"><code class=" hljs rsl">[PBKDF2 derivedKeyHashFunction: SHA1
password: <span class="hljs-string">'aSimplePassword'</span>
salt: <span class="hljs-number">16</span>rFEDCA9876543210
iterations: <span class="hljs-number">4096</span>
<span class="hljs-built_in">length</span>: <span class="hljs-number">256</span>] timeToRun. <span class="hljs-string">"print-it"</span> <span class="hljs-number">0</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">02.328</span>
Derived Key Size <span class="hljs-number">16</span> Bytes, SHA256, <span class="hljs-number">1.000</span> iterations</code></pre>
<h3 id="derived-key-size-16-bytes-sha256-1000-iterations">Derived Key Size 16 Bytes, SHA256, 1.000 iterations</h3>
<pre class="prettyprint"><code class=" hljs rsl">[PBKDF2 derivedKeyHashFunction: SHA256
password: <span class="hljs-string">'aSimplePassword'</span>
salt: <span class="hljs-number">16</span>rFEDCA9876543210
iterations: <span class="hljs-number">1000</span>
<span class="hljs-built_in">length</span>: <span class="hljs-number">16</span>] timeToRun. <span class="hljs-string">"print-it"</span> <span class="hljs-number">0</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">01.303</span>
Derived Key Size <span class="hljs-number">16</span> Bytes, SHA256, <span class="hljs-number">10.000</span> iterations</code></pre>
<h3 id="derived-key-size-16-bytes-sha256-10000-iterations">Derived Key Size 16 Bytes, SHA256, 10.000 iterations</h3>
<pre class="prettyprint"><code class=" hljs rsl">[PBKDF2 derivedKeyHashFunction: SHA256
password: <span class="hljs-string">'aSimplePassword'</span>
salt: <span class="hljs-number">16</span>rFEDCA9876543210
iterations: <span class="hljs-number">10000</span>
<span class="hljs-built_in">length</span>: <span class="hljs-number">16</span>] timeToRun. <span class="hljs-string">"print-it"</span> <span class="hljs-number">0</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">12.772</span>.</code></pre>
<blockquote>
<p>Written with <a href="https://stackedit.io/">StackEdit</a>.</p>
</blockquote>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com1tag:blogger.com,1999:blog-16793465.post-40021454950942706982009-07-22T15:52:00.001+02:002014-08-09T00:27:22.566+02:00Regular DLLs in Smalltalk<div xmlns="http://www.w3.org/1999/xhtml">
IMHO this is one of the longstanding feature requests for Dolphin Smalltalk (the other being Unicode support :-)) .<br />
<br />
Up to now it was not possible to create <i>normal DLLs</i> in Dolphin. The only thing you could do in Dolphin was creating <i>COM DLLs</i>. But where is the difference between a COM DLL and a normal DLL.<br />
<br />
<big><big><b>Normal DLL</b></big></big><br />
<br />
A normal DLL is a <a href="http://en.wikipedia.org/wiki/Portable_Executable">PE</a> module which <i>exports</i> functions. This means its <a href="http://msdn.microsoft.com/en-us/magazine/cc301808.aspx">export section</a> contains a list of export function names which point to function ordinals - and these ordinals point to (imagebase-relative) function addresses. After loading a DLL you can get it's address by <a href="http://msdn.microsoft.com/en-us/library/ms683212%28VS.85%29.aspx">GetProcAddress()</a>. GetProcAddress does nothing else than trying to find the provided name in the export names table and - if successfull - resolves the address by using the ordinal reference and add the base address (to get an absolute address). However ...<br />
<br />
... Dolphin is not able to create those export tables. This is (IMHO) due to the fact that the export table is part of the DLL stub that Dolphin provides. And except for a few minor changes this stub remains unchanched during deployment. Even if Dolphin could change the export table you'd still have the problem, that the "functions" would actually be Dolphin Callbacks ... and the address of those callbacks are not guaranteed to remain constant.<br />
<br />
So what <i>is </i>Dolphin able to do?<br />
<br />
<b><big><big>COM DLL</big></big></b><br />
Dolphin is able to create so called "COM Server DLLs". These COM DLLs are DLLs which "export" COM Objects by using a few predefined regular DLL export functions:<br />
<a href="http://msdn.microsoft.com/en-us/library/ms682162%28VS.85%29.aspx">DllRegisterServer()</a>, <a href="http://msdn.microsoft.com/en-us/library/ms691457%28VS.85%29.aspx">DllUnregisterServer()</a>, <a href="http://msdn.microsoft.com/en-us/library/ms690368%28VS.85%29.aspx">DllCanUnloadNow()</a>, <a href="http://msdn.microsoft.com/en-us/library/ms680760%28VS.85%29.aspx">DllGetClassObject()</a>.<br />
The first two functions are called to (un-)register the control(s) (and type libs) in the registry. The important stuff is the last function. This is the base to get a COM "Class Factory" which is able to create the COM Instances in the DLL. On the image side this is realized by the <b>IIPDolphin </b>interface (implemented by <b>IPDolphin</b>) and the <b>IIPPlughole </b>Interface.<br />
<br />
<big><b>Dolphin COM DLL/Image interaction</b></big><br />
<br />
If a process loads a Dolphin COM DLL the embedded image is not started automatically. This only happens once the first COM Call hits the DLL (i.e. via <b>DllGetClassObject()</b>). In this case the image is started and (after some setup) the current <b>IPDolphin</b>'s <b>#onStartup</b> method is called. This method queries the current DLL's <b>IIPPlugHole </b>interface. This <b>IPPlugHole </b>Interface is then used to inform the DLL about the current <b>IPDolphin </b>instance.<br />
<br />
At this stage the DLL has a (COM Interface) Pointer to the <b>IPDolphin </b>instance. This is then used to forward all the COM stuff into the image and thus allow the image to do most of the COM stuff.<br />
The nice thing about this scheme is that except for a few very low level things most of the COM Implementation is in the image - not in the VM.<br />
<br />
<big><big><b>You said Regular DLLs! I want them!</b></big></big><br />
<br />
So how to do "real" DLLs in Smalltalk. As we already saw it not possible to change the export table - but without export table no "real" DLL.<br />
<br />
The trick is to alter the export table <i>after</i> the DLL has been loaded. I found an <a href="http://kobyk.wordpress.com/2008/08/30/unexporting-a-function-from-a-dll-at-runtime-by-name-obfuscation/">article</a> dealing with <b>un-</b>exporting a function after the DLL has been called. So I thought it must also be possible to do it the other way around.<br />
<br />
To make a long story short: <b>It works</b>.<br />
A bit longer: You have to find the module base address (not that easy ... unless you know how :-) ) and from there walk through the different PE headers until you finally hit a <b>IMAGE_EXPORT_DIRECTORY</b>. This is a structure which basically points to arrays of names, ordinals and (relative) function addresses. So all you have to do is to build new new arrays (including your own names and their associated <b>ExternalCallback</b>s) and change the struct ... and as I said. <b>It works .... kind of</b>.<br />
<br />
<big><big><b>What do you mean with "works .... kind of"?</b></big></big><br />
<br />
There are two things to be aware of:<br />
<br />
<b><big>When does the export table gets modified?</big></b><br />
<br />
The export Table of the DLL, as long as it is stored on the disk, does not contain the modified Export Table. It's only modified once the image (at a very early stage) has run. However it seems (<b>PLEASE CORRECT ME if I'm wrong!!!!</b>) that the image is not started until the first COM call hits the DLL. And you can't expect third party apps to first do a COM call to your library before resolving exported functions.<br />
<br />
So let me state this as clear as possible: <span style="color: red;"><b>If you know a way to execute Smalltalk code in a DLL w/o any COM stuff going on or even better execute Smalltalk code in any event once the lib gets loaded ... <big><big>PLEASE tell me!!!!</big></big></b></span> I'll do/did the rest.<br />
<br />
<big><b>Dolphin Smalltalk X6.1 beta does not support DLL deployment!</b></big><br />
<br />
The current beta is missing the DLL Deployment capability (DLL Stubs are missing). So I did all the testing in 6.0.<br />
<br />
<big><big><b>Summary</b></big></big><br />
<br />
Modifing a modules export table is the way to go. This should cover all use cases of DLL symbols being resolved dynamically (via <b>GetProcAddress()</b>). However I'm quite sure this even works if the dynamic linker does it. And the best thing is ... it's ready!!!!<br />
<br />
So if someone can provide me with a way to get my Smalltalk code running in a DLL in any case as early as possible we will be able to have regular DLLs in Smalltalk. And the great thing is that it's all in Smalltalk - no VM suport needed ("it's turtles all the way down ...").</div>
Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com11tag:blogger.com,1999:blog-16793465.post-49505802872462420552009-05-09T00:14:00.001+02:002009-05-09T00:14:04.627+02:00Blocks in Cocoa ... finally<div xmlns='http://www.w3.org/1999/xhtml'>Apple's Objective-C Implementation and the Cocoa class library is once again getting more similar to Smalltalk. After Panther and Tiger introduced a usable MVC-like framework (Cocoa Bindings) Leopard added garbage collection.<br/><br/>And now it seems that Snow Leopard is getting Blocks as well: <a href='https://developer.apple.com/mac/articles/snowleopard/usingblockswithgrandcentraldispatch.html' target='_blank'>https://developer.apple.com/mac/articles/snowleopard/usingblockswithgrandcentraldispatch.html</a><br/><br/>So it Apple decides to wrap Number and Point as full classes (or do an auto-boxing/un-boxing) IMHO the only remaining difference is the runtime system. In Smalltalk the whole class/method structure is inspectable and changeable during runtime. In ObjC you can query/add classes/methods during runtime. Only removing classes/methods is impossible .... but maybe this will change in Snow Leopard as well.<br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=86150e63-c6dc-8048-8702-3065207749c6' class='zemanta-pixie-img'/></div></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com1tag:blogger.com,1999:blog-16793465.post-45371177122601617982009-05-04T20:33:00.001+02:002009-05-04T20:33:27.734+02:00Just got my Smalltalk BYTE issue!!!!<div xmlns='http://www.w3.org/1999/xhtml'><img src='http://lh5.ggpht.com/_LgtWlMgLwpA/Sf80w1OeVoI/AAAAAAAAAPc/cisbx1CXKi4/%5BUNSET%5D.jpg?imgmax=800' style='max-width: 800px; float: left; margin-top: 10px; margin-bottom: 10px; margin-right: 10px;'/><br/>I got it! I finally got it! I found an auction on EBay where somebody sold the original 1981 BYTE issue introducing Smalltalk to the world!<br/><br/><br/>Maybe I'm crazy - but I like to collect "original" Smalltalk stuff. I got the green, orange and blue book on Ebay ... and now finally the BYTE issue. What a wonderfull day :-)<br/><br/><br/><div class='zemanta-pixie'><img src='http://img.zemanta.com/pixy.gif?x-id=6da42ee7-7648-8d5c-bde3-ebdba1991fc5' class='zemanta-pixie-img'/></div></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-13780694378957314612008-06-11T18:31:00.001+02:002008-06-11T18:31:28.112+02:00Extended STS as Dolphin Smalltalk public source code repository<div xmlns='http://www.w3.org/1999/xhtml'>I just learned that David Gorisek extended STS for shared repository access. You basically keep your own local (shared) STS repository and publish certain Project Editions to the central repository.<br/><br/>This allows you (or a team) to keep your working repository separated from the shared one. If (and only then) a project edition is "stable" you can push it to the shared repository. That's really awesome.<br/><br/>I am working on something similar - although with a different focus: Some of my packages depend on external files (resources, dlls). So I'm concentrating on embedding these files as well - but Davids solution as one huge advantage: It's available and works <b><i>today</i></b>. I'm working with STS on daily basis and can't live w/o it. So go ahead and try it and publish your goodies. This will help the Dolphin community in general IMHO.<br/><br/>You can find all the glory details under <a href='http://sts.gorisek.com/sts/WikiPage' target='_blank'>sts.gorisek.com</a>. This is an WikiDoc server with an additional STS layer. So you can push your stuff to it and also write WikiPages (i.e. with further instructions).<br/></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com1tag:blogger.com,1999:blog-16793465.post-12266131422692047172008-05-22T23:04:00.001+02:002008-05-22T23:06:03.097+02:00How to add/modify contextmenu of URLPresenter/IWebBrowser2?<div xmlns='http://www.w3.org/1999/xhtml'><div style=''>I just found a newgroup entry asking how to "<a href='http://groups.google.com/group/comp.lang.smalltalk.dolphin/browse_thread/thread/c2642ce3429eb083#'>add/modify contextmenu of URLPresenter</a>". So it's time again to give some examples to a goodie I wrote.<br/><br/>URLPresenterWithContextMenu (in package "US Internet Explorer Extensions") allows you to control <i>which</i> context menu is displayed in a WebControl:<br/><ul><li>If the presenters view <code>#allowContextMenu</code> aspect is false no context menu will be shown. Neither a custom one nor the default one.</li><li>If the presenters view <code>#allowContextMenu</code> aspect is true it depends on <code>#contextMenu</code>. If <code>#contextMenu</code> is not nil it will be displayed. If it is nil the default one will be used.</li></ul><br/>Behind the scenes this presenter implements the <code>IDocHostUIHandlerDispatch</code> interface to get queries for some UI events. The interesting one here is <code>ShowContextMenu()</code> which allows you to allow/prevent the display of the default context menu. I'm using this method for the logic using <code>#allowContextMenu</code> and <code>#contextMenu</code>.<br/><br/>However for <i>using</i> this presenter no digging into COM is needed. Simply use <code>#allowContextMenu</code> and <code>#contextMenu</code> as written above.</div></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-85453371099423071502008-05-22T22:49:00.002+02:002008-05-22T22:51:42.057+02:00Embedding link to file in textbox contents<div xmlns='http://www.w3.org/1999/xhtml'><div style=''>I just found a newgroup entry asking how to <a href='http://groups.google.com/group/comp.lang.smalltalk.dolphin/browse_thread/thread/f617b2ac5dceba56#'>add "links" to Textboxes</a>. So it's time again to give some examples to a goodie I wrote.<br/><br/>Welcome to "US RichTextEdit Extensions". This goodie enables some capabilites in the Windows RTF control. Surprisingly enough the RTF control already supports Links and is also able to automatically detect URLs and turn them into links. If the link you want is not a URL you have to make them linkable on your own - but thats not very hard.<br/><br/>Let's see some code:<br/><br /><code><br /><span class="variable">presenter</span> := <span class="variable">RichTextPresenter</span> </br><br /> <span class="message">showOn:</span> <span class="literal">'This is my E-Mail Address: mailto:Udo.Schneider@homeaddress.de . <br />Just drop me a mail or visit me here: http://readthesourceluke.blogspot.com/'</span> </br><br /> <span class="message">asRichText</span>.</br><br />(<span class="variable">presenter</span> <span class="message">view</span>)</br><br /> <span class="message">autoUrlDetect:</span> <span class="literal">true</span>;</br><br /> <span class="message">link:</span> <span class="literal">true</span>;</br><br /> <span class="message">enableMailtoLinks</span>.</br><br /><span class="variable">presenter</span> </br><br /> <span class="message">when:</span> <span class="literal">#linkClicked:</span></br><br /> <span class="message">send:</span> <span class="literal">#value:</span></br><br /> <span class="message">to:</span> </br><br /> [:<span class="variable">link</span> | </br><br /> <span class="variable">MessageBox</span> <span class="message">notify:</span> <span class="variable">link</span></br><br /> <span class="message">caption:</span> <span class="literal">'Link clicked'</span>]<br /></code><br/><br/>So if you have a RichTextPresenter view you can use #autoUrlDetect: to enable/disable the automatic linking of URLs. #link: is used to enable linking in general. So even if #autoUrlDetect is true you won't see any links until you set #link: to true.<br/><br/>The package also contains a method to make mailto: links linkable.<br/>#enableMailtoLinks parses the text and for mailto: links and hides the mailto: prefix so that only the email address remains. However the link itself still contains the mailto: + email combinations. This is a good example how to use non-visible pre- and postfixes for link.<br/><br/>This is i.e. useful if you want to present a "simple link" to the user but need a more descriptive link for your program.<br/><br/>To capture clicked links you simply have to hook up the the #linkClicked: event in your #createSchemanticWiring method. The event parameter is the complete link - not only the user visible part. So in the mailto: link above you will get a "mailto:Udo.Schneider@homeaddress.de" although only "Udo.Schneider@homeaddress.de" is visible to the user.</div></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-4367433522056035582008-04-23T00:35:00.001+02:002008-04-23T00:37:49.655+02:00NotifyArea Icons done right (hopefully this time!)<div xmlns='http://www.w3.org/1999/xhtml'>I had enough of it. Using the "Traybar" with my NotifyView was a pain in the a.. . I admit it - I'm guilty. So I decided to do it right this time. <br/><br/>My "US NotifyView" package contains a new and natural way to deal with NotifyArea Icons. No need to hassle with views. Simply create one (or many) instance(s) of NotifyAreaIcon and use simply messages like <code>#show</code>, <code>#hide</code>, <code>#icon:</code> and <code>#message</code>. That's it. If you want events simply catch <code>#leftButtonPressed</code>, <code>#leftButtonDoubleClicked</code>, <code>#rightButtonPressed</code> or <code>#rightButtonDoubleClicked</code>.<br/><br/>Using NotifyAreaIcons also gives you two things which are IMHO not part of any other Dolphin Traybar goodie.<br/><ul><li><b>Survives Image Reload</b>: If you save/close your image with visible Traybar icons they are restored if you reopen the image</li><li><b>Explorer crash support</b>: If your explorer crashes and rebuilds it's traybar your icons are re-added as well.</li></ul><br/>The following code illustrates it a bit more. Simply download the newest version of my goodies (04/23/2008) and enjoy.<br/><pre><br/>| <span class='temp'><span class='variable'>notifyIcon</span></span> <span class='temp'><span class='variable'>notifyIcons</span></span> |<br/><span class='comment'>"Create your instance. No need to hassle with Views. Simply create an instance"</span><br/><span class='variable'>notifyIcon</span> := <span class='variable'>NotifyAreaIcon</span> <br/> <span class='message'>icon:</span> (<span class='variable'>Icon</span> <span class='message'>fromId:</span> <span class='literal'>'!APPLICATION'</span>)<br/> <span class='message'>message:</span> <span class='literal'>'My Application'</span>.<br/><span class='comment'>"If you want your icon to be displayed, simply send #show"</span><br/><span class='variable'>notifyIcon</span> <span class='message'>show</span>.<br/><span class='comment'>"You can change the tip message and the icon any time by using #icon: and #message: .<br/>If the icon is currently visible it's automatically updated."</span><br/><span class='variable'>notifyIcon</span> <br/> <span class='message'>icon:</span> <span class='variable'>Icon</span> <span class='message'>defaultApplication</span>.<br/><span class='variable'>notifyIcon</span> <span class='message'>message:</span> <span class='literal'>'Changed message'</span>.<br/><span class='comment'>"You can use this i.e. to display animations"</span><br/><span class='variable'>Icon</span> <span class='message'>allInstances</span> <span class='message'>asSet</span> <br/> <span class='message'>do:</span> <br/> [:<span class='variable'>each</span> | <br/> <span class='variable'>notifyIcon</span><br/> <span class='message'>icon:</span> <span class='variable'>each</span>;<br/> <span class='message'>message:</span> <span class='variable'>each</span> <span class='message'>identifier</span> <span class='message'>displayString</span>].<br/><span class='comment'>"The icon triggers several messages which you can intercept using the regular<br/>#when:send:to: mechanism"</span><br/><span class='variable'>notifyIcon</span> <br/> <span class='message'>when:</span> <span class='literal'>#leftButtonPressed</span><br/> <span class='message'>send:</span> <span class='literal'>#value</span><br/> <span class='message'>to:</span> [<span class='variable'>Sound</span> <span class='message'>beep</span>].<br/><span class='variable'>notifyIcon</span> <br/> <span class='message'>when:</span> <span class='literal'>#leftButtonDoubleClicked</span><br/> <span class='message'>send:</span> <span class='literal'>#value</span><br/> <span class='message'>to:</span> <br/> [<span class='variable'>Sound</span> <span class='message'>beep</span>.<br/> (<span class='variable'>Delay</span> <span class='message'>forMilliseconds:</span> <span class='literal'>500</span>) <br/> <span class='message'>wait</span>.<br/> <span class='variable'>Sound</span> <span class='message'>beep</span>].<br/><span class='variable'>notifyIcon</span> <br/> <span class='message'>when:</span> <span class='literal'>#rightButtonPressed</span><br/> <span class='message'>send:</span> <span class='literal'>#value</span><br/> <span class='message'>to:</span> [<span class='variable'>Sound</span> <span class='message'>bell</span>].<br/><span class='variable'>notifyIcon</span> <br/> <span class='message'>when:</span> <span class='literal'>#rightButtonDoubleClicked</span><br/> <span class='message'>send:</span> <span class='literal'>#value</span><br/> <span class='message'>to:</span> <br/> [<span class='variable'>Sound</span> <span class='message'>bell</span>.<br/> (<span class='variable'>Delay</span> <span class='message'>forMilliseconds:</span> <span class='literal'>500</span>) <br/> <span class='message'>wait</span>.<br/> <span class='variable'>Sound</span> <span class='message'>bell</span>].<br/><span class='comment'>"If you don't need the icon anymore (e.g. during #onViewClosed) you can simply hide<br/>it or nil the variable and let GC take care of it"</span><br/><span class='variable'>notifyIcon</span> <span class='message'>hide</span>.<br/><span class='variable'>notifyIcon</span> := <span class='literal'>nil</span>.<br/><br/><span class='comment'>""</span><br/><span class='comment'>"You can even generate a whole bunch of instances"</span><br/><span class='variable'>notifyIcons</span> := <span class='variable'>Icon</span> <span class='message'>allInstances</span> <br/> <span class='message'>asSet</span> <span class='message'>collect:</span> <br/> [:<span class='variable'>each</span> | <br/> <span class='variable'>NotifyAreaIcon</span> <span class='message'>icon:</span> <span class='variable'>each</span><br/> <span class='message'>message:</span> <span class='variable'>each</span> <span class='message'>identifier</span> <span class='message'>displayString</span>].<br/><span class='comment'>"If you want to stress test your system, show /all/ icons"</span><br/><span class='variable'>notifyIcons</span> <br/> <span class='message'>do:</span> [:<span class='variable'>each</span> | <span class='variable'>each</span> <span class='message'>show</span>].<br/><span class='comment'>"Please note, that we don't hide icons here. We simply nil the instance and let GC<br/>take care of it"</span><br/><span class='variable'>notifyIcons</span> := <span class='literal'>nil</span>.<br/><span class='comment'>"You can also force a GC"</span><br/><span class='variable'>MemoryManager</span> <span class='message'>current</span> <span class='message'>collectGarbage</span><br/></pre></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com1tag:blogger.com,1999:blog-16793465.post-79915742662893206482008-04-22T17:43:00.001+02:002008-04-22T17:43:30.625+02:00Did you know? Drag&Drop from Inspector to workspace<div xmlns='http://www.w3.org/1999/xhtml'>I thought I had a great idea how to improve the IDE. Dragging objects from an inspector to a workspace. This would allow you to work with these objects in a "big" workspace and not within the tiny inspector area. After spending some time browsing the class lib to get a clue how to to it I set a break point and simply dragged and object to a workspace. To my great surprise it worked! Dolphin was doing exactly what I was trying to implement.<br /><br />So it turned out that OA already implemented what I wanted!!! Once more it seems that DST is the best IDE one can think of. Even the things one dreams of are already there :-)<br /><br /><br /><script type='text/javascript'>swfobject.embedSWF("http://udos.s3.amazonaws.com/blog/InspectorDnD/InspectorDnD.swf", "InspectorDnD", "565", "722", "9.0.0", "http://udos.s3.amazonaws.com/blog/expressInstall.swf");</script><br /><div id='InspectorDnD'><br /><h1>Flash plugin not installed or too old!</h1><br /><p><a href='http://www.adobe.com/go/getflashplayer'><img alt='Get Adobe Flash player' src='http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif'/></a></p><br /></div></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com2tag:blogger.com,1999:blog-16793465.post-65858731421055739602008-04-14T18:06:00.009+02:002008-04-22T17:37:18.061+02:00Dolphin Smalltak in PSPad<div xmlns='http://www.w3.org/1999/xhtml'>IMHO having a good editor and learn to use it is one of the most important things to do when working with computers. And it will save you a lot of time in the long run!!<br /><br />A few years back I was using UltraEdit until I discovered <a href='http://www.pspad.com/'>PSPad</a>. PSPad offers everything I needed and it is free. It also has the concept of scripts written in JScript, VBScript and Python. As the object model also supports COM it's also possible to access external COMponents.<br /><br />Some time ago I read a blog entry <a href='http://www.cincomsmalltalk.com/userblogs/troy/blogView?showComments=true&printTitle=Phasing_out_TextPad_in_favor_of_NOTEPAD++&entry=3356852200' rel='bookmark'>Phasing out TextPad in favor of NOTEPAD++</a> when I got the idea to embed the workspace text functions of Dolphin Smalltalk into PSPad. Here is what I came up with:<br /><img src='http://udos.s3.amazonaws.com/blog/COMEvaluator/comeval.png'/><br /><br /><b>Demo/Installation</b><br /><br /><ul><li>Load the "US Dolphin COM Evaluator.pac" package. The install scripts register the coclass and interface automatically.</li><li>Register the type library "dolphineval.tlb". You can do this directly from within Dolphin.</li><li>Copy "DolphinSmalltalk.js" into PSPad's Script\JScript directory</li><li>Enjoy Dolphin Smalltalk in PSPad!!!</li></ul><br /><br /><script type="text/javascript">swfobject.embedSWF("http://udos.s3.amazonaws.com/blog/COMEvaluator/COMEvaluator.swf", "PSPad", "854", "738", "9.0.0", "http://udos.s3.amazonaws.com/blog/expressInstall.swf");</script><br /><div id="PSPad"><br /><h1>Flash plugin not installed or too old!</h1><br /><p><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p><br /></div><br /><br /></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-50828152909978808402008-04-14T17:40:00.001+02:002008-04-14T17:40:02.044+02:00Useful components from Terra Informatica<div xmlns='http://www.w3.org/1999/xhtml'>I just found to components on <a href='http://www.terrainformatica.com/'>Terra Informatica</a> which might be worth wrapping them in Smalltalk.<br/><br/><b>HTMLayout</b><br/><div align='left'>The first one is a HTMLView called "<a href='http://www.terrainformatica.com/htmlayout/main.whtm'>HTMLayout</a>". As far as I understand up to know it simply registers it's own window class and communicates via custom window messages and WM_NOTIFY with the host applications. Both things are pretty straight forward in DST<br/></div><br/><b>TIScript</b><br/>The second one is a ECMA-/JavaScript compatible Scripting component called "<a href='http://www.terrainformatica.com/tiscript/'>TIScript</a>". Browsing through the C header files it seems that embedding and providing (wrapped) Smalltalk objects to it is pretty easy.<br/>Up to now I used BeeBasic as a Scripting Engine. However the vendor seems to have disappeared - so I'm searching for alternatives. And no, <i>WSH is not an alternative</i>!<br/> </div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-45773110363990106852008-04-13T00:22:00.001+02:002008-04-13T00:22:35.695+02:00Ghoul for DST6<div xmlns='http://www.w3.org/1999/xhtml'>Sometime ago I patched Ghoul to be compatible with DST6 and wrote Chris about it. As it seems that Metagnostic is down and that there will be no further enhancements of Chris' goodies I decided to release it directly.<br/><br/>So here we have Ghoul again running under Dolphin DST6:<br/><img src='http://udos.s3.amazonaws.com/blog/ghoul/20080412_Ghoul_for_DST6.jpg'/><br/><br/>You can download the package <a href='http://udos.s3.amazonaws.com/blog/ghoul/Ghoul_for_DST6.zip'>here</a>. Please note, that you still need a copy of Chris' goodies to have access to the documentation and more.</div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com2tag:blogger.com,1999:blog-16793465.post-77829734732833328872008-04-12T23:11:00.003+02:002008-04-13T11:13:35.967+02:00External Tools in Dolphin Idea Spaces<div xmlns='http://www.w3.org/1999/xhtml'>Based on a request in <a href='http://groups.google.com/group/comp.lang.smalltalk.dolphin/topics'>c.l.s.d</a> "<a href='http://groups.google.com/group/comp.lang.smalltalk.dolphin/browse_thread/thread/90a360927d7f0e80#'>drag Squeak Shell To Dolphin's IdeaSpace</a>" I decided to investigate an idea I got from an article at <a href='http://www.codeproject.com/'>codeproject</a> (<a href='http://www.codeproject.com/KB/dialog/exeHosting.aspx'>Hosting .exe applications into a dialog</a>). My goal was to get something similar in Dolphin - but packaged in a nice MVP friendly way.<br/><br/>Here is what I came up with:<br/><b><br/>ExternalProcessPresenter/ExternalProcessView</b><br/><br/>This combination allows you to display a external application within a Dolphin View/Presenter. It uses ExternalProcess (from <a href='http://www.nls.net/mp/jarvis/Bob/DolphinGoodies.htm'>Bob Jarvis</a> Goodies) as it's model. This also means that you cannot wrap already running processes with it. The process has to be started from within Dolphin.<br/><br/>So you'll need the model first:<br/><pre><br/>| <span class='temp'><span class='variable'>externalProcess</span></span> |<br/><span class='variable'>externalProcess</span> := (<span class='variable'>ExternalProcess</span> <span class='message'>new</span>)<br/> <span class='message'>commandLine:</span> (<span class='variable'>SpecialFolderRelativeFileLocator</span> <span class='message'>windows</span> <br/> <span class='message'>localFileSpecFor:</span> <span class='literal'>'system32\sol.exe'</span>);<br/> <span class='message'>yourself</span>.<br/></pre><br/>Now we show the presenter:<br/><pre><br/><span class='variable'>ExternalProcessPresenter</span> <span class='message'>showOn:</span> <span class='variable'>externalProcess</span><br/></pre>DONE! This is what you should get:<br/><img src='http://udos.s3.amazonaws.com/blog/externalProcessView/20080412_ExternalProcessPresenter.jpg'/><br/><br/>Cool, isn't it?<br/><br/><b>ExternalToolShell</b><br/><br/>It even get's better. I added a Dolphin Smalltalk Integration to manage a set of external tools and run them within IdeaSpaces. Start the external Tools shell from the addition Tools folder and you'll get a shell with a List of known tools on the left. You are able to add and delete external tools and start them via double click. This allows you to e.g. run Squeak within Dolphin:<br/><img src='http://udos.s3.amazonaws.com/blog/externalProcessView/20080412_ExternalToolShell.jpg' /><br/><br/>I hope this is useful for somebody.<br/><br/><b>WARNINGS/LIMITATIONS</b><br/><br/><ul><li>This goodie is a Hack!!! - even for a Windows app. So you have been warned!!!</li><li>Single toplevel Window Applications only: If the application opens multiple top level windows only one will be shown in an IdeaSpace!</li><li>Force quit on View close: Currently the process' view is destroyed and the process terminated if the ExternalProcessView is closed. There is no onClose Handling</li><li>Redraw problems: Some controls (especially menus) have redraw problems. This is due to the fact that Windows never intended an application to have a MenuBar in a non-TopLevel Window</li><li>Focus Problem: When interacting with controls within the window the parent shell (IdeaSpace) looses the focus.</li></ul><br/><b>Download</b><br/>Just download the newest version of my goodies and have fun!</div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com1tag:blogger.com,1999:blog-16793465.post-54920498799107947282008-03-28T17:29:00.001+01:002008-03-28T17:29:29.182+01:00Autocomplete with Images<div xmlns='http://www.w3.org/1999/xhtml'>My Autocomplete extensions are now part of the goodies package. What's new compared to the last version:<br/><dl><br/><dt>Survives Image Reload</dt><br/><dd>This version deals with image exits/loads and (re-)creates the image cache if needed.</dd><br/><dt>New functionalities</dt><br/><dd>Different MessageSend icons depending on whether you are sending a "normal", private, public, deprecated or development system message.<br/></dd><br/><dt>New Images</dt><br/><dd><ul><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/self.png'/>: self</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/super.png'/>: super</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/Context.png'/>: thisContext</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/ClassVariable.png'/>: Class Variable</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/InstanceVariable.png'/>: Instance Variable</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/MethodVariable.png'/>: Method Variable (Argument or temp)</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/MessageSend.png'/>: "Normal" method</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/PublicMessageSend.png'/>: Public method</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/PrivateMessageSend.png'/>: Private method</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/DeprecatedMessageSend.png'/>: Deprecated method</li><br/><li><img src='http://udos.s3.amazonaws.com/blog/autocomplete/DevelopmentMessageSend.png'/>: Development method</li><br/></ul></dd><br/></dl><br/>With this goodie it's more important than ever to use good looking class icons (see also <a href='http://dolphinseaside.blogspot.com/2007/11/keep-it-candy.html'>Keep it candy</a>) as they are not only shown in the Class Browser but in every Autocompletition menu as well :-)</div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-32688972416909930002008-03-28T15:21:00.002+01:002008-04-14T10:59:58.294+02:00Filenames from Clipboard and via native Drag&DropI just found two tiny packages which might help you to improve the native integration of your app with Windows. Both deal with getting file(names) from the user.<br /><br />1) Clipboard (US Clipboard Extensions)<br />You can get filenames from the Clipboard using <code>#getFilenamesIfNone:</code> or simply using <code>#getFilenames:</code><br /><pre><br /><span class='variable'>filenames</span> := <span class='variable'>Clipboard</span> <span class='message'>current</span> <span class='message'>getFilenamesIfNone:</span> [].<br /><span class='variable'>filenames</span> := <span class='variable'>Clipboard</span> <span class='message'>current</span> <span class='message'>getFilenames</span>.<br /></pre><br />2) (Native) Drag&Drop (US DragAndDrop Extensions)<br />This package allows you to get filenames from a Drag&Drop Session using <code>#dragFilenames:</code>:<br /><pre><br /><span class='variable'>filenames</span> := <span class='variable'>aDragDropSession</span> <span class='message'>dragFilenames</span><br /></pre><br />E.g. you can use it in the following D&D code:<br /><pre><br /><span class='selector'>onDragOverList:</span> <span class='variable'>aDragDropSession</span> <br /> | <span class='temp'><span class='variable'>filenames</span></span> |<br /> <span class='variable'>filenames</span> := <span class='variable'>self</span> <br /> <span class='message'>filterFilenames:</span> <span class='variable'>aDragDropSession</span> <span class='message'>dragFilenames</span>.<br /> <span class='variable'>aDragDropSession</span> <br /> <span class='message'>operation:</span> (<span class='variable'>filenames</span> <span class='message'>notEmpty</span> <br /> <span class='message'>ifTrue:</span> [<span class='literal'>#copy</span>]<br /> <span class='message'>ifFalse:</span> [<span class='literal'>#none</span>])<br /><br /><span class='selector'>onDropOverList:</span> <span class='variable'>aDragDropSession</span> <br /> | <span class='temp'><span class='variable'>filenames</span></span> |<br /> <span class='variable'>filenames</span> := <span class='variable'>self</span> <br /> <span class='message'>filterFilenames:</span> <span class='variable'>aDragDropSession</span> <span class='message'>dragFilenames</span>.<br /> <span class='variable'>filenames</span> <span class='message'>notEmpty</span> <br /> <span class='message'>ifTrue:</span> <br /> [<span class='variable'>self</span> <span class='message'>addFiles:</span> <span class='variable'>filenames</span>]<br /></pre><br /><br /><code>#filterFilenames:</code> is one of my methods which selects only extensions acceptable for the Application.<br /><br />Both packages are part of my goodies which are available on this site.Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-25232301564031980262007-11-21T10:04:00.001+01:002007-11-21T10:04:02.123+01:00Dolphin Map - To Do List<div xmlns='http://www.w3.org/1999/xhtml'><ul><li>Clean up backend code</li><li>Polish up the natvie GUI</li><li>Built a Seaside frontend</li></ul></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-61442335320870915122007-11-21T10:03:00.001+01:002007-11-21T10:03:08.072+01:00Dolphin Map Online Repository works<div xmlns='http://www.w3.org/1999/xhtml'>The client and server side is ready. Due to Swazoo it was very easy to create a DolphinMap resource to accepts client requests. As the client uses standard HTTP for communication this should also work w/o problems behind firewalls and in proxy setups.<br/></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-58139485293035543532007-11-19T12:04:00.001+01:002008-03-28T17:51:18.855+01:00Dolphin Map is comming along...<div xmlns='http://www.w3.org/1999/xhtml'>DolphinMap just hit its first Milestone. The current version is able to:<br/><ul><li>Use a local file based repository</li><li>Import Packages (and/or additional files) into Bundles</li><li>Sign Bundles with Dolphin Sure certificates</li><li>Export Bundles to filesystem</li><li>Export Bundles as Zip</li><li>Manage Bundles (Update and Delete)</li></ul><br/>The next step is an online repository which will allow us to move/copy bundles between different repositories.<br/><br/>Although not yet complete I'm already using it on a daily basis for Zip File creation. You simply define once what's in a bundle (packages and additional files like icons and documentation) and then simply update bundles if anything changes. These bundles can then easily be exported to zip files.<br/><br/></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com1tag:blogger.com,1999:blog-16793465.post-13149210528227871002007-11-16T17:30:00.001+01:002007-11-21T00:03:56.707+01:00My Image Startup script<div xmlns='http://www.w3.org/1999/xhtml'>Following a previous post some people asked me how my Image Startup script looks like. Well - here it is. I run this script in a clean image and it sets all the correct bits and pieces and loads all necessary packages.<br /><br /><pre><br /><span class='variable'>Transcript</span> <span class='message'>clear</span>.<br /><br /><span class='comment'>"Set personal Settings"</span><br />(<span class='variable'>SmalltalkSystem</span> <span class='message'>current</span>)<br /> <span class='message'>autoFormatMethodSource:</span> <span class='literal'>true</span>;<br /> <span class='message'>showSplashAtStartup:</span> <span class='literal'>false</span>.<br /><span class='variable'>SmalltalkSystem</span> <span class='message'>current</span> <span class='message'>tipOfTheDayClass</span> <br /> <span class='message'>showTipsAtStartup:</span> <span class='literal'>false</span>.<br /><span class='variable'>SmalltalkSystem</span> <span class='message'>current</span> <br /> <span class='message'>workspaceShellClass</span> <span class='message'>variableTips:</span> <span class='literal'>true</span>.<br /><span class='comment'>"Connect STS Repositry"</span><br /><span class='variable'>stsRepositryPath</span> := <span class='literal'>'S:\Dolphin Smalltalk X6\STS Repositry'</span>.<br /><span class='variable'>StsManager</span> <span class='message'>startUpOn:</span> <span class='variable'>stsRepositryPath</span>.<br /><span class='comment'>"Backup Repositry and reorganize"</span><br /><span class='variable'>stsBackupPathStream</span> := <span class='variable'>ReadWriteStream</span> <br /> <span class='message'>on:</span> <span class='variable'>String</span> <span class='message'>new</span>.<br /><span class='variable'>stsBackupPathStream</span><br /> <span class='message'>nextPutAll:</span> <span class='variable'>stsRepositryPath</span>;<br /> <span class='message'>nextPutAll:</span> <span class='literal'>'/Repository.BACKUP_'</span>.<br /><span class='variable'>Date</span> <span class='message'>today</span> <br /> <span class='message'>printOn:</span> <span class='variable'>stsBackupPathStream</span><br /> <span class='message'>format:</span> <span class='literal'>'yyyyMMdd'</span>.<br /><span class='variable'>Time</span> <span class='message'>now</span> <br /> <span class='message'>printOn:</span> <span class='variable'>stsBackupPathStream</span><br /> <span class='message'>format:</span> <span class='literal'>'HHmmss'</span>.<br />(<span class='variable'>StsManager</span> <span class='message'>current</span> <span class='message'>databaseConnection</span>)<br /> <span class='message'>createBackupOn:</span> <span class='variable'>stsBackupPathStream</span> <span class='message'>contents</span>;<br /> <span class='message'>reorganize</span>.<br /><span class='comment'>"Install Restore as this can't be loaded from STS"</span><br /><span class='variable'>Package</span> <span class='message'>manager</span> <span class='message'>install:</span> <span class='literal'>'S:\Dolphin Smalltalk X6\Solutions Software\ReStore120_D6\SSW ReStore MVP.pac'</span>.<br /><span class='comment'>"Packages to ignore"</span><br /><span class='variable'>ignorePackageNames</span> := #(<span class='literal'>'US ActiveX'</span> <span class='literal'>'US Speedometer Control'</span>).<br /><span class='comment'>"Find all US Packages to be loaded"</span><br /><span class='variable'>loadPackageNames</span> := ((<span class='variable'>StsManager</span> <br /> <span class='message'>current</span> <span class='message'>getAllPackageNames</span> <br /> <span class='message'>select:</span> <br /> [:<span class='variable'>eachPackageName</span> | <br /> <span class='variable'>eachPackageName</span> <span class='message'>beginsWith:</span> <span class='literal'>'US'</span>]) <br /> <span class='message'>reject:</span> <br /> [:<span class='variable'>eachPackageName</span> | <br /> <span class='variable'>ignorePackageNames</span> <br /> <span class='message'>includes:</span> <span class='variable'>eachPackageName</span>]) <br /> <span class='message'>asOrderedCollection</span>.<br /><span class='comment'>"Load Packages and Prerequsisites"</span><br />[<span class='variable'>loadPackageNames</span> <span class='message'>notEmpty</span>] <span class='message'>whileTrue:</span> <br /> [<span class='variable'>currentPackageName</span> := <span class='variable'>loadPackageNames</span> <br /> <span class='message'>removeFirst</span>.<br /> <span class='variable'>stsPackage</span> := (<span class='variable'>StsManager</span> <span class='message'>current</span> <br /> <span class='message'>getPackageEditionsFor:</span> <span class='variable'>currentPackageName</span>) <br /> <span class='message'>first</span>.<br /> <span class='variable'>prerequisitePackageNames</span> := (<span class='variable'>stsPackage</span> <br /> <span class='message'>prerequisiteNames</span> <span class='message'>reject:</span> <br /> [:<span class='variable'>each</span> | <br /> (<span class='variable'>ignorePackageNames</span> <span class='message'>includes:</span> <span class='variable'>each</span>) <br /> <span class='message'>or:</span> <br /> [<span class='variable'>Package</span> <span class='message'>manager</span> <br /> <span class='message'>includesPackageNamed:</span> <span class='variable'>each</span>]]) <br /> <span class='message'>asOrderedCollection</span>.<br /> <span class='variable'>prerequisitePackageNames</span> <span class='message'>isEmpty</span> <br /> <span class='message'>ifTrue:</span> <br /> [<span class='variable'>stsPackage</span> <span class='message'>isLoaded</span> <br /> <span class='message'>ifFalse:</span> [<span class='variable'>stsPackage</span> <span class='message'>load</span>]]<br /> <span class='message'>ifFalse:</span> <br /> [<span class='variable'>loadPackageNames</span> := <span class='variable'>loadPackageNames</span> <br /> <span class='message'>,</span> <span class='variable'>prerequisitePackageNames</span>.<br /> <span class='variable'>loadPackageNames</span> <br /> <span class='message'>addLast:</span> <span class='variable'>currentPackageName</span>]]<br /></pre></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-35760644919679209562007-11-13T18:07:00.001+01:002007-11-13T18:07:35.556+01:00New version of Seaside (IDB Package clash fixes)<div xmlns="http://www.w3.org/1999/xhtml">Esteban just published an <a href="http://dolphinseaside.blogspot.com/2007/11/and-again.html">updated version</a> of Seaside which fixes the package clash problems I had.<br />That's IMHO one of the great things in the Dolphin Community: Reaction times are absolutely amazing. I'm loving it.<br /></div>Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0tag:blogger.com,1999:blog-16793465.post-2535470962310148792007-11-13T15:24:00.002+01:002008-04-29T09:48:07.325+02:00Can't connect to Seaside (SOLVED)It seems that accessing Dolphin/Seaside is <b>only possible using the URL <code>http://localhost:8888/seaside</code></b>. Every other host (e.g. "127.0.0.1" or an external IP) doesn't work. This definitely limits it's use - however I cannot imagine that this is a bug. I think this is intended behavior which I simply do not understand.<br /><br /><big><b>UPDATE:</b></big><br />This was indeed intended behavoir - of Swazoo in this case. Swazoo uses "Sites" defined by hostname, ip and port to offer virtual hosting. And these Site definitions are very strict. E.g.<br /><pre><br /><span class="variable">site</span> := <span class="variable">Site</span> <span class="message">new</span> </br><br /> <span class="message">name:</span> <span class="literal">'seaside'</span>.</br><br /><span class="variable">site</span> </br><br /> <span class="message">host:</span> <span class="literal">'localhost'</span></br><br /> <span class="message">ip:</span> <span class="literal">'127.0.0.1'</span></br><br /> <span class="message">port:</span> <span class="literal">8888</span>.</br><br /><span class="variable">site</span> </br><br /> <span class="message">addResource:</span> (<span class="variable">composite</span> := <span class="variable">CompositeResource</span> </br><br /> <span class="message">uriPattern:</span> <span class="literal">'/'</span>).</br><br /><span class="variable">composite</span> </br><br /> <span class="message">addResource:</span> (<span class="variable">SeasideSwazooResource</span> </br><br /> <span class="message">uriPattern:</span> <span class="literal">'seaside'</span>).</br><br /><span class="variable">site</span></br><br /> <span class="message">addAlias:</span> (<span class="variable">SiteIdentifier</span> </br><br /> <span class="message">ip:</span> <span class="literal">'127.0.0.1'</span></br><br /> <span class="message">port:</span> <span class="literal">8888</span></br><br /> <span class="message">host:</span> <span class="literal">'localhost'</span>);</br><br /> <span class="message">addAlias:</span> (<span class="variable">SiteIdentifier</span> </br><br /> <span class="message">ip:</span> <span class="literal">'127.0.0.1'</span></br><br /> <span class="message">port:</span> <span class="literal">8888</span></br><br /> <span class="message">host:</span> <span class="literal">'172.16.1.128'</span>).</br><br /><span class="variable">SwazooServer</span> <span class="message">singleton</span> </br><br /> <span class="message">addSite:</span> <span class="variable">site</span>.</br><br /><span class="variable">SwazooServer</span> <span class="message">start</span><br /></pre><br /><br />This site definition will listen only to <code>http://localhost:8888/seaside/</code>. Even <code>http://127.0.0.1:8888/seaside/</code> won't work as <code>127.0.0.1</code> does not equal <code>localhost</code> for Swazoo (although it does for DNS).<br /><br />The solution is to use Site Aliases to allow Swazoo to handle thos situations. E.g.:<br /><pre><br /><span class="variable">site</span></br><br /> <span class="message">addAlias:</span> (<span class="variable">SiteIdentifier</span> </br><br /> <span class="message">ip:</span> <span class="literal">'127.0.0.1'</span></br><br /> <span class="message">port:</span> <span class="literal">8888</span></br><br /> <span class="message">host:</span> <span class="literal">'127.0.0.1'</span>);</br><br /> <span class="message">addAlias:</span> (<span class="variable">SiteIdentifier</span> </br><br /> <span class="message">ip:</span> <span class="literal">'127.0.0.1'</span></br><br /> <span class="message">port:</span> <span class="literal">8888</span></br><br /> <span class="message">host:</span> <span class="literal">'172.16.1.128'</span>)<br /></pre><br />This allows the site to be called using <code>http://127.0.0.1:8888/seaside/</code> and <code>http://172.16.1.128:8888/seaside/</code>.Udo Schneiderhttp://www.blogger.com/profile/03800840524438939459noreply@blogger.com0