<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="FeedCreator 1.8" -->
<?xml-stylesheet href="https://www.baszerr.eu/lib/exe/css.php?s=feed" type="text/css"?>
<rss version="2.0">
    <channel xmlns:g="http://base.google.com/ns/1.0">
        <title>BaSzErr - blog:2017:04:17</title>
        <description></description>
        <link>https://www.baszerr.eu/</link>
        <lastBuildDate>Wed, 06 May 2026 09:46:27 +0000</lastBuildDate>
        <generator>FeedCreator 1.8</generator>
        <image>
            <url>https://www.baszerr.eu/lib/exe/fetch.php?media=wiki:dokuwiki.svg</url>
            <title>BaSzErr</title>
            <link>https://www.baszerr.eu/</link>
        </image>
        <item>
            <title>2017-04-17_-_easter_40000</title>
            <link>https://www.baszerr.eu/doku.php?id=blog:2017:04:17:2017-04-17_-_easter_40000</link>
            <description>
&lt;h1 class=&quot;sectionedit1&quot; id=&quot;easter_40000&quot;&gt;2017-04-17 - Easter 40000&lt;/h1&gt;
&lt;div class=&quot;level1&quot;&gt;

&lt;p&gt;
&lt;a href=&quot;https://www.baszerr.eu/lib/exe/detail.php?id=blog%3A2017%3A04%3A17%3A2017-04-17_-_easter_40000&amp;amp;media=blog:2017:04:17:wh40k_easter.jpg&quot; class=&quot;media&quot; title=&quot;blog:2017:04:17:wh40k_easter.jpg&quot;&gt;&lt;img src=&quot;https://www.baszerr.eu/lib/exe/fetch.php?w=750&amp;amp;tok=ba1043&amp;amp;media=blog:2017:04:17:wh40k_easter.jpg&quot; class=&quot;media&quot; loading=&quot;lazy&quot; title=&quot;easter warhammer 40k dreadnought&quot; alt=&quot;easter warhammer 40k dreadnought&quot; width=&quot;750&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;/div&gt;
</description>
            <author>anonymous@undisclosed.example.com (Anonymous)</author>
            <pubDate>Tue, 15 Jun 2021 20:09:48 +0000</pubDate>
        </item>
        <item>
            <title>2017-04-17_-_finding_invalid_characters</title>
            <link>https://www.baszerr.eu/doku.php?id=blog:2017:04:17:2017-04-17_-_finding_invalid_characters</link>
            <description>
&lt;h1 class=&quot;sectionedit1&quot; id=&quot;finding_invalid_characters&quot;&gt;2017-04-17 - finding invalid characters&lt;/h1&gt;
&lt;div class=&quot;level1&quot;&gt;

&lt;p&gt;
some time ago, in a project i work in, i needed to parse very often, some really big text files (some GBs). syntax was simple, but it still need to be checked, and ensured that the format is valid. long sotry short – majority of work boiled down to being able to quickly determine if all the characters in a sequence are from a given alphabet, known at compile-time. in other words, the task is to write a function with a signature:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;bool isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;std&lt;span class=&quot;sy0&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;me2&quot;&gt;string&lt;/span&gt; const&lt;span class=&quot;sy0&quot;&gt;&amp;amp;&lt;/span&gt; input&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
returning true, if all characters are from a given alphabet, and false otherwise. i&amp;#039;ve played around and come up with a neat solution, that generated code much faster than the original approach. let&amp;#039;s have a look how it evolved…
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;2017-04-17 - finding invalid characters&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;finding_invalid_characters&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:0,&amp;quot;secid&amp;quot;:1,&amp;quot;range&amp;quot;:&amp;quot;1-780&amp;quot;} --&gt;
&lt;h2 class=&quot;sectionedit2&quot; id=&quot;function_s_main_loop&quot;&gt;function&amp;#039;s main loop&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;
note that for this function can return false right away, once invalid character is found, so it can look like this:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; c&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt; input&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt; not isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
easy, right? yes – easy… and slow.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;function&amp;#039;s main loop&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;function_s_main_loop&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:1,&amp;quot;secid&amp;quot;:2,&amp;quot;range&amp;quot;:&amp;quot;781-1062&amp;quot;} --&gt;
&lt;h2 class=&quot;sectionedit3&quot; id=&quot;branch-less_check&quot;&gt;branch-less check&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;
have a look at the loop. we&amp;#039;ll talk about &lt;em&gt;isValid()&lt;/em&gt; in a second - for now let&amp;#039;s assume that &lt;em&gt;isValid()&lt;/em&gt; takes no time at all. where&amp;#039;s the potential bottle neck? there is an &lt;em&gt;if&lt;/em&gt; statement inside the tight loop! more over, we do not honestly expect it to fail – i.e. normally &lt;em&gt;isValid()&lt;/em&gt; will always return true! it&amp;#039;s just a rare, edge case, where it might return false (read error or a corrupted file from god knows where). so actually we can rewrite the look like this:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;std&lt;span class=&quot;sy0&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;me2&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;me2&quot;&gt;size_type&lt;/span&gt; errors &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; c&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt; input&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
  errors &lt;span class=&quot;sy0&quot;&gt;+=&lt;/span&gt; static_cast&lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;unsigned&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt; not isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; errors &lt;span class=&quot;sy0&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
