I am writing a GCD calculator in LaTeX.
Here I wrote Euclid's recursive algorithm, which should work with logarithmic time.
The code here counts GCD of 377 and 233 (which is 1). The code works fine, but takes almost nine seconds on my machine (compiled with latexmk
).
\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{etoolbox}
\newcommand*{\programmerdiv}[2]{%
\ifnum #1 = 0\relax%
0%
\else%
\the\numexpr (2*#1 - #2) / (2 * #2) \relax%
\fi%
}
\newcommand*{\modab}[2]{%
\the\numexpr #1 - \programmerdiv{#1}{#2} * #2 \relax%
}
\newcommand*{\gcdab}[2]{%
\ifnum #2 = 0\relax%
#1%
\else%
\gcdab{#2}{\modab{#1}{#2}}%
\fi%
}
\begin{document}
\gcdab{377}{233}
\end{document}
The next pairs of fibonacci sequence numbers as input take much more time: GCD(610, 377) takes 32 seconds to compile; GCD(987, 610) takes 240 seconds. Such growth in compile time is not what I expect, as getting from one pair to another in my examples takes just one Euclid's algorithm step.
I believe the problem is in the recursion: compiling twelve \ifnum
and \modab
of respective numbers for calculating GCD(377, 233) takes just 640 ms. (the compilation time of the file without any computations is around 610ms).
\begin{document}
\ifnum 233 = 0\relax
\else
\modab{377}{233}
\ifnum 144 = 0\relax
\else
\modab{233}{144}
\ifnum 89 = 0\relax
\else
\modab{144}{89}
\ifnum 55 = 0\relax
\else
\modab{89}{55}
\ifnum 34 = 0\relax
\else
\modab{55}{34}
\ifnum 21 = 0\relax
\else
\modab{34}{21}
\ifnum 13 = 0\relax
\else
\modab{21}{13}
\ifnum 8 = 0\relax
\else
\modab{13}{8}
\ifnum 5 = 0\relax
\else
\modab{8}{5}
\ifnum 3 = 0\relax
\else
\modab{5}{3}
\ifnum 2 = 0\relax
\else
\modab{3}{2}
\ifnum 1 = 0\relax
\else
\modab{2}{1}
\ifnum 0 = 0\relax
1
\else
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\fi
\end{document}
What is the problem with this implementation? Why does my recursion take so long and is it possible to write a proper recursion in LaTeX?