Add exercise: [HMP32] Modular tetration - libzahl - big integer library | |
git clone git://git.suckless.org/libzahl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit f9fac01b221cd41af5352d95a45ba43b47460a41 | |
parent c9c9a5b8fe7cdde58d2e3b6b21332c4cbd32b9b3 | |
Author: Mattias Andrée <[email protected]> | |
Date: Fri, 29 Jul 2016 12:34:29 +0200 | |
Add exercise: [HMP32] Modular tetration | |
Signed-off-by: Mattias Andrée <[email protected]> | |
Diffstat: | |
M doc/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} |