5 Bit Basics

\(\newcommand{\footnotename}{footnote}\) \(\def \LWRfootnote {1}\) \(\newcommand {\footnote }[2][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\newcommand {\footnotemark }[1][\LWRfootnote ]{{}^{\mathrm {#1}}}\) \(\let \LWRorighspace \hspace \) \(\renewcommand {\hspace }{\ifstar \LWRorighspace \LWRorighspace }\) \(\newcommand {\TextOrMath }[2]{#2}\) \(\newcommand {\mathnormal }[1]{{#1}}\) \(\newcommand \ensuremath [1]{#1}\) \(\newcommand {\LWRframebox }[2][]{\fbox {#2}} \newcommand {\framebox }[1][]{\LWRframebox } \) \(\newcommand {\setlength }[2]{}\) \(\newcommand {\addtolength }[2]{}\) \(\newcommand {\setcounter }[2]{}\) \(\newcommand {\addtocounter }[2]{}\) \(\newcommand {\arabic }[1]{}\) \(\newcommand {\number }[1]{}\) \(\newcommand {\noalign }[1]{\text {#1}\notag \\}\) \(\newcommand {\cline }[1]{}\) \(\newcommand {\directlua }[1]{\text {(directlua)}}\) \(\newcommand {\luatexdirectlua }[1]{\text {(directlua)}}\) \(\newcommand {\protect }{}\) \(\def \LWRabsorbnumber #1 {}\) \(\def \LWRabsorbquotenumber "#1 {}\) \(\newcommand {\LWRabsorboption }[1][]{}\) \(\newcommand {\LWRabsorbtwooptions }[1][]{\LWRabsorboption }\) \(\def \mathchar {\ifnextchar "\LWRabsorbquotenumber \LWRabsorbnumber }\) \(\def \mathcode #1={\mathchar }\) \(\let \delcode \mathcode \) \(\let \delimiter \mathchar \) \(\def \oe {\unicode {x0153}}\) \(\def \OE {\unicode {x0152}}\) \(\def \ae {\unicode {x00E6}}\) \(\def \AE {\unicode {x00C6}}\) \(\def \aa {\unicode {x00E5}}\) \(\def \AA {\unicode {x00C5}}\) \(\def \o {\unicode {x00F8}}\) \(\def \O {\unicode {x00D8}}\) \(\def \l {\unicode {x0142}}\) \(\def \L {\unicode {x0141}}\) \(\def \ss {\unicode {x00DF}}\) \(\def \SS {\unicode {x1E9E}}\) \(\def \dag {\unicode {x2020}}\) \(\def \ddag {\unicode {x2021}}\) \(\def \P {\unicode {x00B6}}\) \(\def \copyright {\unicode {x00A9}}\) \(\def \pounds {\unicode {x00A3}}\) \(\let \LWRref \ref \) \(\renewcommand {\ref }{\ifstar \LWRref \LWRref }\) \( \newcommand {\multicolumn }[3]{#3}\) \(\require {textcomp}\) \(\newcommand {\intertext }[1]{\text {#1}\notag \\}\) \(\let \Hat \hat \) \(\let \Check \check \) \(\let \Tilde \tilde \) \(\let \Acute \acute \) \(\let \Grave \grave \) \(\let \Dot \dot \) \(\let \Ddot \ddot \) \(\let \Breve \breve \) \(\let \Bar \bar \) \(\let \Vec \vec \) \(\renewcommand {\vec }{\boldsymbol }\) \(\newcommand {\Edge }{\ensuremath {\,\textemdash \,}}\) \(\newcommand \Const [1]{\text {\textsf {#1}}}\) \(\DeclareMathOperator {\lerp }{lerp}\) \(\DeclareMathOperator {\bitlen }{bitlen}\) \(\DeclareMathOperator {\sign }{sign}\) \(\newcommand {\I }{\mathrm {i}}\) \(\newcommand \AND {\mathbin {\&}}\) \(\newcommand \OR {\mathbin {|}}\) \(\newcommand \XOR {\mathbin {{}^{\wedge }}}\) \(\newcommand \shl {\ll }\) \(\newcommand \shr {\ggg }\) \(\newcommand \asr {\gg }\) \(\newcommand \NOT {\ensuremath {\mathord {\sim }}}\) \(\newcommand {\isep }{\mathrel {{.}\,{.}}}\) \(\newcommand {\Id }[1]{\mathit {#1}}\) \(\newcommand {\const }[1]{\mathsf {#1}}\) \(\newcommand {\algorithmname }[1]{\text {\textsc {#1}}}\) \(\newcommand {\bits }[1]{\text {#1}}\) \(\newcommand {\hexa }[1]{\mathtt {0x#1}}\) \(\newcommand {\num }[1]{#1}\) \(\newcommand {\qed }{\quad \square }\) \(\newcommand {\idiv }[2]{\lfloor #1/#2\rfloor }\) \(\newcommand \attribdot {\ensuremath {\mkern 1.5mu.\mkern 1.5mu}}\) \(\newcommand \attribxr [2]{#1\attribdot \text {#2}}\) \(\newcommand \attribir [2]{\Id {#1}\attribdot \text {#2}}\) \(\newcommand \attribii [2]{\Id {#1}\attribdot \Id {#2}}\) \(\newcommand \textsc [1]{#1}\) \(\require {colortbl}\) \(\let \LWRorigcolumncolor \columncolor \) \(\renewcommand {\columncolor }[2][named]{\LWRorigcolumncolor [#1]{#2}\LWRabsorbtwooptions }\) \(\let \LWRorigrowcolor \rowcolor \) \(\renewcommand {\rowcolor }[2][named]{\LWRorigrowcolor [#1]{#2}\LWRabsorbtwooptions }\) \(\let \LWRorigcellcolor \cellcolor \) \(\renewcommand {\cellcolor }[2][named]{\LWRorigcellcolor [#1]{#2}\LWRabsorbtwooptions }\) \(\newcommand {\tcbset }[1]{}\) \(\newcommand {\tcbsetforeverylayer }[1]{}\) \(\newcommand {\tcbox }[2][]{\boxed {\text {#2}}}\) \(\newcommand {\tcboxfit }[2][]{\boxed {#2}}\) \(\newcommand {\tcblower }{}\) \(\newcommand {\tcbline }{}\) \(\newcommand {\tcbtitle }{}\) \(\newcommand {\tcbsubtitle [2][]{\mathrm {#2}}}\) \(\newcommand {\tcboxmath }[2][]{\boxed {#2}}\) \(\newcommand {\tcbhighmath }[2][]{\boxed {#2}}\) \(\newcommand {\toprule }[1][]{\hline }\) \(\let \midrule \toprule \) \(\let \bottomrule \toprule \) \(\def \LWRbooktabscmidruleparen (#1)#2{}\) \(\newcommand {\LWRbooktabscmidrulenoparen }[1]{}\) \(\newcommand {\cmidrule }[1][]{\ifnextchar (\LWRbooktabscmidruleparen \LWRbooktabscmidrulenoparen }\) \(\newcommand {\morecmidrules }{}\) \(\newcommand {\specialrule }[3]{\hline }\) \(\newcommand {\addlinespace }[1][]{}\) \(\newcommand {\LWRsubmultirow }[2][]{#2}\) \(\newcommand {\LWRmultirow }[2][]{\LWRsubmultirow }\) \(\newcommand {\multirow }[2][]{\LWRmultirow }\) \(\newcommand {\mrowcell }{}\) \(\newcommand {\mcolrowcell }{}\) \(\newcommand {\STneed }[1]{}\) \(\newcommand {\LWRldelimtwo }[1][]{\text {#1}~\LWRbigdelim }\) \(\newcommand {\LWRldelimone }[2][]{\LWRldelimtwo }\) \(\def \ldelim #1#2{\def \LWRbigdelim {#1}\LWRldelimone }\) \(\newcommand {\LWRrdelimtwo }[1][]{\LWRbigdelim ~\text {#1}}\) \(\newcommand {\LWRrdelimone }[2][]{\LWRrdelimtwo }\) \(\def \rdelim #1#2{\def \LWRbigdelim {#1}\LWRrdelimone }\) \(\let \symnormal \mathit \) \(\let \symliteral \mathrm \) \(\let \symbb \mathbb \) \(\let \symbbit \mathbb \) \(\let \symcal \mathcal \) \(\let \symscr \mathscr \) \(\let \symfrak \mathfrak \) \(\let \symsfup \mathsf \) \(\let \symsfit \mathit \) \(\let \symbfsf \mathbf \) \(\let \symbfup \mathbf \) \(\newcommand {\symbfit }[1]{\boldsymbol {#1}}\) \(\let \symbfcal \mathcal \) \(\let \symbfscr \mathscr \) \(\let \symbffrak \mathfrak \) \(\let \symbfsfup \mathbf \) \(\newcommand {\symbfsfit }[1]{\boldsymbol {#1}}\) \(\let \symup \mathrm \) \(\let \symbf \mathbf \) \(\let \symit \mathit \) \(\let \symsf \symsfit \) \(\let \symtt \mathtt \) \(\let \symbffrac \mathbffrac \) \(\newcommand {\mathfence }[1]{\mathord {#1}}\) \(\newcommand {\mathover }[1]{#1}\) \(\newcommand {\mathunder }[1]{#1}\) \(\newcommand {\mathaccent }[1]{#1}\) \(\newcommand {\mathbotaccent }[1]{#1}\) \(\newcommand {\mathalpha }[1]{\mathord {#1}}\) \(\def\Alpha{\unicode{x1D6E2}}\) \(\def\Beta{\unicode{x1D6E3}}\) \(\def\Gamma{\unicode{x1D6E4}}\) \(\def\Digamma{\mathit{\unicode{x03DC}}}\) \(\def\Delta{\unicode{x1D6E5}}\) \(\def\Epsilon{\unicode{x1D6E6}}\) \(\def\Zeta{\unicode{x1D6E7}}\) \(\def\Eta{\unicode{x1D6E8}}\) \(\def\Theta{\unicode{x1D6E9}}\) \(\def\Vartheta{\unicode{x1D6F3}}\) \(\def\Iota{\unicode{x1D6EA}}\) \(\def\Kappa{\unicode{x1D6EB}}\) \(\def\Lambda{\unicode{x1D6EC}}\) \(\def\Mu{\unicode{x1D6ED}}\) \(\def\Nu{\unicode{x1D6EE}}\) \(\def\Xi{\unicode{x1D6EF}}\) \(\def\Omicron{\unicode{x1D6F0}}\) \(\def\Pi{\unicode{x1D6F1}}\) \(\def\Rho{\unicode{x1D6F2}}\) \(\def\Sigma{\unicode{x1D6F4}}\) \(\def\Tau{\unicode{x1D6F5}}\) \(\def\Upsilon{\unicode{x1D6F6}}\) \(\def\Phi{\unicode{x1D6F7}}\) \(\def\Chi{\unicode{x1D6F8}}\) \(\def\Psi{\unicode{x1D6F9}}\) \(\def\Omega{\unicode{x1D6FA}}\) \(\def\alpha{\unicode{x1D6FC}}\) \(\def\beta{\unicode{x1D6FD}}\) \(\def\varbeta{\unicode{x03D0}}\) \(\def\gamma{\unicode{x1D6FE}}\) \(\def\digamma{\mathit{\unicode{x03DD}}}\) \(\def\delta{\unicode{x1D6FF}}\) \(\def\epsilon{\unicode{x1D716}}\) \(\def\varepsilon{\unicode{x1D700}}\) \(\def\zeta{\unicode{x1D701}}\) \(\def\eta{\unicode{x1D702}}\) \(\def\theta{\unicode{x1D703}}\) \(\def\vartheta{\unicode{x1D717}}\) \(\def\iota{\unicode{x1D704}}\) \(\def\kappa{\unicode{x1D705}}\) \(\def\varkappa{\unicode{x1D718}}\) \(\def\lambda{\unicode{x1D706}}\) \(\def\mu{\unicode{x1D707}}\) \(\def\nu{\unicode{x1D708}}\) \(\def\xi{\unicode{x1D709}}\) \(\def\omicron{\unicode{x1D70A}}\) \(\def\pi{\unicode{x1D70B}}\) \(\def\varpi{\unicode{x1D71B}}\) \(\def\rho{\unicode{x1D70C}}\) \(\def\varrho{\unicode{x1D71A}}\) \(\def\sigma{\unicode{x1D70E}}\) \(\def\varsigma{\unicode{x1D70D}}\) \(\def\tau{\unicode{x1D70F}}\) \(\def\upsilon{\unicode{x1D710}}\) \(\def\phi{\unicode{x1D719}}\) \(\def\varphi{\unicode{x1D711}}\) \(\def\chi{\unicode{x1D712}}\) \(\def\psi{\unicode{x1D713}}\) \(\def\omega{\unicode{x1D714}}\) \(\def\upAlpha{\unicode{x0391}}\) \(\def\upBeta{\unicode{x0392}}\) \(\def\upGamma{\unicode{x0393}}\) \(\def\upDigamma{\unicode{x03DC}}\) \(\def\upDelta{\unicode{x0394}}\) \(\def\upEpsilon{\unicode{x0395}}\) \(\def\upZeta{\unicode{x0396}}\) \(\def\upEta{\unicode{x0397}}\) \(\def\upTheta{\unicode{x0398}}\) \(\def\upVartheta{\unicode{x03F4}}\) \(\def\upIota{\unicode{x0399}}\) \(\def\upKappa{\unicode{x039A}}\) \(\def\upLambda{\unicode{x039B}}\) \(\def\upMu{\unicode{x039C}}\) \(\def\upNu{\unicode{x039D}}\) \(\def\upXi{\unicode{x039E}}\) \(\def\upOmicron{\unicode{x039F}}\) \(\def\upPi{\unicode{x03A0}}\) \(\def\upVarpi{\unicode{x03D6}}\) \(\def\upRho{\unicode{x03A1}}\) \(\def\upSigma{\unicode{x03A3}}\) \(\def\upTau{\unicode{x03A4}}\) \(\def\upUpsilon{\unicode{x03A5}}\) \(\def\upPhi{\unicode{x03A6}}\) \(\def\upChi{\unicode{x03A7}}\) \(\def\upPsi{\unicode{x03A8}}\) \(\def\upOmega{\unicode{x03A9}}\) \(\def\itAlpha{\unicode{x1D6E2}}\) \(\def\itBeta{\unicode{x1D6E3}}\) \(\def\itGamma{\unicode{x1D6E4}}\) \(\def\itDigamma{\mathit{\unicode{x03DC}}}\) \(\def\itDelta{\unicode{x1D6E5}}\) \(\def\itEpsilon{\unicode{x1D6E6}}\) \(\def\itZeta{\unicode{x1D6E7}}\) \(\def\itEta{\unicode{x1D6E8}}\) \(\def\itTheta{\unicode{x1D6E9}}\) \(\def\itVartheta{\unicode{x1D6F3}}\) \(\def\itIota{\unicode{x1D6EA}}\) \(\def\itKappa{\unicode{x1D6EB}}\) \(\def\itLambda{\unicode{x1D6EC}}\) \(\def\itMu{\unicode{x1D6ED}}\) \(\def\itNu{\unicode{x1D6EE}}\) \(\def\itXi{\unicode{x1D6EF}}\) \(\def\itOmicron{\unicode{x1D6F0}}\) \(\def\itPi{\unicode{x1D6F1}}\) \(\def\itRho{\unicode{x1D6F2}}\) \(\def\itSigma{\unicode{x1D6F4}}\) \(\def\itTau{\unicode{x1D6F5}}\) \(\def\itUpsilon{\unicode{x1D6F6}}\) \(\def\itPhi{\unicode{x1D6F7}}\) \(\def\itChi{\unicode{x1D6F8}}\) \(\def\itPsi{\unicode{x1D6F9}}\) \(\def\itOmega{\unicode{x1D6FA}}\) \(\def\upalpha{\unicode{x03B1}}\) \(\def\upbeta{\unicode{x03B2}}\) \(\def\upvarbeta{\unicode{x03D0}}\) \(\def\upgamma{\unicode{x03B3}}\) \(\def\updigamma{\unicode{x03DD}}\) \(\def\updelta{\unicode{x03B4}}\) \(\def\upepsilon{\unicode{x03F5}}\) \(\def\upvarepsilon{\unicode{x03B5}}\) \(\def\upzeta{\unicode{x03B6}}\) \(\def\upeta{\unicode{x03B7}}\) \(\def\uptheta{\unicode{x03B8}}\) \(\def\upvartheta{\unicode{x03D1}}\) \(\def\upiota{\unicode{x03B9}}\) \(\def\upkappa{\unicode{x03BA}}\) \(\def\upvarkappa{\unicode{x03F0}}\) \(\def\uplambda{\unicode{x03BB}}\) \(\def\upmu{\unicode{x03BC}}\) \(\def\upnu{\unicode{x03BD}}\) \(\def\upxi{\unicode{x03BE}}\) \(\def\upomicron{\unicode{x03BF}}\) \(\def\uppi{\unicode{x03C0}}\) \(\def\upvarpi{\unicode{x03D6}}\) \(\def\uprho{\unicode{x03C1}}\) \(\def\upvarrho{\unicode{x03F1}}\) \(\def\upsigma{\unicode{x03C3}}\) \(\def\upvarsigma{\unicode{x03C2}}\) \(\def\uptau{\unicode{x03C4}}\) \(\def\upupsilon{\unicode{x03C5}}\) \(\def\upphi{\unicode{x03D5}}\) \(\def\upvarphi{\unicode{x03C6}}\) \(\def\upchi{\unicode{x03C7}}\) \(\def\uppsi{\unicode{x03C8}}\) \(\def\upomega{\unicode{x03C9}}\) \(\def\italpha{\unicode{x1D6FC}}\) \(\def\itbeta{\unicode{x1D6FD}}\) \(\def\itvarbeta{\unicode{x03D0}}\) \(\def\itgamma{\unicode{x1D6FE}}\) \(\def\itdigamma{\mathit{\unicode{x03DD}}}\) \(\def\itdelta{\unicode{x1D6FF}}\) \(\def\itepsilon{\unicode{x1D716}}\) \(\def\itvarepsilon{\unicode{x1D700}}\) \(\def\itzeta{\unicode{x1D701}}\) \(\def\iteta{\unicode{x1D702}}\) \(\def\ittheta{\unicode{x1D703}}\) \(\def\itvartheta{\unicode{x1D717}}\) \(\def\itiota{\unicode{x1D704}}\) \(\def\itkappa{\unicode{x1D705}}\) \(\def\itvarkappa{\unicode{x1D718}}\) \(\def\itlambda{\unicode{x1D706}}\) \(\def\itmu{\unicode{x1D707}}\) \(\def\itnu{\unicode{x1D708}}\) \(\def\itxi{\unicode{x1D709}}\) \(\def\itomicron{\unicode{x1D70A}}\) \(\def\itpi{\unicode{x1D70B}}\) \(\def\itvarpi{\unicode{x1D71B}}\) \(\def\itrho{\unicode{x1D70C}}\) \(\def\itvarrho{\unicode{x1D71A}}\) \(\def\itsigma{\unicode{x1D70E}}\) \(\def\itvarsigma{\unicode{x1D70D}}\) \(\def\ittau{\unicode{x1D70F}}\) \(\def\itupsilon{\unicode{x1D710}}\) \(\def\itphi{\unicode{x1D719}}\) \(\def\itvarphi{\unicode{x1D711}}\) \(\def\itchi{\unicode{x1D712}}\) \(\def\itpsi{\unicode{x1D713}}\) \(\def\itomega{\unicode{x1D714}}\) \(\let \lparen (\) \(\let \rparen )\) \(\newcommand {\cuberoot }[1]{\,{}^3\!\!\sqrt {#1}}\,\) \(\newcommand {\fourthroot }[1]{\,{}^4\!\!\sqrt {#1}}\,\) \(\newcommand {\longdivision }[1]{\mathord {\unicode {x027CC}#1}}\) \(\newcommand {\mathcomma }{,}\) \(\newcommand {\mathcolon }{:}\) \(\newcommand {\mathsemicolon }{;}\) \(\newcommand {\overbracket }[1]{\mathinner {\overline {\ulcorner {#1}\urcorner }}}\) \(\newcommand {\underbracket }[1]{\mathinner {\underline {\llcorner {#1}\lrcorner }}}\) \(\newcommand {\overbar }[1]{\mathord {#1\unicode {x00305}}}\) \(\newcommand {\ovhook }[1]{\mathord {#1\unicode {x00309}}}\) \(\newcommand {\ocirc }[1]{\mathord {#1\unicode {x0030A}}}\) \(\newcommand {\candra }[1]{\mathord {#1\unicode {x00310}}}\) \(\newcommand {\oturnedcomma }[1]{\mathord {#1\unicode {x00312}}}\) \(\newcommand {\ocommatopright }[1]{\mathord {#1\unicode {x00315}}}\) \(\newcommand {\droang }[1]{\mathord {#1\unicode {x0031A}}}\) \(\newcommand {\leftharpoonaccent }[1]{\mathord {#1\unicode {x020D0}}}\) \(\newcommand {\rightharpoonaccent }[1]{\mathord {#1\unicode {x020D1}}}\) \(\newcommand {\vertoverlay }[1]{\mathord {#1\unicode {x020D2}}}\) \(\newcommand {\leftarrowaccent }[1]{\mathord {#1\unicode {x020D0}}}\) \(\newcommand {\annuity }[1]{\mathord {#1\unicode {x020E7}}}\) \(\newcommand {\widebridgeabove }[1]{\mathord {#1\unicode {x020E9}}}\) \(\newcommand {\asteraccent }[1]{\mathord {#1\unicode {x020F0}}}\) \(\newcommand {\threeunderdot }[1]{\mathord {#1\unicode {x020E8}}}\) \(\newcommand {\Bbbsum }{\mathop {\unicode {x2140}}\limits }\) \(\newcommand {\oiint }{\mathop {\unicode {x222F}}\limits }\) \(\newcommand {\oiiint }{\mathop {\unicode {x2230}}\limits }\) \(\newcommand {\intclockwise }{\mathop {\unicode {x2231}}\limits }\) \(\newcommand {\ointclockwise }{\mathop {\unicode {x2232}}\limits }\) \(\newcommand {\ointctrclockwise }{\mathop {\unicode {x2233}}\limits }\) \(\newcommand {\varointclockwise }{\mathop {\unicode {x2232}}\limits }\) \(\newcommand {\leftouterjoin }{\mathop {\unicode {x27D5}}\limits }\) \(\newcommand {\rightouterjoin }{\mathop {\unicode {x27D6}}\limits }\) \(\newcommand {\fullouterjoin }{\mathop {\unicode {x27D7}}\limits }\) \(\newcommand {\bigbot }{\mathop {\unicode {x27D8}}\limits }\) \(\newcommand {\bigtop }{\mathop {\unicode {x27D9}}\limits }\) \(\newcommand {\xsol }{\mathop {\unicode {x29F8}}\limits }\) \(\newcommand {\xbsol }{\mathop {\unicode {x29F9}}\limits }\) \(\newcommand {\bigcupdot }{\mathop {\unicode {x2A03}}\limits }\) \(\newcommand {\bigsqcap }{\mathop {\unicode {x2A05}}\limits }\) \(\newcommand {\conjquant }{\mathop {\unicode {x2A07}}\limits }\) \(\newcommand {\disjquant }{\mathop {\unicode {x2A08}}\limits }\) \(\newcommand {\bigtimes }{\mathop {\unicode {x2A09}}\limits }\) \(\newcommand {\modtwosum }{\mathop {\unicode {x2A0A}}\limits }\) \(\newcommand {\sumint }{\mathop {\unicode {x2A0B}}\limits }\) \(\newcommand {\intbar }{\mathop {\unicode {x2A0D}}\limits }\) \(\newcommand {\intBar }{\mathop {\unicode {x2A0E}}\limits }\) \(\newcommand {\fint }{\mathop {\unicode {x2A0F}}\limits }\) \(\newcommand {\cirfnint }{\mathop {\unicode {x2A10}}\limits }\) \(\newcommand {\awint }{\mathop {\unicode {x2A11}}\limits }\) \(\newcommand {\rppolint }{\mathop {\unicode {x2A12}}\limits }\) \(\newcommand {\scpolint }{\mathop {\unicode {x2A13}}\limits }\) \(\newcommand {\npolint }{\mathop {\unicode {x2A14}}\limits }\) \(\newcommand {\pointint }{\mathop {\unicode {x2A15}}\limits }\) \(\newcommand {\sqint }{\mathop {\unicode {x2A16}}\limits }\) \(\newcommand {\intlarhk }{\mathop {\unicode {x2A17}}\limits }\) \(\newcommand {\intx }{\mathop {\unicode {x2A18}}\limits }\) \(\newcommand {\intcap }{\mathop {\unicode {x2A19}}\limits }\) \(\newcommand {\intcup }{\mathop {\unicode {x2A1A}}\limits }\) \(\newcommand {\upint }{\mathop {\unicode {x2A1B}}\limits }\) \(\newcommand {\lowint }{\mathop {\unicode {x2A1C}}\limits }\) \(\newcommand {\bigtriangleleft }{\mathop {\unicode {x2A1E}}\limits }\) \(\newcommand {\zcmp }{\mathop {\unicode {x2A1F}}\limits }\) \(\newcommand {\zpipe }{\mathop {\unicode {x2A20}}\limits }\) \(\newcommand {\zproject }{\mathop {\unicode {x2A21}}\limits }\) \(\newcommand {\biginterleave }{\mathop {\unicode {x2AFC}}\limits }\) \(\newcommand {\bigtalloblong }{\mathop {\unicode {x2AFF}}\limits }\) \(\newcommand {\arabicmaj }{\mathop {\unicode {x1EEF0}}\limits }\) \(\newcommand {\arabichad }{\mathop {\unicode {x1EEF1}}\limits }\)

5.6 Problems

Cellular Automata

Exercise 5.15. A cellular automaton is a simple “machine” that can change its internal state in response to the states of nearby automata. We already met such automata in Exercise 2.6: in the Game of Life, cells live and die on a two-dimensional grid depending on the number of neighbors in their immediate vicinity.

In this exercise we are concerned with elementary cellular automata, which are the simplest such automata: They have two internal states, on or off, and are influenced by their direct neighbors to the left and right. The behavior of such an automaton can be specified graphically as follows:

The three squares in the top row show the current state of a cell and its two neighbors. Since each cell can be either on or off, there are \(2^3=8\) different configurations of these three cells. The single square in the bottom row indicates the new state of the cell in the center. For example, the first column tells us that a cell turns off if it is surrounded by two active cells. This transition table is also called the automaton’s rule.

We can visualize the behavior of different rules by starting with a row of cells in which only the one in the center is on:

(-tikz- diagram)

We assume that cells wrap around, which means that the leftmost and rightmost cells are considered neighbors; this convention is also known as periodic boundary conditions. We can now determine the new state of each cell using the rule shown above. Since most cells and their neighbors are off, the last column of the rule tells us that they remain off; The exception are the three cells in the center, which turn on. After the first step the cells are in the following state:

(-tikz- diagram)

In the next generation, the three cells in the center have more than one active cell in their neighborhood so they turn off, but the two cells on the boundary turn on:

(-tikz- diagram)

If you continue in this way and stack all the generations on top of each other, you obtain the image shown in Fig. 5.7. It’s our old friend the Sierpiński triangle, this time produced using a cellular automaton.

Figure 5.7 Successive generations of the cellular automaton discussed in the text. The top row contains a single active cell in the center, and each successive row shows the evolution of the previous row.
  • a) Consider the rule shown in the following picture:

    Start again with a single active cell and manually construct the next five generations. What pattern do you observe?

In our discussion so far, we have described cellular automata in a tabular form, by listing all combinations of cells and their two direct neighbors in the top row and the resulting state in the bottom row. The top row is fixed, but the bottom row can be chosen freely, so there are \(2^8=256\) different elementary automata. We can assign a unique integer to each such automaton by interpreting the bottom row as a binary number. For instance, the bottom row of the cellular automaton that generates the Sierpiński triangle corresponds to the binary number \(00010110_2\), which is 22 in decimal; this rule is therefore called rule 22.

  • b) What is the number of the rule in part (a)?

  • c) Write a program that takes a rule as a number between 0 and 255 and simulates the corresponding cellular automaton by evolving a one-dimensional array of cells, returning a new array of cells. Use periodic boundary conditions.

  • d) Study the behavior of all 256 elementary cellular automata by creating images similar to the one in Fig. 5.7. Which rules generate interesting patterns?

Large Bit Sets

Exercise 5.16.In Section 5.4 we discussed how to represent sets of small integers using bits and how to perform elementary set operations using bit operations. In this exercise we will implement a class BitSet that uses arrays of integers to store and manipulate bit sets of arbitrary size.

An outline of the class we will implement is shown in Listing 5.10. There is a single field bits[] that holds the bit set itself. The size of the array determines the range of integers that can be stored in the data structure: An array of \(n\) long integers has \(64n\) bits and can therefore represent sets of integers in the range from 0 up to and including \(64n-1\). All methods that modify the bit set must enlarge the array if necessary.

Listing 5.10ch5 / BitSet

// A set of integers stored in an array of bits.
public class BitSet implements Iterable<Integer> {
    private long[] bits = new long[1];

    public BitSet() {}

    // ...
}

Let’s start with our first set of methods that handles access to individual elements of the set.

  • a) Implement an add() method that adds a number to the bit set by setting the corresponding bit to 1. The method must enlarge the bits[] array if necessary.

    public boolean add(int value);
    

    The return value of add() indicates whether the set was modified by the operation, in other words, it returns true if value wasn’t contained in the set before.

  • b) Implement contains() and remove().

    public boolean contains(int value);
    public boolean remove(int value);
    

    The contains() method tests whether an integer is contained in the set, and remove() removes an integer from the set. How do you handle numbers that lie outside the range of the current bits[] array?

