☰

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.4 Bit Sets

So far we have treated the bits in an integer as abstract “bit patterns,” but there is an alternative interpretation that is just as useful. If we identify each bit with its position in the pattern, a group of bits can also be regarded as a set of integers. For instance, a group of four bits can represent all possible sets of the four integers \(0, 1, 2, 3\):

\begin{equation*} \begin{array}{@{}llll@{}} {0000} = \emptyset & {0001} = \{0\} & {0010} = \{1\} & {0011} = \{0,1\}\\ {0100} = \{2\} & {0101} = \{0, 2\}& {0110} = \{1, 2\}& {0111} = \{0, 1, 2\}\\ {1000} = \{3\}& {1001} = \{0, 3\}& {1010} = \{1, 3\}& {1011} = \{0,1, 3\}\\ {1100} = \{2, 3\}& {1101} = \{0, 2, 3\}& {1110} = \{1, 2, 3\}& {1111} = \{0, 1, 2, 3\}\\ \end {array} \end{equation*}

The \(k\)th bit is set to 1 if the number \(k\) is contained in the set. The same idea works for any number of bits: There is a one-to-one correspondence between \(n\)-bit patterns and sets of integers in the range \(0\isep n-1\). Bit patterns that are used in this way are also called bit sets. When working with sets of small integers, bit sets consume far less memory than other set data structures, and they are also significantly faster. As we will see, most set operations can be expressed using simple bit operations.

Constructing Bit Sets

Let’s start with a few ways of constructing bit sets. The empty set \(\emptyset \) is trivial to construct since it is always represented by the number 0, and for singleton sets that contain a single integer \(\{k\}\), the corresponding bit set consists of a single bit at position \(k\), which we can construct by shifting 1 the required number of places to the left:

\begin{align*} \emptyset \quad &\longleftrightarrow \quad 0\\ \{k\}\quad &\longleftrightarrow \quad 1 \shl k \end{align*} The bitwise OR of two or more such singleton sets produces a bit set that contains multiple integers. For instance, the bit set that contains two integers \(k\) and \(l\) has 1-bits at those same positions:

\begin{align*} \{k,l\}\quad &\longleftrightarrow \quad (1\shl k) \OR (1\shl l). \end{align*} Similar relationships hold for more than two elements.

The functions bit() and bits() in Listing 5.5 implement these two operations and return long integers with bits at the specified positions. Notice that the bits() functions has normal set semantics in the sense that the entries in positions can be in any order and contain duplicates. For instance, just as \(\{3, 3, 1\} \) and \(\{1, 3\}\) denote the same set of integers, the two calls bits(3, 3, 1) and bits(1, 3) produce the same bit set.

Listing 5.5ch5β€―/β€―Bits

// Return a long integer that has the k-th bit set.
public static long bit(int k) {return 1L << k;}

// Return a long integer that has the specified bits set.
public static long bits(int... positions) {
    long bits = 0;
    for (int n : positions)
        bits |= 1L << n;
    return bits;
}

A different approach is useful for constructing bit sets that consist of a sequence of consecutive integers. As we discussed in Section 5.2, the bit pattern of \(2^n-1\) consists of \(n\) ones in the least significant bits and zeros elsewhere, whereas the bit pattern of \(-2^n\) consists of \(n\) zeros in the least significant and ones elsewhere. We therefore have the following correspondence between sets and bit sets:

\begin{align*} \{0,1,\ldots ,n-1\}\quad &\longleftrightarrow \quad 2^{n}-1\\ \{n,n+1,\ldots ,63\}\quad &\longleftrightarrow \quad -2^{n} \end{align*} Likewise, the set \(\{k, k+1, \ldots , k+n-1\}\) can be obtained by first computing \(2^n-1\) and then shifting the result \(k\) places to the left. The two functions in Listing 5.6 use these identities to create bit sets for ranges of integers. The first range() function with two arguments creates a bit set that includes every integer from first up to but not including stop. For instance, range(0,0) returns the empty set and range(5, 8) the set \(\{5, 6, 7\}\). The range() function with one argument creates a bit set that includes the numbers between first and 63.

