tag:blogger.com,1999:blog-75556716578876358872024-03-06T06:18:32.368+01:00Pragmatic ProgrammingReflexions about programming directed by a fun and pragmatic approach.Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-7555671657887635887.post-62327966728840547902018-04-07T20:38:00.004+02:002018-04-07T20:38:37.578+02:00New blog !Hello, I've been absent for a long time, a lot of things have changed for me.<br />
<br />
I've decided to set-up a new blog using github-pages, it's far more simpler to edit and publish for me.<br />
<br />
Long story short, here is the link: <a href="https://slashvar.github.io/">slashvar.github.io</a><br />
<br />
There's already so posts: a GNU Make tutorial, some thoughts on my past life as a programming teacher and another attempt to define a good programmer !<br />
<br />
I'll let you read, I'll try to post link to new article here to make the connexion.<br />
<br />
On a more personal side, I'm now a software engineer at <a href="http://algolia.com/">algolia.com</a> working on their ground breaking search engine.<br />
<br />Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-70882949250998708842016-10-21T12:12:00.000+02:002016-10-21T12:12:05.098+02:00Beginner's corner: Let's talk C++<div style="text-align: justify;">
Been a long time, I've got several articles under constructions for quite some times … This one wasn't planified, I just think I can share some basic but nice C++.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
C++ is huge language, it's probably impossible to explore all the features in a lifetime, and trying to apprehend what theses features can bring you is probably out of reach for a normal human being. But, we can sometimes grasp some interesting ideas.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
My approach of C++ is not traditional, in the sense that I'm not using C++ as an object oriented language, more like a higher-level C, objects and classes are just one of the interesting aspects. Anyway, I'll use some object here, but without inheritance and all the buzz around object design.</div>
<div style="text-align: justify;">
<br /></div>
<h3 style="text-align: justify;">
Power to the destructor</h3>
<div style="text-align: justify;">
As in any sane language, when closing a scope, variables local to that scope <i>dies</i>. But, in C++ some of these local variables can be direct objects (not pointers to object like in Java) and thus, when a variable dies, the object must be destroy. This happen transparently and can easily be coded:</div>
<div style="text-align: justify;">
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="cp" style="color: #8f5902; font-style: italic;"># include <iostream></span>
<span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">S</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">id</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">S</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">i</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">id</span><span class="p" style="font-weight: bold;">(</span><span class="n">i</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">"Building S("</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">id</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">")"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">~</span><span class="n">S</span><span class="p" style="font-weight: bold;">()</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">"Destroying S("</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">id</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">")"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="p" style="font-weight: bold;">};</span>
<span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="nf">main</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">void</span><span class="p" style="font-weight: bold;">)</span>
<span class="p" style="font-weight: bold;">{</span>
<span class="c1" style="color: #8f5902; font-style: italic;">// Building in main</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">">> main <<"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">S</span> <span class="n">s1</span><span class="p" style="font-weight: bold;">(</span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">{</span> <span class="c1" style="color: #8f5902; font-style: italic;">// Sub context</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">">>> Sub context <<<"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">S</span> <span class="n">s2</span><span class="p" style="font-weight: bold;">(</span><span class="mi" style="color: #0000cf; font-weight: bold;">2</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">">>> Sub context last statement <<<"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">">> main last statement <<"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
<br />
Running this piece of code shows when destructors are implicitly called.<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre>>> main <<
Building S(1)
>>> Sub context <<<
Building S(2)
>>> Sub context last statement <<<
Destroying S(2)
>> main last statement <<
Destroying S(1)
</pre>
</div>
<br />
It's a classic C++ example, and if you're not familiar with this, you should start over your learning of C++ …<br />
<br />
The real question is: <i>what can we do with that ? Things, a</i> lot of things …<br />
<br />
<h3>
RAII</h3>
C++ programmers should be familiar with a concept called RAII: Resource Acquisition Is Initialisation. <a href="http://cppreference.com/w/cpp/language/raii">cppreference</a> describes RAII:<br />
<br />
<blockquote class="tr_bq">
Resource Acquisition Is Initialization or RAII, is a C++ programming technique which binds the life cycle of a resource (allocated memory, thread of execution, open socket, open file, locked mutex, database connection—anything that exists in limited supply) to the lifetime of an object.</blockquote>
<br />
You can find classical examples of RAII in STL, one of the most interesting is the <span style="font-family: "courier new" , "courier" , monospace;">std::lock_guard</span> class. In short, at creation it locks a mutex and unlocks it when destroyed.<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">counter</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">unsigned</span> <span class="n">c</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">mutex</span> <span class="n">m</span><span class="p" style="font-weight: bold;">;</span>
<span class="kt" style="color: #204a87; font-weight: bold;">void</span> <span class="nf">incr</span><span class="p" style="font-weight: bold;">()</span> <span class="p" style="font-weight: bold;">{</span>
<span class="c1" style="color: #8f5902; font-style: italic;">// guard lock m when constructed</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">lock_guard</span><span class="o" style="color: #ce5c00; font-weight: bold;"><</span><span class="n" style="text-align: start;">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n" style="text-align: start;">mutex</span><span class="o" style="color: #ce5c00; font-weight: bold;">></span> <span class="n">guard</span><span class="p" style="font-weight: bold;">(</span><span class="n">m</span><span class="p" style="font-weight: bold;">);</span></pre>
<pre style="line-height: 17.5px; text-align: start;"> <span class="n">c</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">;</span>
<span class="c1" style="color: #8f5902; font-style: italic;">// guard get destroyed and unlock m</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="p" style="font-weight: bold;">};</span></pre>
</div>
<br />
<br />
Using lock-guards greatly improves and simplifies algorithm using lock. It also provides a strong guarantee that mutexes are always unlocked when leaving a function or code block, even in the presence of exceptions. This example demonstrate how lock-guards can simplify code using mutexes, using lock-guards avoid the need of adding an unlock statement whenever you want to leave your code.<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="k" style="color: #204a87; font-weight: bold;">template</span><span class="o" style="color: #ce5c00; font-weight: bold;"><</span><span class="k" style="color: #204a87; font-weight: bold;">typename</span> <span class="n">T</span><span class="o" style="color: #ce5c00; font-weight: bold;">></span>
<span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">list</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">node</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">T</span> <span class="n">data</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">node</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span><span class="n">next</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">node</span><span class="p" style="font-weight: bold;">()</span><span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">next</span><span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">nullptr</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{}</span>
<span class="n">node</span><span class="p" style="font-weight: bold;">(</span><span class="n">T</span> <span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">node</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span><span class="n">n</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">data</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span><span class="p" style="font-weight: bold;">),</span> <span class="n">next</span><span class="p" style="font-weight: bold;">(</span><span class="n">n</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{}</span>
<span class="p" style="font-weight: bold;">};</span>
<span class="n">node</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span><span class="n">head</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">mutex</span> <span class="n">mutex</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">list</span><span class="p" style="font-weight: bold;">()</span> <span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">head</span><span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">new</span> <span class="n">node</span><span class="p" style="font-weight: bold;">())</span> <span class="p" style="font-weight: bold;">{}</span>
<span class="cm" style="color: #8f5902; font-style: italic;">/* using lock_guard */</span>
<span class="kt" style="color: #204a87; font-weight: bold;">bool</span> <span class="n">member</span><span class="p" style="font-weight: bold;">(</span><span class="n">T</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">lock_guard</span><span class="o" style="color: #ce5c00; font-weight: bold;"><</span><span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">mutex</span><span class="o" style="color: #ce5c00; font-weight: bold;">></span> <span class="n">guard</span><span class="p" style="font-weight: bold;">(</span><span class="n">mutex</span><span class="p" style="font-weight: bold;">);</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">auto</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">head</span><span class="p" style="font-weight: bold;">;</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">;</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">if</span> <span class="p" style="font-weight: bold;">(</span><span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">data</span> <span class="o" style="color: #ce5c00; font-weight: bold;">==</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">true</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">false</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="cm" style="color: #8f5902; font-style: italic;">/* using explicit lock/unlock */</span>
<span class="kt" style="color: #204a87; font-weight: bold;">bool</span> <span class="n">member_old</span><span class="p" style="font-weight: bold;">(</span><span class="n">T</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">mutex</span><span class="p" style="font-weight: bold;">.</span><span class="n">lock</span><span class="p" style="font-weight: bold;">();</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">auto</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">head</span><span class="p" style="font-weight: bold;">;</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">;</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">if</span> <span class="p" style="font-weight: bold;">(</span><span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">data</span> <span class="o" style="color: #ce5c00; font-weight: bold;">==</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">mutex</span><span class="p" style="font-weight: bold;">.</span><span class="n">unlock</span><span class="p" style="font-weight: bold;">();</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">true</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="n">mutex</span><span class="p" style="font-weight: bold;">.</span><span class="n">unlock</span><span class="p" style="font-weight: bold;">();</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">false</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="cm" style="color: #8f5902; font-style: italic;">/* using lock_guard */</span>
<span class="kt" style="color: #204a87; font-weight: bold;">bool</span> <span class="n">insert</span><span class="p" style="font-weight: bold;">(</span><span class="n">T</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">lock_guard</span><span class="o" style="color: #ce5c00; font-weight: bold;"><</span><span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">mutex</span><span class="o" style="color: #ce5c00; font-weight: bold;">></span> <span class="n">guard</span><span class="p" style="font-weight: bold;">(</span><span class="n">mutex</span><span class="p" style="font-weight: bold;">);</span>
<span class="k" style="color: #204a87; font-weight: bold;">auto</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">head</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(;</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&&</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">data</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">)</span>
<span class="k" style="color: #204a87; font-weight: bold;">continue</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">if</span> <span class="p" style="font-weight: bold;">(</span><span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&&</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">data</span> <span class="o" style="color: #ce5c00; font-weight: bold;">==</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">false</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="k" style="color: #204a87; font-weight: bold;">new</span> <span class="n">node</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">);</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">true</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="cm" style="color: #8f5902; font-style: italic;">/* using explicit lock/unlock */</span>
<span class="kt" style="color: #204a87; font-weight: bold;">bool</span> <span class="n">insert_old</span><span class="p" style="font-weight: bold;">(</span><span class="n">T</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">mutex</span><span class="p" style="font-weight: bold;">.</span><span class="n">lock</span><span class="p" style="font-weight: bold;">();</span>
<span class="k" style="color: #204a87; font-weight: bold;">auto</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">head</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(;</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&&</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">data</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span> <span class="n">cur</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">)</span>
<span class="k" style="color: #204a87; font-weight: bold;">continue</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">if</span> <span class="p" style="font-weight: bold;">(</span><span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&&</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">data</span> <span class="o" style="color: #ce5c00; font-weight: bold;">==</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">mutex</span><span class="p" style="font-weight: bold;">.</span><span class="n">unlock</span><span class="p" style="font-weight: bold;">();</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">false</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="k" style="color: #204a87; font-weight: bold;">new</span> <span class="n">node</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">cur</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">next</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">mutex</span><span class="p" style="font-weight: bold;">.</span><span class="n">unlock</span><span class="p" style="font-weight: bold;">();</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="nb" style="color: #204a87;">true</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="p" style="font-weight: bold;">};</span></pre>
</div>
<br />
Lock-guards provide coding comfort similar to synchronized blocks in Java or try-finally constructions.<br />
<br />
The next example demonstrates another use case. The idea is to provide a simple almost non-intrusive benchmarking object. Here is the class definition:<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="cp" style="color: #8f5902; font-style: italic;">#include</span> <span class="cpf"><chrono></span><span class="cp" style="color: #8f5902; font-style: italic;"></span>
<span class="k" style="color: #204a87; font-weight: bold;">using</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">chrono</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">duration_cast</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">using</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">chrono</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">nanoseconds</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">using</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">chrono</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">steady_clock</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">scoped_timer</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">scoped_timer</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span> <span class="n">s</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">seconds</span><span class="p" style="font-weight: bold;">(</span><span class="n">s</span><span class="p" style="font-weight: bold;">),</span> <span class="n">t0</span><span class="p" style="font-weight: bold;">(</span><span class="n">steady_clock</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">now</span><span class="p" style="font-weight: bold;">())</span> <span class="p" style="font-weight: bold;">{}</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">~</span><span class="n">scoped_timer</span><span class="p" style="font-weight: bold;">()</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">steady_clock</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">time_point</span> <span class="n">t1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">steady_clock</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">now</span><span class="p" style="font-weight: bold;">();</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">chrono</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">duration</span><span class="o" style="color: #ce5c00; font-weight: bold;"><</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span><span class="o" style="color: #ce5c00; font-weight: bold;">></span> <span class="n">diff</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">t1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span> <span class="n">t0</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">seconds</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">diff</span><span class="p" style="font-weight: bold;">.</span><span class="n">count</span><span class="p" style="font-weight: bold;">();</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span> <span class="n">seconds</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">steady_clock</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">time_point</span> <span class="n">t0</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">};</span></pre>
</div>
<br />
Here is simple code usage:<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"> <span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">seconds</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">{</span> <span class="n">scoped_timer</span> <span class="n">clock</span><span class="p" style="font-weight: bold;">(</span><span class="n">seconds</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">"benched code blocks"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">"elapsed time: "</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">seconds</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">"s"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span></pre>
</div>
<br />
Once again the trick is to take advantage of the pair constructor/destructor of the object. The scoped_timer get a reference on a double and when destroyed push the time difference in this reference when destroyed.<br />
<br />
<h3>
More ?</h3>
<div>
C++ coding exercise: we want a <i>something</i> that behaves like the assert construction with the ability to emit a message. The use case looks like this:</div>
<div>
<br /></div>
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"> <span class="n">log_assert</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span> <span class="o" style="color: #ce5c00; font-weight: bold;">></span> <span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">"hello "</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span></pre>
</div>
<div>
<br /></div>
<div>
If the condition is true (in our case x is positive) nothings happen, but if it's false, the message gets be printed and the program exits.</div>
<div>
<br /></div>
<div>
Looks easy ? If you write <span style="font-family: "courier new" , "courier" , monospace;">log_assert</span> as a function, you'll get exactly what you don't want: the message get printed only if you don't leave the program …</div>
<div>
<br /></div>
<div>
The expression <span style="font-family: "courier new" , "courier" , monospace;">log_assert(b)</span> can be a call to a constructor, you see the idea now ?<br />
<br />
As a hint, let's see what happen with our first class example if you just call the constructor without naming the resulting object:</div>
<div>
<br /></div>
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="nf">main</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">void</span><span class="p" style="font-weight: bold;">)</span>
<span class="p" style="font-weight: bold;">{</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">">> main <<"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">S</span><span class="p" style="font-weight: bold;">(</span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">cout</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="s" style="color: #4e9a06;">">> main last statement <<"</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
<div>
<br /></div>
<div>
The output:</div>
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre>>> main <<
Building S(1)
Destroying S(1)
>> main last statement <<
</pre>
</div>
<div>
<br />
Yes, we build the object and it get destroyed <i>directly</i> ! In fact, the object is created for the statement only, and thus get destroyed on the semi-colon.<br />
<br />
So, all we need is to handle the leave on assertion in the destructor and add some overloading on the operator <span style="font-family: "courier new" , "courier" , monospace;"><<</span>. Here is a possible implementation:<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">log_assert</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">bool</span> <span class="n">cond</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">log_assert</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">bool</span> <span class="n">c</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">cond</span><span class="p" style="font-weight: bold;">(</span><span class="n">c</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{}</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">~</span><span class="n">log_assert</span><span class="p" style="font-weight: bold;">()</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">if</span> <span class="p" style="font-weight: bold;">(</span><span class="n">cond</span><span class="p" style="font-weight: bold;">)</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">clog</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">endl</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">abort</span><span class="p" style="font-weight: bold;">();</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="k" style="color: #204a87; font-weight: bold;">template</span><span class="o" style="color: #ce5c00; font-weight: bold;"><</span><span class="k" style="color: #204a87; font-weight: bold;">typename</span> <span class="n">T</span><span class="o" style="color: #ce5c00; font-weight: bold;">></span>
<span class="n">log_assert</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span> <span class="k" style="color: #204a87; font-weight: bold;">operator</span><span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">const</span> <span class="n">T</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">if</span> <span class="p" style="font-weight: bold;">(</span><span class="o" style="color: #ce5c00; font-weight: bold;">!</span><span class="n">cond</span><span class="p" style="font-weight: bold;">)</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">clog</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><<</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span><span class="k" style="color: #204a87; font-weight: bold;">this</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="p" style="font-weight: bold;">};</span></pre>
</div>
<br />
There's probably better way to do that, but it will be enough for now …<br />
<br />
<h3>
And this why …</h3>
There's a classical trap related to this pattern when using RAII resources. A good example can be found with the <span style="font-family: "courier new" , "courier" , monospace;">std::async</span> construction. <span style="font-family: "courier new" , "courier" , monospace;">std::async</span> provides a lazy parallel evaluation of a function. The common mistake arises when you use it to launch a computation and don't need to wait for completion explicitly, like in the following code sample:<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="kt" style="color: #204a87; font-weight: bold;">void</span> <span class="nf">run</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">unsigned</span> <span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="kt" style="color: #204a87; font-weight: bold;">unsigned</span> <span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">len</span><span class="p" style="font-weight: bold;">)</span>
<span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">unsigned</span> <span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">;</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><</span> <span class="n">len</span><span class="p" style="font-weight: bold;">;</span> <span class="o" style="color: #ce5c00; font-weight: bold;">++</span><span class="n">i</span><span class="p" style="font-weight: bold;">)</span>
<span class="n">printf</span><span class="p" style="font-weight: bold;">(</span><span class="s" style="color: #4e9a06;">">> %u - %u <<</span><span class="se" style="color: #4e9a06;">\n</span><span class="s" style="color: #4e9a06;">"</span><span class="p" style="font-weight: bold;">,</span> <span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">i</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="nf">main</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">void</span><span class="p" style="font-weight: bold;">)</span>
<span class="p" style="font-weight: bold;">{</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">async</span><span class="p" style="font-weight: bold;">(</span><span class="n">run</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">100</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">async</span><span class="p" style="font-weight: bold;">(</span><span class="n">run</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">2</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">100</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
<br />
The two <span style="font-family: "courier new" , "courier" , monospace;">std::async</span> statements are not run in parallel, if you want parallelism, you need to write it that way:<br />
<br />
<div style="background-color: #f0f0f0; border-color: black; border-style: solid; border-width: 1px; padding: 10px;">
<pre style="line-height: 17.5px; text-align: start;"><span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="nf">main</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">void</span><span class="p" style="font-weight: bold;">)</span>
<span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">auto</span> <span class="n">w1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">async</span><span class="p" style="font-weight: bold;">(</span><span class="n">run</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">100</span><span class="p" style="font-weight: bold;">);</span>
<span class="k" style="color: #204a87; font-weight: bold;">auto</span> <span class="n">w2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">std</span><span class="o" style="color: #ce5c00; font-weight: bold;">::</span><span class="n">async</span><span class="p" style="font-weight: bold;">(</span><span class="n">run</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">2</span><span class="p" style="font-weight: bold;">,</span> <span class="mi" style="color: #0000cf; font-weight: bold;">100</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
<br />
On destruction the object returned by <span style="font-family: "courier new" , "courier" , monospace;">std::async</span> wait for the completion of the submitted task, so if you don't keep alive the returned object, the execution is not parallel since it waits for the completion of the first task before passing to the second statement.<br />
<br />
Once again, it's all about understanding when things get destroyed …<br />
<br />
<h3>
Conclusion</h3>
I've just played with very basic C++ notions, but there's a lot of applications. Understanding the dependencies and order of destruction of objects is important in C++.<br />
<br />
RAII is almost behind smart pointers, an important concept in modern C++ programming. Even if the concrete implementation of a smart pointer class is a little bit tricky, the basic concept (releasing memory when the smart pointer dies) is easy to get once you understand RAII. Among all C++ features, the automatic invocation of destructors when objects go out of scope is probably one of the most useful.</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-90222193131797887312015-08-03T19:20:00.003+02:002015-08-03T19:20:51.213+02:00Reference counting: practice and trouble<div class="wmd-preview-section preview-content" id="wmd-preview-section-1" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Reference counting is a well known strategy used to provide simple garbage collection. As automatic garbage collection, it has a lot of issues among which not correctly handling circular data-structures is the most obvious.</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
On the other hand, used for semi-automatic GC, it is pretty accurate, easy to implement and solves probably most of the use cases. People using C++11 <tt style="box-sizing: border-box; outline: none !important;">shared_ptr</tt> probably see what I mean.</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
But I'm here to talk about concurrent programming and especially non-blocking data-structures. There’s a lot of academic explaining why ref-count won't help you, but still a lot of people think that we can use ref-count without impact.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-2" style="box-sizing: border-box; outline: none !important;">
<h4>
Safe world: sequential code and lock protection</h4>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
The classical way of using ref-counting, in a safe context, is to store the counter in the data (the memory cell.) While the accounted pointer is reachable, the counter count at least one reference corresponding to the placeholder of the pointer and thus will never get down to 0 and, thus, memory won't be freed.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Being alone on the data (due to lock protection or simply because there’s only one thread currently running) a thread can safely increment the pointer without any risk of hazardous memory access. Even when using optimistic or lazy locking, locks may prevent conflicting increment/decrement situations.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Anyway, we can present a simple and usable ref-count in C using intrusive data structure.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-3" style="box-sizing: border-box; outline: none !important;">
<h3>
Simple and generic ref-count in C</h3>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
We now introduce a simple ref-count using intrusive data-structure. Intrusive data structures have been discussed in this blog in a previous post.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
In our case, what we need is: a small structure containing the counter and a pointer to the delete function, an operation to increase the counter, an operation to decrease it and eventually call the delete function and finally some macro to retrieve the parent structure pointer from the pointer of our intrusive structure. Here is the basic code (without any locking support):</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-4" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; outline: none !important; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">/* Simple ref-count */</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># ifndef REF_COUNT_H_</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># define REF_COUNT_H_</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// needed for offsetof</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <stddef.h></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Intrusive tools to retrieve access to the including structure</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># define containerof(TYPE_, FIELD_, PTR_) \</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">((</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">TYPE_</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*)((</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">char</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*)(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">PTR_</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> offsetof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">TYPE_</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> FIELD_</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)))</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Typedef for the delete function pointer</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// increase readability</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typedef</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">delete_ptr</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// The ref-count intrusive structure</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> counter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
delete_ptr deleter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Init function, set the counter to 1</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count_init</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> delete_ptr ptr</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">counter </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deleter </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ptr</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Increasing count</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count_get</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">counter </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Decreasing count</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// call deleter if count get downto 0</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count_release</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">counter </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">if</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">counter </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">==</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deleter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># endif /* REF_COUNT_H_ */</span></span></code></pre>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
And, because that’s better with usage example:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-5" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; outline: none !important; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Testing our ref-count</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <stdio.h></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <stdlib.h></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include "ref_count.h"</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Some data</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// last field ref is our ref-count intrusive structure</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> an_int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">float</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> a_float</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Now the delete function</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data_delete</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">p</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">main_struct</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
main_struct </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> p</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
free</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">main_struct</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// A builder for our data</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> new_data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">float</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
d </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> malloc</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">sizeof</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">an_int </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">a_float </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_init</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data_delete</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// A toy function using the data</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> do_some_stuff</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Holding the pointer, get it !</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_get</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"Data (%p) : %d %g\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">an_int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">a_float</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// We're done, release the pointer</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_release</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// run using valgrind or clang's address sanitizer to check for memory leaks.</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">()</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
d </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> new_data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">42</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3.14</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// count already set to 1</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
do_some_stuff</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// get and release</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
do_some_stuff</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// get and release</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_release</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">d</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// we're done</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></span></code></pre>
<pre style="background-color: rgba(128, 128, 128, 0.0470588); border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; outline: none !important; padding: 0px;"><span style="font-size: xx-small;">==20934== Memcheck, a memory error detector
==20934== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==20934== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==20934== Command: ./testing
==20934==
Data (0x51d8040) : 42 3.14
Data (0x51d8040) : 42 3.14
==20934==
==20934== HEAP SUMMARY:
==20934== in use at exit: 0 bytes in 0 blocks
==20934== total heap usage: 1 allocs, 1 frees, 24 bytes allocated
==20934==
==20934== All heap blocks were freed -- no leaks are possible
==20934==
==20934== For counts of detected and suppressed errors, rerun with: -v
==20934== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)</span></code><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;">
</code></pre>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Of course, this implementation is <strong style="box-sizing: border-box; outline: none !important;">not thread safe</strong>. Having a safe locking mechanism protecting the ref-count is not that easy and is outside of the scope of this article.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-6" style="box-sizing: border-box; outline: none !important;">
<h3>
More complete example: data in 2 containers</h3>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Here I provide an example using intrusive lists as containers and where data chunks belong to two lists at the same time. Follow code comments:</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
First the intrusive list implementation:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-7" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; outline: none !important; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// list.h : Basic intrusive lists</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># ifndef LIST_H_</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># define LIST_H_</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <stddef.h></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// No explicit ref-count, but we need containerof</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include "ref_count.h"</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Init circular double linked list</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Used to init sentinel</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list_init</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// list is empty</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list_is_empty</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">==</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> l</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Insert before current node</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list_insert_before</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Insert after current node</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list_insert_after</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Detach current node</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list_detach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Foreach tools</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Simple foreach</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// entry = list entry point (sentinel)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// cur = variable used as iterator, only active in loop</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># define list_foreach(entry, cur) \</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">for</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">!=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// deque like interface</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// should be used only with sentinel as input</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// mainly wrappers</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// deque is empty</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque_is_empty</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">==</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Push front</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque_push_front</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">elm</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_insert_after</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> elm</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Push back</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque_push_back</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">elm</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_insert_before</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> elm</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Getting (not detached) front cursor</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// return NULL if empty</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque_front</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">if</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_is_empty</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">))</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Getting (not detached) back cursor</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// return NULL if empty</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">inline</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque_back</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">if</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_is_empty</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">))</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">prev</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># endif /* LIST_H_ */</span></span></code></pre>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
And now the code:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-8" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; outline: none !important; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Demonstration of intrusive lists and ref-count</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># define _XOPEN_SOURCE 500</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <stdlib.h></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <stdio.h></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include "list.h"</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include "ref_count.h"</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Kind of a selection sort</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// we look for the smallest element in a list and push it in front of the</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// deque but only if it is not already there</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// After building the deque, we remove clear the original list, then print the</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// content of the deque and finally clear it also</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Data: simple int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Data structure: each element belongs to 2 lists and has a ref-count</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> val</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list main_list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list deque</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> ref_count </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Now the delete function</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data_delete</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">p</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">main_struct</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
main_struct </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> p</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
free</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">main_struct</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// For simplicity we put almost everything in a single function</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// sentinel for each list are local entity, and thus automatically freed</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">void</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> example</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">size_t</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Sentinels</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Building the list</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_init</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">for</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">size_t</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> i </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> i </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> i</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">++)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> malloc</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">sizeof</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> random</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">()</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">%</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">100</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// init ref counting, no need to account current copy</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_init</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data_delete</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_insert_after</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">main_list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Display the list</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_foreach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">((&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main_list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"%02d->"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"end\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Starting the sort</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// iterate over the list to find smallest element</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// add the cell in the deque if it is not already thre</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// lastval in order to avoid the same value again and again</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// No negative entry, use -1 as initial value</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> lastval </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-</span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_init</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">for</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">size_t</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> i </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> i </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> i</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">++)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">min </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> minval </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">100</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// maximum possible value</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_foreach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">((&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main_list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">if</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> lastval </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">&&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> minval</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
min </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
minval </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> min</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">if</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">min </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">!=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> NULL </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">&&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> min</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> lastval</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Add an element</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_get</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">min</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
deque_push_back</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">min</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
lastval </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> min</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Display the deque</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_foreach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">((&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"%02d->"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"end\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Clear the main list</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">while</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(!</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">list_is_empty</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">))</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Extract next element</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">iter </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> list_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">.</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">next</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_detach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// No more ref in the list</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_release</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main_list</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Display the deque</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_foreach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">((&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> iter</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"%02d->"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">val</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"end\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// Now clear the deque</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">while</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(!</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_is_empty</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">))</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
cell </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> containerof</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> deque_front</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque_entry</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
list_detach</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">deque</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;">// No more ref in the list</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
ref_count_release</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(&(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cell</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">ref</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">()</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
example</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">10</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></span></code></pre>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Once again, the code runs without any memory leak (try with valgrind … )</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-9" style="box-sizing: border-box; outline: none !important;">
<h4>
Trying to be non-blocking</h4>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Obviously, using ref-counting in a multithreaded context requires locks.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
The legitimate question is: if we use atomic integer for the counter and we limit the usage of our ref-count to some safe situation, can we have non-blocking ref-count ?</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-10" style="box-sizing: border-box; outline: none !important;">
<h3>
Safe Concurrent Ref-counting ?</h3>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Let’s consider the following case: we have a pointer between shared between a group of reader threads and a single updater thread, updates are only performed by replacing the pointer, not modifying the content. This is, basically, the traditional example used to illustrate RCU.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
During the update, the writer thread first get the pointer, allocate a new one, eventually copy the old data in the new allocated area and when ready atomically replace the old pointer with new one. Once the pointer has been replaced, no readers can access it, and the writer can then wait for readers still active on the old data before releasing the memory.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Now that we want to implement the <em style="box-sizing: border-box; outline: none !important;">wait for readers</em> stage using ref-count on pointers. The protected pointer goes through two states: before update, since it is attached to some placeholders, its ref-count is at least 1 even if no threads hold it; after the update, since the pointer is not anymore attached to the placeholders, its ref-count value reflect the number of still active readers. The nice aspect of this is that starting from the update, the ref-count is now only decreasing, and thus, when the last reader release the pointer, automatic garbage collection frees the memory.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
So, if the pointer is visible, you have the guarantee that the count will never get down to 0 and thus it will stay valid, on the other hand, when the pointer has been replaced, no new threads can grab it and increase the counter.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Stated this way, it seems that we have a less difficult synchronization problem: we just need to be sure that counts are correctly handled, and a simple atomic storage can provide that. <strong style="box-sizing: border-box; outline: none !important;">Are we really safe ?</strong></div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
In parallel computing, issues rise in the details, and in the complexity of transition states. Here, the potential problem may rise when the pointer is replaced. Consider the following schema:</div>
<ul style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; margin-top: 0px; outline: none !important;">
<li style="box-sizing: border-box; outline: none !important;">no reader hold the pointer</li>
<li style="box-sizing: border-box; outline: none !important;">a writer is active and ready to update the pointer</li>
<li style="box-sizing: border-box; outline: none !important;">a new reader arrive and get its hand on the shared pointer <strong style="box-sizing: border-box; outline: none !important;">before</strong> the update</li>
<li style="box-sizing: border-box; outline: none !important;">the writer performs the change, decreasing the ref-counter, at this point, the only remaining reference is in the writer’s hand.</li>
<li style="box-sizing: border-box; outline: none !important;">the writer releases its own copy <strong style="box-sizing: border-box; outline: none !important;">before</strong> the reader had time to increase the counter (the reader may have been scheduled for example)</li>
<li style="box-sizing: border-box; outline: none !important;">Being the last thread holding a reference, the writer thread see the ref-count getting downto 0 and enter in the memory release code</li>
<li style="box-sizing: border-box; outline: none !important;">now, even if the reader succeed at increasing the ref-count, the pointer will be invalidated, causing potential improper dereference.</li>
</ul>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
We're facing a classical <strong style="box-sizing: border-box; outline: none !important;">race-condition</strong>.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
In order to prevent that kind of situation, you need lock, or more clever constructions (hey RCU here you are … ), but the ref-count doesn’t help alone. The problem is that a reader need to take two actions: grab the data and increase the counter at the same time, there’s no atomic operations able to do that. Eventually, you can think of a kind of tagged pointer, where the ref-count is contiguously attached to the pointer, that sounds good, but it means that getting the pointer no longer requires one atomic load, but a fail/retry loop of compare-and-swap which will be expensive when in the presence of a lot of readers.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-11" style="box-sizing: border-box; outline: none !important;">
<h3>
Ref-counting and Lock-free Data Structures</h3>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Another use-case we may consider is life-time of memory cells in lock-free data structures. As an example, I’ll consider the classical lock-free queue of <br style="box-sizing: border-box; outline: none !important;" />Micheal&Scott <a href="http://www.research.ibm.com/people/m/michael/podc-1996.pdf" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; background: transparent; box-sizing: border-box; color: #4fa1db; outline: none !important; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms</a>.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
In this case we have two problem related to pointers: use after free and ABA. <br style="box-sizing: border-box; outline: none !important;" />Let’s have a quick overview of the part of the algorithm that introduce these <br style="box-sizing: border-box; outline: none !important;" />issues:</div>
<ul style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; margin-top: 0px; outline: none !important;">
<li style="box-sizing: border-box; outline: none !important;">The queue is single linked list with 2 entry points (tail and head/)</li>
<li style="box-sizing: border-box; outline: none !important;">The head points to a recycled sentinel which points to the real top of the queue.</li>
<li style="box-sizing: border-box; outline: none !important;">Update operations are based on compare-and-swap.</li>
<li style="box-sizing: border-box; outline: none !important;">A consumer (after checking for emptyness) will get the value from the next of the head, detach the old head and replace it with its next (recycling the element as a sentinel.)</li>
</ul>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
The problem: an acting consumer grab the head pointer and a pointer to its next element and keep it until it succeeds in updating the head pointer or fail (and the retry its operation.) Consider what happen to the head: when the a consumer thread arrives, the first things it does is to get the head pointer, but in the same time, another active consumer may finish its job and update this pointer. Atomicity, enforce the fact that the new consumer thread will either see the old head or the new head, if it sees the old one, it’ll try to access the content in order to grab the next pointer. Again, in a race condition scenario, if the thread that update the head had time to release the memory cell, the new thread will dereference a freed pointer.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Since the lock-free algorithm relies heavily on compare-and-swap and thus often check pointers, one can avoid the use-after-free by simply recycling the memory cells rather than freeing them. Now, we introduce, or at least we increase the risk of, another problem: ABA.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
ABA is a classical problem associated with compare-and-swap updates. Most CAS based algorithms check that a pointer hasn't changed before updating it, in the presence of recycling, it may happen that the same pointer has been detached and then reused while the thread was scheduled. Thus, seeing the same pointer doesn’t mean that it hasn’t change.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
<em style="box-sizing: border-box; outline: none !important;">Again, can we use ref-count to solve these issues ?</em></div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Like before, the idea is that the pointer has two different life: when its attached (and its ref-count will be at least 1) and when it has been detached (and then its ref-count will only decrease.) The problem is still in the transition phase. Just consider the use-after-free scenario: when the new consumer thread get the head pointer, it may fetch a pointer that will be detached immediately after. Once again, if add a ref-count, where is it ? And how can we fetch the pointer and increment the ref-count at the same time so that it won’t be freed ? <strong style="box-sizing: border-box; outline: none !important;">Race condition, again !</strong></div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
As expected (this isn't a new result), ref-count is <strong style="box-sizing: border-box; outline: none !important;">not</strong> the right tools for non-blocking algorithm.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-12" style="box-sizing: border-box; outline: none !important;">
<h4>
Solutions</h4>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
In the previous examples, I describes problems that can’t be solved using ref-counting, but is there any solution anyway ?</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-13" style="box-sizing: border-box; outline: none !important;">
<h3>
RCU, Hazard Pointers and Procrastination Based Programming</h3>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Managing life-time of pointers in a (almost) non-blocking manner, can be done using techniques that basically belongs to procrastination or relativistic programming. The base idea is that you don't need to do it as soon as you can, but just wait for a better moment.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
RCU is an approach heavily used in the Linux kernel and is becoming available in userland. How does it work ? I’ll write something about it later, but in short, the writer (the one who wants to delete the pointer) waits while readers are still active. How does he now that readers are active ? All threads go through a <em style="box-sizing: border-box; outline: none !important;">quiescent</em> state from time to time where they no longer need coherency, all the job of the RCU framework is to provide the simplest possible code (on the reader side) that provides the correct wait period. Things are not exactly simple in userland, but it works. A lot of ressources are available in <a href="http://www.rdrop.com/~paulmck/RCU/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; background: transparent; box-sizing: border-box; color: #4fa1db; outline: none !important; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">Introduction to RCU</a></div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Hazard Pointers are a little bit more classical. They provide two aspects: deferred deletes and <em style="box-sizing: border-box; outline: none !important;">protection</em> for in use pointers. Each thread has a set of hazard pointers (variable shared for reading only) where they put their current pointers; on the delete side, pointers scheduled for delete are accumulated in a wait list, when this list reach a given size, the current thread take the difference between the wait list and the pointers in the hazard pointers of other threads and delete the result. The original article presents most of what you need to know on the subject <a href="http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; background: transparent; box-sizing: border-box; color: #4fa1db; outline: none !important; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects</a>.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-14" style="box-sizing: border-box; outline: none !important;">
<h4>
Is it worth the effort ?</h4>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
I've made some experiment with my own hazard pointers implementation and C++11 <tt style="box-sizing: border-box; outline: none !important;">shared_ptr</tt>, in order to see the impact of synchronization in smart pointer using ref-counting.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
The experiment is pretty simple: a bunch of threads reading a shared buffer, eventually another thread comes and updates the buffer (change the pointer). The buffer is not protected by synchronization but we fetch the pointer using atomic load (with full sequential consistency.) As a reference, we have a version with only readers and no extensions related to memory reclamation (not needed in this case.) The two others versions support only reading and sporadic updates, the first one use smart pointers and the second uses hazard pointers.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Hazard pointers add some code to the readers: once the pointer has been fetched and stored in the hazard pointer, we need to check that it hasn’t change. The pointer is only protected when stored in the hazard pointer, meaning that you can have an update between the first fetch and the storage in the HP, with the risk of seeing the pointer invalidated between the two operations.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
The read itself only do a kind of <tt style="box-sizing: border-box; outline: none !important;">strlen</tt> on a buffer of 256 bytes, exactly 2²⁴ times, while the reader updates the buffer with a sleeping time of 50 micro-seconds between each update.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
This is a micro-bench, and thus you should take it with the usual care, but results are pretty self explanatory: smart pointers performances are way down below the others.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Experiment were run on a two dual-core CPU (Dual-Core AMD Opteron Processor 2220) thus four physical cores, with 16GB of RAM in two NUMA banks. The code were produced with gcc 5.1.0 using <tt style="box-sizing: border-box; outline: none !important;">-O3</tt> flag. I use out of the box Archlinux distribution (and thus pre-emptive kernel.) Timings are done inside the code directly using C++11 monotonic wall-clock.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
Raw results for reading only cases: the table presents execution time for each version and for different number of threads.</div>
<table style="background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 20px; max-width: 100%; outline: none !important;"><thead style="box-sizing: border-box; outline: none !important;">
<tr style="box-sizing: border-box; outline: none !important;"><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">Version</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">2</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">4</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">8</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">16</th></tr>
</thead><tbody style="box-sizing: border-box; outline: none !important;">
<tr style="box-sizing: border-box; outline: none !important;"><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">No sync</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">1.67829</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">1.672315</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">3.27503</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">6.50652</td></tr>
<tr style="box-sizing: border-box; outline: none !important;"><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;"><tt style="box-sizing: border-box; outline: none !important;">shared_ptr</tt></td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">13.11705</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">26.9322</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">62.7429</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">129.811</td></tr>
<tr style="box-sizing: border-box; outline: none !important;"><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">Hazard ptr</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">1.81462</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">1.769805</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">3.49345</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">6.977785</td></tr>
</tbody></table>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
The second table presents results in the presence of a single writer:</div>
<table style="background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 20px; max-width: 100%; outline: none !important;"><thead style="box-sizing: border-box; outline: none !important;">
<tr style="box-sizing: border-box; outline: none !important;"><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">Version</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">2</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">4</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">8</th><th style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: bottom;">16</th></tr>
</thead><tbody style="box-sizing: border-box; outline: none !important;">
<tr style="box-sizing: border-box; outline: none !important;"><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;"><tt style="box-sizing: border-box; outline: none !important;">shared_ptr</tt></td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">8.80095</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">28.9339</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">65.05</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">137.608</td></tr>
<tr style="box-sizing: border-box; outline: none !important;"><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">Hazard ptr</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">1.78479</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">1.81097</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">3.56837</td><td style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; outline: none !important; padding: 8px; vertical-align: top;">7.05612</td></tr>
</tbody></table>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-15" style="box-sizing: border-box; outline: none !important;">
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img height="395" src="https://lh3.googleusercontent.com/o6mtTaEgtl5jTNJfCCdGdXdt18JIDKiF0JnKQsXXbNaVMSTybhd_SVfBioK0IIcrMWLSTijxVDuKjEKtiZswDWo_WMKAr_lFQimdCiVx19rmiGpN6W22qiKxFu7FNwLTSAl0nhj4Qje1" style="margin-left: auto; margin-right: auto;" width="640" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Read operations per second per thread</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img height="396" src="https://lh6.googleusercontent.com/IDYV1QCRSEKpywH1t88YzOQUcXzXkM3aA85652aLZNBxZTo_EaKz9Ek-d0q7LE7f5X1laeNukVwlqiABlAYMLd_8uPkpwcHKc4RXomTbGFt9tQgyoXaFwRrfahIYQnNBZPE-3qh44bEo" style="margin-left: auto; margin-right: auto;" width="640" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Read operations per second per thread</td></tr>
</tbody></table>
<h4>
<span id="docs-internal-guid-9e2bbb68-f493-6ed8-75ac-9a239bed6969" style="font-weight: normal;"></span></h4>
<h4>
<br />Conclusion</h4>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
So, while ref-counting can be useful tool in a lot of cases (like in my simple C piece of code) using it in multithreaded environment may become expensive.</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
I started this article because I was, once again, trap by the false idea that we can use ref-count (in some specific cases) safely, but as you can see, removing constraints doesn’t solve the synchronization issue. While I'm speaking, there isn't official implementation of real non-blocking memory reclamation techniques like hazard pointers. A userland RCU implementation is available (and I’m in the process of writing my own in C++ style) but it’s not really portable (at least, it works on most modern Unixes, but not all architectures.)</div>
<div style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; margin-bottom: 1.1em; outline: none !important;">
There exists other approaches, like tagged pointers, that solves ABA problems in lock-free data structures, but as it seems, deferred memory reclamations seems to be pretty efficient. I strongly encourage you to read RCU papers (both web articles about its uses in Linux and academics ones.) With working RCU, a lot of concurrent accesses problems can be solved easily with almost no specific code and almost no overhead on the reader side.</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com1tag:blogger.com,1999:blog-7555671657887635887.post-26792487174726864392015-07-04T17:09:00.000+02:002015-07-04T17:09:03.907+02:00Intrusive AVL: a simple generic data structure in C<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Our goal to day is to implement classical AVL (balanced binary trees) in C. But with a touch of genericity !</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
In order to achieve genericity, we'll use intrusive data structure. This simple trick, moving data out of the structure, simplifies a lot the implementation of generic containers in C. If you're looking for a real-life example, take a look into the Linux kernel where almost any containers are intrusive.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
<strong style="box-sizing: border-box;">Disclaimer:</strong> the following code is provide as-is without any guarantee, it hasn't really been tested so you use it at your own risk. If you use that code, feel free to pay me a beer if we meet someday.</div>
<h2 id="intrusive-data-structures" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 2.15em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Intrusive data structures</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The idea is pretty simple: the container structure doesn’t contain data but the data contains the container … OK, that doesn't seem clear this way ? Take a simple example: linked list.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
A linked list node normally contains links (next and eventually previous) and data, but list operations don’t care about the data. The only place where you need the data is when you create nodes. A first modification you can do to your code is let the caller take care of the allocation:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> push_front</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">l</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// We use sentinel</span><span class="pln" style="box-sizing: border-box; color: black;">
new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088;">next</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> l</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088;">next</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
l</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="kwd" style="box-sizing: border-box; color: #000088;">next</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
This function works, as long as <tt style="box-sizing: border-box;">next</tt> has the same offset, the rest of the node is not important. So, take a look at this data layout:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> list </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">next</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> list node</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Put you data here ...</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The node structure is embedded into our data, since we put it as a first member, a pointer to our data can be since as list node. But, we can have an even more generic version: we're able to recompute the address of the data from one of its field using the<tt style="box-sizing: border-box;"></tt></div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000;">// Getting data from node</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;"># define get_data(type_, member_, node_ptr_) \</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="pln" style="box-sizing: border-box; color: black;">type_</span><span class="pun" style="box-sizing: border-box; color: #666600;">*)((</span><span class="kwd" style="box-sizing: border-box; color: #000088;">char</span><span class="pun" style="box-sizing: border-box; color: #666600;">*)(</span><span class="pln" style="box-sizing: border-box; color: black;">node_ptr_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> offsetof</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">type_</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> member_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)))</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
<i>Note: you can easily recode the <tt style="box-sizing: border-box;">offsetof(3)</tt> macro using field address …</i></div>
<h2 id="implementing-avl" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 2.15em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Implementing AVL</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
AVL are balanced binary search tree, so what we need is a binary tree data structures, some information about balance and operations that repair a <i>not too much</i> unbalanced tree.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Here is my node structure:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000;">// Node</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Balance is describe by what we call <em style="box-sizing: border-box;">balance factor</em>, defined as the difference of height between the left and right subtree:</div>
<pre style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; padding: 0px;">bal_factor = Height(left) - Height(right)
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
We store this value in each node of the tree. A node is correct if its balance factor is between (included) -1 and 1. The idea is to maintain this property all along the evolution of the tree. When adding or removing a node in the tree, as soon as a node get out of the balance range, we <em style="box-sizing: border-box;">repair</em> it using rotations.</div>
<h3 id="rotations" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 1.7em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Rotations</h3>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
A rotation just grab one of the child and replace the root with it:</div>
<pre style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; padding: 0px;">left_rotation(node):
save = node->right
node->right = save->left
save->left = node
node = save
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The only remaining part is to recompute the balance factor of the impacted node. For this we only care about the cases that effectively repairs a node: the root got a balance factor of -2 (left rotation) or 2 (right rotation) and the target child (right for the left rotation and left for the right rotation) as a balance factor of -1 or 0 for left rotation and 0 or 1 for the right rotation. The following are the balance factors after rotation depending on the target child balance factor before the rotation.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
<strong style="box-sizing: border-box;">Left Rotation:</strong></div>
<table style="background-color: white; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: black; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 20px; max-width: 100%; text-align: justify;"><thead style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">bal right</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">left bal</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">root bal</th></tr>
</thead><tbody style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td></tr>
</tbody></table>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
<strong style="box-sizing: border-box;">Right Rotation:</strong></div>
<table style="background-color: white; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: black; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 20px; max-width: 100%; text-align: justify;"><thead style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">bal right</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">left bal</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">root bal</th></tr>
</thead><tbody style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td></tr>
</tbody></table>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
As you may notice, I don’t talk about the case for -2 and 1 or 2 and -1. The reason is that in this situation the simple rotation is not sufficient (it just inverts the case) and we need a double rotation !</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The following tables give the balance factors after the corresponding double rotation depending on the corresponding grand-child.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
<strong style="box-sizing: border-box;">Right Left Rotation:</strong></div>
<table style="background-color: white; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: black; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 20px; max-width: 100%; text-align: justify;"><thead style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">bal right left</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">left bal</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">right bal</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">root bal</th></tr>
</thead><tbody style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
</tbody></table>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
<strong style="box-sizing: border-box;">Left Right Rotation:</strong></div>
<table style="background-color: white; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; color: black; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 20px; max-width: 100%; text-align: justify;"><thead style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">bal left right</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">left bal</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">right bal</th><th align="center" style="border-top-width: 0px; box-sizing: border-box; line-height: 20px; padding: 8px; text-align: left; vertical-align: bottom;">root bal</th></tr>
</thead><tbody style="box-sizing: border-box;">
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
<tr style="box-sizing: border-box;"><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">-1</td><td align="center" style="border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; line-height: 20px; padding: 8px; vertical-align: top;">0</td></tr>
</tbody></table>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
For more details about rotations, open a good algorithmic textbook.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Here is the rotations implementations, I don't try to factorize the code since it won’t really simplify the code:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000;">// Left Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> lr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">s </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Balance factor recomputing</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Right Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> rr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">s </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Balance factor recomputing</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Right Left Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> rlr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">s </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Balance factor recomputing</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;"> bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Left Right Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> lrr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Rotation</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">s </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">t </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> s</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Balance factor recomputing</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;"> bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
s</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<h3 id="order-in-avl" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 1.7em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Order in AVL</h3>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
AVL are binary search trees (BST), meaning that there’s an order on node: the left subtree only contains keys smaller than the current node and the right subtree only contains keys bigger than the current node. Thus we need to be able to compare keys, we don't have them ! And anyway, we want a generic tree, so we can’t assume that comparison operators will fit our need.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The idea is to store the comparison function in the tree so that each operation will use the same function. We'll use a sentinel for our tree structure, containing the root node and the comparison function:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000;">// Comparing function type</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">typedef</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cmp_fun_type</span><span class="pun" style="box-sizing: border-box; color: #666600;">)(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">*,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">*);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Main wrapper</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> intrusive_avl </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
cmp_fun_type cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">root</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
As you can see, the comparison function takes two nodes and return an integer, we use the traditional convention: 0 for equality, negative number if the first is smaller and positive otherwise. A comparison function will probably looks like this:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> compare</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">a_</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">b_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">a </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> get_data</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> a_</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">b </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> get_data</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> b_</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Do the compare job here</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">...;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Note the usage of <tt style="box-sizing: border-box;">get_data</tt> macro in order to retrieve the pointer to the data.</div>
<h3 id="finding-elements" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 1.7em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Finding elements</h3>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Finding elements is the easiest task. The only question is how do compare and select elements. In order to keep coherency, we rely on the comparison function store in the tree. This choice forces the user of the tree to provide a fake node with data corresponding to its search.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
While the construction of a fake node seems a constraint, the other solution, provide a pseudo-predicate function, is far more annoying for the user (we don't have lambda in C !)</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> find_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp_fun_type cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> avl_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> intrusive_avl </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> find_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">root</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
This function returns the corresponding node (or <tt style="box-sizing: border-box;">NULL</tt> if not found) providing a way to update data (if it doesn't change the node position in the tree … )</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The search follow the classical binary search in BST: if the current node doesn’t contains the searched element, we continue on the left if the searched element is smaller, on the right otherwise. The complexity depends only on the height of the tree, and since the tree is normally well balanced we can expect a logarithmic number of steps in worst cases.</div>
<h3 id="adding-elements" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 1.7em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Adding elements</h3>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Inserting an element is a two phases job: find the position then update the tree (add the node, recompute balance factor and when needed rebalance (rotations.)</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
In order to simplify balance factor computation (we don't want to recompute the height of subtree) the main algorithm returns the change of height of the subtree (exactly, it returns zero for no change.) Here is a quick sketch of the algorithm:</div>
<ul style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; margin-top: 0px; text-align: justify;">
<li style="box-sizing: border-box;">If the node is empty, we replace it with the new node and return one</li>
<li style="box-sizing: border-box;">If the node match the inserted key (comparison function returns 0) we return a special value to indicate that the node was already present.</li>
<li style="box-sizing: border-box;">In the general case, we choose the direction of insertion (like a search) and perform a recursive call: <br style="box-sizing: border-box;" /><ul style="box-sizing: border-box; margin-bottom: 1.1em; margin-top: 0px;">
<li style="box-sizing: border-box;">If the call return 0 (or the special value) we just transmit it, no further change</li>
<li style="box-sizing: border-box;">Otherwise we update the balance factor and, if needed, apply the correct rotation</li>
</ul>
</li>
</ul>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The caller provides the new node to be inserted. One possible issue is the presence of the inserted key in the tree. In terms of intrusive data structure, it means that a node of the tree may be considered equal by the comparison function. In this case, we get out of the recursion with a special value and set a provided pointer to it. Our insertion function is more an insert or update function.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Here is the code:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000;">// Insert</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> insert_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp_fun_type cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">inserted_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Insertion point</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">inserted_node </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> c </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">c </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Key present</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">inserted_node </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">42</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> dir</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> tmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">c </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
dir </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
dir </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
tmp </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> insert_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> inserted_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> tmp </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">||</span><span class="pln" style="box-sizing: border-box; color: black;"> tmp </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">42</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> tmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> dir</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">switch</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">case</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> rlr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> lr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">break</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">case</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> lrr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> rr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">break</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> avl_insert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> intrusive_avl </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">inserted_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> insert_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">root</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> new_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> inserted_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">42</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
I let you read the code and refer to algorithmic textbook for further information.</div>
<h3 id="extracting-a-node" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 1.7em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Extracting a node</h3>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Since allocation is external, removing a value will just detach the corresponding node (an repair the tree) and return it to the caller. Like for the search, the caller must provide a fake node such that the comparison function will return 0 for the desired value.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
We use the same trick as in insert: the recursive call indicate whether the height has changed or not.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The real difficulty when removing is how to manage the case where the target is not at the bottom of the tree. The usual strategy is to select a good candidate that respect the tree order (minimal value of the right subtree or maximal value on the left sub-tree.) The current node is replaced by the chosen one which is then detached from of its original location.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
In order to implement this strategy in an intrusive structure, we need to find and detach the target node at the same time, updating the tree while coming back. This lead us to write two subroutines one for the maximal value, the other for the minimal. Find extreme values is pretty straightforward: you<br />
follow the right border for the maximal value and left border for the minimal one.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Here are the functions:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> del_min</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> del_min</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">-=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
rlr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
lr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> bal</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> del_max</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> del_max</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">-=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
lrr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
rr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> bal</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
We can see the same kind rebalancing as in insertion. Note that these function doesn’t really care about the actual value (no call to the comparison function) only the position is relevant. I’ve declared these functions static since they are for internal use only, but if we need to extract min/max, the wrapper is pretty easy to write.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The main algorithm is now pretty straightforward, here is the code:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> detach_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">b</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> node_swap</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">a</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">b</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
a</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
a</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
a</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
detach_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">b</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> delete_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp_fun_type cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">**</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> b </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> del_min</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
node_swap</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> b </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> b </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> del_max</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
node_swap</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> b </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">-=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> bal</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
detach_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> bal</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">delete_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">-=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
rlr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
lr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">delete_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
lrr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
rr</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> bal </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> bal</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> avl_delete</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> intrusive_avl </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
delete_</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">root</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">cmp</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The subroutines <tt style="box-sizing: border-box;">detach_node</tt> and <tt style="box-sizing: border-box;">node_swap are just small helper for code factorization.</tt></div>
<h3 id="comments" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 1.7em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Comments</h3>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
The code presented here is almost a direct implementation of the classical algorithms. I’ve tried to keep it clear, but there’s probably some possible factorizations and optimizations.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Among possible evolution, you may want to unrecursify these functions. If you take a look at the insertion algorithm, you can see that you only need one rotation in the worst case. In fact, you can detect which node may require rotation during insertion. The iterative version will do a first traversal,<br />
looking for insertion point and possible rotation point, after that first pass, we retraverse the tree from the rotation point in order to update the balance factor.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
For the delete algorithm, more than one rotation may be needed and thus we need to store the sequence of traversed nodes in order to perform updates.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
But note, that since these operations are logarithmic, the number of required recursive steps is pretty small, something like 20 steps for a million elements in the tree, thus it isn't worth the effort of rewriting everything without recursion.</div>
<h2 id="using-intrusive-data-structure" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 2.15em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Using intrusive data structure</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Using the code is pretty straightforward, I just give you a basic example where the AVL is used as a set of integers:</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; line-height: 1.45; margin-bottom: 1.1em; padding: 10px 20px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; padding: 0px;"><span style="font-size: xx-small;"><span class="com" style="box-sizing: border-box; color: #880000;">// content</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> key</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node node</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// comparison function</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> compare</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">a_</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">b_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">a </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> get_data</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> a_</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">b </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> get_data</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> b_</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> ka </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> kb </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">ka </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> kb</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">ka </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> kb</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Verifying that the AVL is correctly balanced</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// recursive function</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> balcheck</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">||</span><span class="pln" style="box-sizing: border-box; color: black;"> cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> h1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> balcheck</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">h1 </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> h2 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> balcheck</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">h2 </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> h </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">h1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> h2 </span><span class="pun" style="box-sizing: border-box; color: #666600;">?</span><span class="pln" style="box-sizing: border-box; color: black;"> h1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> h2</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> h1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> h2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">?</span><span class="pln" style="box-sizing: border-box; color: black;"> h </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// wrapper call</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> balance_check</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> intrusive_avl </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> balcheck</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">root</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// A simple test</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// len is the number of inserted elements</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> fill_test_no_rand</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="typ" style="box-sizing: border-box; color: #660066;">size_t</span><span class="pln" style="box-sizing: border-box; color: black;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> intrusive_avl tree_</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">tree </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">tree_</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
avl_init</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> compare</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> key </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Insert len keys</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(;</span><span class="pln" style="box-sizing: border-box; color: black;"> len </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600;">--,</span><span class="pln" style="box-sizing: border-box; color: black;"> key</span><span class="pun" style="box-sizing: border-box; color: #666600;">++)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">data </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> calloc</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">sizeof</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
data</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">key </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> key</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Insert the element</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">avl_insert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&(</span><span class="pln" style="box-sizing: border-box; color: black;">data</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">node</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Element must be inserted using provided node</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(&(</span><span class="pln" style="box-sizing: border-box; color: black;">data</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">node</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Element must be in the tree and finded element must match</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;">avl_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&(</span><span class="pln" style="box-sizing: border-box; color: black;">data</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">node</span><span class="pun" style="box-sizing: border-box; color: #666600;">)))</span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;">NULL </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> get_data</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">key </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> key</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Check that the tree is well balanced</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">balance_check</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Now remove keys</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">key </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
key</span><span class="pun" style="box-sizing: border-box; color: #666600;">--;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// fake search element</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data search </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">node</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">left</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;">NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">right</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;">NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">bal_factor</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> node </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// extract node</span><span class="pln" style="box-sizing: border-box; color: black;">
target </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> avl_delete</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&(</span><span class="pln" style="box-sizing: border-box; color: black;">search</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">node</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// we get what we're looking for</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;">NULL </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> get_data</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> node</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)-></span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// element is not in the tree anymore</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">avl_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> target</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// release memory</span><span class="pln" style="box-sizing: border-box; color: black;">
free_node</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">target</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// we removed everything ?</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">tree</span><span class="pun" style="box-sizing: border-box; color: #666600;">-></span><span class="pln" style="box-sizing: border-box; color: black;">root </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
That just a basic test, it demonstrates the usage of that kind of structure. Full code is available here <a href="http://kh405.net/IntrusiveAVL/IntrusiveAVL.tar.bz2" style="background: transparent; box-sizing: border-box; color: #428bca; text-decoration: none;">IntrusiveAVL.tar.bz2</a>.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
Compiled with clang’s <tt style="box-sizing: border-box;">-fsanitize=address</tt> option activated, it runs without any issue.</div>
<h2 id="conclusion" style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 2.15em; font-weight: 300; line-height: 1.1; margin: 1.5em 0px;">
Conclusion</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Source Sans Pro', sans-serif; font-size: 15px; line-height: 21.75px; margin-bottom: 1.1em; text-align: justify;">
AVL is classic data structures, I consider it as a must see for any beginner that really want to up-skill on programming and algorithmics. This version using intrusive structures is also interesting, it demonstrates that we can do generic data structures in C without <tt style="box-sizing: border-box;">void*</tt> storage or unreadable macro based pseudo-template.</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-54839854426043546612015-05-24T18:16:00.000+02:002015-05-24T18:16:02.851+02:00Let's play with C++ std::function<div class="wmd-preview-section preview-content" id="wmd-preview-section-1" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Evolution of the C++ standard (C++0x and then C++11, C++14 and the future C++17) introduced aspects related to functional programming like lambda (anonymous functions) and a form of higher order.</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
My purpose is to discuss some disturbing behavior when trying to use these extensions.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-2" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<h4 style="box-sizing: border-box; color: inherit; font-family: inherit; line-height: 1.1; margin: 1.5em 0px; outline: none !important; text-align: justify;">
<span style="font-size: large;">Higher Order ?</span></h4>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Higher order is a concept that comes from theoretical roots like lambda-calculus and functional programming language. In pure lambda calculus, every-thing is a function and thus naturally functions can be used as values: they can be passed (and returned) to (by) functions. Extension like simply typed lambda-calculus or polymorphic variant (System F, ML … ) while re-introducing the notion of value (other than functions) keep this idea that function entities are just another kind of values.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Types system for higher order languages, most of the time, have, in their type algebra, a functional type constructor (most of the time noted ->.) From a typing point of view, typing an expression involving first class functions is not really different as typing for more traditional expressions.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Of course, implementation implies the introduction of notions like closures, but typing is somehow straightforward.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-3" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<h4 style="box-sizing: border-box; color: inherit; font-family: inherit; line-height: 1.1; margin: 1.5em 0px; outline: none !important; text-align: start;">
<span style="font-size: large;">And in C++ ?</span></h4>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Building functional-values in OO-languages has always been possible, a closure can build as an object that embeds context (values and/or references) and provides a special method corresponding to the function.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
In C++, thanks to overloading of operator(), resulting objects can even looks like real functions. The only remainging issues are anonymous functions that by nature must be built on the fly, and of course typing.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Typing issue arise from the fact that an object-function (sometimes called functor) has a specific type, and since most OO languages used a class based typing (type of an object is defined by its instantiating or declaring class, not its content) code relying on object-functions must used inheritance or template in order to solve typing issues.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
Introducing higher order in an OO language requires an extension to the types system, or some constraint on the nature functional values. For example, in recent Java (1.8), you have a syntax extension used to define anonymous functions (and/or use methods as functional values), but in terms of typing, it’s still based on object-functions and single method interfaces.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
In C++, lambda extensions define, on the fly, a new class for each lambda and thus a new type. Combined with other ways of passing functions (object-functions, function pointers … ), we ended with no uniform type parameters for functional arguments.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
This is where <tt style="box-sizing: border-box; outline: none !important;">std::function</tt> enter the scene.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-4" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<h4 style="box-sizing: border-box; color: inherit; font-family: inherit; line-height: 1.1; margin: 1.5em 0px; outline: none !important; text-align: start;">
<span style="font-size: large;">A generic interface for function type ?</span></h4>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
The functional header defines a generic wrapper for functions: <tt style="box-sizing: border-box; outline: none !important;">std::function</tt>, let’s look at an example::</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-5" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <functional></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <iostream></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> y</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">y</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">*</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">()</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f2 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">4</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">4</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
This seems nice: our function apply can take a lambda or a function name, as long as types are correct, it’s working. But, what happen if I try something a little more generic ?</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-6" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">template</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> T</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">T</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> T x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
I just want to have a generic input type for the parameter of my functional argument. First, let’s try to call this new version:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-7" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
The compiler disagrees:</div>
<pre style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;">candidate template ignored: could not match
'function<int (type-parameter-0-0)>' against 'int (*)(int)'
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
And I’ve got a similar message if I try with the lambda …</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
OK, it may seems strange, but you need to explicitly transform your function into an <tt style="box-sizing: border-box; outline: none !important;">std::function</tt>:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-8" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
OK, let’s go a little further, I want a more generic function: input and output types should be generic, and thanks to variadic template I’ll be able to have a totally generic invocation function:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-9" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <functional></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="com" style="box-sizing: border-box; color: #880000; outline: none !important;"># include <iostream></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">template</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> my_invoke</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...)></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">()</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f1 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f2 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> my_invoke</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">int</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> my_invoke</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">0</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
The first call is correct, nice, no surprise. But, the second one raise an error …</div>
<pre style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;">candidate template ignored: deduced conflicting types for parameter 'Args' (<unsigned int> vs. <int>)
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
<strong style="box-sizing: border-box; outline: none !important;">WAT</strong> ?</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
We’re used to be able, for years, to see integer constant promoted to the correct type. I hope you know that in C and C++ all integer literal are (unless specified differently) always of type <tt style="box-sizing: border-box; outline: none !important;">int</tt> and when you need another integer type, the compiler is able to insert conversions when needed (of course if it’s relevant.)</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
That’s really disturbing. But, OK, I can accept that, if you take a careful look at what happen here, it’s not that surprising, several typing mechanism can conflict here. Solving the problem is pretty straightforward, we just need to pass an unsigned integer explicitly:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-10" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> my_invoke</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3u</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Now, let’s push the example a little bit further: I want a double call of my generic functions:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-11" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">template</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> pairf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...)></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">pair</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">make_pair</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
And now, call that function:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-12" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> p </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> pairf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
You expected an error, just like the previous example ? … and … NO ERROR !</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
<strong style="box-sizing: border-box; outline: none !important;">WAT !</strong></div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Yes, it’s working now … Why ? The reason is pretty complicated to understand (I’m still digging in the standard to find out the exact rational) but in short a different set of rules are applied here, and the type resolution is done at a different point, solving the first issue.</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
My invocation functions are generic and variadic (the template is variadic, but anyway) and thus why not trying to pass functions with more than one argument ?</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-13" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> pair </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
pairf</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">4</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Does it compile ? Yes … and no ! I’ve tried this example with clang (3.6.0) and gcc (4.9.2 20150304 prerelease) and got different result: clang accept the code and gcc doesn’t.</div>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Gcc fails while selecting the correct template instantiation:</div>
<pre style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;">basic_fun4.cc:19:21: error: no matching function for call to ‘pairf(std::function<unsigned int(unsigned int, unsigned int)>, int, int, int, int)’
1, 2, 3, 4);
^
basic_fun4.cc:19:21: note: candidate is:
basic_fun4.cc:6:6: note: template<class R, class ... Args> std::pair<R, R> pairf(std::function<_Res(_ArgTypes ...)>, Args ..., Args ...)
auto pairf(std::function<R(Args...)> f, Args... args1, Args... args2)
^
basic_fun4.cc:6:6: note: template argument deduction/substitution failed:
basic_fun4.cc:19:21: note: inconsistent parameter pack deduction with ‘’ and ‘’
1, 2, 3, 4);
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
I must admit that I don’t know which compiler is correct on this, or if the standard provides sufficient on that issue. Anyway, once again the behavior is disturbing.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-14" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<h4 style="box-sizing: border-box; color: inherit; font-family: inherit; line-height: 1.1; margin: 1.5em 0px; outline: none !important; text-align: start;">
<span style="font-size: large;">Other solutions ?</span></h4>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
The invocation function can be rewritten in a better form without relying on <tt style="box-sizing: border-box; outline: none !important;">std::function</tt>:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-15" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">template</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> F</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">result_of</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">F</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...)>::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">type
my_apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">F f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Which can be called more directly:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-16" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f1 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f2 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> y</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> y</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> my_apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">cout </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> my_apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><<</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="str" style="box-sizing: border-box; color: #008800; outline: none !important;">"\n"</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
Another solution is to put that in a class/struct which induces simpler type resolution:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-17" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">template</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typename</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">struct</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> invoke </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">typedef</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">function</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...)></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> F</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">F f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">static</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">pair</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> pair_apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">F f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">...</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> args2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">make_pair</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> R</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...),</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
f</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">std</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">forward</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="typ" style="box-sizing: border-box; color: #660066; outline: none !important;">Args</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">args2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)...));</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">}</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 1.1em; outline: none !important;">
This is now easier to call:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-18" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; font-size: 18px; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<pre class="prettyprint prettyprinted" style="background-color: rgba(128, 128, 128, 0.0470588); border-radius: 5px; border: 0px; box-sizing: border-box; color: #333333; font-family: 'Source Code Pro', monospace; font-size: 0.9em; line-height: 1.45; margin-bottom: 1.1em; outline: none !important; padding: 10px 20px; text-align: start; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;"><code style="background-color: transparent !important; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: 'Source Code Pro', monospace; font-size: inherit; outline: none !important; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f1 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> f2 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">[](</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> y</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">)</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">-></span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">{</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">return</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">+</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> y</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">;</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">};</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> pair1 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
invoke</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">pair_apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">auto</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> pair2 </span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">=</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">
invoke</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;"><</span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088; outline: none !important;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">>::</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">pair_apply</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">(</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;">f2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">1</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">2</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">3</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">,</span><span class="pln" style="box-sizing: border-box; color: black; outline: none !important;"> </span><span class="lit" style="box-sizing: border-box; color: #006666; outline: none !important;">4</span><span class="pun" style="box-sizing: border-box; color: #666600; outline: none !important;">);</span></code></pre>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-19" style="background-color: #f6f6f6; box-sizing: border-box; color: #3f3f3f; font-family: 'Source Sans Pro', sans-serif; line-height: 26.1000003814697px; outline: none !important; text-align: justify;">
<h4 style="box-sizing: border-box; color: inherit; font-family: inherit; line-height: 1.1; margin: 1.5em 0px; outline: none !important; text-align: start;">
<span style="font-size: large;">So ?</span></h4>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
I first ran into that kind of issues while working with students: lot of them got obscure errors when dealing with constructions that take functions and their parameters. The fact that passing explicitly typed arguments solved the problem disturbed me and before facing the same issue this year I decided to investigate this a little bit.</div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
I must admit that most examples here are useless code, generic invocation functions are almost useless (and C++2017 will have one, anyway), but in much <span style="line-height: 26.1000003814697px;">complex cases, that kind of annoying situation can rise.</span></div>
<div style="box-sizing: border-box; font-size: 18px; margin-bottom: 1.1em; outline: none !important;">
C++ is an awesome language with a lot of interesting aspects and endless possibilities. But sometimes, choices are disturbing, like the default private inheritance (I’m still looking for a realistic use case for non-public inheritance … ) the redundant keywords (do you use <tt style="box-sizing: border-box; outline: none !important;">typename</tt> or <tt style="box-sizing: border-box; outline: none !important;">class</tt> in template parameters ?) or the obscure difference of <tt style="box-sizing: border-box; outline: none !important;">class</tt> and <tt style="box-sizing: border-box; outline: none !important;">struct</tt>.</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-24210417347573808622014-08-09T12:00:00.000+02:002014-08-09T12:00:22.497+02:00More Numerical Computations<div class="wmd-preview-section preview-content" id="wmd-preview-section-2" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<h2 id="optimization-and-details" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
Optimization and Details</h2>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
I’ve already talk about optimization for simple computation like trigonometric functions (see one of the previous post) trying to find the best implementation. I’m back on the subject, looking at the small details, and this time playing with integer, most-significant bit and integer square root.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-3" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<h2 id="most-significant-bit" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px; text-align: justify;">
Most Significant Bit</h2>
<div style="box-sizing: border-box; margin-bottom: 15px;">
I’ve recently read a post (<a href="http://www.codingforspeed.com/fast-power-two-equal-large-than-32-bit-int/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">Fast Power of Two Equal or Larger than a 32-bit Integer (1)</a>) about computing the smallest power of two bigger than a given integer. The idea is to find the most significant bit (msb.) If <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-1-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-1" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-2" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-3" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">k<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> is the msb of <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-2-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-4" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-5" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-6" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> then we know that <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-3-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-7" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 7.146em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 5.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.489em 1000.003em 2.86em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-8" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-9" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-10" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-11" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">k<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-12" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="mi" id="MathJax-Span-13" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-14" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><</span><span class="msubsup" id="MathJax-Span-15" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.831em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-16" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-17" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-18" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-19" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">k<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-20" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">+</span><span class="mn" id="MathJax-Span-21" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.361em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.211em; width: 0px;"></span></span></nobr></span>. The easiest way to compute the msb is to divide <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-4-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-22" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-23" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-24" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> by two until it reaches <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-5-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-25" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-26" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-27" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> and counting the number of steps. We can compute the power of two in the same loop, yielding the following code (with unused computation removed):</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-4" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> next_pow2_a</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(;</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
The post proposes another version, where it computes the msb with following idea: we can fill all the significant bit of an integer using 5 shift. In fact, this operation directly compute the power of 2 we’re looking for, the code (extracted from [<a href="http://www.codingforspeed.com/fast-power-two-equal-large-than-32-bit-int/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">1</a>]) look like that:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-5" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><div style="text-align: justify;">
<span class="kwd" style="background-color: transparent; box-sizing: border-box; color: #000088; font-size: inherit; line-height: 1.428571429;">static</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> </span><span class="kwd" style="background-color: transparent; box-sizing: border-box; color: #000088; font-size: inherit; line-height: 1.428571429;">inline</span></div>
<code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> npow</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">|=</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">|=</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">|=</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">|=</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">|=</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> next_pow2_b</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(!</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">||</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> npow</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
To be completed, I decided to test two other methods based on a binary search. The first one is the classical binary search applied to bits:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-6" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> next_pow2_c</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> l </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">32</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> l </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> m </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="pln" style="box-sizing: border-box; color: black;">l</span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;">r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)>></span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> m</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> m</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
l </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> m</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
The second one take advantages of the fact that we can unroll completely the loop being on 32bits integer and after some simplification we arrived at the following code:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-7" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> next_pow2_d</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
Finally, I wanted to compare all these methods against x86 bsr instruction:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-8" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> next_pow2_e</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
__asm__</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"bsrl %1,%0"</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;">"=r"</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">msb</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;">"r"</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">msb </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
In order to compare all the function, I needed a simple framework to automate the call against a huge array of random integer without loosing the inlining. Playing a little bit with macro, I’ve finally wrote the following code:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-9" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><div style="text-align: justify;">
<span style="background-color: transparent; color: #880000; font-size: inherit; line-height: 1.428571429;">// Time diff for bench</span></div>
<code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> nanodiff</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> timespec t0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> timespec t1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> s0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> t0</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">tv_sec </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">t0</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">tv_nsec</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1e-9</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> s1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> t1</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">tv_sec </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">t1</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">tv_nsec</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1e-9</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> s0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> s1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Type of the core loop bench functions</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">typedef</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(*</span><span class="pln" style="box-sizing: border-box; color: black;">func</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600;">*,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Macro generating core loops for bench</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Here we try to keep inlined function (avoiding use pointer)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">#define</span><span class="pln" style="box-sizing: border-box; color: black;"> CORE_BENCH_NAME</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">FNAME_</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> VER_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> core_bench_</span><span class="com" style="box-sizing: border-box; color: #880000;">##FNAME_##_##VER_</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">#define</span><span class="pln" style="box-sizing: border-box; color: black;"> CORE_BENCH</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">FNAME_</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> VER_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> core_bench_</span><span class="com" style="box-sizing: border-box; color: #880000;">##FNAME_##_##VER_(unsigned data[], unsigned len) { \</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;">len</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">++</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> FNAME_</span><span class="com" style="box-sizing: border-box; color: #880000;">##_##VER_(*cur); \</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(!</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">||</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Generate core bench loops for various version</span><span class="pln" style="box-sizing: border-box; color: black;">
CORE_BENCH</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">next_pow2</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
CORE_BENCH</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">next_pow2</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
CORE_BENCH</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">next_pow2</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> c</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
CORE_BENCH</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">next_pow2</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> d</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
CORE_BENCH</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">next_pow2</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> e</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> bench</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> data</span><span class="pun" style="box-sizing: border-box; color: #666600;">[],</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> func core</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">char</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">name</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> timespec t0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> t1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
clock_gettime</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">CLOCK_PROCESS_CPUTIME_ID</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">t0</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
core</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">data</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">len</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
clock_gettime</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">CLOCK_PROCESS_CPUTIME_ID</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">t1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"Bench %s: \t%gs\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> name</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> nanodiff</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">t1</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> t0</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
Here are the timing results compiled with clang and run on i7 (3770) for <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-6-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-28" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.66em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.317em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.089em 1000.003em 2.346em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-29" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-30" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.317em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-31" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-32" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-33" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-34" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">26</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.289em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> integers and compiler optimizations turned off (-O0) and sorted by time:</div>
<pre style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">Bench a (naive version): 3.92489s
Bench c (loop version): 1.63613s
Bench d (if-bin version): 1.01329s
Bench b (fast version): 0.781902s
Bench e (bsrl version): 0.291132s
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
The same with -O3 :</div>
<pre style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">Bench a (naive version): 1.34297s
Bench c (loop version): 0.703433s
Bench d (if-bin version): 0.398467s
Bench b (fast version): 0.116604s
Bench e (bsrl version): 0.0957188s
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
So obviously the asm version is faster in all cases, and the version from the [<a href="http://www.codingforspeed.com/fast-power-two-equal-large-than-32-bit-int/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">1</a>] has good perf. It’s also worth noticing that loop version of the binary search is nearly 2 times slower than the unrolled version.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-10" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<h2 id="square-root" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px; text-align: justify;">
Square Root</h2>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Computing msb is useful to set up a first approximation of a square root and thus, I found it interesting to see the impact of the msb computation time on a integer square root functions.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
I used the Heron method (or specialized Newton’s method.) The basic version used the argument as a first approximation, giving the following code:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-11" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> int_sqrt</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
The idea is then to replace the first approximation, using the following idea: if <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-7-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-35" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 7.146em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 5.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.489em 1000.003em 2.86em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-36" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-37" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-38" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-39" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">k<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-40" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="mi" id="MathJax-Span-41" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-42" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><</span><span class="msubsup" id="MathJax-Span-43" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.831em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-44" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-45" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-46" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-47" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">k<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-48" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">+</span><span class="mn" id="MathJax-Span-49" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.361em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.211em; width: 0px;"></span></span></nobr></span>, then <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-8-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-50" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 6.746em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 5.374em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.489em 1000.003em 2.974em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-51" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msqrt" id="MathJax-Span-52" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-53" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-54" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.883em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.06em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-55" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="msubsup" id="MathJax-Span-56" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 2.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-57" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-58" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-59" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-60" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-61" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">k<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-62" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">+</span><span class="mn" id="MathJax-Span-63" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span class="mo" id="MathJax-Span-64" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span><span class="texatom" id="MathJax-Span-65" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-66" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-67" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">/</span></span></span><span class="mn" id="MathJax-Span-68" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.575em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>. So, once we got the msb, we can have a first approximation with a division by two, some addition and a shift.</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
In order to avoid rewriting the same code several time, I, once again, play with macro:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-12" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000;">// Automatic square root function</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">#define</span><span class="pln" style="box-sizing: border-box; color: black;"> INT_SQRT_NAME</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">VER_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> int_sqrt_</span><span class="com" style="box-sizing: border-box; color: #880000;">##VER_</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">#define</span><span class="pln" style="box-sizing: border-box; color: black;"> INT_SQRT</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">VER_</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> int_sqrt_</span><span class="com" style="box-sizing: border-box; color: #880000;">##VER_(unsigned x) { \</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> msb_</span><span class="com" style="box-sizing: border-box; color: #880000;">##VER_(x - 1); \</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;"> \
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> \
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
These macro use a function returning the approximation, so the first version is just returning its argument (the name is badly choosen, since it doesn’t return the msb … ) :</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-13" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb_a</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
Then comes the naive loop again:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-14" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb_b</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(;</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
We can’t used msb computation from [<a href="http://www.codingforspeed.com/fast-power-two-equal-large-than-32-bit-int/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">1</a>] since it doesn’t compute the rank but directly the corresponding power of 2, but we can recycle our binary search versions:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-15" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb_c</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> l </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> h </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">32</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> h </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> l </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> m </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">h </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> l</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1u</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> m</span><span class="pun" style="box-sizing: border-box; color: #666600;">))</span><span class="pln" style="box-sizing: border-box; color: black;">
h </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> m</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
l </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> m</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> h</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb_d</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">16</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">>=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
And finally, the asm version:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-16" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb_e</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> msb</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
__asm__</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"bsrl %1,%0"</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;">"=r"</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">msb</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;">"r"</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">((</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> msb</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
I’ve tested this code with the same methods presented earlier, and get the following results for -O0 (and the same <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-9-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-69" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.66em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.317em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.089em 1000.003em 2.346em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-70" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-71" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.317em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-72" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-73" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-74" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-75" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">26</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.289em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> random integers):</div>
<pre style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">Bench a (simple version): 12.1927s
Bench b (basic msb version): 6.90088s
Bench c (bin loop version): 4.4s
Bench d (if bin version): 3.61818s
Bench e (bsrl version): 3.30704s
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
And with -O3:</div>
<pre style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">Bench a (simple version): 7.05185s
Bench b (basic msb version): 2.22483s
Bench c (bin loop version): 2.10562s
Bench d (if bin version): 1.58189s
Bench e (bsrl version): 1.55542s
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
The most import result is that a good approximation makes a huge difference ! Note also that the unrolled binary search is nearly as good as the asm version, giving an opportunity to write a fast portable code (almost portable … )</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-17" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<h2 id="more-hardware-backend" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
More Hardware Backend</h2>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Most modern CPU provides square root functions that are (supposed to be) really fast. I’ve decided to try SSE code using intrinsic instructions. After reading <a href="http://stackoverflow.com/questions/1528727/why-is-sse-scalar-sqrtx-slower-than-rsqrtx-x" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">a stackoverflow question (2)</a> I’ve decided to use the reverse-square root SSE instruction.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
The first issue was that this operator computes a floating point approximation that is less accurate than my other functions. Rather than decreasing my accuracy, I decided to complete the SSE code with some more steps of the previous algorithm. Here is the function (you can see that I borrowed the code from [<a href="http://stackoverflow.com/questions/1528727/why-is-sse-scalar-sqrtx-slower-than-rsqrtx-x" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">2</a>]):</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-18" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">static</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">inline</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> int_sqrt_sse</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> pIn </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> pOut </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
__m128 </span><span class="kwd" style="box-sizing: border-box; color: #000088;">in</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> _mm_load_ss</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">pIn </span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
_mm_store_ss</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&</span><span class="pln" style="box-sizing: border-box; color: black;">pOut</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> _mm_mul_ss</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">in</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> _mm_rsqrt_ss</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">in</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">pOut</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">do</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">out</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
And then test it using the same framework described earlier. The result are without any doubts the fastest version ! With a timing of <strong style="box-sizing: border-box;">0.45167s </strong>(with -O3, using clang and the same tests as before), it’s three time faster than all other versions !</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-19" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<h2 id="accuracy" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
Accuracy ?</h2>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
Square root are approximation, only few numbers have a computable square root that can be represented using a computer. So how can we define the accuracy of our computation ?</div>
</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<br />
<div style="text-align: justify;">
<span style="font-size: 14.44444465637207px;">For integer square root, we first observe that given an integer </span></div>
<span aria-readonly="true" class="MathJax" id="MathJax-Element-10-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-76" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-77" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-78" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span>, we can find two square numbers (call them <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-11-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-79" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.574em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-80" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-81" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-82" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-83" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span> and <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-12-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-84" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.574em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-85" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-86" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-87" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-88" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>) such that <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-13-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-89" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 5.889em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 4.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.774em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-90" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-91" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-92" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-93" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-94" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="mi" id="MathJax-Span-95" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-96" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="msubsup" id="MathJax-Span-97" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-98" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-99" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.218em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>. Since square root is a monotonic function, we have <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-14-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-100" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 8.86em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 7.089em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 3.146em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-101" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msqrt" id="MathJax-Span-102" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.374em 1000.003em 4.403em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-103" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-104" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-105" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-106" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.654em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-107" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="msqrt" id="MathJax-Span-108" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-109" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-110" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.883em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.06em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-111" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="msqrt" id="MathJax-Span-112" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.374em 1000.003em 4.403em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-113" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-114" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-115" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-116" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.654em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.504em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.568em; width: 0px;"></span></span></nobr></span>. Finding the best accuracy means finding the smallest <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-15-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-117" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 5.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 4.574em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-118" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-119" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">ϵ</span><span class="mo" id="MathJax-Span-120" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">=</span><span class="msubsup" id="MathJax-Span-121" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-122" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-123" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-124" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">−</span><span class="msubsup" id="MathJax-Span-125" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-126" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-127" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>, and, if we suppose that <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-16-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-128" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-129" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-130" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> is not a square number, we know that <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-17-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-131" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.574em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.46em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-132" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-133" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">ϵ</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> is minimized when there isn’t other square number between <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-18-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-134" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.574em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-135" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-136" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-137" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-138" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span> and <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-19-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-139" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.574em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-140" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-141" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-142" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-143" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>. Thanks again to the monotonicity of the square root, we can easily deduce that the minimum value is obtained for <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-20-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-144" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.574em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.46em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-145" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-146" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">ϵ</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> when <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-21-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-147" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 7.889em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 6.289em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 3.146em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-148" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msqrt" id="MathJax-Span-149" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.374em 1000.003em 4.403em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-150" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-151" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-152" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-153" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.654em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-154" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">−</span><span class="msqrt" id="MathJax-Span-155" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.374em 1000.003em 4.403em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-156" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-157" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-158" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-159" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.654em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-160" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">=</span><span class="mn" id="MathJax-Span-161" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">1</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.432em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.568em; width: 0px;"></span></span></nobr></span> and, if <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-22-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-162" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 4.231em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 3.374em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.831em 1000.003em 3.146em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-163" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-164" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">z</span><span class="mo" id="MathJax-Span-165" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">=</span><span class="msqrt" id="MathJax-Span-166" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.374em 1000.003em 4.403em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-167" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-168" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-169" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-170" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.031em 1000.003em 3.431em -0.511em); left: 0.746em; margin: 0px; padding: 0px; position: absolute; top: -3.769em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXGeneral; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -3.997em; transition: none; vertical-align: 0px;">‾<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.86em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.654em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.361em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.568em; width: 0px;"></span></span></nobr></span>, the solution is <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-23-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-171" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 3.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 2.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-172" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-173" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-174" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-175" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">0</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-176" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">=</span><span class="msubsup" id="MathJax-Span-177" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.86em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.003em 1000.003em 2.803em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-178" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">z</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.403em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-179" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.504em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span> and <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-24-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-180" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 6.574em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 5.26em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-181" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-182" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-183" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">y</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-184" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-185" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">=</span><span class="mo" id="MathJax-Span-186" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-187" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">z</span><span class="mo" id="MathJax-Span-188" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">+</span><span class="mn" id="MathJax-Span-189" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">1</span><span class="msubsup" id="MathJax-Span-190" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.803em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.917em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-191" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.346em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-192" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.575em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>. In that case, the best integer square root for <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-25-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-193" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-194" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-195" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> is <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-26-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-196" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.403em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.003em 1000.003em 2.803em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-197" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-198" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">z</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.789em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.139em; width: 0px;"></span></span></nobr></span>.</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
So in order to verify our result, we just have to check that <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-27-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-199" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 8.574em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 6.86em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.917em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-200" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-201" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.86em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(2.003em 1000.003em 2.803em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-202" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">z</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.403em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-203" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-204" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≤</span><span class="mi" id="MathJax-Span-205" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-206" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><</span><span class="mo" id="MathJax-Span-207" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-208" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">z</span><span class="mo" id="MathJax-Span-209" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">+</span><span class="mn" id="MathJax-Span-210" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">1</span><span class="msubsup" id="MathJax-Span-211" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.803em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.917em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-212" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.346em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-213" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.504em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.282em; width: 0px;"></span></span></nobr></span>. In my test this done using assert:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-20" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">square</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> square</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
What about floating point ? We can’t rely on the <em style="box-sizing: border-box;">next square number</em> idea, but we’re still trying to minimize a distance, here its <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-28-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-214" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 6.289em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 5.031em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.974em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-215" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-216" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-217" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-218" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">|</span></span></span><span class="mi" id="MathJax-Span-219" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-220" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">−</span><span class="mi" id="MathJax-Span-221" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">s</span><span class="mi" id="MathJax-Span-222" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">q</span><span class="mi" id="MathJax-Span-223" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">r<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mi" id="MathJax-Span-224" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">t<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-225" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-226" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="msubsup" id="MathJax-Span-227" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.803em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.917em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-228" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.346em; margin: 0px; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-229" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="texatom" id="MathJax-Span-230" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-231" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-232" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">|</span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.504em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span>. Most of the time, we fix a threshold for that distance defining it as our accuracy level. Unfortunately, this is not the best way of computing error using float.</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
There’s valuable pages (mainly <a href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">Comparing floating point numbers (3)</a> and <a href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">Comparing Floating Point Numbers, 2012 Edition (4)</a>) about comparing float. From our point of view, the interesting aspect is to establish our error not as a difference (or even relative difference) between two floating point number, but rather the kind of digit distance described in [<a href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">3</a>] and [<a href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">4</a>]. I won’t gave you the whole discussion, if you’re really interested in the subject read these articles (especially [<a href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">4</a>]).</div>
</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
So, as far as we’re concerned, what we need is to see how close our square root approximation is closed to the <em style="box-sizing: border-box;">real square root</em>. Here is a possible check for accuracy:</div>
</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-21" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><div style="text-align: justify;">
<span class="kwd" style="background-color: transparent; box-sizing: border-box; color: #000088; font-size: inherit; line-height: 1.428571429;">union</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> float_int </span><span class="pun" style="background-color: transparent; box-sizing: border-box; color: #666600; font-size: inherit; line-height: 1.428571429;">{</span></div>
<code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">int32_t</span><span class="pln" style="box-sizing: border-box; color: black;"> i</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Works only for non-null positive float number</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Without regards to special cases (NaN, infinity ... )</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> ulp_positive_float_compare</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">int32_t</span><span class="pln" style="box-sizing: border-box; color: black;"> ulp_threshold</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// Some acceptable constraints</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">sizeof</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">sizeof</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="typ" style="box-sizing: border-box; color: #660066;">int32_t</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="com" style="box-sizing: border-box; color: #880000;">// to be sure</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">a </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> b </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="com" style="box-sizing: border-box; color: #880000;">// non-null positive</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">assert</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">ulp_threshold </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> ulp_threshold </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">22</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="com" style="box-sizing: border-box; color: #880000;">// proper threshold</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">a </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">union</span><span class="pln" style="box-sizing: border-box; color: black;"> float_int A</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> B</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
A</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
B</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> b</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> abs</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">A</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">i </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> B</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">i</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><=</span><span class="pln" style="box-sizing: border-box; color: black;"> ulp_threshold</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
When exploring various implementation of integer square root, I’ve rejected the use of libC sqrtf, because it where too divergent for me: once translated back to integer, the root doesn’t satisfy my test. In the same idea, the SSE square root needed some more iteration of the main algorithm in order to return a correct value. Why ? Testing sqrtf result with the previous function shows differences that are less than one <em style="box-sizing: border-box;">ULP</em>, meaning that we are as close as we can, from a float point of view, but that doesn’t mean that the integer translation of this result is the closest integer we can get to the square root.</div>
</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-22" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<h2 id="approximation-and-optimization" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
Approximation and Optimization</h2>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
The computation of the float square root relies on an iterative process that get closer to the <em style="box-sizing: border-box;">perfect</em> solution at each step. That’s a recurrent pattern, many numerical approximation works by narrowing a range around the solution. The accuracy of your result is directly linked to the number of iterations and thus the speed of the computation is inversely proportional to the accuracy. </div>
<div style="text-align: justify;">
If, for a given problem, you can obtain a fast approximation, you can cut down the number of steps required to obtain an accurate result. For the integer square root, the approximation based on the MSB is a pretty good example: even with a slow MSB computation the square root is 3 time faster.</div>
</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
That’s the root of all fast square root function for floating pointer numbers. The form of floating pointer numbers offers various <em style="box-sizing: border-box;">tricks</em> to get a very fast approximation of the square root that can be used as a starting point for a Heron/Newton iterative method.</div>
</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
A first version can use the fact that we can obtain a good approximation of <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-29-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-233" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 3.603em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 2.86em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.974em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-234" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-235" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">l<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mi" id="MathJax-Span-236" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">o</span><span class="msubsup" id="MathJax-Span-237" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-238" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">g</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-239" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-240" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-241" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-242" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.289em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span> directly from the binary representation of <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-30-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-243" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-244" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-245" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> (noted <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-31-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-246" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.717em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.374em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.517em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-247" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-248" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.374em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-249" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.054em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-250" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-251" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-252" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">i</span><span class="mi" id="MathJax-Span-253" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">n</span><span class="mi" id="MathJax-Span-254" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">t<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.861em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.282em; width: 0px;"></span></span></nobr></span> in the following expression): <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-32-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-255" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 13.546em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 10.803em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.546em 1000.003em 2.974em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-256" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-257" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">l<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mi" id="MathJax-Span-258" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">o</span><span class="msubsup" id="MathJax-Span-259" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-260" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">g</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-261" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-262" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-263" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-264" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span><span class="mo" id="MathJax-Span-265" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;">≃</span><span class="msubsup" id="MathJax-Span-266" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.289em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.374em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-267" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.054em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-268" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-269" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-270" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">i</span><span class="mi" id="MathJax-Span-271" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">n</span><span class="mi" id="MathJax-Span-272" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">t<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-273" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">×</span><span class="msubsup" id="MathJax-Span-274" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.774em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-275" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">e</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.46em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-276" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-277" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mo" id="MathJax-Span-278" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">−</span><span class="mn" id="MathJax-Span-279" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">23</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-280" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">−</span><span class="mn" id="MathJax-Span-281" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px 0px 0px 0.231em; position: static; transition: none; vertical-align: 0px;">127</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.504em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span> (where <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-33-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-282" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.946em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.546em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.746em -0.397em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-283" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-284" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">127</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> is the bias of the 32bits floating point representation.) From <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-34-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-285" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 3.603em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 2.86em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.717em 1000.003em 2.974em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-286" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-287" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">l<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mi" id="MathJax-Span-288" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">o</span><span class="msubsup" id="MathJax-Span-289" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.974em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.974em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-290" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">g</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -1.997em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-291" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span class="mo" id="MathJax-Span-292" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">(</span><span class="mi" id="MathJax-Span-293" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span><span class="mo" id="MathJax-Span-294" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">)</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.289em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.354em; width: 0px;"></span></span></nobr></span> we can obtain our square root approximation. Here is a basic implementation (based on Wikipedia articles) where <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-35-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-295" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.689em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.517em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.946em 1000.003em 2.746em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.569em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-296" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-297" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">a</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.574em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 0.718em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> is bias adjustment to reduce the approximation error:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-23" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">union</span><span class="pln" style="box-sizing: border-box; color: black;"> float_int </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> f</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> i</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">};</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">const</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> a </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0x4c000</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// sqrt based on log2</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> sqrt_log2</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">union</span><span class="pln" style="box-sizing: border-box; color: black;"> float_int X</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
X</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">union</span><span class="pln" style="box-sizing: border-box; color: black;"> float_int Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">i </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">29</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">X</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">i </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><<</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">22</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
There’s an even faster version based on the reciprocal square root (<span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-36-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; font-size: 14.44444465637207px; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-298" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.546em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17.77777862548828px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.203em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.089em 1000.003em 2.917em -0.397em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.169em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-299" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mfrac" id="MathJax-Span-300" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px 0.117em; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.031em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.603em 1000.003em 2.403em -0.454em); left: 9.010416984558105px; margin: 0px 0px 0px -0.169em; padding: 0px; position: absolute; top: -2.626em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-301" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">1</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.374em 1000.003em 4.346em -0.454em); left: 9.010416984558105px; margin: 0px 0px 0px -0.454em; padding: 0px; position: absolute; top: -3.597em; transition: none; vertical-align: 0px;"><span class="msqrt" id="MathJax-Span-302" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 0.917em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.774em 1000.003em 2.403em -0.511em); left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -2.226em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-303" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mi" id="MathJax-Span-304" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: STIXGeneral; font-size: 12.222222328186035px; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">x<span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0.003em;"></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.231em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(0.917em 1000.003em 1.317em -0.511em); left: 0.517em; margin: 0px; padding: 0px; position: absolute; top: -1.54em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.403em; box-sizing: border-box; display: inline-block; height: 1.25px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.054em; width: 0px;"></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1.089em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(3.146em 1000.003em 4.174em -0.454em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -3.826em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; font-family: STIXVariants; font-size: 12.222222328186035px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">√</span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 4.003em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(0.86em 1000.003em 1.26em -0.511em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -1.311em; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 1.031em; box-sizing: border-box; display: inline-block; height: 1.25px; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: 0.003em; width: 0px;"></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 1.089em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.174em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 2.004em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.782em; width: 0px;"></span></span></nobr></span>). This version gain famed due to its used in Quake III and the fact that it looks somehow <em style="box-sizing: border-box;">magic</em> (to be fair, this version appears first in some SGI code.) While the original code was used directly for reciprocal square root (needed in computer graphics) you can obtain the square root by taking the reciprocal again (or with a step of the Newton method.) The following version (again inspired by the Wikipedia version) is extended with 3 steps of the Newton method with a result as accurate as the libC sqrtf.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-24" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> sqrt_fastinv</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">union</span><span class="pln" style="box-sizing: border-box; color: black;"> float_int X</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
X</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">i </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0x5f3759df</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">X</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">i </span><span class="pun" style="box-sizing: border-box; color: #666600;">>></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.5f</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;">Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="com" style="box-sizing: border-box; color: #880000;">// Newton step with 1/sqrt(x)</span><span class="pln" style="box-sizing: border-box; color: black;">
Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.5f</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="com" style="box-sizing: border-box; color: #880000;">// Classical Newton steps</span><span class="pln" style="box-sizing: border-box; color: black;">
Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.5f</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> Y</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">f</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
To obtain the same accuracy with classic Newton method it requires 5 to 20 steps (for a nine digits number.)</div>
</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-25" style="background-color: #f6f7f9; box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 22.22222328186035px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<h2 id="conclusion" style="box-sizing: border-box; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px; text-align: justify;">
Conclusion</h2>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
OK, we finally finish this survey of basic computations. Its interesting to see how obviously simple computations can be optimized and rewritten to obtain measurable performance gain.</div>
</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
<div style="text-align: justify;">
I’m not a specialist of numerical algorithms but I do know programming and algorithms in general, details matter, and most of the time you’re looking for a trade-off between accuracy and computation time. You also need to consider that fast but no really accurate approximation can serve as a good starting point speed-up a more accurate algorithm.</div>
</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-88044289413720816862014-07-01T11:10:00.001+02:002014-07-01T11:10:49.298+02:00Playing With Parallel Computing and Graph<div class="wmd-preview-section preview-content" id="wmd-preview-section-2" style="background-color: #f6f7f9; box-sizing: border-box;">
<h2 id="parallel-algorithms" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
Parallel Algorithms ?</h2>
<h2 id="parallel-algorithms" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-2" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Parallel programming is an important field in modern programming, it introduces new issues that traditional (sequential) programming doesn’t have:</div>
<ul style="box-sizing: border-box; margin-bottom: 15px; margin-top: 0px;">
<li style="box-sizing: border-box; text-align: justify;">Determinism</li>
<li style="box-sizing: border-box; text-align: justify;">Concurrent memory access</li>
<li style="box-sizing: border-box; text-align: justify;">Communication</li>
<li style="box-sizing: border-box; text-align: justify;">Synchronization</li>
</ul>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
And of course, we need to design new algorithms for a lot of problem that already have sequential ones. For some cases, the migration is obvious or doesn’t really need specific attention and for others it may be impossible.</div>
</div>
</h2>
<h3 id="divide-and-conquer" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.1; margin: 35px 0px 20px; text-align: justify;">
Divide and Conquer</h3>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-3" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
The divide and conquer principle is a classical strategy used in algorithms: the idea is to split the task to be accomplished into smaller pieces (divide) and merge sub-results (conquer.) There are lots of algorithms based on that principle, among which the most known is probably QuickSort.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Divide and conquer strategy are also suited for parallelism: divided tasks can be distributed among threads easily. In fact, lots of recursive algorithms (and even more iterative ones) can be re-implemented that way.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
As a small example consider finding the smallest element in an unsorted array. The classical strategy is to scan the whole array sequentially. We can rewrite this in the following way:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-4" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> find_min</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> lmin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> hmin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">mid </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">)/</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
lmin </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> find_min</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
hmin </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> find_min</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> lmin </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> hmin </span><span class="pun" style="box-sizing: border-box; color: #666600;">?</span><span class="pln" style="box-sizing: border-box; color: black;"> lmin </span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;"> hmin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
This implementation is less efficient in sequential programming than the traditional scan, but you can execute recursive calls in separate threads to obtain a parallel version of your code. In fact, in order to have a correct algorithm, you will need a split-bound (a minimal size bellow which you’ll use sequential search) and probably a task systems to avoid starting new a thread for each call.</div>
</div>
</h2>
<h3 id="parallel-or-distributed" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.1; margin: 35px 0px 20px;">
Parallel or Distributed ?</h3>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-5" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
There’s a lot of definition in the parallel computing world, but we can differentiate to major groups of parallel programs depending on whether data sharing is based on shared memory or on communication. So, the sake of clarity, I’ll call parallel algorithm those using shared memory and distributed algorithm those who rely on communication.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Both kind have different advantages and, of course, issues. In fact, advantages and issues are tight coupled: sharing memory permits efficient data exchange while inducing a lot of concurrent access issues (and thus determinism issues), on the other hand, communication suppress concurrent access issues and introduce synchronization and communication overhead. You may use communication in multi-threaded context, but if you plan to really distribute you application upon multiple processors over a network, you can’t use shared memory (yeah, I know, that’s obvious.)</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Now, what is interesting in divide and conquer strategy is that you never really share the data (most of the time). In fact, the divide part can be simplify to the point where you just split index references to the original data and restrain data exchange to the recollecting part (conquer.)</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
OK, that’s theory, in practice things are far more complicated, otherwise computer scientists in the parallel and distributed fields should have loose their jobs for a long time.</div>
</div>
</h2>
<h2 id="an-example-computing-connected-components-in-undirected-graph" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px; text-align: left;">
An Example: Computing Connected Components in Undirected Graph</h2>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-6" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<blockquote class="tr_bq">
<strong style="box-sizing: border-box;">The purpose of the following example is not to describe a new, nor an efficient algorithm but to analyse and study how can we make a parallel implementation of a sequential algorithm.</strong></blockquote>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Let’s consider a classical algorithm for computing components in an undirected graph: union-find.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
The principle is very straight forward, we associate to each vertex a <em style="box-sizing: border-box;">leader</em> and when we encounter a new edge, we search the leaders of the two ends of the edge and (if they differ) you make one the leader of the other. Here are the two basic functions, considering that vertices have an unique integer identifier (ranging from 0 to the order of the graph):</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-7" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><div style="text-align: justify;">
<span class="kwd" style="background-color: transparent; box-sizing: border-box; color: #000088; font-size: inherit; line-height: 1.428571429;">int</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> find</span><span class="pun" style="background-color: transparent; box-sizing: border-box; color: #666600; font-size: inherit; line-height: 1.428571429;">(</span><span class="kwd" style="background-color: transparent; box-sizing: border-box; color: #000088; font-size: inherit; line-height: 1.428571429;">int</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> leaders</span><span class="pun" style="background-color: transparent; box-sizing: border-box; color: #666600; font-size: inherit; line-height: 1.428571429;">[],</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> </span><span class="kwd" style="background-color: transparent; box-sizing: border-box; color: #000088; font-size: inherit; line-height: 1.428571429;">int</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> v</span><span class="pun" style="background-color: transparent; box-sizing: border-box; color: #666600; font-size: inherit; line-height: 1.428571429;">)</span><span class="pln" style="background-color: transparent; box-sizing: border-box; color: black; font-size: inherit; line-height: 1.428571429;"> </span><span class="pun" style="background-color: transparent; box-sizing: border-box; color: #666600; font-size: inherit; line-height: 1.428571429;">{</span></div>
<code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">v </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> leaders</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">v</span><span class="pun" style="box-sizing: border-box; color: #666600;">])</span><span class="pln" style="box-sizing: border-box; color: black;">
v </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> leaders</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">v</span><span class="pun" style="box-sizing: border-box; color: #666600;">];</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> v</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">void</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">union</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> leaders</span><span class="pun" style="box-sizing: border-box; color: #666600;">[],</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> v0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> v1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> l0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">leaders</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> v0</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> l1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">leaders</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> v1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">l0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> l1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
leaders</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l1</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> l0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
At beginning, each vertex is its own leader. The main algorithm will then traverse the set of edges and call union for each pair of vertex. There’s two major optimizations: path compression and rank.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
This algorithm is somehow <em style="box-sizing: border-box;">incremental</em>: at each step, the current leaders correspond to the real leaders of a graph limited to edges seen so far. We can also <em style="box-sizing: border-box;">merge</em> the results of separate runs on separate sets of edges. In fact, after computing leaders for a given subset of edges, we can build a<em style="box-sizing: border-box;">smaller</em> set of edges where each vertex in a connected component is linked to the leader of the component.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Are we sure the subsets we built are smaller ? If we consider a connected component made of N vertices and K edges, the smallest value for K is N-1. On the other hand, the set of edges built by linking each vertex in the component to the component leader we have exactly N-1 edges. So, we can not enforce that the set is strictly smaller, but it can be bigger. Like other divide and conquer strategies, this approach is not more efficient, but since we can introduce some parallelism, if we bound the induce overhead, we will have it run faster.</div>
</div>
</h2>
<h3 id="strategies-for-parallelism" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.1; margin: 35px 0px 20px;">
Strategies for Parallelism</h3>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-8" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
The way we can split the input is now obvious: we simply split the set of edges into smaller subsets. The question is: how do we merge sub-results.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
So consider we have two subsets of edges, we can, as a first approximation, run union-find on both subsets, then build two new subsets like described earlier, merge them and run again union-find on it. It’s working but is it efficient ?</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
It’s obvious that on most cases, this will almost double the linear cost of the algorithm (if the number of edges is already minimal the parallel pass will be useless … )</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
On the other hand, if we only consider running the algorithm on edges that <em style="box-sizing: border-box;">matter</em>, <em style="box-sizing: border-box;">i.e.</em> edges that can connect components built in different subsets, we could decrease the cost of the merge pass.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
In <em style="box-sizing: border-box;">Introduction to Parallel Computing</em> (Addison Wesley, ISBN: 0-201-64865-2, 2003, by Grama, Gupta, Karyptis and Kumar), the authors present a similar approach to the same problem. They choose to compute connected components of splited subsets of edges using a depth traversal and perform the merge step using union-find. They also present a formal study of the algorithm and its cost for shared memory and communication models.</div>
</div>
</h2>
<h3 id="implementation" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.1; margin: 35px 0px 20px;">
Implementation ?</h3>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-9" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
I choose to make an experimental implementation of the parallel version that I described using the go language (<a href="http://golang.org/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">http://golang.org/</a>).</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
<em style="box-sizing: border-box;">Why go ?</em> A good question, first I was looking for an interesting (but short) project to increase my knowledge of the language and test the go-routine mechanism a little bit further. The idea is also to extend this algorithm into a distributed one (work in progress, stay tune for the next article) using nsq messaging system (<a href="http://nsq.io/" style="-webkit-transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out; box-sizing: border-box; color: #2080df; text-decoration: none; transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, border-color 0.15s ease-in-out;">http://nsq.io/</a>).</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
I’ll publish the code into a public git repository soon (actually it is still in a dirty experimental form and need more testing.) But, don’t be afraid, here are some hints and explanation on how it works ;)</div>
</div>
</h2>
<h4 id="union-find-ranks-and-path-compression" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 18px; font-weight: 500; line-height: 1.1; margin: 25px 0px 15px;">
Union-Find, ranks and path compression</h4>
<h2 style="box-sizing: border-box; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-10" style="box-sizing: border-box;">
<div class="se-section-delimiter" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px;">
</div>
<div style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px; margin-bottom: 15px; text-align: justify;">
Union-find is quite straightfoward to implement, but in order to provide the best performance, we need to add simple optimizations: ranks and path compression.</div>
<div style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px; margin-bottom: 15px; text-align: justify;">
<strong style="box-sizing: border-box;">Ranks:</strong> the idea is to add a simple heuristic in order to choose which among the two founded vertices will become the leader of merged component. For that we store a count of the vertices <em style="box-sizing: border-box;">represented</em> by each leader. At beginning, each vertex is its own leader and thus represent one vertex, when union is called, we choose the one with the biggest count as a leader, updating its count by adding these of the other leader. When count are equal, we choose the first element of the pair.</div>
<div style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px; margin-bottom: 15px; text-align: justify;">
<strong style="box-sizing: border-box;">Path compression:</strong> most of the time of the algorithm is spent in the find function, and this time is due to the iteration required to find the leader. We can simply notice that when searching for the leader all encountered vertices have the same leader and thus we can re-affect them with the found leader. While this add a second loop to the function, it greatly reduces the number of steps to found the leader at each call.</div>
<div style="box-sizing: border-box; margin-bottom: 15px;">
</div>
<div style="color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px; text-align: justify;">
Combining both optimization enforces an amortized complexity of </div>
<span aria-readonly="true" class="MathJax" id="MathJax-Element-1-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; margin: 0px; padding: 0px; word-wrap: normal;"><nobr style="border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; vertical-align: 0px;"><span class="math" id="MathJax-Span-1" style="border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; vertical-align: 0px; width: 4.43em;"><span style="border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; vertical-align: 0px; width: 3.663em;"><span style="border: 0px; box-sizing: border-box; clip: rect(1.833em 1000.003em 3.191em -0.469em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.772em; vertical-align: 0px;"><div style="color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 17px; font-weight: 500; line-height: normal; text-align: justify; white-space: nowrap; word-spacing: normal;">
<span class="mi" id="MathJax-Span-3" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Math; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">O</span><span class="mo" id="MathJax-Span-4" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">(</span><span class="mi" id="MathJax-Span-5" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Math; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">α</span><span class="mo" id="MathJax-Span-6" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">(</span><span class="mi" id="MathJax-Span-7" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Math; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">n</span><span class="mo" id="MathJax-Span-8" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">)</span><span class="mo" id="MathJax-Span-9" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">)</span></div>
<span style="border: 0px; box-sizing: border-box; color: #162029; display: inline-block; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 17px; font-weight: 500; height: 2.777em; margin: 0px; padding: 0px; position: static; vertical-align: 0px; width: 0px;"><div style="text-align: justify;">
</div>
</span></span></span></span></nobr></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-2-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; margin: 0px; padding: 0px; word-wrap: normal;"><nobr style="border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; vertical-align: 0px;"><span class="math" id="MathJax-Span-10" style="border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; vertical-align: 0px; width: 2.541em;"><span style="border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; vertical-align: 0px; width: 2.069em;"><span style="border: 0px; box-sizing: border-box; clip: rect(1.833em 1000.003em 3.191em -0.469em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.772em; vertical-align: 0px;"><div style="color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 17px; font-weight: 500; line-height: normal; text-align: justify; white-space: nowrap; word-spacing: normal;">
<span class="mi" id="MathJax-Span-12" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Math; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">α</span><span class="mo" id="MathJax-Span-13" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">(</span><span class="mi" id="MathJax-Span-14" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Math; font-style: italic; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">n</span><span class="mo" id="MathJax-Span-15" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; word-spacing: normal;">)</span></div>
<span style="border: 0px; box-sizing: border-box; color: #162029; display: inline-block; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 17px; font-weight: 500; height: 2.777em; margin: 0px; padding: 0px; position: static; vertical-align: 0px; width: 0px;"><div style="text-align: justify;">
</div>
</span></span></span></span></nobr></span><br />
<div style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px; margin-bottom: 15px; text-align: justify;">
The implementation supposed that vertex has a unique integer id ranging from 1 to the order of the graph and thus we may use a simple array to store the leader, but since in the parallel implementation we won’t see all vertices, we replace the array with a map from int to int. In the same idea, we use another map for the rank.</div>
<div style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px; margin-bottom: 15px; text-align: justify;">
Here are the algorithm main union-find code:</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-11" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; font-weight: 500; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">package</span><span class="pln" style="box-sizing: border-box; color: black;"> union_find
type </span><span class="typ" style="box-sizing: border-box; color: #660066;">Edge</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Src</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Dst</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
type </span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
leader map</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;">
rank map</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
func </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">key </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">lead </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> _</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> ok </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">leader</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">];</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">!</span><span class="pln" style="box-sizing: border-box; color: black;">ok </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">leader</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> key
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">rank</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> lead </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">leader</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">];</span><span class="pln" style="box-sizing: border-box; color: black;"> lead </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> key </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Count</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">leader</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">lead</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
lead </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">leader</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">key</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
func </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Unify</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">v0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> v1 </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
l0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> l1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">v0</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Find</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">v1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">rank</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l0</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">rank</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l1</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
tmp </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> l0
l0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> l1
l1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> tmp
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">leader</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l1</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> l0
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">rank</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l0</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">rank</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l1</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Comp</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="pln" style="box-sizing: border-box; color: black;">rank</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">l0</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> l0
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
</div>
</h2>
<h3 id="parallelism" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.1; margin: 35px 0px 20px;">
Parallelism</h3>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-12" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Parallel split and merge are done using a divide and conquer strategy. I use another data-structure where I store the maps for the union-find and a set of the vertices present in the current subset. The main idea is to split the set of edges until we reach our threshold, then I build a <em style="box-sizing: border-box;">subgraph</em>containing the set of vertices and the result of the union-find algorithm.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
In order to merge two <em style="box-sizing: border-box;">subgraphs</em> g1 and g2, I rebuild a set of edges mapping each vertex to its leader from g2 and for each new edges (s,d), if s or d appears in g1 I call union on the edge, otherwise I simply add (s,d) in the leader map.</div>
</div>
<div class="wmd-preview-section preview-content" id="wmd-preview-section-13" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<pre class="prettyprint prettyprinted" style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">package</span><span class="pln" style="box-sizing: border-box; color: black;"> subgraph
type </span><span class="typ" style="box-sizing: border-box; color: #660066;">SubGraph</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">struct</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">VertexList</span><span class="pln" style="box-sizing: border-box; color: black;"> map</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="kwd" style="box-sizing: border-box; color: #000088;">bool</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
func </span><span class="typ" style="box-sizing: border-box; color: #660066;">NewSubGraph</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">[]</span><span class="pln" style="box-sizing: border-box; color: black;">union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Edge</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">SubGraph</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">SubGraph</span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">make</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">map</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="kwd" style="box-sizing: border-box; color: #000088;">bool</span><span class="pun" style="box-sizing: border-box; color: #666600;">),</span><span class="pln" style="box-sizing: border-box; color: black;"> union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">NewComponent</span><span class="pun" style="box-sizing: border-box; color: #666600;">()}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> _</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> e </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> range edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">VertexList</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Src</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">true</span><span class="pln" style="box-sizing: border-box; color: black;">
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">VertexList</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Dst</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">true</span><span class="pln" style="box-sizing: border-box; color: black;">
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Unify</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Src</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Dst</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> g
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
func </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">g </span><span class="typ" style="box-sizing: border-box; color: #660066;">SubGraph</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">Merge</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">[]</span><span class="pln" style="box-sizing: border-box; color: black;">union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Edge</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
q </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> make</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">map</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="kwd" style="box-sizing: border-box; color: #000088;">bool</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> _</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> e </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> range edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
newsrc </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">false</span><span class="pln" style="box-sizing: border-box; color: black;">
newdst </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">false</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> newsrc </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">!</span><span class="pln" style="box-sizing: border-box; color: black;">g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">VertexList</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Src</span><span class="pun" style="box-sizing: border-box; color: #666600;">];</span><span class="pln" style="box-sizing: border-box; color: black;"> newsrc </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
q</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Src</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">true</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> newdst </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">!</span><span class="pln" style="box-sizing: border-box; color: black;">g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">VertexList</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Dst</span><span class="pun" style="box-sizing: border-box; color: #666600;">];</span><span class="pln" style="box-sizing: border-box; color: black;"> newdst </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
q</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Dst</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">true</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">!(</span><span class="pln" style="box-sizing: border-box; color: black;">newsrc </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> newdst</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Unify</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Src</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> e</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Dst</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Components</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">AddPair</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">e</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> v </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> range q </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">VertexList</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">v</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">true</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
func rec_compute</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">[]</span><span class="pln" style="box-sizing: border-box; color: black;">union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Edge</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> grain </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">g </span><span class="typ" style="box-sizing: border-box; color: #660066;">SubGraph</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
mid </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> mid </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> grain </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
hout </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> make</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">chan </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
l </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> edges</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;">mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">]</span><span class="pln" style="box-sizing: border-box; color: black;">
h </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> edges</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="pln" style="box-sizing: border-box; color: black;">mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">:</span><span class="pln" style="box-sizing: border-box; color: black;">len</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges</span><span class="pun" style="box-sizing: border-box; color: #666600;">)]</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">var</span><span class="pln" style="box-sizing: border-box; color: black;"> gh </span><span class="typ" style="box-sizing: border-box; color: #660066;">SubGraph</span><span class="pln" style="box-sizing: border-box; color: black;">
go func</span><span class="pun" style="box-sizing: border-box; color: #666600;">()</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
gh </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> rec_compute</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">h</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> grain</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
hout </span><span class="pun" style="box-sizing: border-box; color: #666600;"><-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}()</span><span class="pln" style="box-sizing: border-box; color: black;">
g </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> rec_compute</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">l</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> grain</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;"><-</span><span class="pln" style="box-sizing: border-box; color: black;"> hout
g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Merge</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">gh</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">GetComputedEdges</span><span class="pun" style="box-sizing: border-box; color: #666600;">())</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="typ" style="box-sizing: border-box; color: #660066;">NewSubGraph</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
func </span><span class="typ" style="box-sizing: border-box; color: #660066;">ComputeEdges</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">[]</span><span class="pln" style="box-sizing: border-box; color: black;">union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Edge</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> grain </span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">comp_edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">[]</span><span class="pln" style="box-sizing: border-box; color: black;">union_find</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">Edge</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
g </span><span class="pun" style="box-sizing: border-box; color: #666600;">:=</span><span class="pln" style="box-sizing: border-box; color: black;"> rec_compute</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">edges</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> grain</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
comp_edges </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> g</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="typ" style="box-sizing: border-box; color: #660066;">GetComputedEdges</span><span class="pun" style="box-sizing: border-box; color: #666600;">()</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Parallelism is obtained through go-routines and synchronization use a simple int channel.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
This code is a first draft, I’ve try another implementation without the merge optimization, testing is on the run to see if it’s really accurate.</div>
</div>
</h2>
<h3 id="performances" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.1; margin: 35px 0px 20px;">
Performances ?</h3>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-14" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
I’m still exploring various aspects of the implementation to track down useless computations and bad practices (I’ve still got a lot to learn about go.) I’m also re-considering various choices made for optimization …</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Testing is actually done stupidly: I build a random huge set of edges, with the simplest generator. For 16 millions of edges, I start to see an interesting speed-up over a straight sequential union-find. But, I’ve also noticed that replacing go-routine call with a simple recursion call is slowing down the process (w.r.t. the sequential version) by 70%, there’s probably something to do in the whole process to get better results.</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
For that matter, here are the output from go test -bench -cpu 8:</div>
<pre style="background-color: rgba(102, 128, 153, 0.0470588); border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgba(102, 128, 153, 0.0745098); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">PASS
BenchmarkNewSubGraphLinear-8 1 10374479688 ns/op
BenchmarkComputeEdgeLinear-8 1 17708146949 ns/op
BenchmarkComputeEdgeParallel-8 1 5025817943 ns/op
ok git.lse.epita.fr/users/burell_m/distributed_union_find/subgraph 45.617s
</code></pre>
<div style="box-sizing: border-box; margin-bottom: 15px;">
The first bench test the basic sequential version, the second the divide and conquer without go-routines and the last one corresponds to the code shown in this article. The bench runs with a random graph of <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-3-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-16" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.656em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.361em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.066em 1000.003em 2.305em -0.469em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.122em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-17" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-18" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.302em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.951em 1000.003em 2.955em -0.469em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.772em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-19" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.777em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.534em; margin: 0px; padding: 0px; position: absolute; top: -2.713em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-20" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-21" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-22" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; font-size: 12px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">24</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.305em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.128em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.218em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span> edges and a threshold of <span class="MathJax_Preview" style="box-sizing: border-box; color: #888888;"></span><span aria-readonly="true" class="MathJax" id="MathJax-Element-4-Frame" role="textbox" style="border: 0px; box-sizing: border-box; direction: ltr; display: inline; float: none; line-height: normal; margin: 0px; padding: 0px; white-space: nowrap; word-spacing: normal; word-wrap: normal;"><nobr style="-webkit-transition: none; border: 0px; box-sizing: border-box; margin: 0px; max-height: none; max-width: none; padding: 0px; transition: none; vertical-align: 0px;"><span class="math" id="MathJax-Span-23" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 1.656em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; font-size: 17px; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.361em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.066em 1000.003em 2.305em -0.469em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.122em; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-24" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="msubsup" id="MathJax-Span-25" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 0px; margin: 0px; padding: 0px; position: relative; transition: none; vertical-align: 0px; width: 1.302em;"><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; clip: rect(1.951em 1000.003em 2.955em -0.469em); left: 0.003em; margin: 0px; padding: 0px; position: absolute; top: -2.772em; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-26" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">2</span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.777em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; left: 0.534em; margin: 0px; padding: 0px; position: absolute; top: -2.713em; transition: none; vertical-align: 0px;"><span class="texatom" id="MathJax-Span-27" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mrow" id="MathJax-Span-28" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;"><span class="mn" id="MathJax-Span-29" style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline; font-family: MathJax_Main; font-size: 12px; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px;">20</span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.305em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span></span></span><span style="-webkit-transition: none; border: 0px; box-sizing: border-box; display: inline-block; height: 2.128em; margin: 0px; padding: 0px; position: static; transition: none; vertical-align: 0px; width: 0px;"></span></span></span><span style="-webkit-transition: none; border-left-style: solid; border-width: 0px 0px 0px 0.004em; box-sizing: border-box; display: inline-block; height: 1.218em; margin: 0px; overflow: hidden; padding: 0px; position: static; transition: none; vertical-align: -0.068em; width: 0px;"></span></span></nobr></span>.</div>
</div>
</h2>
<h2 id="next-step" style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
Next Step ?</h2>
<h2 style="box-sizing: border-box; color: #162029; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 30px; font-weight: 500; line-height: 1.1; margin: 50px 0px 30px;">
<div class="wmd-preview-section preview-content" id="wmd-preview-section-15" style="box-sizing: border-box; font-size: 14px; line-height: 20px;">
<div class="se-section-delimiter" style="box-sizing: border-box;">
</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
So, I’m still improving the basic algorithm and testing strategies to obtain an efficient parallel version. I’m also looking for real input data, or at least a random graph where I can control some properties. There’s also questions about the order edges are presented and splited …</div>
<div style="box-sizing: border-box; margin-bottom: 15px; text-align: justify;">
Once all that is fixed, the next step will be to distribute this code using nsq.</div>
</div>
</h2>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-29702081986855153672014-03-12T12:53:00.002+01:002014-03-12T12:53:53.585+01:00Beginner's Corner: Floating Point Numbers<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
Floating point numbers are useful (should I say mandatory) for scientific computations. But they’re also one of the most complex subject for programmers. From a purely theoretical point of view, they are the perfect illustration of the edge between discrete math (arithmetic, symbolic computation … ) and continuous math (math dealing with continuous values like real number and so on … ) Unfortunately for us, almost every scientific field use continuous math and only logic and computer science really care about discrete math.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
Concretely, we have to represent values that have potentially infinite representation into a finite representation.</div>
<h2>
Floating Point Numbers Representation</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
There’s a standard describing how to encode real values in our finite world: floating point numbers (IEEE 754.)</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
You don’t need the details of the standard to do basic stuff (that should interesting for more advanced computations and optimization.) But you do need to understand the idea behind.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
You’ve probably encounters values express in the form 1.234×10³. The idea is to encode in the exponent how large is number (that’s a generalization of unit used in the metric system.) Very large numbers will have a very important exponent and very small numbers a negative one. The exponent is some how moving the point in the number. Floating point numbers are based on the same idea, except that we’re on a computer and used power of two !</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
Representing real values that way let us have very high or very small value encoded using the same representation.</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
The literature is full of details and explanation about floating point, but the whole things you need is:</div>
<ul style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; margin-top: 0px;">
<li style="box-sizing: border-box;">A float is a pair (m,e) (hey, I forgot the sign … ;)</li>
<li style="box-sizing: border-box;">m (the mantissa) is a number with a fixed representation</li>
<li style="box-sizing: border-box;">e (the exponent) is a signed integer (or biased-integer)</li>
</ul>
<h2>
Issues ?</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px; text-align: justify;">
The main issue are often called absorption: small values may be absorbed by wider ones.</div>
<div style="background-color: white; box-sizing: border-box; margin-bottom: 15px;">
</div>
<div style="font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; text-align: justify;">
What does it mean ? Let’s go back to human readable stuff: we decide to have a fixed mantissa with four digits of the form X.XXX and use exponent of 10. Now you wan to compute 1×10⁰ + 1×10¯⁴, <span style="background-color: white;"> </span><span style="background-color: white;">the result should be 1.0001, but it requires five digits and thus we get as answer </span>1×10⁰.</div>
<div style="font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; text-align: justify;">
<span style="background-color: white;"><br /></span></div>
<div style="font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; text-align: justify;">
<span style="background-color: white;">The same apply to floating point numbers, let’s try in C:</span></div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000;">#include</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;"><stdio.h></span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600;">()</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> y </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1e-10</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;">y ==</span><span class="com" style="box-sizing: border-box; color: #880000;"> x)</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"y was absorbed !\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"y wasn' absorbed!\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
This code will print the first message, of course !</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
That’s a classical one and you have probably seen it by yourself previously. But, this simple effect can have huge impact on your code and your results.</div>
</div>
<h2>
Vector Sum</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
A classical case where absorption effect may have strange result is array sum. Let’s take a simple example: we a huge array of float number and we want to compute the sum or the average value. We choose to fill our array is 1, so that the effect is more obvious.</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000;">#include</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;"><stdio.h></span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">#include</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="str" style="box-sizing: border-box; color: #008800;"><stdlib.h></span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> ac</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">char</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">av</span><span class="pun" style="box-sizing: border-box; color: #666600;">[])</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">long</span><span class="pln" style="box-sizing: border-box; color: black;"> size </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">100000000</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> sum </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">tab</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">ac </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> size </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> strtoul</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">av</span><span class="pun" style="box-sizing: border-box; color: #666600;">[</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">],</span><span class="pln" style="box-sizing: border-box; color: black;"> NULL</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">10</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
tab </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> malloc</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">size </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">sizeof</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pun" style="box-sizing: border-box; color: #666600;">));</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> tab</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> tab </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> size</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">++</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> tab</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> tab </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> size</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">++</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
sum </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"size:\t%lu\nsum:\t%.8g\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> size</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
The output of this code is disturbing:</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">size: 100000000
sum: 16777216
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
The sum stop at some point: that’s a typical absorbing effect, when 1 becomes to small with regards to the current sum, the value stop to change. We can easily infer this value: the mantissa is represented using 24bits (in fact, it’s 23, there’s an implicit bit always set to 1 at the beginning), and 2²⁴ = 16777216 !</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
To be sure, let’s play with the array size:</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">size: 16777215
sum: 16777215
size: 16777216
sum: 16777216
size: 16777217
sum: 16777216
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Can we solve this ? Yes, of course, the good solution is to perform a sum by chunks of the array. Here is two examples of implementation:</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000;">#define</span><span class="pln" style="box-sizing: border-box; color: black;"> CHUNK_SIZE </span><span class="lit" style="box-sizing: border-box; color: #006666;">65536</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> splitted_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;"><=</span><span class="pln" style="box-sizing: border-box; color: black;"> CHUNK_SIZE</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> sum </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">++</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
sum </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">mid </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">)/</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> splitted_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> splitted_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> splitted_sum2</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> gsum </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">chunk </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> chunk </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> chunk </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> CHUNK_SIZE</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> sum </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> chunk</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> chunk </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> CHUNK_SIZE </span><span class="pun" style="box-sizing: border-box; color: #666600;">&&</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">++</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
sum </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
gsum </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> gsum</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
First, we should verify that we get a better result: the answer is yes, tested against the same context we get the awaited values:</div>
</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">size: 100000000
sum: 16777216
splitted_sum: 1e+08
splitted_sum2: 1e+08
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Some words about that two functions: the global idea is to perform the sum piece by piece, i.e. we work on smaller sub-array so that individual values won’t get absorbed by the growing result.</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
The first version is a classic using recursive range division: you divide the current range until you reach the threshold, and only then do you do the array sum.</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
The second one is even simpler: two loops, one ranging over sub-arrays and the inner one doing the sum on each sub-array.</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
The positive point is that both solutions work for our case, but which one is better ? Good question ;)</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Globally the recursive version is more robust: since we’re staging sums by pairs, most summed values will be in the same range, while the second version may encounter absorption (for my example, 100,000,000 of 1s, chunks smaller than 16 show absorption.)</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
What about performances ? I’ve made some quick tests … there isn’t any really differences. For small chunks (about 16 cells) the second version is really faster, but we’re also flirting with the error-zone. When around 32/64 the recursive version is faster (but not faster than the loop version with a chunk size of 16.) For bigger chunks, there’s no real differences. Here are some results (time added to previous output) for chunk size of 32:</div>
</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><div style="text-align: justify;">
<span style="background-color: transparent; color: inherit; font-size: inherit; line-height: 1.428571429;">size: 100000000</span></div>
<code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">sum: 16777216 (time 0.0937701s)
splitted_sum: 1e+08 (time 0.0697868s)
splitted_sum2: 1e+08 (time 0.0825487s)
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
There’s another interesting point in building split sum: <strong style="box-sizing: border-box;">parallelism</strong> ! Moving to parallel here just requires computing in separate threads the sums of each chunk. It can be done by hand using threads library or stuff like parallel reduce of TBB …</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Here is an example using C++11 <code style="background-color: rgba(0, 0, 0, 0.0392157); border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; box-sizing: border-box; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; padding: 2px 4px; white-space: nowrap;">std::async</code>, (<em style="box-sizing: border-box;">note that this is not the best way to do that</em>) :</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> simple_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> r </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">for</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">auto</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> cur </span><span class="pun" style="box-sizing: border-box; color: #666600;">!=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">++</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
r </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;">cur</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> r</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> async_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">auto</span><span class="pln" style="box-sizing: border-box; color: black;"> len </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">len </span><span class="pun" style="box-sizing: border-box; color: #666600;"><=</span><span class="pln" style="box-sizing: border-box; color: black;"> CHUNK_SIZE</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> simple_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">auto</span><span class="pln" style="box-sizing: border-box; color: black;"> mid </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> len</span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">auto</span><span class="pln" style="box-sizing: border-box; color: black;"> part1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> std</span><span class="pun" style="box-sizing: border-box; color: #666600;">::</span><span class="pln" style="box-sizing: border-box; color: black;">async</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">async_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">begin</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> async_sum</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">mid</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">end</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> part1</span><span class="pun" style="box-sizing: border-box; color: #666600;">.</span><span class="kwd" style="box-sizing: border-box; color: #000088;">get</span><span class="pun" style="box-sizing: border-box; color: #666600;">();</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
This implementation spawn too many threads and consume too much memory. A good parallel implementation should separate the parallel splitting and the splitting of the array. And note that the <code style="background-color: rgba(0, 0, 0, 0.0392157); border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; box-sizing: border-box; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; padding: 2px 4px; white-space: nowrap;">std::async</code> and the <code style="background-color: rgba(0, 0, 0, 0.0392157); border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; box-sizing: border-box; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; padding: 2px 4px; white-space: nowrap;">std::future</code> is too expensive to (at least in current implementation.)</div>
</div>
<h2>
Approximation And Testing</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Another consequence of floating point approximation is the <em style="box-sizing: border-box;">instability</em> of computation upon expression re-ordering (<em style="box-sizing: border-box;">i.e.</em> using associativity and commutativity.)</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Let’s take a simple example. Here are implementations of the factorial function:</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> fact</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> n</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> n </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> n </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> fact</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">n </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> fact_term</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> n</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;"> n </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> fact_term</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">n </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> n </span><span class="pun" style="box-sizing: border-box; color: #666600;">*</span><span class="pln" style="box-sizing: border-box; color: black;"> a</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
They are classical examples of recursive implementations of the factorial. Here is a simple test:</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600;">()</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> n </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">51</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> r0</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r1</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
r0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> fact</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">n</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
r1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> fact_term</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">n</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"fact(%d) = r0 = %g\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> n</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r0</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"fact_term(%d) = r1 = %g\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> n</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r1</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"r1 - r0 = %g\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> r0</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
The output explains the problem itself:</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">fact(51) = r0 = 1.55112e+66
fact_term(51) = r1 = 1.55112e+66
r1 - r0 = -5.61217e+50
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<strong style="box-sizing: border-box;">That’s make a huge difference !</strong></div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Just to be sure, I tracked the moment when the errors shows up, let’s look at the same code with 50 rather 51 …</div>
</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">fact(50) = r0 = 3.04141e+64
fact_term(50) = r1 = 3.04141e+64
r1 - r0 = 0
</code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<strong style="box-sizing: border-box;">No more errors !</strong></div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
No you understand the difficulty ? Errors in floating point can comes quickly for a simple reordering and can disappear with certain range of values. Our main issue is to be able to test various implementations of the same computation.</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
As an example, I’ll take a Heron based square root and compare it with the result of the standard library function <code style="background-color: rgba(0, 0, 0, 0.0392157); border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; box-sizing: border-box; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; padding: 2px 4px; white-space: nowrap;">sqrt(3)</code>.</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="com" style="box-sizing: border-box; color: #880000;">// Simple Heron method for square root</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="com" style="box-sizing: border-box; color: #880000;">// threshold indicate when to stop refinement</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> mysqrt</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> threshold</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> r0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> r1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">fabs</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> r1</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> threshold</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
r1 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> r0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
r0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">r0 </span><span class="pun" style="box-sizing: border-box; color: #666600;">+</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="pln" style="box-sizing: border-box; color: black;">r0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)/</span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> r0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
The method works by iterative refinement, at each step we try to narrow our range around the square root. We stop as soon as the difference between the current value and the next one falls under the given threshold. Our purpose is to find a good threshold, for that I’ll compute <code style="background-color: rgba(0, 0, 0, 0.0392157); border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; box-sizing: border-box; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; padding: 2px 4px; white-space: nowrap;">sqrt(2, th)</code> with increasing threshold and stop when the difference between my function and the standard function is stable … Just look at the code:</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">int</span><span class="pln" style="box-sizing: border-box; color: black;"> main</span><span class="pun" style="box-sizing: border-box; color: #666600;">()</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> x </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">2</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> my_root</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> c_root</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">double</span><span class="pln" style="box-sizing: border-box; color: black;"> th </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> diff</span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;">HUGE_VAL</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> prev_diff</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> mem </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">unsigned</span><span class="pln" style="box-sizing: border-box; color: black;"> c </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
c_root </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> sqrt</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">do</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
prev_diff </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> diff</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
my_root </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> mysqrt</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;">th</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
diff </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> fabs</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">my_root </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> c_root</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">prev_diff </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> diff </span><span class="pun" style="box-sizing: border-box; color: #666600;"><=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">c </span><span class="pun" style="box-sizing: border-box; color: #666600;">==</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> mem </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> th</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
c </span><span class="pun" style="box-sizing: border-box; color: #666600;">+=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">1</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">else</span><span class="pln" style="box-sizing: border-box; color: black;"> c </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
th </span><span class="pun" style="box-sizing: border-box; color: #666600;">=</span><span class="pln" style="box-sizing: border-box; color: black;"> th</span><span class="pun" style="box-sizing: border-box; color: #666600;">/</span><span class="lit" style="box-sizing: border-box; color: #006666;">8</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">while</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">prev_diff </span><span class="pun" style="box-sizing: border-box; color: #666600;">-</span><span class="pln" style="box-sizing: border-box; color: black;"> diff </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">||</span><span class="pln" style="box-sizing: border-box; color: black;"> c </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">4</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
printf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="str" style="box-sizing: border-box; color: #008800;">"Threshold: %g - %a\nDiff: %g\n"</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> mem</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> mem</span><span class="pun" style="box-sizing: border-box; color: #666600;">,</span><span class="pln" style="box-sizing: border-box; color: black;"> diff</span><span class="pun" style="box-sizing: border-box; color: #666600;">);</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; margin-bottom: 15px;">
<div style="text-align: justify;">
<span style="font-size: 14px; line-height: 20px;">Ok, the code is more a script in C than a real testing program, but you can notice the tricks: we won’t get the same result, unless we use exactly the same algorithm (implemented the same way … ) So, we compute the difference between the expected result and our own value, it appears that we can’t do better than something around 2.22×10¯²</span><span style="font-size: 14px; line-height: 20px;">²</span><span style="font-size: 17px; white-space: nowrap;">.</span><span style="font-size: 14px; line-height: 20px;"> Here is the output:</span></div>
</div>
<pre style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;">Threshold: 5.96046e-08 - 0x1p-24
Diff: 2.22045e-16
</code></pre>
<h2>
Real float format ?</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
A float (32bit floating point numbers) :<br />
<br />
<div style="text-align: center;">
<b>f = (-1^S) × 1.SIGNIFICAND × 2^(EXPONENT - 127)</b></div>
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">These elements are stored in that way:</span><br />
<span style="text-align: justify;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ6Q_1zkSg0xmaCNXU7K5onnVsaBkHUoYpVynPOnRL7CAlfB9Qbm7czNHnkALDnMIilzAOvp8ZZ7SoxE3i_eACq-p6PPwCiPGebi6NTz9Uxp3etYHAz9-qhnma8b65tjYyG5BiZFJKyLU/s1600/float_structure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ6Q_1zkSg0xmaCNXU7K5onnVsaBkHUoYpVynPOnRL7CAlfB9Qbm7czNHnkALDnMIilzAOvp8ZZ7SoxE3i_eACq-p6PPwCiPGebi6NTz9Uxp3etYHAz9-qhnma8b65tjYyG5BiZFJKyLU/s1600/float_structure.png" height="106" width="320" /></a></div>
<span style="text-align: justify;"><br /></span></div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
As you may notice, the one before the point is not stored, the idea is that the mantissa is scaled such that it start with a one (remember, we’re in binary, that’s not a problem.)</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
The main consequences it’s some times difficult to compare values and non-strict comparing are sometime fuzzy. That’s a complex field of study and still a problem for many applications.</div>
</div>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
A funny consequence of the format is the existence of two zero ! The sign in the representation is an independent bit, not like in signed integer and thus we can all the value set to zero but the sign bit set to one ! A classical example is this absolute value function:</div>
</div>
<pre class="prettyprint prettyprinted" style="background-color: #f8f8f8; border-bottom-left-radius: 0px; border-bottom-right-radius: 5px; border-color: rgb(238, 238, 238); border-style: solid; border-top-left-radius: 0px; border-top-right-radius: 5px; border-width: 0px 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px !important; line-height: 1.428571429; margin-bottom: 15px; padding: 10px 15px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code style="background-color: transparent !important; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Consolas, 'Courier New', monospace; font-size: inherit; padding: 0px;"><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> fabsf</span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="kwd" style="box-sizing: border-box; color: #000088;">float</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">{</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;">></span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">if</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="pun" style="box-sizing: border-box; color: #666600;">(</span><span class="pln" style="box-sizing: border-box; color: black;">x </span><span class="pun" style="box-sizing: border-box; color: #666600;"><</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">)</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> x</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="kwd" style="box-sizing: border-box; color: #000088;">return</span><span class="pln" style="box-sizing: border-box; color: black;"> </span><span class="lit" style="box-sizing: border-box; color: #006666;">0.0</span><span class="pun" style="box-sizing: border-box; color: #666600;">;</span><span class="pln" style="box-sizing: border-box; color: black;">
</span><span class="pun" style="box-sizing: border-box; color: #666600;">}</span></code></pre>
<h2>
Conclusion</h2>
<div style="background-color: white; box-sizing: border-box; font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif; font-size: 14px; line-height: 20px; margin-bottom: 15px;">
<div style="text-align: justify;">
Dealing with floating point numbers is not easy task, there’s a lot of traps, and you haven’t seen all here, I’m not a scientific computation specialist, I just report my simple experience.</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-53519637127031460142014-03-08T18:16:00.000+01:002014-03-08T18:16:00.236+01:00Playing With C …<div style="text-align: justify;">
Most of the time, when you're interested in C programming, you're also interested in performances. Doing homemade micro-benchmarks is, in itself, an interesting activity even if it's not productive at all …</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Recently, after reading an article about pipeline and optimization (<a href="http://lolengine.net/blog/2011/9/17/playing-with-the-cpu-pipeline">Playing with the CPU pipeline</a>), I decided to test that by myself. This was also the occasion to (re)discover classical math functions.</div>
<h2>
Computing sinus</h2>
<div style="text-align: justify;">
The easiest way to compute a trigonometric function is to use the traditional Taylor decomposition, there's better way, but we're not here to provide the best sinus function, we just want to play around …</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
I'll use the same approximation as my starting articles (since I want to test the code in it … ) The first naive version uses a homemade power and factorial functions.</div>
<div style="text-align: justify;">
<br /></div>
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 16.25px;"><span class="kt" style="color: #204a87; font-weight: bold;">uint64_t</span> <span class="nf">fact</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">uint64_t</span> <span class="n">n</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">uint64_t</span> <span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(; </span><span class="n">n</span><span class="p" style="font-weight: bold;">; </span><span class="o" style="color: #ce5c00; font-weight: bold;">--</span><span class="n">n</span><span class="p" style="font-weight: bold;">)</span> <span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*=</span> <span class="n">n</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">r</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="nf">qpower</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">p</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">p</span> <span class="o" style="color: #ce5c00; font-weight: bold;">==</span> <span class="mi" style="color: #0000cf; font-weight: bold;">1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">?</span> <span class="n">x</span> <span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="n">qpower</span><span class="p" style="font-weight: bold;">(</span><span class="n">x </span><span class="o" style="color: #ce5c00; font-weight: bold;">* </span><span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">p </span><span class="o" style="color: #ce5c00; font-weight: bold;">>> </span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="p" style="font-weight: bold;">(</span><span class="n">p </span><span class="o" style="color: #ce5c00; font-weight: bold;">% </span><span class="mi" style="color: #0000cf; font-weight: bold;">2 </span><span class="o" style="color: #ce5c00; font-weight: bold;">? </span><span class="n">x </span><span class="o" style="color: #ce5c00; font-weight: bold;">: </span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">}</span>
<pre><span class="c1" style="color: #8f5902; font-style: italic;">// Taylor version</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="nf">sin_taylor</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span>
<span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">s</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">i </span><span class="o" style="color: #ce5c00; font-weight: bold;">= </span><span class="mi" style="color: #0000cf; font-weight: bold;">3</span><span class="p" style="font-weight: bold;">;</span> <span class="n">i </span><span class="o" style="color: #ce5c00; font-weight: bold;">< </span><span class="mi" style="color: #0000cf; font-weight: bold;">16</span><span class="p" style="font-weight: bold;">;</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">2</span><span class="p" style="font-weight: bold;">,</span> <span class="n">s</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*=</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">)</span>
<span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+=</span> <span class="n">s</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">qpower</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">i</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">/</span> <span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span><span class="p" style="font-weight: bold;">)</span><span class="n">fact</span><span class="p" style="font-weight: bold;">(</span><span class="n">i</span><span class="p" style="font-weight: bold;">);</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">r</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</pre>
</div>
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">I hope you know how a quick exponentiation works (it has a O(log p) complexity).</span></div>
<div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The main issue here is that we're computing several time constant values using a function. So, the next step is to pre-compute the 8 values (I'll use the approximation provides in the aforementioned article that are closer to minimax approximation, which yield more accurate results) and put them in an array (for easier access.)</div>
<div style="text-align: justify;">
<br />
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 16.25px; text-align: start;"><span class="k" style="color: #204a87; font-weight: bold;">static</span> <span class="k" style="color: #204a87; font-weight: bold;">const</span> <span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">Coef</span><span class="p" style="font-weight: bold;">[]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="p" style="font-weight: bold;">{</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">+</span><span class="mf" style="color: #0000cf; font-weight: bold;">1.0</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">-</span><span class="mf" style="color: #0000cf; font-weight: bold;">1.666666666666580809419428987894207e-1</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">+</span><span class="mf" style="color: #0000cf; font-weight: bold;">8.333333333262716094425037738346873e-3</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">-</span><span class="mf" style="color: #0000cf; font-weight: bold;">1.984126982005911439283646346964929e-4</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">+</span><span class="mf" style="color: #0000cf; font-weight: bold;">2.755731607338689220657382272783309e-6</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">-</span><span class="mf" style="color: #0000cf; font-weight: bold;">2.505185130214293595900283001271652e-8</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">+</span><span class="mf" style="color: #0000cf; font-weight: bold;">1.604729591825977403374012010065495e-10</span><span class="p" style="font-weight: bold;">,</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">-</span><span class="mf" style="color: #0000cf; font-weight: bold;">7.364589573262279913270651228486670e-13</span><span class="p" style="font-weight: bold;">,</span>
<span class="p" style="font-weight: bold;">};</span></pre>
</div>
</div>
<div style="text-align: justify;">
<br />
Now we can remove the call to fact (and the division by the way):<br />
<br />
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 16.25px; text-align: start;"><pre style="line-height: 18.75px;"><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="nf">sin_taylor2</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">3</span><span class="p" style="font-weight: bold;">;</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><</span> <span class="mi" style="color: #0000cf; font-weight: bold;">16</span><span class="p" style="font-weight: bold;">;</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">2</span><span class="p" style="font-weight: bold;">)</span>
<span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+=</span> <span class="n">qpower</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span><span class="p" style="font-weight: bold;">,</span> <span class="n">i</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;">>></span> <span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">];</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">r</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</pre>
</div>
<br />
Next optimization deals with the exponentiation: the goal is to rearrange and factorize in order to have less multiplication and try take advantage of the pipeline and out-of-order parallelism. I chose this version (spoil: it will give us the best execution time) upon all variation presented in the original paper:<br />
<br />
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 16.25px; text-align: start;"><pre style="line-height: 18.75px;"><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="nf">sin_v6</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">x</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">x</span><span class="p" style="font-weight: bold;">;</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x4</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">x2</span><span class="p" style="font-weight: bold;">;</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x8</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">x4</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">x4</span><span class="p" style="font-weight: bold;">;</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">A</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="p" style="font-weight: bold;">(</span><span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">1</span><span class="p" style="font-weight: bold;">]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="p" style="font-weight: bold;">(</span><span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">2</span><span class="p" style="font-weight: bold;">]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">3</span><span class="p" style="font-weight: bold;">]));</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">B</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">4</span><span class="p" style="font-weight: bold;">]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="p" style="font-weight: bold;">(</span><span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">5</span><span class="p" style="font-weight: bold;">]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="p" style="font-weight: bold;">(</span><span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">6</span><span class="p" style="font-weight: bold;">]</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x2</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">Coef</span><span class="p" style="font-weight: bold;">[</span><span class="mi" style="color: #0000cf; font-weight: bold;">7</span><span class="p" style="font-weight: bold;">]));</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">x</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="p" style="font-weight: bold;">(</span><span class="n">A</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="n">x8</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">B</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</pre>
</div>
<br />
Is it faster ? It's time to test !<br />
<h2>
Measuring Performances ?</h2>
<div>
How can we measure correctly execution time ? We don't have <i>good solutions</i>, the only way is to find an accurate clock (probably provided by the system) take its value before and after calling our function and computing the difference.</div>
<div>
<br /></div>
<div>
I choose the POSIX <span style="font-family: Courier New, Courier, monospace;">clock_gettime(2)</span> function with <span style="font-family: Courier New, Courier, monospace;">CLOCK_MONOTONIC</span> which seems suited for our job. This will look like that:</div>
<div>
<br />
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 16.25px; text-align: start;"> <span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">timespec</span> <span class="n">c0</span><span class="p" style="font-weight: bold;">,</span> <span class="n">c1</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">clock_gettime</span><span class="p" style="font-weight: bold;">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p" style="font-weight: bold;">,</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c0</span><span class="p" style="font-weight: bold;">);</span>
<span class="c1" style="color: #8f5902; font-style: italic;">// Do your dirty work here</span>
<span class="n">clock_gettime</span><span class="p" style="font-weight: bold;">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p" style="font-weight: bold;">,</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c1</span><span class="p" style="font-weight: bold;">);</span></pre>
</div>
<br />
OK, that's how we do usually. To compute the difference between clocks, we have to take a look at the timespec structure since operations like timersub(3) operate on timeval structure not timespec (timeval provides microseconds while timespec provides nanoseconds … )</div>
<div>
<br />
According to the man-page, timespec contains (at least) two fields, one with the seconds, the other with the nanoseconds. The simplest way to compute difference is to convert timespec into double float:<br />
<br />
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 16.25px; text-align: start;"><span class="kt" style="color: #204a87; font-weight: bold;">double</span> spec_to_double<span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">timespec</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span><span class="n">ts</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">ts</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">tv_sec</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="mf" style="color: #0000cf; font-weight: bold;">1e-9</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">ts</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">tv_nsec</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
<br />
I prefer writing a function, and then tag it as static inline rather than directly doing computation in the code, it's much more readable and the compiler is able to optimize this correctly. Never be afraid of functions, they are better documentation than any comments.<br />
<br />
OK, I'm now able to measure execution time, normally with a precision of a nanosecond. I don't really believe it: what is the cost of calling clock_gettime(2) ? According to its manual section, its a system call. And, is my function slow enough to be measured ?<br />
<br />
I got several answers to that:<br />
<br />
<ul>
<li>Take some measures ! We'll just measure time between two consecutive call to clock_gettime(2)</li>
<li>Don't run your function only once ! We'll call our function about thousands or more time, to obtain some average …</li>
<li>Run your test several time, if the result is stable, it may have some meaning.</li>
</ul>
<div>
So, I wrote a small piece of code that compute the time between two consecutive calls of clock_gettime(2), then the same with a call to the libc sin function. I run that 10 times and compute an average. I also print intermediary results. Here is the code:</div>
<div>
<br /></div>
<div>
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 18.75px; text-align: start;"><span class="cp" style="color: #8f5902; font-style: italic;">#define _XOPEN_SOURCE 500</span>
<span class="cp" style="color: #8f5902; font-style: italic;">#include <math.h></span>
<span class="cp" style="color: #8f5902; font-style: italic;">#include <stdio.h></span>
<span class="cp" style="color: #8f5902; font-style: italic;">#include <stdlib.h></span>
<span class="cp" style="color: #8f5902; font-style: italic;">#include <time.h></span>
<span class="k" style="color: #204a87; font-weight: bold;">static</span> <span class="kr" style="color: #204a87; font-weight: bold;">inline</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="nf">spec_to_double</span><span class="p" style="font-weight: bold;">(</span><span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">timespec</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span><span class="n">ts</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">ts</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">tv_sec</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+</span> <span class="mf" style="color: #0000cf; font-weight: bold;">1e-9</span> <span class="o" style="color: #ce5c00; font-weight: bold;">*</span> <span class="n">ts</span><span class="o" style="color: #ce5c00; font-weight: bold;">-></span><span class="n">tv_nsec</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="nf">main</span><span class="p" style="font-weight: bold;">()</span> <span class="p" style="font-weight: bold;">{</span>
<span class="k" style="color: #204a87; font-weight: bold;">struct</span> <span class="n">timespec</span> <span class="n">c0</span><span class="p" style="font-weight: bold;">,</span> <span class="n">c1</span><span class="p" style="font-weight: bold;">;</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">r</span><span class="p" style="font-weight: bold;">,</span> <span class="n">s0</span><span class="p" style="font-weight: bold;">,</span> <span class="n">s1</span><span class="p" style="font-weight: bold;">,</span> <span class="n">a</span><span class="o" style="color: #ce5c00; font-weight: bold;">=</span><span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">;</span>
<span class="k" style="color: #204a87; font-weight: bold;">for</span> <span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">int</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">;</span> <span class="n">i</span> <span class="o" style="color: #ce5c00; font-weight: bold;"><</span> <span class="mi" style="color: #0000cf; font-weight: bold;">10</span><span class="p" style="font-weight: bold;">;</span> <span class="o" style="color: #ce5c00; font-weight: bold;">++</span><span class="n">i</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="n">clock_gettime</span><span class="p" style="font-weight: bold;">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p" style="font-weight: bold;">,</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c0</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">clock_gettime</span><span class="p" style="font-weight: bold;">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p" style="font-weight: bold;">,</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c1</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">s0</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">spec_to_double</span><span class="p" style="font-weight: bold;">(</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c1</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span> <span class="n">spec_to_double</span><span class="p" style="font-weight: bold;">(</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c0</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">clock_gettime</span><span class="p" style="font-weight: bold;">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p" style="font-weight: bold;">,</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c0</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">r</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">sin</span><span class="p" style="font-weight: bold;">(</span><span class="mf" style="color: #0000cf; font-weight: bold;">1.5</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">clock_gettime</span><span class="p" style="font-weight: bold;">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p" style="font-weight: bold;">,</span> <span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c1</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">s1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">=</span> <span class="n">spec_to_double</span><span class="p" style="font-weight: bold;">(</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c1</span><span class="p" style="font-weight: bold;">)</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span> <span class="n">spec_to_double</span><span class="p" style="font-weight: bold;">(</span><span class="o" style="color: #ce5c00; font-weight: bold;">&</span><span class="n">c0</span><span class="p" style="font-weight: bold;">);</span>
<span class="n">a</span> <span class="o" style="color: #ce5c00; font-weight: bold;">+=</span> <span class="n">s1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span> <span class="n">s0</span><span class="p" style="font-weight: bold;">;</span>
<span class="n">printf</span><span class="p" style="font-weight: bold;">(</span><span class="s" style="color: #4e9a06;">"> %g</span><span class="se" style="color: #4e9a06;">\n</span><span class="s" style="color: #4e9a06;">"</span><span class="p" style="font-weight: bold;">,</span> <span class="n">s1</span> <span class="o" style="color: #ce5c00; font-weight: bold;">-</span> <span class="n">s0</span><span class="p" style="font-weight: bold;">);</span>
<span class="p" style="font-weight: bold;">}</span>
<span class="n">printf</span><span class="p" style="font-weight: bold;">(</span><span class="s" style="color: #4e9a06;">"%g</span><span class="se" style="color: #4e9a06;">\n</span><span class="s" style="color: #4e9a06;">"</span><span class="p" style="font-weight: bold;">,</span> <span class="n">a </span><span class="o" style="color: #ce5c00; font-weight: bold;">/ </span><span class="mi" style="color: #0000cf; font-weight: bold;">10</span><span class="p" style="font-weight: bold;">);</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="mi" style="color: #0000cf; font-weight: bold;">0</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
</div>
<div>
<br /></div>
<div>
I ran that piece of code on a i7 3770 compiled with clang and -O0 optimization flag and get the following result:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 1.034e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 3.35043e-07</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 7.19447e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 6.07688e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> -1.81608e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 7.0082e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 9.19681e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 1.28057e-07</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 9.17353e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 8.68458e-08</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">1.12583e-06</span></div>
</div>
<div>
<br /></div>
<div>
Wait, what was that ? I've got a negative result … This is exactly what I was looking for: our clock is not sufficiently precise and sometimes (Ok, that was not the first run, but it happens say 1 time out of 3) the time without the sin is longer.</div>
<div>
<br /></div>
<div>
There's also this first value, which is often longer. There's probably a rational for that related to processor cache (the first time the code of sin need to be copied from library to the cache, and it's small enough to fit in and stay there for the other run.)</div>
<div>
<br /></div>
<div>
Anyway, those values are not interesting, they only show the fact that we're not able to perform precise measures, but we can use loops. Replacing the call to sin by a loop performing the same line thousand of time yield the following results:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 3.72389e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 4.90241e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 4.39051e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 4.30089e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 4.2367e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 4.86639e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 4.08019e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 3.8858e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 3.86741e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 3.90329e-05</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">4.21575e-05</span></div>
</div>
<div>
<br /></div>
<div>
Ok, that's a little bit more stable, but we still got a variation of about 20 or 25% of the measured time ! Adding a zero, give us a more accurate result:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.00025304</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000266933</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000270017</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000247684</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000247303</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000247422</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000249467</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000247646</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000248894</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">> 0.000247764</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">0.000252617</span></div>
</div>
<div>
<h2>
Let's Go !</h2>
So, I'm now able to do all my tests. I've implemented almost all versions presented in the original article with some minor variations. And since I was planning to see the interaction with compiler optimizations, my first runs was compiled using gcc and -O3, then clang and -O3 also. Let's have a look at the result:</div>
</div>
<div>
<ul>
<li>Empty Loop: just a loop doing sum in a variable</li>
<li>libm sin: sin from C math library</li>
<li>sin_taylor: the first Taylor series version</li>
<li>sin_taylor2: the same but with constant rather than call to fact</li>
<li>sin_v6: high/low factor split</li>
</ul>
</div>
<div>
<span id="docs-internal-guid-1f3b52d2-5bfb-3da3-3771-bf26bd9ee04c">
<br /><span style="font-family: Arial; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;"></span></span></div>
<div>
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="79"></col><col width="134"></col><col width="126"></col><col width="126"></col><col width="134"></col><col width="134"></col></colgroup><tbody>
<tr style="height: 17px;"><td style="border: 1px solid rgb(0, 0, 0); direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">Compiler</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">Empty Loop</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">libm sin</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_taylor</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_taylor2</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_v6</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O3</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2355035080</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4698114789</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">3.8808501901</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.6006171431</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3628679269</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O3</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2359491119</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4803164639</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">7.7066486869</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">4.2942729190</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3918996351</td></tr>
</tbody></table>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace;">gcc version: 4.8.2 20140206 (prerelease) (Arch Linux package)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">clang version: 3.4 (tags/RELEASE_34/final)</span><span style="font-family: 'Courier New', Courier, monospace;"> </span><span style="font-family: 'Courier New', Courier, monospace;">(Arch Linux package)</span></div>
<div>
<br />
Each run corresponds to 100,000,000 calls to the corresponding sinus function. The loop is also accumulating the errors (variation) against standard sin function (libm.) We use a pre-filled vector of random float numbers to avoid accounting the cost of the random generator.<br />
<br /></div>
<div>
Nice results, isn't it ? But, I cheated a little bit, my first version yielded strange timing, so let's see why and how I obtain these results.<br />
<br /></div>
<h3>
Strange Timing</h3>
<div>
<br />
In a previous version, I got the following values:</div>
<div>
<br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="79"></col><col width="134"></col><col width="126"></col><col width="126"></col><col width="134"></col><col width="134"></col></colgroup><tbody>
<tr style="height: 17px;"><td style="border: 1px solid rgb(0, 0, 0); direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">Compiler</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">Empty Loop</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">libm sin</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_taylor</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_taylor2</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_v6</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O3</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2317026760</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2314439011</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2314896642</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2314374300</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2321709669</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O3</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2313979832</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4239284832</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2317965080</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2321117199</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.2316789902</td></tr>
</tbody></table>
</div>
<div>
<br />
Almost all timing was identical, and worst, it was similar to the empty loop.</div>
<div>
<br /></div>
<div>
I made two errors here:</div>
<div>
<ul>
<li>rather than having a vector of random float, I used the same float for all calls</li>
<li>I forgot the builtin functions of gcc</li>
</ul>
<div>
What's the deal with benching with the same value ? All my functions are in my main file and with <span style="font-family: Courier New, Courier, monospace;">-O3</span> optimization, the compiler is able to understand that the expression is constant in the loop and compute it just one time. Fail.</div>
</div>
<div>
<br /></div>
<div>
The second error is about testing the libm function: it seems that gcc is able to optimize it the same way as <i>local</i> functions, while clang runs it at each loop step. Why ? It takes me sometimes to realize what happens.</div>
<div>
<br /></div>
<div>
The traditional way of solving this kind of issues is to take a look at the generated code (assembly) and try to understand how your functions are called. My testing code is rather ugly and not factorized at all, combine with <span style="font-family: Courier New, Courier, monospace;">-O3</span>, it becomes very difficult to find the difference. In that case, there's a better test: the option <span style="font-family: Courier New, Courier, monospace;">-fno-builtin</span> !</div>
<div>
<br /></div>
<div>
Yeah … gcc has a builtin function for sinus and thus it can safely do constant propagation to avoid computing the sinus at each step !<br />
<br />
So, when comparing your code against standard functions, you should deactivate builtin function most of the time in order to have coherent results.<br />
<br />
<h3>
Compiler Optimization Impact</h3>
<div>
<br /></div>
<div>
Running your code in <span style="font-family: Courier New, Courier, monospace;">-O3</span> is nice, things seems to go faster, OK. But what is the real impact is your code really efficient ? You should consider running your code with various level of optimization to see the differences. Here is the same example with optimization ranging from <span style="font-family: Courier New, Courier, monospace;">-O0</span> to <span style="font-family: Courier New, Courier, monospace;">-O3</span>, using gcc and clang. I also add <span style="font-family: Courier New, Courier, monospace;">-ffast-math</span> (I know, it may yield altered floating points results.)<br />
<br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="143"></col><col width="120"></col><col width="120"></col><col width="120"></col><col width="120"></col></colgroup><tbody>
<tr style="height: 17px;"><td style="border: 1px solid rgb(0, 0, 0); direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">Compiler</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">libm sin</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_taylor</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_taylor2</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; direction: ltr; font-weight: bold; padding: 0px 3px; text-align: center; vertical-align: bottom;">sin_v6</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O0</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.6409693051</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">23.3574157010</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">10.5755215578</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.2111645590</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O1</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.5236257040</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">11.4717926630</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">5.8669155310</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.4126090182</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O2</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4710729450</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">8.2207018428</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">5.2849696029</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.4066506480</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O3</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4698114789</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">3.8808501901</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.6006171431</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3628679269</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">gcc -O3 -ffast-math</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4753928279</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">3.7690614581</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.5001044261</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3611039480</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O0</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.5616187491</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">26.0482794449</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">11.4370708941</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.0181730469</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O1</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4805616608</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">8.9057888780</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">4.7333046419</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.4122427311</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O2</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4777696838</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">7.7755847869</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">4.4436145930</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3908856600</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O3</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4803164639</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">7.7066486869</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">4.2942729190</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3918996351</td></tr>
<tr style="height: 17px;"><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; direction: ltr; padding: 0px 3px; vertical-align: bottom;">clang -O3 -ffast-math</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">1.4799877519</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">7.6862258611</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">4.2904554280</td><td style="border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 0px 3px; text-align: right; vertical-align: bottom;">0.3916952400</td></tr>
</tbody></table>
<br />
Small gains on the first column, come probably from loop optimizations (clang does not optimize it, and I deactivate builtin for gcc.) Tests for the empty loop (not shown here) yield a globally constant time for all compiler's options. Which tends to enforce our testing process: the loop in itself can safely be removed from execution time.<br />
<br />
Another interesting point is the average error of our functions. I choose to use the standard sin function from libm as a referent. Globally, sin_v6 has an average error around of <span style="font-family: Courier New, Courier, monospace;">-9.60791e-23</span> (on the range<span style="font-family: inherit;"> -<span style="background-color: white; line-height: 20px; text-align: left;">π/2 to </span><span style="background-color: white; line-height: 20px; text-align: left;">π/2.) Even with -ffast-math, it seems that this version output a result with the same average precision.</span></span><br />
<span style="font-family: inherit;"><span style="background-color: white; line-height: 20px; text-align: left;"><br /></span></span>
<span style="background-color: white; text-align: left;"><span style="font-family: inherit;"><span style="line-height: 20px;">It could be interesting to investigate a little bit more on precision, my actual version is not a real </span></span><i style="font-family: inherit; line-height: 20px;">minimax polynomial approximation</i><span style="font-family: inherit;"><span style="line-height: 20px;">, but the global code is quite the same and we should have similar performances. If you're interest on this precision topic, there's another article on the same website as the </span></span><span style="line-height: 20px;">aforementioned</span><span style="font-family: inherit;"><span style="line-height: 20px;"> article: </span></span></span><span style="line-height: 20px;"><a href="http://lolengine.net/blog/2011/12/21/better-function-approximations">Better function approximations: Taylor vs. Remez</a>.</span></div>
<h2>
Conclusion</h2>
</div>
<div>
Ok, what do we got:</div>
<div>
<ul>
<li>Before evaluating performances, you should be sure of your tools for measuring.</li>
<li>Beware of your compiler's impact: builtin functions and optimization may invalidate some of your results.</li>
<li>Even if the compiler is better than you for most optimization, a clever code can be faster.</li>
<li>Yes, you can have an homemade math function performing better than the corresponding libc function (but only for a reduced range … )</li>
</ul>
<h2>
Bonus</h2>
</div>
<div>
You may ask why haven't you wrote an assembly version ? Good question, here it is an implementation using Intel FPU instruction FSIN:</div>
<div>
<br /></div>
<div>
<div style="border: 1px solid #305060; padding: 5px;">
<pre style="line-height: 18.75px; text-align: start;"><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="nf">sin_v7</span><span class="p" style="font-weight: bold;">(</span><span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">x</span><span class="p" style="font-weight: bold;">)</span> <span class="p" style="font-weight: bold;">{</span>
<span class="kt" style="color: #204a87; font-weight: bold;">double</span> <span class="n">r</span><span class="p" style="font-weight: bold;">;</span></pre>
<pre style="line-height: 18.75px; text-align: start;"> <span class="kr" style="color: #204a87; font-weight: bold;">__asm</span> <span class="p" style="font-weight: bold;">(</span>
<span class="s" style="color: #4e9a06;">"fldl %1</span><span class="se" style="color: #4e9a06;">\n</span><span class="s" style="color: #4e9a06;">"</span>
<span class="s" style="color: #4e9a06;">"fsin</span><span class="se" style="color: #4e9a06;">\n</span><span class="s" style="color: #4e9a06;">"</span>
<span class="s" style="color: #4e9a06;">"fstpl %0</span><span class="se" style="color: #4e9a06;">\n</span><span class="s" style="color: #4e9a06;">"</span>
<span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="s" style="color: #4e9a06;">"=m"</span><span class="p" style="font-weight: bold;">(</span><span class="n">r</span><span class="p" style="font-weight: bold;">)</span><span class="o" style="color: #ce5c00; font-weight: bold;">:</span> <span class="s" style="color: #4e9a06;">"m"</span><span class="p" style="font-weight: bold;">(</span><span class="n">x</span><span class="p" style="font-weight: bold;">));</span>
<span class="k" style="color: #204a87; font-weight: bold;">return</span> <span class="n">r</span><span class="p" style="font-weight: bold;">;</span>
<span class="p" style="font-weight: bold;">}</span></pre>
</div>
<span class="p"><br /></span>
<span class="p">I've test it using the same framework, and guess what ? </span><span class="p" style="font-weight: bold;">It's slower !</span><br />
<span class="p" style="font-weight: bold;"><br /></span>
For the same condition (hundreds of million calls) I get a time of 2.87384s which is nearly ten time slower than the sin_v6 function !<br />
<br />
You want to know why ? That's probably due to the way FPU works: it induce a context switch just for one operation, so even if the operation itself is faster, the function is inefficient …</div>
</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-25640161256498431092013-11-08T17:22:00.002+01:002013-11-08T17:22:06.464+01:00More C++11 threading: I want my lock-free !<div style="text-align: justify;">
Last time, I've tried to describe the change in C++11 that impact multi-threading. Now, I'll talk about implementing a lock-free data structures.</div>
<div style="text-align: justify;">
<br /></div>
<h4>
Sharing Memory</h4>
<div>
<div style="text-align: justify;">
<br />
Before talking about lock-free, let me refresh your memory about the most important issue when doing parallel code: <b>concurrent memory access</b>.</div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
If two (or more) threads share (<i>i.e.</i> use) a common memory location, like a counter or the entry point of a data-structure, each time they access that shared location, conflicts can arise.</div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The most striking example is the shared counter problem: some threads shared a common integer (our shared counter) and try to simple increment it. That's it, they just want to do a simple <tt>++i</tt> !</div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Even with this simple example, you'll get a bad behavior. To convince you I've got some interesting results: I've got a bunch of threads (from 2 to 256) and each thread is running a simple loop (with exactly 2²² rounds) that do a simple <tt>++i</tt>, with <tt>i</tt> a shared counter. So normally the final value should be <i>number_of_threads * 2²²</i> and thus we can compute a kind of error measure: <i>(expected_value - real_value)/expected_value</i> (in percent.) Here are the results:<br />
<br />
<hr />
<table border="1">
<thead>
<tr><td>Number of threads</td><td>Error</td>
</tr>
</thead>
<tbody>
<tr><td>2</td><td>49.24%</td></tr>
<tr><td>4</td><td>68.99%</td></tr>
<tr><td>8</td><td>84.21%</td></tr>
<tr><td>256</td><td>89.87%</td></tr>
</tbody></table>
<i><span style="font-size: xx-small;">This test was run on a Intel Core i7-3770 (so 4 cores and 2 hyperthreads per core.)</span></i><br />
<hr />
Impressive, isn't it ?
<br />
<br />
How can a simple increment be so wrong ? It's quite simple, to increment you shared variable you've got at least to operation (from the memory point of view): in the first one you load the value at the given location; in the second one, you store the newly computed value (based on the loaded value) in the memory location. The issue is that between your load and your store, some others threads may have modified this value and you won't see it.<br />
<br />
To solve that kind of issue, the usual solution is to use lock (for the given example, you can now use atomic types.)<br />
<br />
When dealing with a data structure (lists, queues, trees … ) protecting access is even more critical since, not only you may loose information, but you can also completely break the data-structure.<br />
<br />
<h4>
Lock free ?</h4>
<div>
<i><br /></i>
<i>« OK, I got your point about protecting memory access, so what's that lock-free stuff ? »</i></div>
<div>
<i><br /></i></div>
<div>
Locks (any kind of locks) are probably the kind of operation that you want to avoid.</div>
<div>
<br /></div>
<div>
When a thread holds a lock, all other threads that are trying to obtain the same lock are blocked until the actual owner release the lock. That's the expected purpose. But, processes are blocked, even if the owner is not active.</div>
<div>
<br /></div>
<div>
The problem really arise when the number of threads or processes on the system is growing. Once again, it's quite simple: if the thread holding the lock is scheduled, all other threads waiting for the lock are blocked while the owner of the lock isn't really using the data !</div>
<div>
<br /></div>
<div>
So, intuitively, a lock-free algorithm provides a global progression property: there can always be an active thread making progress.</div>
<div>
<br /></div>
<div>
<i>« I've heard about <b>wait-free </b>algorithm, is that the same thing ? »</i></div>
<div>
<i><br /></i></div>
<div>
No … here are some definition:</div>
<div>
<br /></div>
<div>
<ul>
<li><b>lock-free:</b> an algorithm (or the operation on a data-structure) is lock-free if « <i>the suspension of one or more threads will not stop the potential progress of the remaining threads.</i> »</li>
<li><b>wait-free:</b> an algorithm is wait-free if « <i>every operation has a bound on the number of steps the algorithm will take before the operation completes.</i> »</li>
</ul>
<div>
In lock-free algorithm, the <i>system</i> (that is our set of threads) maintains progression, while in wait-free algorithm, every threads have progression.</div>
</div>
<div>
<br /></div>
<h3>
What do we need ?</h3>
<div>
<i><br /></i>
<i>Let me guess … brain grease ?</i></div>
<div>
<i><br /></i></div>
<div>
There're a lot of results about primitive needed to implement lock-free or wait-free operations. The main is result is that only one basic mechanism is needed, and two are available for that job:<br />
<ul>
<li><b>Atomic Compare&Swap</b> (CAS)</li>
<li><b>Load-Link/Store-Conditional</b> (ll/sc)</li>
</ul>
<div>
A CAS belongs to the family of <i>read-modify-write</i> operations, but while most of operations of this family doesn't offer a better consensus number than 2 (can only be used to provide a lock-free algorithm for 2 processes), the CAS provides has an infinite consensus number. This operation is quite simple:</div>
<div>
<br /></div>
<pre>bool CAS(int *mem, int value, int cmp) {
if (*mem == cmp) {
*mem = value;
return true;
}
return false;
}
</pre>
<div>
<br /></div>
<div>
On the other hand, ll/sc, is a pair of operations: the first one (Load-Link) load the content of a shared memory and keep track of that load, then the store-conditional update the memory location, only if it hasn't change.</div>
<div>
<br /></div>
<div>
The ll/sc mechanism is, theoretically, more powerful than a simple CAS. But that's theoretically. For various reason, most (all) concrete ll/sc implementation miss the theoretically semantics, breaking a lot of algorithm.</div>
<div>
<br /></div>
<div>
Since implementing CAS with ll/sc is simple (even with broken ll/sc), most algorithm prefer CAS.<br />
<br />
<h3>
How do we use CAS ?</h3>
</div>
</div>
<div>
<br />
So, we found that the CAS operation will be our primitive. It is available in the C++11 atomic operation, so we can use it (if you take a look at that <a href="http://blog.lse.epita.fr/articles/42-implementing-generic-double-word-compare-and-swap-.html">article</a>, you'll a find a template providing double-word compare swap for x86 and x86-64 using ASM inline.)</div>
<div>
<br /></div>
<div>
Here are some example using CAS to provide fetch&add and to implement a simple spin-lock.<br />
<br />
First the fetch&add (like operator <tt>+=</tt> )<br />
<pre>template<typename t="">
T fetch_and_add(std::atomic<t>& x, T value) {
T tmp;
tmp = x.load();
while (!x.compare_exchange_weak(tmp, tmp+value)) {}
return tmp+value;
}
</t></typename></pre>
<br />
And the simple spin-lock class:<br />
<br />
<pre>class mylock {
public:
struct guard {
guard(mylock& _lock) : lock(_lock) {
lock.lock();
}
~guard() {
lock.unlock();
}
mylock& lock;
};
mylock(): _on(0) {}
mylock(const mylock& x) = delete;
void lock() {
// C++11 CAS need a ref
int tmp = 0;
while (!_on.compare_exchange_weak(tmp, 1)) {
tmp = 0; // needed since C++11 CAS back-up changed value in tmp
std::this_thread::yield(); // don't waste cycles
}
}
void unlock() {
_on = 0; // ok atomic store
}
bool try_lock() {
int tmp = 0;
return _on.compare_exchange_weak(tmp,1);
}
private:
// we use here a CAS for the demo, but C++11 provide atomic_flag which should
// be more accurate here.
std::atomic<int><bool> _on;
};
</int></pre>
<br />
So as you can see, most of the time we use a kind of retry-loop schema to achieve our goal.<br />
<br />
You may have notice that I used <tt>compare_exchange_weak()</tt> in my code. What's weak is all about ? In the documentation, it seems that the weak version may fail for spurious reason but is less expensive for a retry-loop than the strong version. That's probably a matter of lower-level implementation, and since I'm using a loop, I'll use the weak version.<br />
<br />
<h4>
Lock Free Queue ?</h4>
</div>
<div>
<br />
So, how do I implement a lock free queue ?</div>
<div>
<br /></div>
<div>
There's few main ideas behind that kind of data structures: behind able to fail and retry (like a transaction), find linearization point and try to concentrate global structure modification into one or eventually two atomic operation and finally, find a way to <i>finish other threads works</i>.</div>
<div>
<br /></div>
<div>
<i>A linearization point is where the effects of an operation appears to happen for observers (other threads.)</i></div>
<div>
<br /></div>
<div>
For example, if you have a pointer to the first element in a linked list and want to delete that first element. So we want something like this (suppose Head is a shared global entry point of some list):</div>
<div>
<br /></div>
<pre>tmp = Head; // retrieve the head pointer
Head = tmp->next; // cut-off the head
... // do what you want with it
</pre>
<div>
Main issue in a concurrent context is that Head and <tt>Head->next</tt> may change while we're using it. Also note that the linearization point is when I switch the head with it's successor. This operation must be atomic and thus it needs a CAS.<br />
<br />
<h3>
Let's Build That Queue</h3>
<br />
So, the global idea is to fetch the pointer we need and try to switch the head, if it fails (if the head has changed since our previous read) we need to retry, here is a possible implementation (pseudo code):<br />
<br /></div>
<pre>do {
tmp = Head; // fetch the head
next = tmp->next; // fetch the next element
// be sure our pointer is still accurate
if (tmp != Head) continue;
// get the content
// switch the head and the next element
if (CAS(&Head, next, tmp)) break;
// if CAS fails, try again !
} while (true);
</pre>
<div>
<br />
This example doesn't manage empty list case and some other details. To avoid issue when dealing with empty list or list with one element (there's more issues with one element than an empty list), we use a sentinel: the head of the list is always a dumb node, only the second one matters. Here is a complete version of a pop operation (C++11 version):<br />
<br />
<pre>struct List {
struct node {
int value;
std::atomic<node> next;
node() { next = 0; }
node(int x) : value(x) {}
};
std::atomic<node> Head, Tail;
List() {
Head = new node();
Tail = Head;
}
bool pop(int *lvalue) {
node *head, *tail, *next;
do {
// acquire pointers
head = Head.load();
tail = Tail.load();
next = head->next.load();
// check if we're coherent
if (Head != head) continue;
if (next = 0) return false; // empty queue
if (head == tail) {
// missing completion on tail (see later)
// do the job of an unfinished push
Tail.compare_exchange_weak(tail, next);
continue;
}
lvalue = next->value; // copy value
// done ? try to cut the head off
if (Head.compare_exchange_weak(head, next)) break;
// fails ? got to retry
} while (true);
}
void push(int x); // see later
};
</node></node></pre>
<br />
Next step is the push operation. While for the pop operation we only have one modification in the list (replace head with its next) for the push operation we need two modification: changing the next of the tail element and then replace the tail with the new element.<br />
<br />
A thread can arrive on the queue with the next field of the tail element not null (that is: we have added the element but haven't update the tail pointer.) In that case, the current thread can try to finish the operation. We've already done that in the pop operation: when the head and the tail are equal but their next pointer is not null, the poping thread can do the CAS itself to update the tail.<br />
<br />
An interesting point with this CAS is that if the original pushing thread do the update itself between the test and the CAS of the other thread (the one that want to finish the job) since the tail pointer has already been updated the CAS will fail silently without any consequences !<br />
<br />
To summarize: when pushing, you'll build your new list cell, and try to attach it to the last cell (the tail) of the list, once done you can replace the tail pointer with the pointer to the new cell. During an update (push or pop), if a thread find the queue in an intermediary state, it can do the update itself.<br />
<br />
Here is the code:<br />
<br />
<pre>void List::push(int x) {
node *node = new node(x);
node *tail;
do {
tail = Tail.load();
if (Tail != tail) continue;
if (tail->next != 0) {
// missing completion on tail
Tail.compare_exchange_weak(tail,tail->next);
continue;
}
// update the next of the tail
if (tail->next.compare_exchange_weak(next,node)) break;
} while (true);
// finally update the tail (may fail, but we don't care)
Tail.compare_exchange_weak(tail, node);
}
</pre>
<br />
Note that the final CAS can fail, but, if it does the only reason is that someone has already done the job for us, so we don't need to care !<br />
<br />
<h4>
Memory Issues</h4>
<br /></div>
<div>
In the previous example we avoid the question of releasing/recycling memory, for a good reason.</div>
<div>
<br /></div>
<div>
<i>Why ?</i></div>
<div>
<i><br /></i></div>
<div>
You can delete a list-cell in the pop operation once you swap the head with its next pointer (at the end of the function after the loop.) But are you sure that you <b>safely</b> delete it ?<br />
<br />
<i>What can go wrong</i> ? Some other thread holds the same pointer and may try to use it.<br />
<br />
Once again, that's a question of timing: a thread trying to take an element of the queue will keep and use the pointer to the head in order to access its next field, so if the corresponding node has been freed this operation may fail.<br />
<br />
A lot of lock-free implementation are done in Java where there's a garbage collector: a node won't be freed until all its persistence roots are active. But, in C++ there's no such thing …<br />
<br />
A possible solution to avoid segfault is to use a recycling allocator: cells are not deleted but reuse as new nodes. Thus, accessing a node will always make sense, and won't fail.<br />
<br />
Are we safe now ? No, another issue arise with recycling: <b>the ABA problem</b>.<br />
<br />
<i>ABA ?</i><br />
<br />
No, we don't talk about Swedish pop music. The ABA issue is the weak point of the CAS operation: observing only if a pointer has changed may not be enough.<br />
<br />
In brief: a first thread get the head of the queue, found a pointer A and get scheduled, during its inactivity phase, another thread take the first element of the queue and the head pointer becomes B, but some other changes may occurs and finally, the head pointer becomes A again (but it's content has change.) The first thread won't see that change, but if it has stored the head and its next, the next value will be false, but the CAS won't fail and we loose data coherency !<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiebny2VYmpJfkFk_CRkn4z7gGsIAMoX8UtIfj5lyLzCZnyi790cg-wQnkIhluZWM_nFzWOX6LZ2AzSL6PC0QaaPxITrZuS8OkyIwoejBS4qSxI-pAh-gXnucHXAjL-bx6hTU9b9hp3nEk/s1600/ABA_Problem.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiebny2VYmpJfkFk_CRkn4z7gGsIAMoX8UtIfj5lyLzCZnyi790cg-wQnkIhluZWM_nFzWOX6LZ2AzSL6PC0QaaPxITrZuS8OkyIwoejBS4qSxI-pAh-gXnucHXAjL-bx6hTU9b9hp3nEk/s400/ABA_Problem.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">ABA issue in a stack</td></tr>
</tbody></table>
There are various solutions to the ABA problem:<br />
<br />
<ol>
<li>Use a garbage collector (like in Java)</li>
<li>Use the so-called IBM solution with <i>tagged pointers</i></li>
<li>Use Hazard Pointers</li>
</ol>
<div>
The GC solution is still not possible and in fact, it's not really interesting. Let's see the two others.</div>
<div>
<br /></div>
<h3>
Tagged Pointers</h3>
<div>
<br /></div>
<div>
The idea of tagged pointers is to associate a counter with our pointer and manipulate the pair (stored contiguously) as a whole value. The counter is <b>not</b> a reference counter: it's not really possible to implement an efficient ref-count in lock-free. Our counter here is just a kind of tag that we increase each time we use the pointer. So when comparing the pair pointer/counter even if the pointer has the same value, if it has been updated, the counter will have different value and the CAS will fail.</div>
<div>
<br /></div>
<div>
This technique is quite simple and efficient, but it requires a double-world CAS, that is a CAS that work on one location but for two contiguous words (not to be confused with a double CAS, that works like two CAS on two different locations.) Such an operation exists on most 32bits processors but is only available on modern x86 processors with 64bit extension. C++11 provides 16, 32 and 64 bits CAS for atomic types but no 128bits version.</div>
<div>
<br /></div>
<div>
This method is used in the original article describing the lock-free queue: <b><a href="http://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html">Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms</a></b></div>
<div>
<br /></div>
<div>
I've also write an article explaining how to use <span style="font-family: Courier New, Courier, monospace;">cmpxchg16b </span><span style="font-family: inherit;">instruction using C++ template and inline ASM: <b><a href="http://blog.lse.epita.fr/articles/42-implementing-generic-double-word-compare-and-swap-.html">Implementing generic double-word compare and swap for x86/x86-64</a></b></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<h3>
Hazard Pointers</h3>
<div>
<br /></div>
<div>
Hazard Pointers is a technique describe in an other article from Magged Micheal (one of the author of the work on lock-free queue): <a href="http://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf" style="font-weight: bold;">Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects</a> (pdf)</div>
<div>
<br /></div>
<div>
It's like a simplified GC: each threads has some <i>hazard pointer variables</i> where it stores pointers that need to be preserved and when some thread tries to delete some pointers, it first verifies that this pointer is not in used (stored in a hazard pointer var.)</div>
<div>
<br /></div>
<div>
Hazard pointer variables (HP) are in fact shared variable that is writing by one thread and readable by all others. When a thread want to delete a pointer, it first adds it to a wait-list, when this list reach a threshold, it retrieve all the pointers that are stored in a HP and only delete those that are not in used.</div>
<div>
<br /></div>
<div>
Despite some tricky details about managing the attribution of HP, the implementation is quite simple, it is wait-free and when choosing the right data-structures it can be pretty fast. In practice, I've seen no difference in performance with the IBM techniques (tagged pointers.)</div>
<div>
<br /></div>
<div>
I've got a full implementation available here: <a href="https://bitbucket.org/marwan_burelle/lockfreeexperiment/src/16b9e15966eeb521fa560d5ceb099fd55314a41a/HazardPointers/hazard_pointer.hh?at=master">hazard_pointer.hh</a></div>
<div>
<br /></div>
<h4>
More ?</h4>
<div>
<br /></div>
<div>
So that's just a beginning, I start playing around programming all those data structures (available in a beta version) and you can take a look at it in my bitbucket repos: <a href="https://bitbucket.org/marwan_burelle/lockfreeexperiment">https://bitbucket.org/marwan_burelle/lockfreeexperiment</a></div>
<div>
<br /></div>
<div>
Of course there's a lot of information on the net, but start from the two paper already cited (lock-free queue and hazard pointers.)</div>
<div>
<br /></div>
<div>
My next step will be to implement <b>wait-free</b> data structures using ideas presented in recent works that announce very good performances, that's another story …</div>
</div>
</div>
</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-22673855067902762292013-05-14T01:05:00.002+02:002013-05-14T13:25:38.118+02:00Playing With C++11 Multi-Threading Stuff<div style="text-align: justify;">
So, you may be interested in what I'm doing in my spare time ? I'm playing with concurrent-friendly data structures. The idea is to implement in C++ data structures that are available for Java programmers in the Java framework (and some newer ones if possible.)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
It started when I was searching algorithmic example for parallel programming lecture. I found the classical article from <a href="http://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html">Micheal&Scott</a> published in PODC96 called: <i>Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms</i>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This paper presents two queue algorithm a blocking one with two locks and a non-blocking one (also called <i>lock-free</i>.) So I wanted to implement both algorithm in order to explain them to the student.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The blocking algorithm is very simple, in fact it belongs to that kind of algorithm that seems obvious after reading it. It echoed some ideas I've tried by myself and solved all the issues I was thinking of.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The non-blocking algorithm requires more time. In fact, I was blocked by the fact that my programming language (C) doesn't provide a <i>CompareAndSwap</i> operation (I've finally found what I was looking for in gcc intrinsinc, but only to found another issue in the 64bit version.)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I've finally managed to solve that question by implementing mixing ASM and C++ template in order to have a working double-word <i>CompareAndSwap</i> operation. You can find all the story in this <a href="http://blog.lse.epita.fr/articles/42-implementing-generic-double-word-compare-and-swap-.html">article</a> published on the LSE's <a href="http://blog.lse.epita.fr/">blog</a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
And then I've started reading about C11 and C++11 stuff. And found that it become the right time to explore both the new elements in the standards and alll that funny data structures.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
But, let's start with C++11, will talk about lock-free later.</div>
<div style="text-align: justify;">
<br /></div>
<h4>
What's the deal with all that stuff on the memory model ?</h4>
<div style="text-align: justify;">
In fact what is a memory model anyway ?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
So, we need to take a look at some notions in compiler and programming languages.<br />
<br /></div>
<div style="text-align: justify;">
<h3>
Semantics ?</h3>
If you're a programmer, you probably have some knowledge on that compiling stuff: you give <i>higher-level</i> code to some program (the compiler) and it gives you back a binary file, that suppose to be some <i>machine-level</i> code. If you try to wrote ASM by yourself, you've probably found that there's quite a huge gap between your favorite programming language constructions and assembly code. Of course, for the experienced eyes, even if you don't know the target assembly, you'll see patterns in the code and probably understand the link between the two world.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
But, anyway, the translation between higher-level code and assembly code is not simple. That's not just basic line to line translation. The formal way to understand this translation is what we call <b>semantics</b>. Language semantics explains what value an expression (for example) should return, and eventually what memory cells are affected by the computation.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
When dealing with <i>well-founded semantics</i>, like with most functional programming languages, the description is theoretic, even with small-steps operational semantics that can be directly implemented in an interpreter, we don't really have a description on how to obtain results, but what results are expected. This way, the language can be implemented in several ways, and doesn't rely on specific architectures, or algorithms.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
C and C++ doesn't belong to that kind of languages (may say hopefully … ) But, lot of people think (and I was also thinking that way when I was student) that the compiler describe the semantics. That is: the semantics of C program is defined by how standard compilers translate the code.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This is false and stupid. C and C++ have a semantics, but when a well-founded programming language validation system try to forbid code for which no semantics is clearly defined, C and C++ let the compiler decide. So, this is not simple, but the thing you need to understand is that the semantics gives a lot of liberty to the compiler on how to translate things. And the semantics only gives a loose definition of the expected results for a subset of the language.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
One of the key idea behind this approach is to give the maximum liberty to the compiler so that it can optimized the code using all the available tricks.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Take this little code sample:</div>
<div style="text-align: justify;">
<br /></div>
<div>
<pre>int res = p1->x * p2->x + p1->y * p2->y + p1->z * p2->z;</pre>
</div>
<br />
<div style="text-align: justify;">
(given that <tt>p1</tt> and <tt>p2</tt> are pointers to some kind of 3D point structure.)<br />
<br />
<i><b>Edit:</b> I've moved this code from float to integer. Because, as you know re-ordering and floating point …</i><br />
<br />
If you played with SIMD extensions of some CPUs you know that we can obtain the same result with faster code using these extensions. But it will change the order (ok, not much) in which the expression is evaluated. You know that it doesn't change the final result, but a too restrictive semantics will forbid that kind of rewriting.<br />
<br />
What's the deal with re-ordering ? It doesn't change the result ? Yes, but only because we don't have any side-effect here, nor do we need to respect some order in our memory accesses (think about accessing a hardware for example.)<br />
<br />
So, rather than making too restrictive rules (with the hope that clever compilers' writers find a way to auto-magically detect when the semantics can be brake), people writing standards for C and C++ decided to give maximum freedom and less constraints, with the drawback that some piece of code will have undefined behavior.<br />
<br />
There's a lot of stuff to explain about this approach, but a good example is better: the standard doesn't give any rules on the order that kind of stuff be executed …<br />
<br />
<div>
<pre>t1[i++] = t2[i++];</pre>
</div>
<br />
This is an <b>undefined behavior</b> and for that matter, the compiler may decide to produce code that wipe out your drives, because the standard doesn't say it can't do that.<br />
<br />
<h3>
Going Parallel</h3>
<div>
<i>And now add some fun to that: multiple processors, multiple threads and a single memory. </i>You begin to see what's happening next ?<br />
<br />
So, let's dive into the hardware first. When dealing with memory accesses in the presence of multiple processors we got a lot of issues solve.<br />
<br />
Basically the question is: <i>do we need to synchronize memory operations</i> ?<br />
<br />
Let's take a <i>real life example</i>: at the crossing of two roads, we may add some traffic lights to avoid accidents. But, most of the time we don't need it, why ? Because, there isn't enough cars and if we use traffic lights we may block cars when it's not needed.<br />
<br />
For shared memory it's the same idea: most memory operation doesn't require any synchronization because they won't conflict. Beware, I'm not saying that when accessing the <i>same</i> memory cell with two processors there isn't any risk, no I'm saying that most of the time processors won't access the same memory cells. So, you'll need to specify what's happening when you know conflicts can arise.<br />
<br />
Then rather than synchronizing all memory operations, or even rather than trying to synchronize all dangerous memory accesses, most hardware are based on what we call the relaxed memory model: you must explicitly describe when you need synchronization, when you don't, you will have no guarantee of what will happen.<br />
<br />
So what kind of synchronization do we have:<br />
<br />
<ul>
<li><b>atomic operations</b>: an atomic operation is a complex operation (doing more than one memory access) that executes as if it were a simple access. The usual operations are <i>atomic exchange</i>, <i>compare-and-swap</i> …</li>
<li><b>acquire barrier</b>: this barrier enforces that operations after the barrier will be re-ordered before the barrier (that is, the processor won't try to antcipate load operations after the barrier.)</li>
<li><b>release barrier</b>: this barrier enforces that all operations begin before the barrier will be finished before crossing it (that is, the processor won't defer concrete memory stores after the barrier.)</li>
<li><b>full memory fence</b>: a full memory fence is a kind of combined acquire and release barrier: all pending operation must finish before the barrier and no new operation will start before the barrier.</li>
</ul>
<div>
The acquire/release things often disturb new comer in the world of concurrent memory accesses. The first things you need to know is that your processor doesn't act in a linear fashion for a lot of good reasons. To be short: it is able to start loading data from memory as soon as it able to decode the target address, even if some prior instruction are not yet finished; it is also able to <i>defer</i> store operation to a later point, that is start operations that are after the storing operation before concretely storing the data (note that you compiler may also try to do similar changes in your code.)</div>
<div>
<br /></div>
<div>
The classic example is the <i>I-have-finished</i> <i>boolean</i> mistake. Let's take a look at the following pseudo code:</div>
<div>
<br /></div>
<div>
<pre>shared int x = 0;
shared bool ok = false;
worker0() {
x = 42;
ok = true;
}
worker1 {
if (ok)
print(x);
else
print("not yet");
}
</pre>
</div>
<div>
<br />
So, a quick reading let you think that this program will either print "42" or "not yet" but not "0", right ? Wrong !<br />
<br />
The processor will probably defer some of the storage operations, if it's <i>longer</i> to write to x, it can change the ok to true before storing 42 in x. On the other part, it can also start reading x before ok, and thus read the older value and then the true flag in ok.<br />
<br />
Barrier can be used that way here:<br />
<br />
<div>
<pre>shared int x = 0;
shared bool ok = false;
worker0() {
x = 42;
release-barrier;
ok = true;
}
worker1 {
if (ok) {
acquire-barrier;
print(x);
} else
print("not yet");
}
</pre>
</div>
</div>
</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This will solve the issue.
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>And thus, what about C and C++ ?</b></div>
<div style="text-align: justify;">
<b><br /></b></div>
<div style="text-align: justify;">
For years, the standard avoided the question. C99 and C++98 don't even mention that kind of issues as undefined behavior, no, they simply don't deal with concurrency. Until the release of 2011 new standards C11 and C++11 (in fact this was for quite some times in C++0x.)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
What's the difference now ? Hey, guess what ? (most) concurrent accesses are undefined behavior !</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
What a (r)evolution, you may say. But in fact it is, because the standard also provides a way to introduce barriers. And thus, we are now able to code using atomic operations and memory barriers, without relying on the supposed behavior of a compiler and a processor.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If you have looked for implementation or discussion about implementing lock-free data structures, you may have noticed that most of them are done in Java, the only reason was that Java make the move to the relaxed memory model (basically the one I described to you) since the release of Java 1.5. So, you can rely on that model to justify you implementation, and be sure that your benchmarks make sense.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I hope that the arrival of the new C++ memory model will gives us a chance to see more C++ implementations.</div>
<div style="text-align: justify;">
<br /></div>
<h4>
And the other stuff ?</h4>
<div>
You want to know more about C++11 threads ? Read the specs !</div>
<div>
<br /></div>
<div>
I've got some slides (in English) on the subject here: <a href="http://wiki-prog.infoprepa.epita.fr/images/4/4d/2013-progpara-threads.pdf">Threads</a></div>
<div>
<br />
You can also find interesting information in this (old but still accurate) article by Maurice Herlihy: <a href="http://www.diku.dk/OLD/undervisning/2005f/dat-os/skrifter/lockfree.pdf">Wait-Free Synchronization</a> (pdf format.)<br />
<br /></div>
<div>
The next article will talk about my implementation of <i>Hazard Pointers</i>, their use in lock-free queues and maybe some words about testing all that code.</div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-58033520075527648342013-03-23T20:43:00.002+01:002013-03-23T20:43:16.583+01:00Beginners' corner: factorization !<div style="text-align: justify;">
This a sample extracted from an exercise given to beginners students in C: a simple graph implementation. We're looking at function that add an edge between two vertices.</div>
<div style="text-align: justify;">
<h3>
Context</h3>
The types are following traditional graph implementations, and tends to respect formalism used in algorithmic classes (so don't bother me about typedefed pointers !)</div>
<div style="text-align: justify;">
<br /></div>
<pre>typedef struct s_adj *adj;
struct s_adj {
size_t src, dst;
adj next;
};
typedef struct s_vertex *vertex;
struct s_vertex {
size_t ins, outs;
adj succ, pred;
};
struct s_graph {
size_t order;
vertex vertices;
};
</pre>
<br />
<div style="text-align: justify;">
Our representation stores directed edges in both ends: in the source's successors and in the destination's predecessors. Our function will take the graph and the identifiers of source and destination (index in the vertices tables).</div>
<div style="text-align: justify;">
<br />
<h3>
Naive code</h3>
<br /></div>
<div style="text-align: justify;">
Straightforward implementation look like that:<br />
<br /></div>
<pre>void add_link(graph g, int src, int dst) {
adj cell_succ;
cell_succ = malloc(sizeof (struct s_adj));
cell_succ->src = src;
cell_succ->dst = dst;
cell_succ->next = g->vertices[src].succ;
g->vertices[src].succ = cell_succ;
g->vertices[src].ins += 1;
adj cell_pred;
cell_pred = malloc(sizeof (struct s_adj));
cell_pred->src = src;
cell_pred->dst = dst;
cell_pred->next = g->vertices[dst].pred;
g->vertices[dst].pred = cell_pred;
g->vertices[dst].outs += 1;
}
</pre>
<div style="text-align: justify;">
<br />
We build two cells for the lists of successors and predecessors of both ends. This code works, but that's all, it is far too long and looks dirty. And, even if it's a short piece of code, it is <i>unmaintainable</i>: if we change simple details (like the fact that the edge is described in the same direction in both ends) we have at least two modifications per change.<br />
<br />
First, add variables for our vertices. Our type defines vertices as pointer to structure, and that's correct for me, I'll use pointer rather than array cells, so the new version looks like:<br />
<br /></div>
<pre>void add_link(graph g, int src, int dst) {
vertex s = g.vertices + src;
vertices d = g.vertices + dst;
adj cell_succ;
cell_succ = malloc(sizeof (struct s_adj));
cell_succ->src = src;
cell_succ->dst = dst;
cell_succ->next = s->succ;
s->succ = cell_succ;
s->ins += 1;
adj cell_pred;
cell_pred = malloc(sizeof (struct s_adj));
cell_pred->src = src;
cell_pred->dst = dst;
cell_pred->next = s->pred;
s->pred = cell_pred;
s->outs += 1;
}
</pre>
<div style="text-align: justify;">
<br />
It's a small change, but it gains a little more on readability. Oh, just a note: I don't like long lines, and long variable's (or function's) names, even they seems more explanatory, a variable with more than 5 characters makes your code unreadable. Reserve long name for major functions, class or types name, not for local variables nor parameter's names. This is a common error: thinking that saying more make the code more readable, but that's wrong, if you can't figure out what this variable is used for, it means that the code your reading is already fucked-up, you don't need an explicit name, nor a comment.<br />
<br />
And about the vertex declaration: I prefer the use of pointer's arithmetic here for readability. It may seems strange to not use array notation, but, what do you think is better: <tt>&(g->vertices[src])</tt> or <tt>g->vertices + src</tt> ? For me the choice is obvious …<br />
<br />
<h3>
Now: factorization !</h3>
The biggest issue in this function is the two almost identical blocks of code. A good idea should be to deffer cell initialization to an external function. This function is doing half of the link job, which give us a good name for that new function:<br />
<br /></div>
<pre>void add_half_link(int src, int dst, adj cell) {
cell->src = src;
cell->dst = dst;
}
</pre>
<div style="text-align: justify;">
<br />
But can we attach this cell to the cell directly to their corresponding list ? Yes, just pass a pointer to the list (I really mean a pointer to the list, thus a pointer to the pointer to cell in the list, the list is already a pointer, not a structure.<br />
<br /></div>
<pre>void add_half_link(int src, int dst, adj cell, adj *l) {
cell->src = src;
cell->dst = dst;
cell->next = *l;
*l = cell;
}
</pre>
<div style="text-align: justify;">
<br />
Our new function to the job for half of the link and the way we passed the list of edeges, let us use it in both cases (successors and predecessors.)<br />
<br />
<h3>
Putting everything together …</h3>
Now we just have to integrate our sub-function in the original one:<br />
<br /></div>
<pre>static inline
void add_half_link(int src, int dst, adj cell, adj *l) {
cell->src = src;
cell->dst = dst;
cell->next = *l;
*l = cell;
}
void add_link(graph g, int src, int dst) {
vertex s = g->vertices + src;
vertex d = g->vertices + dst;
add_half_link(src, dst, malloc(sizeof (struct s_adj)), &(s->succ));
add_half_link(src, dst, malloc(sizeof (struct s_adj)), &(d->pred));
d->ins += 1;
s->outs += 1;
}
</pre>
<div style="text-align: justify;">
<br />
Note that I have declared our sub-function as <tt>static inline</tt>, it is obviously static since we don't want it to be exported, and asking for inline seems logic. We could have find a way to increment degrees (ins and outs) in the sub-function also …<br />
<br />
Finally we got a code, that is (not so) smaller, but, and that's the most important, is more readable and maintainable.<br />
<br />
Of course, you should have written the second version directly …<br />
<br />
This is a simple example showing the idea that you can increase your code quality by using factorization.<br />
<br />
Oh, and for the record, the functions only need a <i>specification comment</i> for the main one. Avoid as much as possible inner comments, they don't increase readability nor understanding of code, and most of the time they break the <i>reading flow</i>. That kind of functions are <i>self-explanatory</i>, and so must be most of your code, if you feel the need to explain it, think of reorganizing it or some other kind of refactor, only very specific tricks need comments, if you too many, you're probably doing things the wrong way.<br />
<br />
There's another points about code comments: they tend to desynchronize. Your code will change, you'll probably find bugs … are you sure that all your comments are in sync with these changes ? No comment, no problem …<br />
<br />
That's it for today ! Code well !<br />
<br />
<br /></div>
Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-74191019277721383342013-02-19T15:38:00.001+01:002013-02-19T15:38:34.421+01:00New post on LSE blogA new post (in fact, an old one, written in july 2012 but forgotten in the publication queue) on the LSE blog.<br />
<br />
<a href="http://blog.lse.epita.fr/articles/42-implementing-generic-double-word-compare-and-swap-.html">http://blog.lse.epita.fr/articles/42-implementing-generic-double-word-compare-and-swap-.html</a><br />
<br />
It's all about playing with asm-inline and C++ template ;)Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-70126425280728098392012-07-31T00:50:00.001+02:002012-07-31T03:23:51.052+02:00Rules won't help …<div style="text-align: justify;">
As I mentioned earlier, mantras and empiric rules are often more misleading than helping in programming. In fact, I thought that directing your programming activities through a set of established rules is more dangerous than you can think.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
It doesn't mean that you'll never achieve your goal if you follow those rules, but it will give you a false sense of security.</div>
<div style="text-align: justify;">
<br />
<br /></div>
<h3>
Rules to failure …</h3>
<div style="text-align: justify;">
<br />
Using rules to conduct some activities is natural and comfortable. But, are we sure that following those rules will produce the desired effect ?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Take, for example, recipes (cooking ones.) We all experienced that before: you want to make a cake, choose one in your cook book (one with a very nice photo and not much work), you follow the recipe carefully, and end with some sort of ugly dead creature from outer-space that taste like burned plastic.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
What went wrong ? After several similar failures, it appears that changing various elements (time, quantity even ingredients … ) of the recipe provides a far more satisfactory result. Why ?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There's plenty of reasons. Of course, you can blame the book (and you may be right), but there's more. A good recipe, designed and written by a cooking expert (and maybe reviewed by some more cooking experts), is in fact a description of a chemical experiment. If you've done some, you know that too much approximation may leads to dramatic (and sometimes dangerous) unexpected results. Cooking is less dangerous (except for your taste), but the logic is the same: a wrong combination of manipulations, approximate timing and measuring leads to inedible meals and cakes.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
At that point, you may think that the point is that you haven't do the job by the book and that you'll need to be more careful next time. But again, it's false. You won't be able to achieve a descent result without adapting the recipe.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let's consider another example: on some packed sandwiches (you know that tasteless triangle things that you can buy in super-market), I've found opening instructions: « twist and pull » with a curved arrow indicating twisting direction. I've tried about 5 minutes to perform the operation and finally get a « shaken sandwich » (not without using some cutting tools to open the damned things.)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
All of that because, there's the rule, the intention behind it, the way you understand it, the way you try to applied it, and the real action to perform. In fact, there's probably more than one way to do it, and some are simpler for you than the one described in rules.</div>
<div style="text-align: justify;">
<br /></div>
<h3>
So ? And what's about programming, then ?</h3>
<div style="text-align: justify;">
<br />
Programming is finally no more than writing rules for the computer.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Thus, it may seems legit to apply to your self some rules when designing and programming ?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
But again, there's some hidden issues there.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There's a lot of designing methodologies and software conception processes. All those tools are supposed to lead you through the best way to achieve your primary goals. They are collections of best practices and rationalized procedures, known to provides grant success in many other projects.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>That's bullshit !</b> Success of most projects are due to people in the project, not how they organized. Of course, well suited methodology can help you and may event prevent some important mistake. But you can still get a bunch of craps, it will be the best designed bunch of craps of all time, but still a bunch of craps.</div>
<div style="text-align: justify;">
<br /></div>
<h4>
Next lesson: how to fail using programming design methodology:</h4>
<div>
<ol>
<li><span style="background-color: white;">Choose a small random project with well known solutions (in order to compare to your production), possibly a project more directed to algorithms than data-managing. For example: « <i>Your program will help </i></span><i>a fictitious character lost in a maze to get out by the shortest path. You'll have access to the whole map.</i> » You'll recognize a classic application for path-finding algorithm.</li>
<li>Now, choose a method. I'll stay abstract on that matter (due to a lake of place.) So basically, you'll have an outer specification phase, a data model specification, then interaction specification and finally you'll get to more technical aspects and code.</li>
<li>So, our program take what look like a map and the description of the character to somehow leads the character to the exit. The maze is provided as a bitmap with a distinct color for rooms and tunnels linking rooms.</li>
<li>The main element that appears in the description seems to be the character (it comes first and the subject is to lead it in the maze.) We'll use it as our central element.</li>
<li>Following our method, we will design a class diagram based on the idea that the main character is moving on an (almost) open-field (the original bitmap.)</li>
</ol>
<div>
At that point you may have notice that we're in trouble. While, a careful examination of the subject triggers some idea about path-finding in graph, we're stuck with bitmap exploration.</div>
</div>
<div>
<br /></div>
<div>
The error is obvious, we haven't choose the most efficient way to solve the problem. Basically, we should have notice that even if the input is in form of a bitmap, there's a notion of rooms (graph vertex) and tunnel (graph edges.) I made this mistake on purpose, to show you that a conception method won't help you to solve an issue, but help you to organize the process of building a solution.</div>
<div>
<br /></div>
<div>
This is a common mistake: project organization methodology, conception tools and any other software engineering processes are guidelines that kept you on track with big project, but they will never save you from bad ideas.</div>
<div>
<br /></div>
<h4>
False security</h4>
<div style="text-align: justify;">
This notion of rules guided conception provides a false sense of security. You're respecting a well establish software process, thus you shouldn't fail. Experience prove the contrary, the only things that a methodology can avoid are dispersion and diversion from the original concept: it keep you on track and help you evaluate the progression (and thus, possible delays.)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This is the main issue on relying on rules, just like the cooking recipes, following it won't lead you to success automatically.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
And just like cooking, if you don't have good programmers to implement your design, even if the design is the best possible piece of conception, your project won't work.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I'm not talking about managed project against tech-lead, I'm just saying that rules, methodology (and thus management) are not guarantees of success, they're only there for keeping project on tracks.<br />
<br /></div>
<div>
<br /></div>
<h3>
Security, cryptography and laws.</h3>
<div>
<br />
Let's move to another related subject: <b>security</b>.</div>
<div>
<br /></div>
<h4>
Playing with rules.</h4>
<div style="text-align: justify;">
Non technical people often think that security can be enforce using security laws. This is somewhat related to playing some strategy game.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
For example, when you play chess, you have a finite set of rules, and normally you can't play outside of these rules. These rules are constraint: at each point of the game, there's a finite set of possible moves. Based on this fact, you can use rules to protect yourself against your opponent's attack. For example, moving your king to be outside of the range of your opponent's menacing piece. Since, you both play with the same rules, he won't be able to conclude his attack (provides that you estimate all possible situation.)</div>
<div style="text-align: justify;">
<br />
If your opponent doesn't respect the rules, he's a cheater, and cheating implies loosing the game, unless no one sees it. So, rules are protecting you (you know the range of possible attacks) and still protect you when the other player is not fair.<br />
<br /></div>
<div style="text-align: justify;">
Real life don't follow this scheme: if your opponent has an important goals, breaking rules won't stop him.<br />
<br /></div>
<h4>
Laws against efficient technical solutions ?</h4>
<div style="text-align: justify;">
There's recurring debates in many countries about regulating cryptography or software reverse engineering. The common idea is that if you forbid the use of strong cryptography, criminals and terrorist won't be able to securely exchange information. <b>Bullshit !</b></div>
<div style="text-align: justify;">
<b><br /></b></div>
<div style="text-align: justify;">
Accessing strong cryptography, even when it's prohibited by laws, for someone that plans to perform criminal actions, is not impossible. In fact, it is relatively simple to find a sufficiently safe cipher with basic mathematical knowledge (an homemade cipher, based on <i>xoring</i> data with one time pad is quite simple as soon as you can transmit the key sequence to your buddy.)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The real result of constraining usage of strong cryptography is compromising normal users' security ! Since they can't use efficient tools (or they must rely on tools with known vulnerabilities), they expose their communication and their data to security threats !</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
Another common mistake is about reverse-engineering (or more generally analyzing software security.) For example, if someone decided to break a security protection of a credit card system for his own profit, it's main crime is not breaking the security protection, it's to exploit the security breach to steal money ! He is already on the wrong side of the laws, he won't care about another minor crime.</div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
On the other hand, a security researcher that found some vulnerabilities in credit card protection is helping us ! Proving that there's a breach in a system that a lot of users trust, is far more important than prohibiting the break of the protection.<br />
<br />
Once again, the point is that protection and safety don't come from rules or laws, they come from good and efficient software.<br />
<br />
<h4>
Secure programming recipes.</h4>
<div>
Another classical subject in software security is : <i>secure programming.</i> There's plenty of books on the subject, but unfortunately, most of them are recipes books: they show you well known mistakes to avoid and predefined code patterns that normally won't fail. The result is that we still have a lot of bad programs around there with plenty of (possibly yet to discover) vulnerable code.</div>
<div>
<br /></div>
<div>
I can sum-up what I think, secure programming should be:</div>
<div>
<ul>
<li>Your program <b>must</b> only do what was specified in the first place</li>
<li>Your program <b>must not</b> do anything outside of the scope of its specification</li>
<li>Your program <b>must</b> be free of bugs.</li>
</ul>
<div>
The first two points imply that a program can only be safe if its specification includes what what must be done and what must not be done. A secure specification requires that you define the expected behavior in terms of authorized and unauthorized aspects.</div>
</div>
<div>
<br /></div>
<div>
The last point is the hard part, once again it emphasizes the need for technical qualities. But, it is also important that a program free of bug is not by itself safe. A good is example is the telnet protocol: the protocol is flawed by design (transmitting in clear text all the sufficient data for authentication is stupid) meaning that even if you're certain that your implementation is bug free, using telnet will never be safe (at least in wide open environment.)</div>
<div>
<br /></div>
And, again about recipes for secure programming, be aware that following them is not sufficient. For two reasons: first they not cover all possible mistakes; second, even if you follow them you can open some breach.<br />
<br />
Let's take a basic example. When copying C strings, you should not use the infamous <tt>strcpy</tt> function and prefer <tt>strncpy</tt>. The reason is quite obvious: the first form assumes that the destination points to memory chunk that can hold all characters from the source parameters, on the other the later one take a bound for the copy. The issue is the well known buffer overflow attack (providing a very long string you can rewrite the return address of the function.)<br />
<br />
But, using the later form is no more safe. Of course, you can pass a too small value as bound, but there's another issue: reading the manual of <span style="font-family: monospace;">strncpy</span>, we can see that if the source string is wider than the bound, no terminating null character will be added to the destination. What's the issue ? A further use of the destination string may again overflow, offering the opportunity to access sensitive data, or once again overwriting important values. This second form of error, may not lead to a new security issue, but it can, it will far more complex to track down since it won't break directly where the mistake was made.<br />
<br />
The following toy-example will demonstrate a simple example:<br />
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void copy_and_print(char *text)
{
char secret[] = "Hidden text.";
char buf[32];
// first copy the the original text in buf
strncpy(buf,text,32);
// Then print it using printf.
printf("copied text: %s\n",buf);
// use secret to avoid warning.
fprintf(stderr, " secret text: %s\n", secret);
}
int main()
{
// prepare a long piece of text
// wider than the 32bytes used in our function
char text[34];
for (size_t i=0; i<33; ++i)
text[i] = 'a';
text[33] = 0;
// So try our function
copy_and_print(text);
// What happend ?
return 0;
}
</string.h></stdio.h></stdlib.h></pre>
<br />
If your stack and compiler is similar to mine, it will print the <i>hidden messages</i> twice …<br />
<br />
<h3>
About constraining languages</h3>
<div>
Since I'm passionate about programming, I've tried and learnt many programming languages. While some language hasn't fit me for <i>taste</i> reason or because I've no use of it, some have let me a strange sensation of resistance, you know where you feel like if you're moving like molasses.</div>
<div>
<br /></div>
<div>
It takes me sometime to realize that it was related to languages that try to force you to use <i>best practices</i>. The first example (for me) was Pascal. Pascal is language designed for teaching and enforcing good practices of structured programming (against <i>evil gotos and unguarded loops</i>) and Pascal is somehow very restrictive.</div>
<div>
<br /></div>
<div>
The next in row was Java, once again, Java has for its goal to promote good object oriented methodology.</div>
<div>
<br /></div>
<div>
What happen when you code (or at least when I code;) using these languages ? You're forced to circumvent the constraints to be able to achieve your goals. Some simple example of (safe) piece of code became a huge and complex plumbing because the direct way to do it is prohibited by the language.</div>
<div>
<br /></div>
<div>
A curious aspect of such languages, is that they tend to prefer keywords rather than symbols. In more recent languages, it can also appears in constraint over code formatting (like fascist languages using indentation to delimit blocks.)</div>
<h3>
Conclusion</h3>
<div>
<br /></div>
<div>
So, what was it all about ? I'm deeply convinced that while using guideline may proven some help in maintaining a process on track, it won't help you build better software. At least, you know that you'll be able to go as far as your idea can lead you, if the idea was bad, it won't save you from failure.</div>
<div>
<br /></div>
<div>
This concept is not only software related: rules, laws and the like are only able to protect you in games ! In real life, the only safeguard are hard-works and technical skills.</div>
</div>
</div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-55108117568218577912012-06-27T12:10:00.001+02:002012-08-30T14:26:23.269+02:00New article on LSE's blogAnother article on LSE's blog about the C! programming language, read this out !<br />
<br />
<b><a href="http://blog.lse.epita.fr/articles/23-c---system-oriented-programming---syntax-explanati.html" target="_blank">C! - system oriented programming - syntax explanation</a></b><br />
<br />
The article presents basis of C! syntax and is a follow-up of my previous article introducing the language (also on LSE's blog.)Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-77154368949825128832012-06-27T11:48:00.002+02:002012-06-27T11:48:29.711+02:00Back To C: tips and tricks<div style="text-align: justify;">
<blockquote class="tr_bq">
<i>Note: I've begun this articles months ago, but due to a heavy
schedule (combine with my natural laziness), I've postponed the
redaction. So, the article may be a little rambling, I apologize for
that but I hope you'll found it interesting.</i> </blockquote>
<br />
The C programming language is probably the one of the widely used, and widely known programming language. Even if there's some obscure syntax tricks, it's a simple language, syntactically speaking. But, it's probably one of the harder to learn and to use correctly !</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There's several reason for that:</div>
<div style="text-align: justify;">
</div>
<ul>
<li>since it is intended to be a low-level tools, it let you do a lot of things, things that are most of the time considered ugly but necessary in some cases.</li>
<li>it's original behavior does not include modern notions of type checking and other kind of verification, you're just playing with a machine gun without any safety lock …</li>
<li>expressive power with simple syntax often means more complex work: C belongs to the same kind of languages as assembly or lambda-calculus, you can do anything you want, but you just have to code the whole things completely from scratch.</li>
</ul>
<div>
<br />
<div style="text-align: justify;">
One the most important things about coding using C, is to understand how it evolves and what it was mean to be and what it is really now. Back in the first Unix days, Denis Ritchie presented its language as a high level portable assembler, a tools for system, kernel and low-level programming. But, since then, there are standards (ANSI, ISO … ) and the language is no longer the original low-level tool.</div>
<br />
<div style="text-align: justify;">
Using C nowadays is a difficult exercise and the path to working code is full of traps and dead-ends.</div>
<br />
<div style="text-align: justify;">
I'll try to lay down some of my « tricks » and experiences. I've been using C for almost 15 years now, and I'm teaching it for about half of that time, I've seen a lot of things, but I can still be surprised every day.</div>
<br />
<h2>
Listen to your compiler !</h2>
<span class="Apple-style-span" style="font-size: large;"><b><br />
</b></span><br />
<div style="text-align: justify;">
Historically, C compilers are <i>a little bit silent</i>. Basically, most bad uses are not really errors, they may even be legit in some cases. So, most compilers prefer to emit warnings rather than errors.</div>
<br />
<div style="text-align: justify;">
This is why you should activate <b>all</b> warnings, and even better activate « warnings as error ».</div>
<br />
<div style="text-align: justify;">
A good example is the warning about affectation in condition, take a look at the following code</div>
</div>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">while ( i = read(fd, buf + off, SIZE - off) )
off += i;
</pre>
<br />
<div>
<div style="text-align: justify;">
This code will trigger a warning (« <i>warning: suggest parentheses around assignment used as truth value</i> » in gcc.) Of course, my example is a legit usage of affectation in condition. But, the usual confusion of « = » instead of « == » is one of the most common error in C, and probably one of the most perverse bug.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This warning is probably far better than putting left-value on the right hand-side, which only work if one of the operands is not a left-value (hey, you never compare two variables ?)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As the message said, you just have to put extra parentheses to avoid the warning, like that:</div>
<div style="text-align: justify;">
</div>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">while ( (i = read(fd, buf + off, SIZE - off)) )
off += i;
</pre>
<div>
<br /></div>
<div style="text-align: justify;">
Even if this example may seems <i>naive</i>, it reflects the way you should use your C compiler: activate all warnings and alter your code so legit use won't trigger any messages, rather than shut the screaming off !</div>
<div style="text-align: justify;">
<br />
Oh, and if you want <b>good</b> warnings and error messages, I strongly recommend the use the clang compiler (based on llvm), it gives the best error messages I've seen so far.<br />
<br />
And, for my pleasure, here is another classical example of test and affect combined in a <i>if-statement</i>:<br />
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">int fd;
if ( (fd = open("some_file",O_RDONLY)) == -1)
{
perror("my apps (openning some_file)");
exit(3);
}
/* continue using fd */
</pre>
<br /></div>
<h2>
Identify elements syntactically</h2>
<br />
<div style="text-align: justify;">
Have you ever mask an enum with a variable ? Or, fight with an error for hours just because a variable, a structure field or a function was replaced by a macro ? In C, identifiers are not syntactically separated, so you can do horror like that:</div>
</div>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">enum e_example { A, B };
enum e_example f(void)
{
enum e_example x;
float A = 42.0;
x = A;
return x;
}
int main()
{
printf("> %d\n", f());
return 0;
}
</pre>
<br />
<div style="text-align: justify;">
What does this code print ? <b>42</b> of course ! Why ? Simply because the float variable <tt>A</tt> mask the enum constant <tt>A</tt>. The ugly part is that your compiler won't warn you and won't complain.<br />
<br />
So, there's no solution on the compiler side, we have to protect ourselves from that kind of errors. A usual solution is to adopt syntactical convention: each kind of symbol have its own <i>marker</i>, for example you can write enum constant like <tt>A_E</tt> or, in order to have different names for each enum definition, you can prefix your constant with the name of the type.<br />
<br />
Basically, you should have a dedicated syntax for type name, macro constants, enum member or any other ambiguous identifiers. Thus, my previous enum should be written:</div>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">enum e_example { A_E, B_E }; /* using _E as enum prefix for example */
</pre>
<br />
<div>
Just keep in mind that identifier's size should be kept relatively small in order to preserve readability and avoid typing annoyance (you won't enjoy typing <tt>e_example_A</tt> more than once.)<br />
<br />
<h2>
Understanding Sequence Points</h2>
<br />
There's a notion of <i>sequence points</i> in the language: any code between two sequence points can be evaluated in any order, the only things you know is that all side-effects syntactically before a sequence point take place before going further and no side-effect syntactically after the sequence point will begin before the sequence point.<br />
<br />
So, this notion obviously forbid ambiguous code like <tt>i++ * i++</tt> or <tt>i = i++</tt>. In fact this code is not strictly forbidden (sometimes the compiler may issue a warning, but that's all), it belongs to the infamous category of <i>undefined behavior</i> and you don't want to use it.<br />
<br />
But that's not all. What you should understand and enforce is that no more than one modification to the same location should occur between two sequence points, but also whenever a memory location is modified between two points, the only legit access should be in the scope of the modification (<i>i.e.</i> you're fetching the value to compute the new value.<br />
<br />
So, you should not write something like: <tt>t[i] = i++</tt>, but you can write (of course) <tt>i = i + 1</tt>.<br />
<br />
Now, what constructions mark those sequence points ?<br />
<ul>
<li>Full expressions (an expression that is not a sub-expression of another)</li>
<li>Sequential operators: <tt>||</tt>, <tt>&&</tt> and <tt>,</tt></li>
<li>Function call (all elements necessary for the call, like parameters, will be computed before the call itself.)</li>
</ul>
<div>
That's all, meaning that in the expression: <tt>f() + g()</tt> you don't know if <tt>f()</tt> will be called before <tt>g()</tt> !<br />
<br />
Here are my personal rules to avoid those ambiguous cases:<br />
<br />
<ul>
<li>Prefer pure functions in expressions</li>
<li>Keep track of global states modified by your functions so you can establish which function can't be used in the same sub-expression</li>
<li>Each function should have a bounded scope: a function must do one things and if it you can't avoid global side effects, it must be limited to one or two global states per function.</li>
<li>Prefer local static states rather than global states so you can bound modification through the use of one function.</li>
<li>Prefer pointer above implicit references for function (C++)</li>
</ul>
<div>
The last point may disturb you, implicit references (in the sens of C++ or Pascal) are used, in both call-site and body of the function, like non reference arguments, hiding the persistence of the modification. This pose no threat where it used with intended modification, but inside expression this can lead to that kind of bug you fight against for hours. Using an explicit pointer requires a reference operator indicating the possible modification.<br />
<br />
<h2>
Functions' prototype have to be explicit</h2>
</div>
</div>
<div>
In C, pointers are used for a lot of things: array, mutable arguments, data-structures …<br />
<br />
So you can pass a pointer to a function for a lot of reason and it could be interesting to find a way to differentiate the various usage of pointer as parameter.<br />
<br />
I'll give you a quick overview of my coding style:<br />
<ul>
<li>Pointer as array: when the pointer parameter is in fact an array, I <b>always </b>use the empty bracket rather than the start, for example: </li>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">float vect_sum(float tab[], size_t len)
{
float res = 0;
float *end = tab + len;
for (; tab != end; ++tab)
res += *tab;
return res;
}
</pre>
<br />
<li>Pointer as reference (mutable argument): when passing a pointer to a variable in order to keep modification of the value of the variable in calling context, I explicitly use a star:</li>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">void swap(int *a, int *b)
{
int c;
c = *a;
*a = *b;
*b = c;
}
</pre>
<br />
<li>Data structure: most (all) linked data structures (list, tree … ) have a pointer as entry point. In fact, the structure is the pointer (for example the linked list is the pointer not the structure.) So, I hide the pointer in the <tt>typedef</tt> rather than let it be visible:</li>
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">typedef struct s_list *list;
struct s_list
{
list next;
int content;
};
size_t list_len(list l)
{
size_t r = 0;
for (; l; l = l->next)
++r;
return r;
}</pre>
<br />
</ul>
The last point is often disturbing for student and it need some explanation. First, consider the logic of a linked list: a list is recursively define as an empty list or a pair of an element and a list. Thus, the <tt>NULL</tt> pointer representing the empty list is a list, meaning that the <b>list is the pointer</b> not the structure (a pair can be viewed as a structure or a pointer to a structure, to be coherent we must choose the later definition.)<br />
<b>So, you're list is a pointer and thus the type <tt>list</tt> must reflect this fact.</b><br />
This is where comes the usual argument: « <i>but, if the pointer is not obvious in the prototype how do I know that I must use an arrow rather than a dot to access the structure member ? </i>» There's two answers to this question:<br />
<ul>
<li>First, when dealing with the code manipulating the list <i>you know what you're doing</i>, so there's no question !</li>
<li>You must be coherent, if you include the star in the <tt>typedef</tt>, you won't do a <tt>typedef</tt> on a <tt>struct</tt>. You don't flag the case where you should use an arrow but when you should use a dot !</li>
</ul>
Combining the rule for pointer as reference and pointer as data structure, you'll have a coherent strategy to define functions that modify the content of the data structure and functions that modify the structure itself (specially when modifying the entry point.) The following example show a <i>functional</i> add (adding an element at the head of a linked list without modifying the given pointer) and a procedural add (adding again at the head but modifying the given pointer.)<br />
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">/* we're using the previous list definition */
list fun_add(list l, int x)
{
list t;
t = malloc(sizeof (struct s_list));
t->content = x;
t->next = l;
return t;
}
/* note that l is passed as a pointer to a list, not a list */
void proc_add(list *l, int x)
{
list t;
t = malloc(sizeof (struct s_list));
t->content = x;
t->next = *l;
*l = t;
}
</pre>
<br />
The star in the second version indicate that the function may modify the head of the list (in fact, it will.)<br />
<br />
Forbidding <tt>typedef</tt> of structure has an other positive aspect: when passing a structure to a function (or when returning it), the structure is copied (and thus duplicated) inducing a (small) overhead at the function call (or function return) and bigger memory usage. Hiding the fact that the value is a structure induces what I call hidden complexity: what look like a simple operation has in fact a non-negligible cost. Thus, once again, the good strategy is to let the fact that the value is a structure visible.<br />
<br />
The special case of <i>strings</i>: in C, strings have no specific type, you use pointer to characters. Normally, you can view a string as an array of characters, but the usual convention is to describe strings as <tt>char*</tt> rather than <tt>char[]</tt>, so strings are the only case where I use the star rather than the bracket syntax. It solves also the issue of arrays of strings, you can't use <tt>char[][]</tt> (this a two dimensional array, but since the compiler need the size of <i>line</i> to correctly translate indexes, you can't write such a type) the solution is to mix star and bracket, as in the following example:<br />
<br />
<pre style="background-color: #f0f0ff; border: 1px dashed; padding: 3px;">/* argv is an array of strings */
int main(int argc, char *argv[])
{
/ ..
return 0;
}
</pre>
<br />
<h2>
Conclusion</h2>
I hope these <i>tricks</i> where useful or interesting to you. As I say in opening, programming in C requires careful concentration and a bit of understanding the underlying semantics of the language.<br />
<br />
These <i>tricks</i> are not magical receipts, if you want to be a C programmer, you'll need practice. The first rule of a programmer should be: Code and when you think you have code enough, then code again !<br />
<br />
By coding I mean: try out ideas, implement toys, compare behaviors of various implementation of the same idea, take a look at the generated ASM code (yes, you should do that … ) And <b>don't be afraid of pointers</b>, pointers are you friends, you need them, they are always useful in a lot of situation, but you got to be nice with them and treat them properly (or you'll pay !)<br />
<br />
As a second rule, I'll propose: <i>find a convenient coding style !</i> Coding style are often useful to avoid misuse of data structures or ambiguous situation (such as the examples on enum), but when building a coding style, don't focus on code presentation, organization, comments nor forbidden features. The most important part of a coding style is the naming convention and a coherent way of describing function prototypes.</div>
</div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-89928364212371635422012-05-09T15:51:00.004+02:002012-05-09T15:51:44.594+02:00C! Programming Language - LSE blog articlesI wrote a new article presenting the C! programming language.<br />
<br />
<a href="http://blog.lse.epita.fr/articles/12-c---system-oriented-programming.html" target="_blank">C! on LSE's blog</a><br />
<br />
<div style="text-align: justify;">
C! is a system oriented programming language. Started as a simple revisited syntax for C, it now offers simple objects and similar features.</div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-22685147527687064472011-08-30T17:40:00.000+02:002011-08-30T17:40:43.941+02:00Language design<div style="text-align: justify;">Programming languages are our principal tools, the things with work with every day. Most programmers (real ones) have a particular relation to their favorite language, but, they're also very curious about new languages, new paradigms (or at least paradigms, they haven't test so far), new concepts …</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">This is probably the reason why it is so hard too have clear answers from programmers to questions like “what is the best programming language ?” or “what is the worst programming language ?”</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">So, I'll try to make a small survey of ideas on language design that I found most useful when trying to classify languages. I'll also add my personal visions on what is a good language.</div><div style="text-align: justify;"><br />
</div><blockquote><b>Semantics ?</b></blockquote><div style="text-align: justify;">Lot of people began classification of programming languages using execution model (compiled or not) or paradigm (functional, object oriented, declarative, procedural … ) This is probably a good idea, but I won't do it that way.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">From my own point of view there are two major groups of programming languages: those with practical approach and those with theoretic foundations. This is how I understand the evolution of programming languages.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">The practical way follow the history of computer evolution: early computers have a minimal interface (switches, punched cards … ) and programmers where using direct machine code. As computers were able to treat bigger programs, programmers start to use assemblers that transforms an “almost” human-readable source code into binary machine code. And the evolution continue in the direction of more abstractions: conditional jump were replaced by <i>if-then-else</i> constructions, <i>while</i> and <i>for</i> loops simplified basic algorithms and so on. This where the birth of structured programming. The basis of this evolution is to abstract recurring coding constructions using a simpler syntax. Starting from machine code, the practical way has reached structured and object oriented programming paradigms.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">On the other side, the theoretical way, take birth in mathematical models for computing like lambda-calculus. This branch of language evolution take a completely different direction: we start with an abstract concept, often with a very formal definitions, and try to build a concrete programming language. The evolution is now reverted, since the goal is to found lower level translation of abstract syntax, rather than building new syntax for known constructions.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Both evolution produce a lot languages like Cobol, Fortran or C/C++ for the practical way and Lisp, Scheme, Prolog or ML family for the theoretical way. The interesting fact is that the two ways are converging ! Practical languages tends to introduce concepts with theoretical foundations (like in Java or C#) and theoretical languages are more and more able to produce efficient concrete machine code.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">So, why starting a classification like this ? Just because the way a language was built has a great impact on how the language can be used.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Languages with well founded semantics are good in implementing clever algorithms and theoretical data manipulation (symbolic processing, compiler, code analysis tools … ) On the other hand, more practical languages (like C) are more suited for system programming and any other activities involving lower level manipulations.</div><blockquote><b>Dynamic or Static ?</b></blockquote><div style="text-align: justify;">An other important discriminating criterion is the nature of the language execution model. Rather than talking about compilation versus interpretation (or virtual machine, JIT … ) I prefer to push the distinction in the field of dynamic versus static languages (there are compilers for dynamic languages and interpreter for static ones.)</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Again, using one kind or the other is a matter of goals. Dynamic languages are often considered as toys or scripting languages, but this is too restrictive since modern languages (such as Perl, Python or Ruby) are probably as good as other languages for writing applications.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">In fact, this is more a matter of program design and software conception. Dynamic programming tends to encourage programming by accretion: you build a small kernel of functionality, and then make it grows. The dynamic nature of such languages, let you modify or add behavior to existing code without complete rewriting.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">On the other hand, when you need (or you already have) a well established design, static languages are more suited: they enforced your design choices by making them mandatory. The usual benefits are faster error detection and probably better performances.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">So, to summarized, dynamic languages are more suited for prototyping or <i>unguided</i> programming (you know, when you code, but don't really know where're you going … ), while static languages offer better context for bigger projects involving more conceptions. But, in my opinion, this is more <b>a matter of taste !</b></div><blockquote><b>Hidden Complexity</b></blockquote><div style="text-align: justify;">Now, we are on the dangerous field of what is good and bad in programming language. <i>Hidden complexity</i> is about language's simple constructions that involved heavy computation.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">We can find a good example in OCaml's operators on lists. You have two operators that are often seen as similar: <tt>::</tt> and <tt>@</tt>. The first one is a constructor for the list type while the second one is in fact a shorthand for a function on two lists (append.) So, the issue is that the former operator looks like a simple inexpensive operation, while it can induce very high complexity cost like in the following example:</div><br />
<pre>let rec rev = function
| [] -> []
| h::t -> (rev t) @ [h]
</pre><br />
<div style="text-align: justify;">This function has a quadratic complexity (<i>O(n²)</i>) due to the append operator while this is not evident (if you don't count the cost of the append, this function has a linear complexity.)<br />
<br />
Most of the time, hidden complexity appears in <i>magic operators</i>, the kind of operators that seems to solve a lot of issues.<br />
<br />
A very common source of hidden complexity is operator overloading and implicit operations. C++ is full of this kind of traps: when objects are passed by copy (that is, the default way of passing objects to a function) a special constructor is invoked, which is a simple memory copy unless someone has redefined it (“<i>Hey ! Who add an Ackerman function to the copy-constructor of this object !”</i>)</div><blockquote><b>Keywords or symbols ?</b></blockquote><div style="text-align: justify;">Again, a matter of taste: language's syntax can be keyword oriented (Pascal) or symbol oriented (C++.)<br />
<br />
For example, a Pascal's function will look like this:<br />
<br />
</div><pre>PROCEDURE swap(VAR a: integer, VAR b: integer)
VAR
c : integer;
BEGIN
c := a;
a := b;
b:= c;
END</pre><br />
<div style="text-align: justify;">While in C++ we would have something like:</div><br />
<pre>void swap(int &a, int &b)
{
int c;
c = a;
a = b;
b = c;
}
</pre><br />
<div style="text-align: justify;">The C/C++ syntax relies more on symbol than keywords ({…} against begin … end for example.) What is best ? I tend to prefer the symbol way rather than the keyword one, but its a matter of taste. Of course, it's also a matter of balance, you probably can find some purely symbolic languages and you'll probably find it too criptic (have you ever opened a sendmail.cf file ?)<br />
<br />
In fact, it doesn't need to be purely symbolic to be cryptic, C++ syntax is a good example, an average C++ piece of code is full of <i>symbolic details </i>which probably can't be understand with <i>fast-reading</i> since details can change semantics (and I don't speak about operators overloading … )<br />
<br />
Here are my own rules about syntax:<br />
<ol><li>one meaning for one symbol</li>
<li>symbol should only be used for immediate operations (no hidden complexity)</li>
<li>uncommon operations deserve keywords rather than symbol</li>
<li>default behavior and usual operations should have the simplest syntax (or no specific syntax at all)</li>
</ol><div>In my opinion, the C (not C++) syntax can be considered as a good example of a language well balanced between symbols and keywords while C++ is seminal example of all possible mistakes in language design (at least about syntax.) The Pascal syntax tends to be a little bit verbose and have a pedantic back-taste (this is that kind of languages that prefer to say <tt>integer</tt> rather than <tt>int</tt> to be sure you understand them well, in case you've missed some point, you they are <em>teaching languages</em>.)<br />
<blockquote><b>Humorous classification</b></blockquote>As a so called conclusion, here is a draft for a programming languages classification:<br />
<ul><li><b><i>Rudimentary </i>languages</b>: they're here for decades, they're probably older than you, and you don't want to use them but some times you can't avoid them (BASIC, COBOL … )</li>
<li><b><i>Sedimentary </i>languages</b>: built using a geological process of accretion, they were designed as stack of concepts in hope every cases where covered … (C++ … )</li>
<li><b><i>Alimentary </i>languages</b>: you learn them and use them because programming is a job, job brings you money and money buys you food. You probably don't like them but in fact, you don't like what you're doing with them (maybe you don't like programming at all) (Java, C#, VB, Php … )</li>
<li><b><tt>|-|4><0r</tt> languages</b>: you need to be <tt>l33t</tt> to understand them … (Brainfuck, whitespace … )</li>
<li><b><i>Will-be-dead-next-years-for-decades</i> languages</b>: we all agree, these languages are alive abominations escaped from Jurassic ages, but they're still there and used ! (COBOL, FORTRAN … )</li>
<li><b><i>Teaching</i> languages</b>: sometimes, you feel like if the compiler stares at you with a cold and calm face and a wooden stick in its hand while the rest of the class is holding its breath. When such time comes, you know that you, naughty boy, haven't declared your thrown exceptions, or have used a deprecated method … (Pascal, Java … )</li>
<li><b><i>We've-got-anything-you-want </i>languages</b>: have you ever dream of a procedural structured functional language with object oriented extensions, concurrent programming primitives, embedded assembly, static validation and dynamic assertion testing ? Ada is there for you …</li>
<li>…</li>
</ul><div><br />
</div></div></div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-31916523206417310332011-07-30T21:36:00.002+02:002011-07-30T23:05:55.704+02:00Rule 0 - Do It !<div style="text-align: justify;">So, I've already listed some rules about programming (do I need to recall you that the most important one is <i>don't trust the maxims</i>) but I recently come up with a new one, some kind of rule 0, the rule above the rules. So, the rule is pretty simple:</div><blockquote><div style="text-align: justify;"><b>Do It !</b></div></blockquote><div style="text-align: justify;">Simple isn't it ?</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">So what do I mean by <i>Do It</i> ? There are several topic where this rule can apply, I'll cover what seems to be the most important to me: programming learning, fixing bugs and rewriting/refactoring.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>For the beginner:</b></div><div style="text-align: justify;">Learning programming (or even learning a new programming language) can be separate in two parts: theoretical principles, syntax and structure studying and practicing.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Many beginner falls into the <i>over-studying</i> symptom: they spent a lot of time trying to understand inner concepts and to recall every specific syntax construction before practicing. But when it comes to code, they just do the same mistakes and face the same issues as if they haven't spend a lot of time to understand how it works.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Why ? Just think of it: if I explain to you how it is to ride a bicycle, I can explain you a lot of things, even show various videos and schema, but until you get yourself on a real bike and fall face to the ground, you won't be able to ride it.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Programming is no exception. You need to practice in order to learn. A damn good example are pointers. Pointers are a mandatory concept in many languages and probably in many traditional algorithms, so a programmer can not avoid pointers manipulations. When facing it for the first time, they appears as strange entities with complex usage and semantics: they are value by them selves but they also seems to be containers, you can obtain a pointer from various operations (referencing a variable, allocating memory … ) All of this with various syntax a special cases (the worst of all is to begin to learn pointers with different languages using different syntax, say Pascal and C … )</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">The fact is simply that, you need to practice to learn. I've test a lot of way to explain pointers concepts to various students and never find a better way than practicing. The usual box and arrow diagram always lake important point. Explaining the idea of pointer as array indices for the big array that is memory won' help more. But a bunch of pointer and pointer's arithmetic exercises will always do the job.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Practicing break out another beginner's symptom: the fear of the difficulty. When facing a new kind of problems, measuring the real difficulty of solving it is quite hard. Trying to solve it in your head or with some useless schema on a sheet of paper won't help you, you should give it a try. A good example is writing a memory allocator (a pretty good exercise to understand pointers and memory management), if you had never try it before, you can't figure out how one should do it. But, as you begin to code, you'll find that there's no mystery nor magic and (if you stay on the simple path, of course, good generic and efficient allocators are not so simple) you'll see that the task is really affordable.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">So, to summarize: don't waste your time over-thinking your code, just code, <b>do it !</b></div><div style="text-align: justify;"><b><br />
</b></div><div style="text-align: justify;"><b>Bug fixing:</b></div><div style="text-align: justify;">When building a projects there's always two possible tasks: continue to the next missing features and fix the existing ones. So should I prefer push the project to the some fixed bounds (achieving a functionality goal) or should I fix issues in what was already written.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">My advice is to never postpone bug fix, even if it's a minor one. Bugs, incomplete cases and things like that are bombs awaiting to blow you all works down. There are several reason not to postpone corrections:</div><div style="text-align: justify;"><br />
</div><ol><li style="text-align: justify;">It's simpler to fix something when the code is still fresh in your head</li>
<li style="text-align: justify;">The bug fix may induce deeper modifications than it seems</li>
<li style="text-align: justify;">Building a new part of a project on rotten bases will always end up in a big crash</li>
</ol><div><div style="text-align: justify;">You can extend this idea to <i>real bug fixes</i>: that is, you should not let ugly workaround sit in your base code. Workaround are far pernicious than bug in the sense that they hide the error without (most of the time) really fixing it.</div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;"><b>Rewriting/Refactoring:</b></div></div><div><div style="text-align: justify;">To illustrate this part I'll give a personal example: I'm actually working on an experimental language (mostly like a C variant but with a cleaner syntax and some syntactic sugar), the project began when it appears that we can't escape the use of the C language for writing kernels. We give a try to a lot of languages and face up various issues, mainly because <i>modern</i> languages are oriented toward userland programming, not kernel programming. After a long and trollish discussion on our mailing list, I came up with idea of rewriting the C syntax and extend it with various <i>comfort</i> syntactic sugar and high levels extensions.</div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;">So, I lay down a quick version of an AST (Abstract Syntax Tree) for a kind of C language, write up a pretty printer for it and then a parser. When it was clear that the idea works (and facing enthusiastic messages on the list), I go the next step and write down type checking. At that point, the original AST was not completely suited in the sense that it was an immutable value (I was using OCaml for the project) but I found a way to circumvent the difficulties and continue along this axis.</div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;">We then begin to write code generation (thanks to the fact that we were writing a compiler-to-compiler rather than a real compiler this wasn't so hard in the first place.) But as the project evolves, my badly designed AST give us more and more difficulties. And then, one day (after almost a year of code), it appears to me that if we want to push the project to its end, I must change my data structure. So, how to do it ? the task seems unaffordable since the AST was the skeleton of the project.</div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;">I take out my favorite text editor, allow myself five minutes of reflexion, and decide that if I can't rewrite parsing and typing within a few days, I'll give up and try to fix the original code. Guess what ? A week later, 90% of the project was rewritten and some parts was even more advanced than in the original version ! Of course, the first two days was a total rush, I came up writing 5000 lines of code in 48 hours ! But, thanks to the new design and to experiences gathered on the previous work, most of the task was straightforward.</div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;">Two weeks later (yes, this a really recent story ;), our compiler is now more functional than the previous version !</div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;">What did I learn ? First that I'm still capable of writing very big amount of code in few days (this good for my self esteem ;) Second, that rewriting is far simpler than it may seems at first glance. There are several reason you should give a try to rewriting:</div></div><div><ol><li style="text-align: justify;">Previous work wasn't a waste of time, it points you out where difficulties are</li>
<li style="text-align: justify;">A better design and data structure will greatly simplify the rest of the code</li>
<li style="text-align: justify;">If you fail, you can still go back to the previous work</li>
<li style="text-align: justify;">There's always be external part that can be reused</li>
<li style="text-align: justify;">If you feel the need to do it, things gonna be worst if you postpone it !</li>
</ol><div><div style="text-align: justify;">Of course, rewriting is not always the only solution: this example is quite extreme in a sense that the whole project was based on the part that I want to change, and many things inside the project was to be rewritten.</div></div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;">Refactoring is, most of the time, a better way to fix bad design. The main idea is to rewrite your code chunks by chunks but still preserving the state of the project. There's a lot of patterns to do that (you can find good books on the subject, Marc Espie, which is a person I consider as a real expert programmer, pointed me out with the book: "Refactoring" by Martin Fowler, you should probably read it, I will as soon as I find times for it.) </div></div><div><div style="text-align: justify;"><br />
</div></div><div><div style="text-align: justify;"><b>Conclusion:</b></div></div><div><div style="text-align: justify;">So, my new rule, <i style="font-weight: bold;">Do It !</i>, is all about going straight to the point rather than wasting your time in useless preparation or postponing important fix or rewrite. There's no better way to do something than actually doing it !</div></div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-34244679828538666602011-07-09T21:39:00.000+02:002011-07-09T21:39:57.312+02:00Functional Programming ?<div style="text-align: justify;"><b>Do you know functional programming ?</b></div><br />
<div style="text-align: justify;">Functional programming (FP) is an interesting subject for a lot of reasons. Those of us that have used (and still used) functional programming languages (FPL) often pointed out two disappointing facts:</div><div style="text-align: justify;"><br />
</div><ol><li style="text-align: justify;">Lots of programmers doesn't really understand what is it</li>
<li style="text-align: justify;">Despite the fact that FP and FPL are pleasant to use but also quite efficient, it is still not largely used</li>
</ol><br />
<div style="text-align: justify;"><b>Am I a FP fan ?</b> the quick answer is "no more", the longest one is more complicated. I have used OCaml for now more than 10 years, I've found it very useful and pleasant many time. But, I've also found a lot of unsatisfactory points. It is hard to really explain why, but on bigger project, the absence of constraints on global program structure often leads to unreadable code, some syntax choices are annoying ... Other FPL haven't convince me yet ...</div><br />
<div><div style="text-align: justify;">So, here are my <i>humble opinion</i> (how I hate this expression ... )</div><div style="text-align: justify;"><br />
</div></div><br />
<div><div style="text-align: justify;">First, I'll attempt to define FP and what should be an FPL. <b>You should right now forget the erroneous idea that FP is about recursion and recursive functions !</b></div></div><div style="text-align: justify;"><div style="text-align: justify;">FP arise from early days of formal languages (before computers in fact), exactly λ-calculus is (at least for me) the starting point of FP. So what is the main characteristic of λ-calculus ? Function as first class value ! In fact, functions are the only value in λ-calculus !</div></div><div><div style="text-align: justify;">First class value are language entities that can be passed (and returned) to (by) functions. So, λ-calculus can directly manipulate functions, this is what we call higher-order. So, the first requirement of a FPL is higher-order.</div><div style="text-align: justify;"><br />
</div></div><div style="text-align: justify;"><div style="text-align: justify;">λ-calculus, being a mathematical model, have no notion of mutable entities and side effects (in fact mutable and side effects can be expressed in pure functional semantics.) Thus, languages inspired by λ-calculus try to avoid these notions to match the original model, but it's a matter of style. </div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">Another aspect of FP and FPL is the notion of <i>everything evaluate to a value</i>: we should always return something and there's no difference between statement and expression as in imperative languages. This is strongly linked with the absence of side-effect: you don't modify a state, you return a new value.</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>What about loops in FP ?</b> The fact that in FP we prefer recursion over loops, is a consequences of the <i>everything is an expression</i>: a loop does not return a value. But, FOR-loops (<i>i.e.</i> bounded iterations) can exist without mutable entities and thus fit in the model (we can somehow handle the <i>loop returns nothing</i>, since in FPL nothing can be <i>something</i>) on the other hand, integrating WHILE-loops in the semantics of a pure FPL is far more difficult (we need to express a changing state.)</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;">So, to summarize: an FPL is language with higher-order where everything is expression and where we prefer to limit mutable entities and side-effect. Everything else is comes from those facts (partial evaluation and curryfied functions, recursion rather than loop and even lazy evaluation.)</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Is there good FPL ?</b> This is hard and dangerous question. I tend to prefer strongly typed FPL, and thus my list of good FPL will be limited to the ML family (and derived languages.) My favorite is OCaml for various reason: I learnt FP with it, it is not too purist (in OCaml you have imperative aspects and even objects), it has a good module approach (functors ... ) and resulting code works well. I found Haskell interesting but too extremist to my taste. Lisp and scheme derivatives haven't convince me (but again, I prefer typed languages ... )</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><br />
</div><div style="text-align: justify;"><b>Interesting FPL features</b>: except for pure FP aspects, many FPL have interesting features.:</div><br />
<ul><li><i>Pattern Matching</i>: this probably the most impressive features, it lets you describe complex cases and extract values. Combined with variants, it offers the best way to traverse abstract syntax trees.</li>
<li><i>Module systems</i>: to organize your code, module are very useful and some FPL provides very powerful framework. For example, the module system of OCaml lets you define nested modules, independant module interfaces and the powerful functors (function over modules.)</li>
<li><i>Lazy evaluation</i>: lazy values is mix between functions and expressions, as functions it is not evaluated when defined, but as expressions, it is evaluated only once. This lets you define expressions that will be evaluated only when needed but then resulting value is <i>memoized</i>. A good<br />
example is infinite generated lists: elements of the lists are generated only when traversed, but then you don't need to compute it for each access.</li>
</ul><br />
<div>Now, how about the lack of users of FPL ? Since, I'm myself a disappointed user of FPL, I can understand the relatively low audience of FPL.</div><br />
<div>First of all, most FPL are research projects and as such are never quite yet <i>finished</i>: the language changes too often, priority is put on new features rather than production necessity ... Thus, it is hard to develop a long and stable project using an FPL.</div><div>On the side of the languages them selves, there are also some disturbing points. Even compiled FPL have an original syntax designed for interpretors, thus program written with those syntax are often badly organized. For example, there's no explicit entry point in OCaml, you must carefully organize your code so that the execution flow go directly where you want.</div><br />
<div>From a syntaxic point of view, language history has shown that language with explicitly delimited blocks and instructions have a better impact than too permissive one. Most FPL are syntactically permissive languages.</div><br />
<div>So, I think that despite being very interesting programming languages, FPL are not a good choice for practical reason. These reasons are not tied to the FP model but to the implementations of this model. If we want to see FPL regarded as usable as other main languages some day, we need a more stable language with something like a C syntax.</div><br />
</div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com1tag:blogger.com,1999:blog-7555671657887635887.post-48654846482483266782011-06-26T01:44:00.003+02:002011-07-09T20:03:00.059+02:00Marwan's Programming Guiding RulesOk, now that I have expose my view on maxims, I can write my own ! (but remember, don't trust the maxims !)<br />
<br />
I'll start with pure coding guidelines (and keep the rest for later.)<br />
<br />
<blockquote><b>copy/paste are evil !</b></blockquote><br />
<div>(with its corollary: <b>copying code implies copying bugs</b>)</div><div><br />
</div><div>This one is classic (at least for my students): whenever you want to copy/paste some code, you should reorganize it. Most of the time, a function (or something similar) will be useful later, and even if there'll be only one copy, you will probably find a better way to write it.</div><div><br />
</div><div>Just take some examples: here it is two function on linked list, a simple first place add and a sorted insertion, with copy/paste:</div><div><br />
<pre>typedef struct s_list *t_list;
struct s_list
{
t_list next;
int data;
};
t_list add(int x, t_list l)
{
t_list t;
t = malloc(sizeof (struct s_list));
t->data = x;
t->next = l;
return t;
}
void insert(int x, t_list *l)
{
if (*l == NULL || x < (*l)->data)
{
t_list t = malloc(sizeof (s_list));
t->data = x;
t->next = *l;
*l = t;
}
else
insert(x, &((*l)->next));
}
</pre><br />
<div>Now, the version of <tt>insert</tt> without copy/paste:</div><br />
<pre>void insert(int x, t_list *l)
{
if (*l == NULL || x < (*l)->data)
*l = add(x,*l);
else
insert(x, &((*l)->next));
}
</pre><div>First, the later version is shorter. But that's not all, in the second version, the reference to the size of the struct is done in one place. If you finally want to use a specific allocator (such as a recycling pool) you have one change to make, not two nor more.</div><br />
<div>Another toy example, with "one copy" (no need to write a function), we implement FIFO queue using circular list (this is only the push operation):</div><br />
<pre>// with copy/paste
void push(int x, t_list *q)
{
t_list t;
if (*q)
{
t = malloc(sizeof (struct s_list));
t->data = x;
t->next = (*q)->next;
(*q)->next = t;
*q = t;
}
else
{
t = malloc(sizeof (struct s_list));
t->data = x;
t->next = t;
*q = t;
}
}
//without
void push(int x, t_list *q)
{
t_list t;
t = malloc(sizeof (struct s_list));
t->data = x;
if (*q)
{
t->next = (*q)->next;
(*q)->next = t;
}
else
t->next = t;
*q = t;
}
</pre><br />
<div>Again, the code is smaller and simpler to verify. Those two example are very basic, and most programmer will probably use the second form intuitively, but in more complex situation, taking as guideline to avoid copy/paste may save you from long nightmarish bug hunt.</div><br />
<blockquote><b>Any programming features is good as long as it fit your need.</b></blockquote><div>There's no reason to not use a feature in your programming language as long as you understand it and it do the job. If it's possible, it means that somehow, it was meant by the language designers for a good reason (or, else, they should have find a way to forbid it.)</div><br />
<div>When teaching programming, I often heard students arguing about bad practices, rules they have read on the net that they don't really understand. Most of the time, theses rules only take sense in a precise context or express a taste rather than a reasonable motivation.</div><br />
<div>The main goal of programmer is to make its code works, it's not to produce shinny piece of code or perfect models of how to code. This lead us to my next rule:</div><br />
<blockquote><b>The end justifies the means.</b></blockquote><div>To understand this one, we must define the <i>end</i> and the <i>means</i>. The <i>end</i> is your goal, what my program should do. But it's also all the requirements linked to it: should it be fast ? should it be robust and reliable ? what will be its life cycle (one shot or high availability permanent run) ? would it be extended ? ...</div><br />
<div>The means deal with how you will produce it and it's strongly connected to the end: don't spend to much time on code for a one shot script, make it works, on the other hand remove all quick and dirty implementation from a production release !</div><br />
<div>Building a program is most of the time some parts of professional work you're paid for. So, this is not a challenge of best programming practices, there's no jury's prices for nice attempt: you have to make it works the way your future users expected it to work. If they ask for simple script that will save them hours of boring manipulation, they don't want months until you find it finally presentable, the want it now !</div><br />
<div>The important point is to define the correct goals, and make the right efforts to achieve these goals.</div><br />
<div>This also means that any tricks are fine as long as it makes your code works. Again, students some times seems disappointed by some hacks they found in some piece of code. They saw it as <i>cheating</i> as if finding a way to get around some difficulties is not elegant and should not be tolerated !</div><br />
<div>Coding is no game, you can have fun doing it, but there's no place for ridiculous honor code. You will find that the satisfying users' expectations will probably force you to produce code as clean as it can be and that you won't need arbitrary rules to guide you.</div><br />
<div>Take for example the use of goto and the particular cases of goto into the body of loop: goto is generally considered evil and goto inside a loop is the probably the most heretic things you can do. But, there are some cases where this can be useful. The best known example is the Duff Device example of smart loop unwinding, take a look at it, it's worth the read. I will use a simpler example, not focus on optimization, that I found more striking.</div><br />
<div>The idea is simple, you have a list or an array and want to print each element separated by a ';', by separated we really mean that the separator is between each element and not after, thus the last element will not be followed by a ';'. There are several ways to do that, let's take a first example:</div><br />
<pre>void printArray(int tab[], size_t count)
{
size_t i;
size_t i;
for (i=0; i < count; ++i)
{
if (i > 0) // not the first time
printf(";");
printf("%d",tab[i]);
}
}
</pre><div>Ok, this is not the best version you can write, but it focus on the fact that the first case is handle separately. We can have done like that also:</div><br />
<pre>void printArray(int tab[], size_t count)
{
if (count)
{
size_t i;
printf("%d",tab[0]);
for (i=1; i < count; ++i)
printf(";%d",tab[i]);
}
}
</pre><br />
<div>In this version, the treatment of the first case is less obvious and we need to check the count. Now, take a look at this one:</div><br />
<pre>void printArray(int tab[], size_t count)
{
if (count)
{
size_t i=0;
goto start;
for (; i < count; ++i)
{
printf(";");
start:
printf("%i",tab[i]);
}
}
}
</pre><br />
<div>We use a goto to skip the first printf in the loop. The result is better than the first version and it let appears the specificity of the first case. Of course, this is a toy example, and the goto version is not dramatically better in any way, but it illustrate the fact that dirty code can be useful and readable.</div><br />
<blockquote><b>Keep it simple, stupid !</b></blockquote>One of the classic ! Prefer the simplest path. When you can't figure out yourself how your code work, it means that it's too complex and will probably won't work. Here are some other maxims and quote on the subjects:<br />
<br />
<blockquote><i>"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it ?"</i> (Brian Kernighan, "The Elements of Programming Style", 2nd edition, chapter 2)</blockquote><blockquote>Smarter code means smarter bugs ! (me ;)</blockquote><blockquote><i>"There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies."</i> (C.A.R. Hoare)</blockquote>So, all those rules deal finally with the same issues: <b>making your programs work ! </b>That's the only things that really matter in programming.</div>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-85517959582226950122011-06-19T01:55:00.001+02:002011-06-19T01:57:58.175+02:00Reading ...In the previous entry, I quoted Rob Pike's Notes on Programming in C.<br />
<br />
This leads me to re-read it. This is a damn good paper, it is worth reading it, not too long and very interesting. I found that Rob Pike and I have quite the same ideas most discussed matter in his paper.<br />
<br />
Maybe, I'm not so dumb ;)<br />
<br />
SO, if you haven't read it before, read it: <a href="http://www.lysator.liu.se/c/pikestyle.html">Rob Pike: Notes on Programming in C</a>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-9364538217088651952011-06-19T01:08:00.001+02:002011-06-19T01:10:52.941+02:00About commentsOkay, comments are one of the most obscure subject in programming. Yes, obscure, I really mean it.<br />
<br />
Why ? Probably because there is no good way to use comments in your code. As I remember, in my student days, teachers explain to us that comments are mandatory, that a good source code is made up of more comments line than code line and so on, but none explains what to put in that damn comments.<br />
<br />
Of course, there's the running joke on the "<i>increments i</i>" comment, but that's all.<br />
<br />
As I'm now on the other side (yeah, I'm teaching programming), it was obvious that I should not make same mistake. But, how on earth should I explain to student how to comment their code, if I still don't know how myself ?<br />
<br />
So, for some times I was doing like my teachers did, which means I avoided the subject !<br />
<br />
But, then I ran into some text from Rob Pike (about programming in general) and he makes a strange remark: "<i>I tend to err on the side of eliminating comments, for several reasons.</i>" (<a href="http://www.lysator.liu.se/c/pikestyle.html">Rob Pike: Notes on Programming in C</a>) This sentence strike me first, but then I realize that it was the good way to manage comments.<br />
<br />
<blockquote><b>Most of the time comments are useless !</b></blockquote><br />
Why ? Just because the code is probably the best way to explain what you are trying to do !<br />
<br />
So, should we always avoid comments ? Of course not, but we should use wisely ! The first question is "why" (not when or how !):<br />
<br />
<br />
<ul><li>You need comments to explain how to use your code</li>
<li>You need comments to describe where to find some piece of code</li>
<li>Sometimes, you need comments to explain a trick or an unusual hack</li>
<li>You may need comments to track down modifications, but fixes and ugly workarounds</li>
</ul><div>Other comments are just a waste of time.</div><div><br />
</div><div>So, the first and most important comments are what we should call "<i>interface comments</i>", that is comments in header files or before definitions. Those comments will explain: what the function does, how to call it, and what constraints should verified (pre-conditions, post-conditions and invariant.)</div><div><br />
</div><div>You can also put comments in front of files to explain globally how things work. Take for example what you found in a lot of driver's source files: a global explanation on how the device works and what are the specific points.</div><div><br />
</div><div>Then you can sometimes explain some tricks. But be careful, those comments are often less informative than it seems to be ! Explaining, using natural language, what a complex piece of code is doing is harder than writing the code itself. Most of the time, the reader will be able to understand what your doing by reading the code, if not, he has nothing to do here ...</div><div><br />
</div><div>A good example of bad comments can be found in the source files of GNU C library. Take a look at the definition of the strlen function. The function is quite simple, the glibc version is little bit trickier than usual (read word by word rather than byte by byte) but no so complex. The trickiest part is the detection of the final NULL char inside a whole word. Ok, this can require some explanation, but the comments double fail this job: first, the text is less understandable than the code, second, the comments are obfuscating the reading of the code by breaking it into parts separated by big pieces of text ! And, the actual version is more readable than the first one I see.</div><div><br />
</div><div>So, most of the time don't even try to make a comment on your tricks, or put it outside of the code !</div><div><br />
</div><div>Commenting changes and corrections are the most difficult part. These comments are very useful, but they tend to grow bigger than they should be. You have several way to do it, but I found none very satisfactory. First, you can only rely on your version control system's log, in fact, you are probably already doing it, the only issue is that it very hard to find out the history of a specific piece of code (not a whole file, but a single function or data structure.) You can also add it to the code itself, but again, if you put it in front of the file, you loose the connection with the concerned code and if you put it right to the code, it will break the natural flow of your source code.</div><div><br />
</div><div>It would have been nice to have a clever integration of source files, version control and revision logs, but I haven't found such a tool.</div><div><br />
</div><div>So, as a conclusion, I will use some striking mantra (remember, you can't trust maxim !)</div><blockquote><i><b>Comments are nothing but noise !</b></i></blockquote>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-68388949365096969602011-06-12T22:35:00.000+02:002011-06-12T22:35:47.022+02:00"Don't trust maxims ... "A lot of books, articles or teaching materials are full of "Maxims" or "aphorisms". The intention is to strike the reader and convince him with a strong idea. Based, on my own experience, I'll start this article with my own maxim:<br />
<blockquote>"<i>Don't trust Maxims !</i>"</blockquote>Ok, I ended up with the traditional "don't trust me, I'm a liar". But this contradiction serves my vision: Maxims are most of the time meaningless and of no use unless provided with the right explanations. In fact, my own maxim should be read:<br />
<blockquote>"<i>Don't trust Maxims, understand them !</i>"</blockquote> So, this is general thoughts, what is the relation with programming ?<br />
<br />
After several years of teaching programming and computer science, I often heard students quoting aphorisms religiously and most of the time completely irrelevantly ! Why, because they haven't read the original sources, nor they tried to understand the true meaning behind.<br />
<br />
The most interesting example is the famous:<br />
<blockquote>"<i>Gotos are evil !</i>"</blockquote>This is one of the famous mantras of the structured programming approach. Are "gotos" really evil ? Probably not, there's a lot of legitimate uses of gotos (basic exception mechanism, loop escaping ... ) So, why should gotos be considered evil ?<br />
<br />
Let's us go back to the elder ages of computer, when programming languages were no more than macro-assembly. In that time, the goto instruction were the only way to structure programs. Have you ever read a code with no functions, no procedures, no while loops ? These codes tend to be as cryptic as poem written by a drunk schizophrenic !<br />
<br />
You don't even need to go back to the 60's. The first programming language that I learned was BASIC (for zx81 computer), the last time I read a bunch of code I wrote in those day make feel seek ! It was full of indirections, stupid line numbering and intricate gotos, I was unable to understand it !<br />
<br />
So, yes, used that way gotos are evil, but this does not mean that you should not use it. This is only a matter of code semantic, take a look at the following examples:<br />
<br />
<pre>void user_accept()
{
again:
printf("confirm with <y>: ");
if (getchar() != 'y')
goto again;
}
</y></pre><br />
<i>(Remarque: this code works badly due to the newline read with the input char ... )</i><br />
<br />
This code make sense, this is not a loop, all you want is to read 'y'. So, the goto is not evil in that case. Of course, you should have used a while loop to obtain the same result, but the meaning is the same. On the other hand, the following code is a bad use of goto:<br />
<br />
<pre>int f(int **p)
{
if (!(*p))
goto getsome;
doit:
**p = 42;
goto end;
getsome:
*p = malloc(sizeof (int));
goto doit;
end:
return **p;
}
</pre><br />
The previous code is just stupid (but anyway, it is inherently stupid) and its use of goto is just misleading. In fact. Of course, we shouldn't have write it this way, this is bad style programming, but it reflects the idea of evil goto: using it in place of functions or procedures (here, we can even do it without, but this how you should read it, jumping to a specific piece of code in order to solve some issue before returning to normal behavior.)<br />
<br />
So, returning to our subject, we illustrate a case where a maxim is right but need further refinement. This lead us to my last maxim of today:<br />
<blockquote>"<i>Never restraint yourself for a bad reason, any programming features can be useful.</i>"</blockquote>Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0tag:blogger.com,1999:blog-7555671657887635887.post-4926016823666935932011-06-09T00:19:00.000+02:002013-05-16T12:44:38.732+02:00New blog !After many years of programming and teaching programming, I've accumulate a lot of reflexions that I want to share.<br />
<br />
This won't be a technical blog, but a place for me to share my vision of programming. I'll tend to stay <i>funny</i> and I hope that my poor English won't depreciate my thoughts.<br />
<br />
Test edit, this is just a test, it will disappear soon … $x^y$Marwanhttp://www.blogger.com/profile/06627419687928189438noreply@blogger.com0