\chapter{Bit operations}
\label{chap:Bit operations}

libzahl provides a number of functions that operate on
bits. These can sometimes be used instead of arithmetic
functions for increased performance. You should read
the sections in order.

\vspace{1cm}
\minitoc


\newpage
\section{Boundary}
\label{sec:Boundary}

To retrieve the index of the lowest set bit, use

\begin{alltt}
   size_t zlsb(z_t a);
\end{alltt}

\noindent
It will return a zero-based index, that is, if the
least significant bit is indeed set, it will return 0.

If {\tt a} is a power of 2, it will return the power
of which 2 is raised, effectively calculating the
binary logarithm of {\tt a}. Note, this is only if
{\tt a} is a power of two. More generally, it returns
the number of trailing binary zeroes, if equivalently
the number of times {\tt a} can evenly be divided by
2. However, in the special case where $a = 0$,
{\tt SIZE\_MAX} is returned.

A similar function is

\begin{alltt}
   size_t zbit(z_t a);
\end{alltt}

\noindent
It returns the minimal number of bits require to
represent an integer. That is, $\lceil \log_2 a \rceil - 1$,
or equivalently, the number of times {\tt a} can be
divided by 2 before it gets the value 0. However, in
the special case where $a = 0$, 1 is returned. 0 is
never returned. If you want the value 0 to be returned
if $a = 0$, write

\begin{alltt}
   zzero(a) ? 0 : zbits(a)
\end{alltt}

The definition ``it returns the minimal number
of bits required to represent an integer,''
holds true if $a = 0$, the other divisions
do not hold true if $a = 0$.


\newpage
\section{Shift}
\label{sec:Shift}

There are two functions for shifting bits
in integers:

\begin{alltt}
   void zlsh(z_t r, z_t a, size_t b);
   void zrsh(z_t r, z_t a, size_t b);
\end{alltt}

\noindent
{\tt zlsh} performs a left-shift, and {\tt zrsh}
performs a right-shift. That is, {\tt zlsh} adds
{\tt b} trailing binary zeroes, and {\tt zrsh}
removes the lowest {\tt b} binary digits. So if

$a = \phantom{00}10000101_2$ then

$r = 1000010100_2$ after calling {\tt zlsh(r, a, 2)}, and

$r = \phantom{0100}100001_2$ after calling {\tt zrsh(r, a, 2)}.
\vspace{1em}

{\tt zlsh(r, a, b)} is equivalent to $r \gets a \cdot 2^b$,
and {\tt zrsh(r, a, b)} is equivalent to $r \gets a \div 2^b$,
with truncated division, {\tt zlsh} and {\tt zrsh} are
significantly faster than {\tt zpowu} and should be used
whenever possible. {\tt zpowu} does not check if it is
possible for it to use {\tt zlsh} instead, even if it
would, {\tt zlsh} and {\tt zrsh} would still be preferable
in most cases because it removes the need for {\tt zmul}
and {\tt zdiv}, respectively.

{\tt zlsh} and {\tt zrsh} are implemented in two steps:
(1) shift whole characters, that is, groups of aligned
64 bits, and (2) shift on a bit-level between characters.

If you are implementing a calculator, you may want to
create a wrapper for {\tt zpow} that uses {\tt zlsh}
whenever possible. One such wrapper could be

\begin{alltt}
   void
   pow(z_t r, z_t a, z_t b)
   \{
       size_t s1, s2;
       if ((s1 = zlsb(a)) + 1 == zbits(a) &&
                     zbits(b) <= 8 * sizeof(SIZE_MAX)) \{
           s2 = zzero(b) ? 0 : b->chars[0];
           if (s1 <= SIZE_MAX / s2) \{
               zsetu(r, 1);
               zlsh(r, r, s1 * s2);
               return;
           \}
       \}
       zpow(r, a, b);
   \}
\end{alltt}


\newpage
\section{Truncation}
\label{sec:Truncation}

In \secref{sec:Shift} we have seen how bit-shift
operations can be used to multiply or divide by a
power of two. There is also a bit-truncation
operation: {\tt ztrunc}, which is used to keep
only the lowest bits, or equivalently, calculate
the remainder of a division by a power of two.

\begin{alltt}
   void ztrunc(z_t r, z_t a, size_t b);
\end{alltt}

\noindent
is consistent with {\tt zmod}; like {\tt zlsh} and
{\tt zrsh}, {\tt a}'s sign is preserved into {\tt r}
assuming the result is non-zero.

{\tt ztrunc(r, a, b)} stores only the lowest {\tt b}
bits in {\tt a} into {\tt r}, or equivalently,
calculates $r \gets a \mod 2^b$. For example, if

$a = 100011000_2$ then

$r = \phantom{10001}1000_2$ after calling
{\tt ztrunc(r, a, 4)}.


\newpage
\section{Split}
\label{sec:Split}

