Manual: on division - libzahl - big integer library | |
git clone git://git.suckless.org/libzahl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 07674c3a8eb28b32529ebaf1df5546cd78ceb64d | |
parent 21c3a3445209a0ec3b5085c7807735c47b4af4fb | |
Author: Mattias Andrée <[email protected]> | |
Date: Wed, 1 Jun 2016 19:26:29 +0200 | |
Manual: on division | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M doc/arithmetic.tex | 186 +++++++++++++++++++++++++++++… | |
1 file changed, 185 insertions(+), 1 deletion(-) | |
--- | |
diff --git a/doc/arithmetic.tex b/doc/arithmetic.tex | |
@@ -123,7 +123,191 @@ TODO % zmul zmodmul | |
\section{Division} | |
\label{sec:Division} | |
-TODO % zdiv zmod zdivmod | |
+To calculate the quotient or modulus of two integers, | |
+use either of | |
+ | |
+\begin{alltt} | |
+ void zdiv(z_t quotient, z_t dividend, z_t divisor); | |
+ void zmod(z_t remainder, z_t dividend, z_t divisor); | |
+ void zdivmod(z_t quotient, z_t remainder, | |
+ z_t dividend, z_t divisor); | |
+\end{alltt} | |
+ | |
+\noindent | |
+These function \emph{do not} allow {\tt NULL} | |
+for the output parameters: {\tt quotient} and | |
+{\tt remainder}. The quotient and remainder are | |
+calculated simultaneously and indivisibly, hence | |
+{\tt zdivmod} is provided to calculated both, if | |
+you are only interested in the quotient or only | |
+interested in the remainder, use {\tt zdiv} or | |
+{\tt zmod}, respectively. | |
+ | |
+These functions calculate a truncated quotient. | |
+That is, the result is rounded towards zero. This | |
+means for example that if the quotient is in | |
+$(-1,~1)$, {\tt quotient} gets 0. That that, this | |
+would not be the case for one of the sides of zero. | |
+For example, if the quotient would have been | |
+floored, negative quotients would have been rounded | |
+away from zero. libzahl only provides truncated | |
+division, | |
+ | |
+The remain is defined such that $n = qd + r$ after | |
+calling {\tt zdivmod(q, r, n, d)}. There is no | |
+difference in the remainer between {\tt zdivmod} | |
+and {\tt zmod}. The sign of {\tt d} has no affect | |
+on {\tt r}, {\tt r} will always, unless it is zero, | |
+have the same sign as {\tt n}. | |
+ | |
+There are of course other ways to define integer | |
+division (that is, \textbf{Z} being the codomain) | |
+than as truncated division. For example integer | |
+divison in Python is floored — yes, you did just | |
+read `integer divison in Python is floored,' and | |
+you are correct, that is not the case in for | |
+example C. Users that want another definition | |
+for division than truncated division are required | |
+to implement that themselves. We will however | |
+lend you a hand. | |
+ | |
+\begin{alltt} | |
+ #define isneg(x) (zsignum(x) < 0) | |
+ static z_t one; | |
+ \textcolor{c}{__attribute__((constructor)) static} | |
+ void init(void) \{ zinit(one), zseti(one, 1); \} | |
+ | |
+ static int | |
+ cmpmag_2a_b(z_t a, z_b b) | |
+ \{ | |
+ int r; | |
+ zadd(a, a, a), r = zcmpmag(a, b), zrsh(a, a, 1); | |
+ return r; | |
+ \} | |
+\end{alltt} | |
+ | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_floor(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && isneg(n) != isneg(d)) | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ \} | |
+\end{alltt} | |
+ | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_ceil(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && isneg(n) == isneg(d)) | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ \} | |
+\end{alltt} | |
+ | |
+\begin{alltt} | |
+ /* \textrm{This is how we normally round numbers.} */ | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_half_from_zero(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && cmpmag_2a_b(r, d) >= 0) \{ | |
+ if (isneg(n) == isneg(d)) | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ else | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ \} | |
+ \} | |
+\end{alltt} | |
+ | |
+\noindent | |
+Now to the weird ones that will more often than | |
+not award you a face-slap. % Hade positive punishment | |
+% been legal or even mildly pedagogical. But I would | |
+% not put it past Coca-Cola. | |
+ | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_half_to_zero(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && cmpmag_2a_b(r, d) > 0) \{ | |
+ if (isneg(n) == isneg(d)) | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ else | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ \} | |
+ \} | |
+\end{alltt} | |
+ | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_half_up(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ int cmp; | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && (cmp = cmpmag_2a_b(r, d)) >= 0) \{ | |
+ if (isneg(n) == isneg(d)) | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ else if (cmp) | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ \} | |
+ \} | |
+\end{alltt} | |
+ | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_half_down(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ int cmp; | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && (cmp = cmpmag_2a_b(r, d)) >= 0) \{ | |
+ if (isneg(n) != isneg(d)) | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ else if (cmp) | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ \} | |
+ \} | |
+\end{alltt} | |
+ | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_half_to_even(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ int cmp; | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && (cmp = cmpmag_2a_b(r, d)) >= 0) \{ | |
+ if (cmp || zodd(q)) \{ | |
+ if (isneg(n) != isneg(d)) | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ else | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ \} | |
+ \} | |
+ \} | |
+\end{alltt} | |
+ | |
+\newpage | |
+\begin{alltt} | |
+ void \textcolor{c}{/* \textrm{All arguments most be unique.} */} | |
+ divmod_half_to_odd(z_t q, z_t r, z_t n, z_t d) | |
+ \{ | |
+ int cmp; | |
+ zdivmod(q, r, n, d); | |
+ if (!zzero(r) && (cmp = cmpmag_2a_b(r, d)) >= 0) \{ | |
+ if (cmp || zeven(q)) \{ | |
+ if (isneg(n) != isneg(d)) | |
+ zsub(q, q, one), zadd(r, r, d); | |
+ else | |
+ zadd(q, q, one), zsub(r, r, d); | |
+ \} | |
+ \} | |
+ \} | |
+\end{alltt} | |
+ | |
+% TODO zdivmod's algorithm | |
+ | |
\newpage |