{"id":5224,"date":"2023-08-29T16:14:18","date_gmt":"2023-08-30T00:14:18","guid":{"rendered":"https:\/\/wonghoi.humgar.com\/blog\/?p=5224"},"modified":"2024-02-13T01:59:21","modified_gmt":"2024-02-13T09:59:21","slug":"programming-techniques-bit-hackery","status":"publish","type":"post","link":"https:\/\/wonghoi.humgar.com\/blog\/2023\/08\/29\/programming-techniques-bit-hackery\/","title":{"rendered":"Programming Techniques: Bit hackery"},"content":{"rendered":"\n<p>Sean Eron Anderson (Stanford CS graphics lab)&#8217;s bit twiddling pages often shows a bunch of neat bit tricks, but it&#8217;s more like a recipe book than a unified way to summarize the common concepts behind them. Here&#8217;s my attempt. This page will get updated as I got the time and more useful insights collected.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: Two ways to get two&#8217;s complement<\/h2>\n\n\n\n<p>This is the basics of most bit hacks below. Sometimes the definition itself is a bit trick on its own.<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align}\n\\overline{-x}+1=x \\\\\n-x = \\overline{x}+1 \n\\end{align}<\/pre><\/div>\n\n\n\n<p>the above reads: to flip sign, flip bits then add one.<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align}\n\\overline{x} = -x-1 \\\\\n\\end{align}<\/pre><\/div>\n\n\n\n<p>the above reads: if you flip the bits, you are getting the negative of it subtracted by 1. e.g. ~4 = -5, ~5 = -6, &#8230;, ~(-5) = 4, ~(-4) = 3, &#8230;<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align}\nx = \\overline{-x-1} \\\\\n\\end{align}<\/pre><\/div>\n\n\n\n<p>the above reads: any number can be represented by its negative minus -1, then bit-flipped.<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align}\n\\overline{-x} = x-1 \\\\\n-x = \\overline{x-1}\n\\end{align}<\/pre><\/div>\n\n\n\n<p>reads: to flip sign, subtract one first then flip bits <\/p>\n\n\n\n<p>So it means to change signs, you can choose to <strong>subtract<\/strong> one first then flip bits or flip bits first then <strong>add<\/strong> one. <\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>-x=\\overline{x-1} = \\overline{x}+1 <\/pre><\/div>\n\n\n\n<p>Let&#8217;s try it with 2 instead of 1:<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\overline{x-2} = \\overline{(x-1)-1} = \\overline{x-1}+1 = (\\overline{x}+1)+1 = \\overline{x}+2<\/pre><\/div>\n\n\n\n<p>You can generalize it to an arbitrary number by subtracting -1 more under the bar on the left hand side and you will get +1 more on the right hand side. Every extra -1 under the bar (bit flips) shows up as +1 outside the bar (bit flips).<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\overline{x-3} = \\overline{(x-2)-1} = \\overline{x-2}+1 = (\\overline{x}+2)+1 = \\overline{x}+3<\/pre><\/div>\n\n\n\n<p>This matches the observation that complement schemes (one&#8217;s or two&#8217;s) both have increasing magnitude move in opposite directions for positive and negative numbers. Look at this table: <\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>Unsigned<\/td><td>Binary<\/td><td>Two&#8217;s Complement<\/td><\/tr><tr><td>7<\/td><td>111<\/td><td>-1<\/td><\/tr><tr><td>6<\/td><td>110<\/td><td>-2<\/td><\/tr><tr><td>5<\/td><td>101<\/td><td>-3<\/td><\/tr><tr><td>4<\/td><td>100<\/td><td>-4<\/td><\/tr><tr><td>3<\/td><td>011<\/td><td>3<\/td><\/tr><tr><td>2<\/td><td>010<\/td><td>2<\/td><\/tr><tr><td>1<\/td><td>001<\/td><td>1<\/td><\/tr><tr><td>0<\/td><td>000<\/td><td>0<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">A very important observation that&#8217;d be used over and over blow is that in two&#8217;s complement,  -1 is always a mask of all binary &#8216;1&#8217;s regardless of the word width.<\/figcaption><\/figure>\n\n\n\n<p>This rule can also read as: magnitude offsets goes in opposite directions <\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align}\n-x+(n-1)=\\overline{x-n} = \\overline{x}+n\n\\end{align}<\/pre><\/div>\n\n\n\n<p>Note that <strong>this is <span style=\"text-decoration: underline;\">NOT distributing<\/span> bit-flip<\/strong> to two addition\/subtraction despite it resembles it with an important distinction that the sign of <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">n<\/code> changed without turning into (n-1). If it were to distribute, you&#8217;ll get (n-2) on the left-hand-side instead of the (n-1) term because the -1 would have been counted twice under distribution. <\/p>\n\n\n\n<p>Bit flips simply doesn&#8217;t distribute over the 4 basic (algebraic field) operations. The two&#8217;s complement offset is done <em>once and only once<\/em> when you change the overall representation no matter how many components you break it down into. It&#8217;s merely done to shift over the <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">-0<\/code> in one&#8217;s complement so there&#8217;s an extra space for an extra negative number <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/ql-cache\/quicklatex.com-cb0765b05f974d4879a0355c1c00dbb3_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#45;&#50;&#94;&#110;&#36;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"30\" style=\"vertical-align: 0px;\"\/> which its positive counterpart <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/ql-cache\/quicklatex.com-960f6ec1302ede17cc104428f57df657_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#43;&#50;&#94;&#110;&#36;\" title=\"Rendered by QuickLaTeX.com\" height=\"14\" width=\"31\" style=\"vertical-align: -2px;\"\/> is not representable without starting a new digit.<\/p>\n\n\n\n<p>Note to self: the INT_MIN is just the sign bit of &#8216;1&#8217; followed by all zeros after.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: XOR can be used for bit flips or check for bit changes<\/h2>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: Top bit holds the sign<\/h2>\n\n\n\n<p>Sounds simple, but if you keep in mind that <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">(x&lt;0)<\/code> is really asking to see if the top bit is 1, you can check if two numbers has opposite signs without bit shifting it down by simply XOR-ing them (anything below the top bit are ignored) and use <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">(x^y)&lt;0<\/code> to check for the resulting top bit is 1, which signals that the sign bits are different.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: Sign extensions (the top\/sign bit gets drag-copied when right shifted)<\/h2>\n\n\n\n<p>When you right shift (in signed integers), the top (sign) bit gets drag-copied (sign extended) by the number of bits you right shifted. (Obviously for signed integers, right shifts are zero-filled)<\/p>\n\n\n\n<p>Can exploit this to<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>drag the top (sign) bit all the way down to the bottom (so you either get all 1s or 0s) to provide a conditional mask based on the sign (see below)<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>1??????? \\gg 7 \\textnormal{ (i.e. type bit width - 1)} = 11111111_2 = -1_{10} \\\\\n0??????? \\gg 7 \\textnormal{ (i.e. type bit width - 1)} = 00000000_2 = +0_{10} \\\\<\/pre><\/div>\n\n\n\n<p>Signed extensions also means a negative number will stay negative and a positive number will stay positive if you right shift<\/p>\n\n\n\n<p>Sign extension behavior is not guaranteed by 1987 ANSI C, but it&#8217;s standard on pretty much anything more modern than that. Just make sure anything that uses this behavior are inlined (so the implementation can be easily swapped out), well documented\/commented, and platform checks\/switches are in place, and there&#8217;s a way to quickly check with the slower but platform independent implementation. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: Getting a bit mask of a 1s (if true) and all 0s (if false)<\/h2>\n\n\n\n<p>The ability to convert a logic evaluation (condition) that gives <\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n00000001_2 &amp;= +1_{10} &amp; \\mathrm{(true)}\\\\\n00000000_2 &amp;= +0_{10} &amp; \\mathrm{(false)}\n\\end{align*}<\/pre><\/div>\n\n\n\n<p>into a <strong>conditional <\/strong>mask that gives<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n11111111_2 &amp;= -1_{10} &amp; \\mathrm{(true)}\\\\\n00000000_2 &amp;= +0_{10} &amp; \\mathrm{(false)}\n\\end{align*}<\/pre><\/div>\n\n\n\n<p>is the basis of many branchless &#8216;drop\/keep this if that&#8217; operations.<\/p>\n\n\n\n<p>This can also be achieved by <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>putting a minus sign in front, such as <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">-(cond)<\/code> that will convert a (+1, 0) into (-1, 0), or <\/li>\n\n\n\n<li>more efficiently exploiting sign extensions by dragging the top bit to the bottom (by right shifting by the type&#8217;s bit length-1)<\/li>\n\n\n\n<li>computing absolute using the two&#8217;s complement&#8217;s definition of flip all bits and add 1: drag out a mask that shows that sign, which happens to be a do nothing if all 0s and flip all bits if all 1s in an xor, while the mask of all 1s, which is -1, when subtracted, becomes +1 needed to finish the two&#8217;s complement (and that&#8217;s subtract by 0 for already positive value). <\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/ql-cache\/quicklatex.com-cffcb6c5ce8a64103759bbf1900c2bb8_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#50;&#94;&#110;&#32;&#45;&#32;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"48\" style=\"vertical-align: 0px;\"\/> sets all binary digits below it to a stream of 1s<\/h2>\n\n\n\n<p>When you count binary numbers up, you must exhaust all the lower digits by filling them with all 1s before you get to advance to (set) a new digit on the left of them. For example,<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n1000_2 &amp;= +8_{10}\\\\\n0111_2 &amp;= +7_{10}\n\\end{align*}<\/pre><\/div>\n\n\n\n<p>This can be exploited to create bit-masks that preserves all digits on the left of the first &#8216;1&#8217; seen from the right (LSB), &#8216;0&#8217; at that lowest (LSB) set bit (aka &#8216;1&#8217;), and all &#8216;1&#8217;s below it.<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n0110,1000_2 &amp;= +104_{10}\\\\\n0110,0111_2 &amp;= +103_{10}\n\\end{align*}<\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1015\" height=\"181\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-7.png\" alt=\"\" class=\"wp-image-5228\" srcset=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-7.png 1015w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-7-300x53.png 300w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-7-768x137.png 768w, https:\/\/wonghoi.humgar.com\/blog\/wp-content\/uploads\/2023\/08\/image-7-500x89.png 500w\" sizes=\"auto, (max-width: 1015px) 100vw, 1015px\" \/><\/figure>\n\n\n\n<p>Binary digits are are the (1 or 0) coefficients of a linear combination of powers of 2. Having a loner &#8216;1&#8217; (aka everything else is 0) means the number is a power of 2. <\/p>\n\n\n\n<p>Being the lone &#8216;1&#8217; bit in the number means every bit above it must be zero. Any &#8216;1&#8217;s above the right-most &#8216;1&#8217; means it&#8217;s not the loner, hence not a power of 2. <\/p>\n\n\n\n<p>If you subtract 1 from the power-of-2 number, only all bits below (not including) the line &#8216;1&#8217; bit becomes 1, and that &#8216;1&#8217; bit position become zero, and as mentioned before, all bits above it are 0s by definition since the &#8216;1&#8217; we are working on is a loner. <\/p>\n\n\n\n<p>Since the digits in <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/ql-cache\/quicklatex.com-0288856e580589b0aa07b6eb5048e37e_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#50;&#94;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"17\" style=\"vertical-align: 0px;\"\/> and <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/ql-cache\/quicklatex.com-cffcb6c5ce8a64103759bbf1900c2bb8_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#50;&#94;&#110;&#32;&#45;&#32;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"48\" style=\"vertical-align: 0px;\"\/> are mutually exclusive (see example below)<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n0000,1000_2 &amp;= +8_{10} = 2^3 \\\\\n0000,0111_2 &amp;= +7_{10} = 2^3 -1\n\\end{align*}<\/pre><\/div>\n\n\n\n<p>we can be sure that if we AND them we must get 0 (because one of them has to be zero) and if we XOR them we must get 1. But which one to use?<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n0000,1000_2 &amp;= +8_{10} &amp;=&amp; 2^3 \\\\\n0000,0111_2 &amp;= +7_{10} &amp;=&amp; 2^3 -1 \\\\\n0000,1111_2 &amp;= +15_{10} &amp;=&amp; 2^3 \\textnormal{ or } (2^3 -1)\\\\\n0000,1111_2 &amp;= +15_{10} &amp;=&amp; 2^3 \\textnormal{ xor } (2^3 -1)\\\\\n0000,0000_2 &amp;= +0_{10} &amp;=&amp; 2^3 \\textnormal{ and } (2^3 -1)\\\\\n\\end{align*}<\/pre><\/div>\n\n\n\n<p>Let&#8217;s also check for the non-power of two case<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n0110,1000_2 &amp;= +104_{10}\\\\\n0110,0111_2 &amp;= +103_{10}\\\\\n0110,1111_2 &amp;= +111_{10} &amp;=&amp; 104_{10} \\textnormal{ or } 103_{10}\\\\\n0000,1111_2 &amp;= +15_{10} &amp;=&amp; 104_{10} \\textnormal{ xor } 103_{10}\\\\\n0110,0000_2 &amp;= +96_{10} &amp;=&amp; 104_{10} \\textnormal{ and } 103_{10}\\\\  \n\\end{align*}<\/pre><\/div>\n\n\n\n<p>The <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">xor<\/code> approach does not work because the upper bits are invariant, so we cannot detect the presence of the upper set bits (upper &#8216;1&#8217;s). It unconditionally gives the same bit pattern (mask) marking the lowest first set bit and everything below it 1s and 0s for everything else above it. Which can be exploited to simplify counting the consecutive trailing zeros (from the right) by turning it into counting the contiguous 1s in this invariant pattern, or add 1 to it and binary search the position of the set bit and subtract 1 because the said bit was made into the invariant (xor) pattern as well so +1 move onto the next upper binary digit.<\/p>\n\n\n\n<p>The <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">or<\/code> approach detects the presence of the upper set bits but it&#8217;s a pain to mask out the invariant lower 1s, which curiously you can do by XOR-ing with the invariant pattern generated by <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/ql-cache\/quicklatex.com-113fe7ae2ee851c5639b662ef3c91675_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#50;&#94;&#110;&#32;&#92;&#116;&#101;&#120;&#116;&#110;&#111;&#114;&#109;&#97;&#108;&#123;&#32;&#120;&#111;&#114;&#32;&#125;&#32;&#50;&#94;&#110;&#45;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"103\" style=\"vertical-align: 0px;\"\/> or you can do AND-NOT-ing<\/p>\n\n\n\n<div class=\"wp-block-katex-display-block katex-eq\" data-katex-display=\"true\"><pre>\\begin{align*}\n0110,1000_2 &amp;= +104_{10}\\\\\n0110,0111_2 &amp;= +103_{10}\\\\\n0110,1111_2 &amp;= +111_{10} &amp;=&amp; 104_{10} \\textnormal{ or } 103_{10}\\\\\n0000,1111_2 &amp;= +15_{10} &amp;=&amp; 104_{10} \\textnormal{ xor } 103_{10}\\\\\n1111,0000_2 &amp;= +240_{10} &amp;=&amp; \\overline{104_{10} \\textnormal{ xor } 103_{10}}\\\\\n0110,0000_2 &amp;= +96_{10} &amp;=&amp; (104_{10} \\textnormal{ or } 103_{10}) \\textnormal{ and } \\overline{(104_{10} \\textnormal{ xor } 103_{10})}\\\\  \n0110,0000_2 &amp;= +96_{10} &amp;=&amp; (104_{10} \\textnormal{ or } 103_{10}) \\textnormal{ xor } (104_{10} \\textnormal{ xor } 103_{10})\\\\\n0110,0000_2 &amp;= +96_{10} &amp;=&amp; 104_{10} \\textnormal{ and } 103_{10}\\\\  \n\\end{align*}<\/pre><\/div>\n\n\n\n<p>Which <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">and<\/code> happens to already does the job by keeping the top bits (which non-zero value detects their presence) yet unconditionally clear the lowest set bit and everything below it.<\/p>\n\n\n\n<p>The gut of is <code data-enlighter-language=\"cpp\" class=\"EnlighterJSRAW\">x &amp; (x-1)<\/code> maneuver is that it clears the bit from the lowest set bit and everything down below<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">clearLowestSetBitAndEverythingBelow(x): x &amp; (x-1)<\/pre>\n\n\n\n<p>This is used by Brian W. Kernighan to count number of set bits by knocking them one off at a time starting from below. Of course the worst case scenario is when the 1s are so dense that the algorithm must go through every bit without jumping past the zeros.<\/p>\n\n\n\n<p>So the solution is<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">isPowerOfTwo(x): clearLowestSetBitAndEverythingBelow(x)==0\nisPowerOfTwo(x): (x &amp; (x-1))==0<\/pre>\n\n\n\n<p>However a special case escaped us, which is <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">x=0<\/code>. <code data-enlighter-language=\"generic\" class=\"EnlighterJSRAW\">0x0000 &amp; 0xFFFF<\/code> is 0, but 0 isn&#8217;t a power of 2 unless you consider the minus infinity power which is the territory of floating point anyway. This can be easily patched by making the result unconditionally false if x=0 in the first place.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">isPowerOfTwo(x): x &amp;&amp; ((x &amp; (x-1))==0)<\/pre>\n\n\n\n<p>Note the logical &amp;&amp; which means x is first tested for its non-zeroness (by boiling any non-zero value down to +1) and it also enables the efficient short-circuit evaluation which if x is false, which means the result is unconditionally false under &amp;&amp;, the rest are irrelevant so it&#8217;s not evaluated.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concept: Look up table<\/h2>\n\n\n\n<p>This is unconditionally the O(1) way because you have a mask of every bit in the type ready and you could index by it. However the penalty is that a load operation could be expensive if not everything can fit in the register file.<\/p>\n\n\n\n<p><\/p>\n<div class=\"pvc_clear\"><\/div><p id=\"pvc_stats_5224\" class=\"pvc_stats all  \" data-element-id=\"5224\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p><div class=\"pvc_clear\"><\/div>","protected":false},"excerpt":{"rendered":"<p>Sean Eron Anderson (Stanford CS graphics lab)&#8217;s bit twiddling pages often shows a bunch of neat bit tricks, but it&#8217;s more like a recipe book than a unified way to summarize the common concepts behind them. Here&#8217;s my attempt. This &hellip; <a href=\"https:\/\/wonghoi.humgar.com\/blog\/2023\/08\/29\/programming-techniques-bit-hackery\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_5224\" class=\"pvc_stats all  \" data-element-id=\"5224\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/wonghoi.humgar.com\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[74,30,25,20],"tags":[],"class_list":["post-5224","post","type-post","status-publish","format-standard","hentry","category-bit-manipulation","category-c-programming","category-cpp","category-computer-science"],"_links":{"self":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/5224","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/comments?post=5224"}],"version-history":[{"count":35,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/5224\/revisions"}],"predecessor-version":[{"id":5793,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/posts\/5224\/revisions\/5793"}],"wp:attachment":[{"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/media?parent=5224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/categories?post=5224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wonghoi.humgar.com\/blog\/wp-json\/wp\/v2\/tags?post=5224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}