now the only branch there is is the &lt;em&gt;for()&lt;/em&gt; loop itself. not much more can be removed now.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;branch-less check&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;branch-less_check&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:2,&amp;quot;secid&amp;quot;:3,&amp;quot;range&amp;quot;:&amp;quot;1063-1817&amp;quot;} --&gt;
&lt;h2 class=&quot;sectionedit4&quot; id=&quot;isvalid&quot;&gt;isValid()&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;
so let&amp;#039;s have a look at &lt;em&gt;isValid()&lt;/em&gt; itself. there are different approaches, that can be taken here.
&lt;/p&gt;

&lt;p&gt;
it&amp;#039;s always good to know, if there is some data-specific algorithm, that can be used. for instance, if we&amp;#039;d only need to accept odd characters, our function could look like this:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;bool isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; c &lt;span class=&quot;sy0&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nu12&quot;&gt;0x01&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
unfortunately, in my case the set was just randomly spread through &lt;abbr title=&quot;American Standard Code for Information Interchange&quot;&gt;ASCII&lt;/abbr&gt; alphabet - just ~10 different letters, but no useful pattern there. one must just assume “general case”. let&amp;#039;s try out differetn approaches.
&lt;/p&gt;

&lt;p&gt;
for the approaches below, i assumed pseudo-random sequence of &lt;abbr title=&quot;American Standard Code for Information Interchange&quot;&gt;ASCII&lt;/abbr&gt; characters (seeded with a known seed) of size 1GB. the sequence was checked and the number of errors was reported. letters being considered as “valid”, were ones that form “Just Checking” string.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;isValid()&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;isvalid&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:3,&amp;quot;secid&amp;quot;:4,&amp;quot;range&amp;quot;:&amp;quot;1818-2665&amp;quot;} --&gt;
&lt;h3 class=&quot;sectionedit5&quot; id=&quot;switch_case&quot;&gt;switch/case&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;
probably the first thing that comes to one&amp;#039;s mind. something along the lines:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;bool isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
  swtich&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
  &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;p&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;X&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;Q&#039;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
results:
&lt;/p&gt;
&lt;div class=&quot;table sectionedit6&quot;&gt;&lt;table class=&quot;inline&quot;&gt;
	&lt;thead&gt;
	&lt;tr class=&quot;row0&quot;&gt;
		&lt;th class=&quot;col0&quot;&gt; compiler &lt;/th&gt;&lt;th class=&quot;col1&quot;&gt; time &lt;/th&gt;
	&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tr class=&quot;row1&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; gcc-6.3 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 5.43[s] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr class=&quot;row2&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; clang-3.8 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 6.86[s] &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;table&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;table&amp;quot;,&amp;quot;secid&amp;quot;:6,&amp;quot;range&amp;quot;:&amp;quot;2945-3010&amp;quot;} --&gt;
&lt;p&gt;
this will be our baseline. let&amp;#039;s try sth else…
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;switch\/case&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;switch_case&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:4,&amp;quot;secid&amp;quot;:5,&amp;quot;range&amp;quot;:&amp;quot;2666-3062&amp;quot;} --&gt;
&lt;h3 class=&quot;sectionedit7&quot; id=&quot;if_else&quot;&gt;if/else&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;
another option, that basically meas the same:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt; c &lt;span class=&quot;sy0&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;p&#039;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt; c &lt;span class=&quot;sy0&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;X&#039;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt; c &lt;span class=&quot;sy0&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st0&quot;&gt;&#039;Q&#039;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;co1&quot;&gt;// else&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
one could expect it to be the same as switch/case, but…
&lt;/p&gt;
&lt;div class=&quot;table sectionedit8&quot;&gt;&lt;table class=&quot;inline&quot;&gt;
	&lt;thead&gt;
	&lt;tr class=&quot;row0&quot;&gt;
		&lt;th class=&quot;col0&quot;&gt; compiler &lt;/th&gt;&lt;th class=&quot;col1&quot;&gt; time &lt;/th&gt;
	&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tr class=&quot;row1&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; gcc-6.3 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 2.59[s] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr class=&quot;row2&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; clang-3.8 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 7.17[s] &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;table&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;table1&amp;quot;,&amp;quot;secid&amp;quot;:8,&amp;quot;range&amp;quot;:&amp;quot;3355-3420&amp;quot;} --&gt;