The default constructor in Listing 5.10 creates an empty set, but often it’s convenient to be able to initialize the set using either an existing bit set or an arbitrary collection of integers.

  • c) Implement the following two constructors:

    public BitSet(BitSet other);
    public BitSet(Collection<Integer> other);
    

    Both constructors create a new bit set from a given set or collection of integers.

  • d) Implement equals() and hashCode().

    public boolean equals(Object o);
    public int hashCode();
    

    The equals() and hashCode() methods should be implemented in such a way that any two BitSets that contain the same numbers are considered equal and have the same hash code.

  • e) Implement size() and isEmpty().

    public int size();
    public boolean isEmpty();
    

    The size() method returns the number of elements in the bit set (that is, the population count of the bit pattern), and isEmpty() checks if the set is empty.

  • f) Implement the following four methods.

    public boolean containsAll(BitSet other);
    public boolean addAll(BitSet other);
    public boolean removeAll(BitSet other);
    public boolean retainAll(BitSet other);
    

    The containsAll() method implements the subset relation \(\mathtt {this}\subseteq \mathtt {other}\) and returns true if all elements of this are also contained in other. The other three methods modify the elements of this based on the elements of other: addAll() adds all elements of other, effectively computing the set union \(S\cup T\); removeAll() removes all elements contained in other which corresponds to the set difference \(S-T\); and retainAll() removes all elements that are not contained in other which corresponds to the set intersection \(S\cap T\).

