diff options
| author | Mattias Andrée <maandree@kth.se> | 2016-05-14 16:40:46 +0200 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2016-05-14 16:48:57 +0200 |
| commit | 4ff3671b42f011862ab7a8c6b8ddf66780a2054b (patch) | |
| tree | cf71f901d755bf2305c6dc85e0e8870b6549b59d /doc/bit-operations.tex | |
| parent | Fix typo (diff) | |
| download | libzahl-4ff3671b42f011862ab7a8c6b8ddf66780a2054b.tar.gz libzahl-4ff3671b42f011862ab7a8c6b8ddf66780a2054b.tar.bz2 libzahl-4ff3671b42f011862ab7a8c6b8ddf66780a2054b.tar.xz | |
On bit-shifting
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | doc/bit-operations.tex | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/doc/bit-operations.tex b/doc/bit-operations.tex index 83a08ed..3f2938d 100644 --- a/doc/bit-operations.tex +++ b/doc/bit-operations.tex @@ -25,7 +25,63 @@ TODO % zand zor zxor znot \section{Shift} \label{sec:Shift} -TODO % zlsh zrsh +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 \lfloor a \div 2^b \rfloor$, {\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 |