&lt;p&gt;
it turns out that GCC generated 2x faster code for if/else, while clang lost ~10%. different compilers, different optimizations.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;if\/else&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;if_else&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:5,&amp;quot;secid&amp;quot;:7,&amp;quot;range&amp;quot;:&amp;quot;3063-3552&amp;quot;} --&gt;
&lt;h3 class=&quot;sectionedit9&quot; id=&quot;look-up_tables&quot;&gt;look-up tables&lt;/h3&gt;
&lt;div class=&quot;level3&quot;&gt;

&lt;p&gt;
on the road of fast, branch-less code, LUT technique seems very appropriate. it can however be done in a different ways, too.
&lt;/p&gt;

&lt;p&gt;
as a common theme, let&amp;#039;s defined a helper function, that generates a LUT for our needs:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; makeLut&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
  std&lt;span class=&quot;sy0&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;me2&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;bool&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt; lut&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;co1&quot;&gt;// by default do not accept anything:&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;auto&lt;span class=&quot;sy0&quot;&gt;&amp;amp;&lt;/span&gt; c&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt; lut&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    c &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;co1&quot;&gt;// now the list of exceptions:&lt;/span&gt;
  c&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;p&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  c&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;X&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;
  c&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;Q&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt; &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kw2&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; lut&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
now how can we use that?
&lt;/p&gt;

&lt;/div&gt;

&lt;h4 id=&quot;static_local_lut&quot;&gt;static, local LUT&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;
first idea is to put LUT&amp;#039;s initialization into a function body, as a static variable, so that it&amp;#039;s initialized once, when first used:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
  &lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; lut &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; makeLut&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; lut&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;c &lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
results?
&lt;/p&gt;
&lt;div class=&quot;table sectionedit10&quot;&gt;&lt;table class=&quot;inline&quot;&gt;
	&lt;thead&gt;
	&lt;tr class=&quot;row0&quot;&gt;
		&lt;th class=&quot;col0&quot;&gt; compiler &lt;/th&gt;&lt;th class=&quot;col1&quot;&gt; time &lt;/th&gt;
	&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tr class=&quot;row1&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; gcc-6.3 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 2.84[s] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr class=&quot;row2&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; clang-3.8 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 2.96[s] &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;table&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;table2&amp;quot;,&amp;quot;secid&amp;quot;:10,&amp;quot;range&amp;quot;:&amp;quot;4349-4414&amp;quot;} --&gt;
&lt;p&gt;
we can see big improvements on clang! gcc actually was a bit slower than the original if/else approach.
&lt;/p&gt;

&lt;p&gt;
note however that even though we initialize the LUT once, we neeed to check if it is initialized each and every time the function is called! more over this must be done in a thread-safe manner, so maybe…
&lt;/p&gt;

&lt;/div&gt;

&lt;h4 id=&quot;static_global_lut&quot;&gt;static, global LUT&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;
just put it as a global symbol and mark const - it&amp;#039;s always initialized, when &lt;em&gt;main()&lt;/em&gt; is being executed and that&amp;#039;s it!
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;&lt;span class=&quot;kw4&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; g_lut &lt;span class=&quot;sy0&quot;&gt;=&lt;/span&gt; makeLut&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; isValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
  &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; g_lut&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;c &lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
results?
&lt;/p&gt;
&lt;div class=&quot;table sectionedit11&quot;&gt;&lt;table class=&quot;inline&quot;&gt;
	&lt;thead&gt;
	&lt;tr class=&quot;row0&quot;&gt;
		&lt;th class=&quot;col0&quot;&gt; compiler &lt;/th&gt;&lt;th class=&quot;col1&quot;&gt; time &lt;/th&gt;
	&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tr class=&quot;row1&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; gcc-6.3 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 1.57[s] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr class=&quot;row2&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; clang-3.8 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 1.57[s] &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;table&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;table3&amp;quot;,&amp;quot;secid&amp;quot;:11,&amp;quot;range&amp;quot;:&amp;quot;4999-5064&amp;quot;} --&gt;