BitSet implements the Iterable interface, which makes it possible to iterate over the elements of the set. This interface requires that we implement a single method iterator() that creates a new Iterator object that can be used to loop over the numbers stored in the set.

// Iteration
public Iterator<Integer> iterator();

(The Iterator interface is described in Appendix B.5.)

  • g) Design a class Iter that implements Iterator and can be used to iterate over the elements of a BitSet. Implement BitSet.iterator(). Hint: Since the class needs access to the internal representation of BitSet, it should be defined as a nested class.

Counting Bits

Exercise 5.17.The number of 1-bits in a bit sequence, often called its population count, is an important quantity that naturally occurs in many applications. The population count is simply the sideways sum of the binary digits; for example, the population count of \(11010111\) is \(1+1+0+1+0+1+1+1=6\). In this exercise we discuss a fast algorithm for computing the population count.2

To count the 1-bits in a number \(n\), we can use a divide-and-conquer algorithm that is similar to the recursive min function we discussed in Section 3.1: split \(n\) into to halves, count the bits in each half and then add the results. If we repeat this process recursively, splitting each sequence of bits into smaller and smaller parts, we are eventually left with the problem of computing the population count of a single bit, which is just the value of the bit itself. For example, to count the bits in 11010010, we first split it into two halves 1101 and 0010, then into groups of two bits, and finally into individual bits as shown in the left part of Fig. 5.8.

