# libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | LICENSE

commit f9fac01b221cd41af5352d95a45ba43b47460a41
parent c9c9a5b8fe7cdde58d2e3b6b21332c4cbd32b9b3
Author: Mattias Andrée <maandree@kth.se>
Date:   Fri, 29 Jul 2016 12:34:29 +0200

Add exercise: [HMP32] Modular tetration

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
Mdoc/exercises.tex | 130++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---

1 file changed, 126 insertions(+), 4 deletions(-)
diff --git a/doc/exercises.tex b/doc/exercises.tex
@@ -232,7 +232,7 @@ rather than

-\item {[$\RHD$M15]} \textbf{Modular left-shift}
+\item {[\textit{$\RHD$M15}]} \textbf{Modular left-shift}

Implement a function that calculates
$2^a \text{ mod } b$, using \texttt{zmod} and
@@ -242,7 +242,7 @@ parameters are unique pointers.

-\item {[$\RHD$08]} \textbf{Modular left-shift, extended}
+\item {[\textit{$\RHD$08}]} \textbf{Modular left-shift, extended}

{\small\textit{You should already have solved
Modular left-shift'' before you solve this
@@ -253,7 +253,7 @@ to accept negative $b$ and non-unique pointers.

-\item {[13]} \textbf{The totient}
+\item {[\textit{13}]} \textbf{The totient}

The totient of $n$ is the number of integer $a$,
$0 < a < n$ that are relatively prime to $n$.
@@ -271,6 +271,25 @@ and $\varphi(1) = 1$.

+\item {[\textit{HMP32}]} \textbf{Modular tetration}
+
+Implement the function
+
+\vspace{-1em}
+\begin{alltt}
+   void modtetra(z_t r, z_t b, unsigned long n, z_t m);
+\end{alltt}
+\vspace{-1em}
+
+\noindent
+which calculates $r = {}^n{}b \text{ mod } m$, where
+${}^0{}b = 1$, ${}^1{}b = b$, ${}^2{}b = b^b$,
+${}^3{}b = b^{b^b}$, ${}^b{}b = b^{b^{b^b}}$, and so on.
+You can assume $b > 0$ and $m > 0$. You can also assume
+\texttt{r}, \texttt{b}, and \texttt{m} are mutually
+unique pointers.
+
+
\end{enumerate}

@@ -621,7 +640,8 @@ need to evaluate $2^{2^{64}}$.

\vspace{-1em}
\begin{alltt}
-void modlsh(z_t r, z_t a, z_t b)
+void
+modlsh(z_t r, z_t a, z_t b)
\{
z_t t, at;
size_t s = zbits(b);
@@ -679,5 +699,107 @@ then, $\varphi(n) = \varphi|n|$.

+\item \textbf{Modular tetration}
+
+Let \texttt{totient} be Euler's totient function.
+It is described in the problem The totient''.
+
+We need two help function: \texttt{tetra(r, b, n)}
+which calculated $r = {}^n{}b$, and \texttt{cmp\_tetra(a, b, n)}
+which is compares $a$ to ${}^n{}b$.
+
+\vspace{-1em}
+\begin{alltt}
+void
+tetra(z_t r, z_t b, unsigned long n)
+\{
+    zsetu(r, 1);
+    while (n--)
+        pow(r, b, r);
+\}
+\end{alltt}
+\vspace{-1em}
+
+\vspace{-1em}
+\begin{alltt}
+int
+cmp_tetra(z_t a, z_t b, unsigned long n)
+\{
+    z_t B;
+    int cmp;
+
+    if (!n || !zcmpu(b, 1))
+        return zcmpu(a, 1);
+    if (n == 1)
+        return zcmp(a, b);
+    if (zcmp(a, b) >= 0)
+        return +1;
+
+    zinit(B);
+    zsetu(B, 1);
+    while (n) \{
+        zpow(B, b, B);
+        if (zcmp(a, B) < 0) \{
+            zfree(B);
+            return -1;
+        \}
+    \}
+    cmp = zcmp(a, B);
+    zfree(B);
+    return cmp;
+
+\}
+\end{alltt}
+\vspace{-1em}
+
+\texttt{tetra} can generate unmaintainably huge
+numbers. Will however only call \texttt{tetra}
+when this is not the case.
+
+\vspace{-1em}
+\begin{alltt}
+void
+modtetra(z_t r, z_t b, unsigned long n, z_t m)
+\{
+    z_t t, temp;
+
+    if (n <= 1) \{
+        if (n)
+            zsetu(r, zcmpu(m, 1));
+        else
+            zmod(r, b, m);
+        return;
+    \}
+
+    zmod(r, b, m);
+    if (zcmpu(r, 1) <= 0)
+        return;
+
+    zinit(t);
+    zinit(temp);
+
+    t = totient(m);
+    zgcd(temp, b, m);
+
+    if (!zcmpu(temp, 1)) \{
+        modtetra(temp, b, n - 1, t);
+        zmodpow(r, r, temp, m);
+    \} else if (cmp_tetra(t, b, n - 1) > 0) \{
+        temp = tetra(b, n - 1);
+        zpowmod(r, r, temp, m);
+    \} else \{
+        modtetra(temp, b, n - 1, t);
+        zmodpow(temp, r, temp, m);
+        zmodpow(r, r, t, m);
+        zmodmul(r, r, temp, m);
+    \}
+
+    zfree(temp);
+    zfree(t);
+\}
+\end{alltt}
+\vspace{-1em}
+
+

\end{enumerate}