&lt;p&gt;
not only now both results are much better than the previous ones, but in fact both compilers produce the same time results! skipping this “expensive &lt;em&gt;if&lt;/em&gt;” for initialization did payed off, indeed.
&lt;/p&gt;

&lt;/div&gt;

&lt;h4 id=&quot;functor&quot;&gt;functor&lt;/h4&gt;
&lt;div class=&quot;level4&quot;&gt;

&lt;p&gt;
let&amp;#039;s try one last thing – since we need a function and a date associated with it, it sounds much like a class, doesn&amp;#039;t it? so let&amp;#039;s create a functor:
&lt;/p&gt;
&lt;pre class=&quot;code c&quot;&gt;class IsValid
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
public&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt;
  IsValid&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt; lut_&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt; makeLut&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
  &lt;span class=&quot;kw4&quot;&gt;auto&lt;/span&gt; operator&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;const&lt;/span&gt;
  &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; lut_&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw4&quot;&gt;uint8_t&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;c &lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;
&amp;nbsp;
private&lt;span class=&quot;sy0&quot;&gt;:&lt;/span&gt;
  std&lt;span class=&quot;sy0&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;me2&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;bool&lt;span class=&quot;sy0&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nu0&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt; lut_&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;co1&quot;&gt;// used as: IsValid iv; /* .... */ iv(&#039;x&#039;);&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
results?
&lt;/p&gt;
&lt;div class=&quot;table sectionedit12&quot;&gt;&lt;table class=&quot;inline&quot;&gt;
	&lt;thead&gt;
	&lt;tr class=&quot;row0&quot;&gt;
		&lt;th class=&quot;col0&quot;&gt; compiler &lt;/th&gt;&lt;th class=&quot;col1&quot;&gt; time &lt;/th&gt;
	&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tr class=&quot;row1&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; gcc-6.3 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 0.60[s] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr class=&quot;row2&quot;&gt;
		&lt;td class=&quot;col0&quot;&gt; clang-3.8 &lt;/td&gt;&lt;td class=&quot;col1&quot;&gt; 0.41[s] &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;table&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;table4&amp;quot;,&amp;quot;secid&amp;quot;:12,&amp;quot;range&amp;quot;:&amp;quot;5681-5746&amp;quot;} --&gt;
&lt;p&gt;
now this is something – gcc version is almost 10x faster than the original switch/case approach! clang is almost 17x faster, than the original version!
&lt;/p&gt;

&lt;p&gt;
also, an interesting fact to note is that clang version was actually ~30% faster than gcc. homework – analyze assembly and see what&amp;#039;s up! :)
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;look-up tables&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;look-up_tables&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:6,&amp;quot;secid&amp;quot;:9,&amp;quot;range&amp;quot;:&amp;quot;3553-6045&amp;quot;} --&gt;
&lt;h2 class=&quot;sectionedit13&quot; id=&quot;summary&quot;&gt;summary&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;
&lt;ol&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; measurements can surprise (eg.: switch/cache vs. if/else).&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; look-up tables have beaten all the other approaches.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; when used in an optimal way, can lead to up to 10x speed gain.&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; being branch-less, in a tight loops does pay off!&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;summary&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;summary&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:10,&amp;quot;secid&amp;quot;:13,&amp;quot;range&amp;quot;:&amp;quot;6046-6309&amp;quot;} --&gt;
&lt;h2 class=&quot;sectionedit14&quot; id=&quot;wanna_play&quot;&gt;wanna play? :)&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;
if you want to play around with own ideas/compilers, check out &lt;a href=&quot;https://github.com/el-bart/soft_playground/tree/master/all_characters_in_range&quot; class=&quot;urlextern&quot; title=&quot;https://github.com/el-bart/soft_playground/tree/master/all_characters_in_range&quot; rel=&quot;ugc nofollow&quot;&gt;github repo with example source codes&lt;/a&gt;. have fun! :)
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- EDIT{&amp;quot;target&amp;quot;:&amp;quot;section&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;wanna play? :)&amp;quot;,&amp;quot;hid&amp;quot;:&amp;quot;wanna_play&amp;quot;,&amp;quot;codeblockOffset&amp;quot;:10,&amp;quot;secid&amp;quot;:14,&amp;quot;range&amp;quot;:&amp;quot;6310-&amp;quot;} --&gt;</description>
            <author>anonymous@undisclosed.example.com (Anonymous)</author>
            <pubDate>Tue, 15 Jun 2021 20:09:48 +0000</pubDate>
        </item>
    </channel>
</rss>