Figure 5.8 Counting bits using divide-and-conquer. First divide the bits into smaller groups, then add them pairwise.

We then work our way up, counting the number of bits in each subtree by starting at the leaves and replacing each node with the sum of its two children. For the 2-bit groups, the population counts are 2, 1, 0, and 1; for the 4-bit groups \(2+1=3\) and \(0+1=1\), and for the original 8-bit number \(3+1=4\). This phase of the algorithm illustrated in the right part of Fig. 5.8.

By itself, this decomposition doesn’t buy us anything: To compute the population count of a \(B\)-bit integer, it still requires \(B-1\) additions, which is no better than iterating over the bits one by one. But there is a trick that lets us compute the numbers at each level of the tree in parallel. Consider the nodes just above the leaves, each of which holds the sum of of a pair of adjacent bits. We can compute these four sums in parallel by extracting the bits at odd positions and the bits at even positions, aligning the resulting bit patterns by shifting the bits at odd positions one place to the right, and then adding the bit patterns as if they were regular integers.

Let’s see how this works for \(n=11010010_2\). First we extract from the bit pattern of \(n\) the bits at even and the bits at odd positions and shift the odd bits one place to the right:

\begin{align*} n \AND 01010101_2 &= 01010000_2 && \text {even bits}\\ (n \AND 10101010_2) \shr 1 &= 01000001_2 && \text {odd bits} \end{align*} Adding these two bit patterns yields