Listing 5.6ch5β€―/β€―Bits

// The bit set containing the numbers first to stop (exclusive).
public static long range(int first, int stop) {
    int n = stop - first;
    long nBits = n == 64 ? -1L : (1L << n) - 1;
    return nBits << first;
}

// The bit set containing the numbers from first to 63.
public static long range(int first) {
    return -(1L << first);
}

A technical detail is worth noting about the implementation of range(). In line 4, where we compute a bit pattern that contains n 1-bits, we handle the case for n == 64 specially. This is necessary because in Java all shift operators don’t behave as expected when shifting a long by 64 or more places or a int by 32 or more places. The details are explained in the following note.

The exact rules Java uses to evaluate bit shifts are somewhat arcane because they are modeled after the behavior of bit shifts instructions on microprocessors in the 1990s. The general rule is that bit shifts of the form x << k, x >> k, and x >>> k use only the lowest six bits of k when x is a 64-bit integer, and only the lowest five bits if x is a 32-bit integer. For this reason, the expression 1L << 64 is equivalent to 1L << 0 because the lowest six bits of 64 are zero; similarly, 1L << 65 is equivalent to 1L << 1. An unfortunate consequence of this rule is that 1L << 64 produces a different result than (1L << 63) << 1. Because this is rarely the expected outcome, it is usually best to shift by at most 63 or 31 places and handle other cases explicitly.

Set Operations

In the implementations of bits() in Listing 5.5, we used the bitwise OR operator to combine multiple individual bits. It’s not hard to see that the OR operator computes the union of two bit sets in general. For example, the union of the two sets \(A=\{1, 4, 7\}\) and \(B=\{0, 5, 7\}\) is \(\{0, 1, 4, 5, 7\}\), and for the corresponding bit sets we have

\begin{equation*} \begin{array}{rr} S & \bits {10010010}\\ T & \bits {10100001}\\ \midrule S \OR T & \bits {10110011} \end {array} \end{equation*}

Similarly, the bitwise AND operator computes the intersection of two sets, that is, the set of all elements that are contained in both sets. The intersection of \(\{1, 4, 7\}\) and \(\{0, 5, 7\}\) is \(\{7\}\), and for the corresponding bits sets we have

\begin{equation*} \begin{array}{rr} S & \bits {10110011}\\ T & \bits {10100001}\\ \midrule S\AND T & \bits {10000000} \end {array} \end{equation*}

Just like the intersection of two sets determines which elements they have in common, the intersection of two bit sets determines which 1-bits they have in common. We therefore have the following correspondences:

\begin{equation*} \boxed { \begin{aligned} S\cup T\quad &\longleftrightarrow \quad S \OR T\\ S\cap T\quad &\longleftrightarrow \quad S \AND T \end {aligned} } \end{equation*}

Finally, the set difference \(S-T\) is defined as the set of elements that are contained in \(S\) but not in \(T\). For example, if \(S=\{1, 4, 7\}\) and \(T=\{0, 5, 7\}\), the set difference is \(S-T=\{1, 4\}\). Conceptually, there are two ways to compute the set difference: You either remove the elements of \(S\) that are also contained in \(T\), or you retain the elements of \(S\) that are not contained in \(T\). This second definition can be expressed as the intersection of \(S\) with the complement of \(T\), that is, the set \(\overline {T}\) that contains all elements that are not in \(T\):

\begin{equation} \label {eq:setdiff} S-T = S \cap \overline {T}. \end{equation}

If \(S=\{1, 4, 7\}\) and \(T=\{0, 5, 7\}\), as in the example above, the set difference can be computes as

\begin{equation*} S-T = \{1, 4, 7\} \cap \{1, 2, 3, 4, 6, 8, \ldots \} = \{1, 4\}. \end{equation*}

