Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ etc/tune
tommath.tex
libtommath.pc

# ignore files generated by bibtex/biber
83aea75e0c59d1de027747003151d53dcb2a51c9.bib
*.bbl
*.bcf
*.blg
*.loa
*.lol
*.run.xml


# ignore files generated by testme.sh
gcc_errors_*.txt
test_*.txt
Expand Down
65 changes: 65 additions & 0 deletions demo/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,70 @@ static int test_mp_log_n(void)
return EXIT_FAILURE;
}

static int test_mp_log(void)
{
mp_int a, base, bn, t;
int lb, lb2, i, j;

DOR(mp_init_multi(&a, &base, &bn, &t, NULL));

/*
The small values got tested above for mp_log_n already, leaving the big stuff
with bases larger than INT_MAX.
*/

/* Edgecases a^b and -1+a^b (floor(log_2(256^129)) = 1032) */
for (i = 2; i < 256; i++) {
mp_set_i32(&a,i);
for (j = 2; j < ((i/2)+1); j++) {
DO(mp_expt_n(&a, j, &bn));
mp_set_i32(&base,j);
/* i^j a perfect power */
DO(mp_log(&bn, &a, &lb));
DO(mp_expt_n(&a, lb, &t));
if (mp_cmp(&t, &bn) != MP_EQ) {
fprintf(stderr,"FAILURE mp_log for perf. power at i = %d, j = %d\n", i, j);
goto LBL_ERR;
}
/* -1 + i^j */
DO(mp_decr(&bn));
DO(mp_log(&bn, &a, &lb2));
if (lb != (lb2+1)) {
fprintf(stderr,"FAILURE mp_log for -1 + i^j at i = %d, j = %d\n", i, j);
goto LBL_ERR;
}
}
}

/* Random a, base */
for (i = 1; i < 256; i++) {
DO(mp_rand(&a, i));
for (j = 1; j < ((i/2)+1); j++) {
DO(mp_rand(&base, j));
DO(mp_log(&a, &base, &lb));
DO(mp_expt_n(&base, lb, &bn));
/* "bn" must be smaller than or equal to "a" at this point. */
if (mp_cmp(&bn, &a) == MP_GT) {
fprintf(stderr,"FAILURE mp_log random in GT check");
goto LBL_ERR;
}
DO(mp_mul(&bn, &base, &bn));
/* "bn" must be bigger than "a" at this point. */
if (mp_cmp(&bn, &a) != MP_GT) {
fprintf(stderr,"FAILURE mp_log random in NOT GT check");
goto LBL_ERR;
}
}
}

mp_clear_multi(&a, &base, &bn, &t, NULL);
return EXIT_SUCCESS;
LBL_ERR:
mp_clear_multi(&a, &base, &bn, &t, NULL);
return EXIT_FAILURE;
}


static int test_mp_incr(void)
{
mp_int a, b;
Expand Down Expand Up @@ -2167,6 +2231,7 @@ static int unit_tests(int argc, char **argv)
T1(mp_get_u64, MP_GET_I64),
T1(mp_get_ul, MP_GET_L),
T1(mp_log_n, MP_LOG_N),
T1(mp_log, MP_LOG),
T1(mp_incr, MP_ADD_D),
T1(mp_invmod, MP_INVMOD),
T1(mp_is_square, MP_IS_SQUARE),
Expand Down
27 changes: 14 additions & 13 deletions doc/bn.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1936,14 +1936,21 @@ \section{Root Finding}
\chapter{Logarithm}
\section{Integer Logarithm}
A logarithm function for positive integer input \texttt{a, base} computing $\floor{\log_bx}$ such
that $(\log_b x)^b \le x$.
that $(\log_b x)^b \le x$. The function \texttt{mp\_log\_n} is just a wrapper that converts \texttt{base}
to a bigint and calls \texttt{mp\_log\_n}.

\index{mp\_log}
\begin{alltt}
mp_err mp_log(const mp_int *a, const mp_int *base, int *c)
\end{alltt}

\index{mp\_log\_n}
\begin{alltt}
mp_err mp_log_n(const mp_int *a, int base, int *c)
mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c)
\end{alltt}

\subsection{Example}
Example given for \texttt{mp\_log\_n} only because the single difference is the type of \texttt{base}.
\begin{small}
\begin{alltt}
#include <stdlib.h>
Expand All @@ -1954,15 +1961,15 @@ \subsection{Example}

int main(int argc, char **argv)
{
mp_int x, output;
int base;
mp_int x;
int base, output;
mp_err e;

if (argc != 3) {
fprintf(stderr,"Usage %s base x\textbackslash{}n", argv[0]);
exit(EXIT_FAILURE);
}
if ((e = mp_init_multi(&x, &output, NULL)) != MP_OKAY) {
if ((e = mp_init(&x)) != MP_OKAY) {
fprintf(stderr,"mp_init failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n",
mp_error_to_string(e));
exit(EXIT_FAILURE);
Expand All @@ -1984,15 +1991,9 @@ \subsection{Example}
mp_error_to_string(e));
exit(EXIT_FAILURE);
}
printf("%d\n",output);

if ((e = mp_fwrite(&output, 10, stdout)) != MP_OKAY) {
fprintf(stderr,"mp_fwrite failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n",
mp_error_to_string(e));
exit(EXIT_FAILURE);
}
putchar('\textbackslash{}n');

mp_clear_multi(&x, &output, NULL);
mp_clear(&x);
exit(EXIT_SUCCESS);
}
\end{alltt}
Expand Down
Loading