\begin{align*} & 01010000_2\\ + & 01000001_2\\ = & 10010001_2. \end{align*} If we interpret the result as four 2-bit numbers, the result is \((10_2,01_2,00_2,01_2)\) or \((2, 1, 0, 1)\), which is the number of bits in the 2-bit groups of the original number \(n\). The whole computation can be implemented using just a few bit operations and one addition:

int n2 = (n & 0x55) + ((n >>> 1) & 0x55);

(By shifting n before extracting the bits at even positions, we can use the same bit mask 0x55 twice.) By adding even and odd bits in this way, we effectively perform four additions in parallel!

Each 2-bit block of n2 now contains a number between 0 and 2. Using almost the same trick again, we can sum all 2-bit blocks in parallel:

int n4 = (n2 & 0x33) + ((n2 >>> 2) & 0x33)

This extracts all 2-bit blocks at odd and even positions, aligns them, and adds them to produce two 4-bit numbers that again hold contain the number of bits in the corresponding region of the original number \(n\). Finally, we add the two resulting 4-bit numbers:

int n8 = (n & 0x0f) + ((n >>> 4) & 0x0f)

The variable n8 now holds the population count of the original number n.

Extend this scheme to compute the population count of a 64-bit integer and implement the resulting algorithm.

Exercise 5.18.There is an elegant algorithm for counting the number of trailing zero-bits in an integer that is based on the idea of binary search. Suppose we want to compute \(\text {ntz}(64, v)\), the number of trailing zeros in a 64-bit integer \(v\). If the lower 32 bits of \(v\) are all 0, we count the number of trailing zeros in the upper half of \(v\) and add \(32\); otherwise, we simply count the number of trailing zeros in the lower half of \(v\):