The set \(\{1, 2, 3, 4, 6, 8, \ldots \}\) contains all integers except 0, 5, and 7.

The main advantage of expressing set differences in this way is that Eq. (5.9) can be translated directly into bit operations. The complement of a bit set is obtained by inverting all bits using the NOT operator, so the set difference \(S-T\) can be written as S & ~T:

\begin{equation*} \boxed { S-T\quad \longleftrightarrow \quad S\AND \NOT T } \end{equation*}

For instance, if \(S=\bits {10010010}\) and \(T=\bits {10100001}\), the complement of \(T\) is \(\NOT T=\bits {01011110}\) and the set difference \(S\AND \NOT T\) becomes

\begin{equation*} \begin{array}{rr} S & \bits {10010010}\\ \NOT T & \bits {01011110}\\ \midrule S \AND \NOT T & \bits {00010010} \end {array} \end{equation*}

The resulting bit pattern 00010010 can again be interpreted as the set \(\{1, 4\}\).

We can use set intersections to implement several important membership tests for bit sets. For example, two sets share no elements if their intersection is empty, and at least one element if it is nonempty. Similarly, if \(S\) is any set and \(x\) is a single element, the intersection \(S\cap \{x\}\) is empty only if \(S\) doesn’t contain \(x\) :

\begin{equation*} x\in S\quad \iff \quad S\cap \{x\}\ne \emptyset \end{equation*}

Evaluating the right-hand side is trivial for bit sets: A bit set s contains a number k if s & (1 << k) is nonzero.

\begin{equation*} \boxed { x\in S\quad \longleftrightarrow \quad S\AND (1\shl x) \not =0 } \end{equation*}

The functions containsNone(), containsSome(), and contains() in Listing 5.7 implement these three operations for bit sets.

Listing 5.7ch5β€―/β€―Bits

// Return true if the bit sets 's' and 't' are disjoint.
public static boolean containsNone(long s, long t) {
    return (s & t) == 0;
}

// Return true if the bit sets 's' and 't' have common elements.
public static boolean containsSome(long s, long t) {
    return (s & t) != 0;
}

// Return true if the bit set 'set' contains the number 'k'.
public static boolean contains(long set, int k) {
    return (set & (1L << k)) != 0;
}

// Return true if the bitset 't' is a subset of 's'.
public static boolean containsAll(long s, long t) {
    return (s & t) == t;
}

Finally, \(T\) is a subset of \(S\) if the intersection of \(S\) and \(T\) is equal to \(T\):

\begin{equation*} T\subseteq S\quad \text {if and only if}\quad S\cap T=T. \end{equation*}

For bit sets, the right-hand side again translates to a simple expression involving bit operations:

\[ \boxed { T\subseteq S \quad \longleftrightarrow \quad S \AND T = T } \]

The function containsAll() in Listing 5.7 can be used to test whether one bit set is a subset of another. A summary of set operations and their implementation using bits is provided in Table 5.1.

Table 5.1 Correspondence between sets and bit sets
.

Operation

Sets Bit sets

Empty set

\(\emptyset \) 0

Singleton set

\(\{x\}\) 1 << x, bit(x)

Sets of integers

\(\{x_0, x_1,\ldots \}\) (1 << x0) | (1 << x1) | ...
bits(x0, x1, ...)
\(\{a, a+1, \ldots , b-1\}\) range(a, b)
\(\{a, a+1, \ldots , 63\}\) range(a)

Complement

\(\overline S\) ~s

Intersection

\(S\cap T\) s & t

Union

\(S\cup T\) s | t

Difference

\(S-T\) s & ~t

Containment

\(x\in S\) s & (1 << x) != 0

Equality

\(S=T\) s == t

Subset

\(T\subseteq S\) (s & t) == t
Exercises

Exercise 5.10.Given two bit sets s and t, what is the meaning of the expression (s | t) == t?

Exercise 5.11.If \(S\) and \(T\) are bit sets, what is the interpretation of \(S\XOR T\), where “\(\XOR \)” is the XOR operator?