In \secref{sec:Shift} and \secref{sec:Truncation}
we have seen how bit operations can be used to
calculate division by a power of two and
modulus a power of two efficiently using
bit-shift and bit-truncation operations. libzahl
also has a bit-split operation that can be used
to efficently calculate both division and
modulus a power of two efficiently in the same
operation, or equivalently, storing low bits
in one integer and high bits in another integer.
This function is

\begin{alltt}
   void zsplit(z_t high, z_t low, z_t a, size_t b);
\end{alltt}

\noindent
Unlike {\tt zdivmod}, it is not more efficient
than calling {\tt zrsh} and {\tt ztrunc}, but
it is more convenient. {\tt zsplit} requires
that {\tt high} and {\tt low} are from each
other distinct references.

Calling {\tt zsplit(high, low, a, b)} is
equivalent to

\begin{alltt}
   ztrunc(low, a, delim);
   zrsh(high, a, delim);
\end{alltt}

\noindent
assuming {\tt a} and {\tt low} are not the
same reference (reverse the order of the
functions if they are the same reference.)

{\tt zsplit} copies the lowest {\tt b} bits
of {\tt a} to {\tt low}, and the rest of the
bits to {\tt high}, with the lowest {\tt b}
removesd. For example, if $a = 1010101111_2$,
then $high = 101010_2$ and $low = 1111_2$
after calling {\tt zsplit(high, low, a, 4)}.

{\tt zsplit} is especially useful in
divide-and-conquer algorithms.


\newpage
\section{Bit manipulation}
\label{sec:Bit manipulation}


The function

\begin{alltt}
   void zbset(z_t r, z_t a, size_t bit, int mode);
\end{alltt}

\noindent
is used to manipulate single bits in {\tt a}. It will
copy {\tt a} into {\tt r} and then, in {\tt r}, either
set, clear, or flip, the bit with the index {\tt bit}
— the least significant bit has the index 0. The
action depend on the value of {\tt mode}:

\begin{itemize}
\item
$mode > 0$ ($+1$): set
\item
$mode = 0$ ($0$): clear
\item
$mode < 0$ ($-1$): flip
\end{itemize}


\newpage
\section{Bit test}
\label{sec:Bit test}

libzahl provides a function for testing whether a bit
in a big integer is set:

\begin{alltt}
   int zbtest(z_t a, size_t bit);
\end{alltt}

\noindent
it will return 1 if the bit with the index {\tt bit}
is set in {\tt a}, counting from the least significant
bit, starting at zero. 0 is returned otherwise. The
sign of {\tt a} is ignored.

We can think of this like so: consider

$$ \lvert a \rvert = \sum_{i = 0}^\infty k_i 2^i,~ k_i \in \{0, 1\}, $$

\noindent
{\tt zbtest(a, b)} returns $k_b$. Equivalently, we can
think that {\tt zbtest(a, b)} return whether $b \in B$
where $B$ is defined by

$$ \lvert a \rvert = \sum_{b \in B} 2^b,~ B \subset \textbf{Z}_+, $$

\noindent
or as right-shifting $a$ by $b$ bits and returning
whether the least significant bit is set.

{\tt zbtest} always returns 1 or 0, but for good
code quality, you should avoid testing against 1,
rather you should test whether the value is a
truth-value or a falsehood-value. However, there
is nothing wrong with depending on the value being
restricted to being either 1 or 0 if you want to
sum up returned values or otherwise use them in
new values.


\newpage
\section{Connectives}
\label{sec:Connectives}

libzahl implements the four basic logical
connectives: and, or, exclusive or, and not.
The functions for these are named {\tt zand},
{\tt zor}, {\tt zxor}, and {\tt znot},
respectively.

The connectives apply to each bit in the
integers, as well as the sign. The sign is
treated as a bit that is set if the integer
is negative, and as cleared otherwise. For
example (integers are in binary):

\begin{alltt}
   zand(r, a, b)              zor(r, a, b)
   a = +1010  (input)         a = +1010  (input)
   b = -1100  (input)         b = -1100  (input)
   r = +1000  (output)        r = -1110  (output)

   zxor(r, a, b)              znot(r, a)
   a = +1010  (input)         a = +1010  (input)
   b = -1100  (input)         r = -0101  (output)
   r = +0110  (output)
\end{alltt}

Remember, in libzahl, integers are represented
with sign and magnitude, not two's complement,
even when using these connectives. Therefore,
more work than just changing the name of the
called function may be required when moving
between big integer libraries. Consequently,
{\tt znot} does not flip bits that are higher
than the highest set bit, which means that
{\tt znot} is nilpotent rather than idempotent.

Below is a list of the value of {\tt a} when
{\tt znot(a, a)} is called repeatedly.

\begin{alltt}
   10101010
   -1010101
     101010
     -10101
       1010
       -101
         10
         -1
          0
          0
          0
\end{alltt}