\begin{equation*} \text {ntz}(64, v) = \begin{cases} 32+\text {ntz}(32, v \shr 32) & \text {if the lower 32~bits of $v$ are zero};\\ \text {ntz}(32, v) & \text {otherwise}. \end {cases} \end{equation*}

We can use the same idea to express \(\text {ntz}(32,v)\) in terms of \(\text {ntz}(16, v)\), and so on. Since every step halves the number of bits that must be inspected, computing the number of trailing zeros of an \(n\)-bit integer requires just \(O(\log _2 n)\) steps.

  • a) The base case of the recursive scheme sketched above is the function \(\text {ntz}(1, v)\), which computes the number of trailing zeros of a 1-bit number \(v\). How is this function defined?

  • b) Use this technique to implement a function countTrailingZeros() that computes the number of trailing zeros of a long integer. Hint: you can get rid of the recursion by rewriting code of the form

    if (v & 0xffffffff != 0) {
        return 32 + ntz(32, v >>> 32);
    } else {
        return ntz(32, v);
    }
    

    as

    int count = 0;
    if (v & 0xffffffff != 0) {
        count += 32;
        v >>>= 32;
    } 
    return count + ntz(32, v);
    
  • c) Use the same idea to define a function \(\text {nlz}(64, v)\) that computes the number of leading zeros of a 64-bit integer \(v\), that is, the number of zeros to the left of the most significant 1-bit.

  • d) Implement a function that computes the number of leading zeros. Can you find a trick to get rid of the recursion?

2 In practice, the fastest way to compute the population count is usually the bitCount() function defined in Long and Integer, which uses hardware instructions if available.