%% poormanlog.tex 0.07, 2022/05/25 %% (macros not modified since 0.05, 2019/04/22) %% Copyright (C) 2019-2022, Jean-Francois Burnol %% %% This Work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License version 1.3c. %% %% This Work has the LPPL maintenance status `author-maintained`. %% %% The Author of this Work is Jean-Francois Burnol (jfbu AT free DOT fr) %% %% This Work consists of files poormanlog.tex, poormanlog.sty and the %% README %% % % Package macro private prefix: \PML@ % % SEE README FOR USER DOCUMENTATION % \ifx\numexpr\JFBUundefined \message{**** poormanlog requires e-TeX **** LOADING ABORTED ****}% \endinput\fi % % CATCODES (AND AUXILIARIES FOR PLAIN TEX) % \expandafter\edef\csname @tempa\endcsname {% \catcode0 \the\catcode0 % \catcode`\noexpand\_ \the\catcode`\_ % \catcode`\noexpand\^ \the\catcode`\^ % \catcode`\noexpand\: \the\catcode`\: % \catcode`\noexpand\* \the\catcode`\* % \catcode`\noexpand\@ \the\catcode`\@\relax }% \catcode`\@ 11 % \if1\ifx\@namedef\JFBUundefined1\else\ifx\@namedef\relax1\else0\fi\fi \def\@namedef#1{\expandafter\def\csname #1\endcsname}% \def\@nameuse#1{\csname #1\endcsname}% \fi \long\def\@gobble#1{}% % % TABLES % % The algorithm for \PMLogZ is the reverse engineering of the one I did % for \PMPowTen. I had an other approach for log10 initially but it was % less accurate than what testings of \PMPowTen showed. The same accuracy, even % slightly better, was then obtain with \PMLogZ by imitating the latter % algorithm (the original was faster but achieved only about 6ulp max error, % although most of the time the result was correct up to +2 or -2, % the present one appears to achieve not much worse than 1ulp maximal error). % % method of CORDIX type combined with usage of \numexpr "scaling" operations % \@namedef{PML@1@10}{}% \@namedef{PML@1@9}{*1349157701/1071674055}% \@namedef{PML@1@8}{*946017331/596896583}% \@namedef{PML@1@7}{*495834591/248505967}% \@namedef{PML@1@6}{*870020383/346361353}% \@namedef{PML@1@5}{*1499219281/474094764}% \@namedef{PML@1@4}{*1978893117/497075477}% \@namedef{PML@1@3}{*368683859/73562101}% \@namedef{PML@1@2}{*1295603161/205339263}% \@namedef{PML@1@1}{*1268797901/159732192}% \@namedef{PML@1@0}{*10}% % \@namedef{PML@P1@10}{}% \@namedef{PML@P1@9}{*1071674055/1349157701}% \@namedef{PML@P1@8}{*596896583/946017331}% \@namedef{PML@P1@7}{*248505967/495834591}% \@namedef{PML@P1@6}{*346361353/870020383}% \@namedef{PML@P1@5}{*474094764/1499219281}% \@namedef{PML@P1@4}{*497075477/1978893117}% \@namedef{PML@P1@3}{*73562101/368683859}% \@namedef{PML@P1@2}{*205339263/1295603161}% \@namedef{PML@P1@1}{*159732192/1268797901}% \@namedef{PML@P1@0}{/10}% % \@namedef{PML@2@12}{*1759219355/1983514284}% \@namedef{PML@2@11}{*1038555297/1159316503}% \@namedef{PML@2@10}{*1446048050/1598130251}% \@namedef{PML@2@9}{*200795995/219705814}% \@namedef{PML@2@8}{*19701438/21342313}% \@namedef{PML@2@7}{*699035545/749721341}% \@namedef{PML@2@6}{*342419462/363593499}% \@namedef{PML@2@5}{*262151601/275592401}% \@namedef{PML@2@4}{*643237001/669488001}% \@namedef{PML@2@3}{*909207215/936896697}% \@namedef{PML@2@2}{*14850599/15150601}% \@namedef{PML@2@1}{*119401199/120601201}% \@namedef{PML@2@0}{}% \@namedef{PML@2@-1}{*120601201/119401199}% \@namedef{PML@2@-2}{*15150601/14850599}% \@namedef{PML@2@-3}{*936896697/909207215}% \@namedef{PML@2@-4}{*669488001/643237001}% \@namedef{PML@2@-5}{*275592401/262151601}% \@namedef{PML@2@-6}{*363593499/342419462}% \@namedef{PML@2@-7}{*749721341/699035545}% \@namedef{PML@2@-8}{*21342313/19701438}% \@namedef{PML@2@-9}{*219705814/200795995}% \@namedef{PML@2@-10}{*1598130251/1446048050}% \@namedef{PML@2@-11}{*1159316503/1038555297}% \@namedef{PML@2@-12}{*1983514284/1759219355}% % %\@namedef{PML@3@9}{*166909427/168418392}% %\@namedef{PML@3@8}{*233438999/235314001}% %\@namedef{PML@3@7}{*921380630/927852921}% \@namedef{PML@3@6}{*92333611/92889278}% \@namedef{PML@3@5}{*957602399/962402401}% \@namedef{PML@3@4}{*1871252999/1878753001}% \@namedef{PML@3@3}{*739112555/741333222}% \@namedef{PML@3@2}{*2997001/3003001}% \@namedef{PML@3@1}{*11994001/12006001}% \@namedef{PML@3@0}{}% \@namedef{PML@3@-1}{*12006001/11994001}% \@namedef{PML@3@-2}{*3003001/2997001}% \@namedef{PML@3@-3}{*741333222/739112555}% \@namedef{PML@3@-4}{*1878753001/1871252999}% \@namedef{PML@3@-5}{*962402401/957602399}% \@namedef{PML@3@-6}{*92889278/92333611}% %\@namedef{PML@3@-7}{*927852921/921380630}% %\@namedef{PML@3@-8}{*235314001/233438999}% %\@namedef{PML@3@-9}{*168418392/166909427}% % \@namedef{PML@4@5}{*47988001/48012001}% \@namedef{PML@4@4}{*74985001/75015001}% \@namedef{PML@4@3}{*399940003/400060003}% \@namedef{PML@4@2}{*299970001/300030001}% \@namedef{PML@4@1}{*1199940001/1200060001}% \@namedef{PML@4@0}{}% \@namedef{PML@4@-1}{*1200060001/1199940001}% \@namedef{PML@4@-2}{*300030001/299970001}% \@namedef{PML@4@-3}{*400060003/399940003}% \@namedef{PML@4@-4}{*75015001/74985001}% \@namedef{PML@4@-5}{*48012001/47988001}% %% %% %% LOG IN BASE 10 : \the\numexpr\PML@ ddddddddd.\relax %% %% Exactly 9 digits representing d.dddddddd, first one at least 1. %% Goal is to compute log10(d.dddddddd) with 9 digits %% \def\PML@#1.{\expandafter\PML@a\the\numexpr#1/100000.#1.}% \def\PML@a#1.{\expandafter\PML@ai \the\numexpr \ifnum#1>2817 % \ifnum#1>5622 % \ifnum#1>7078 \ifnum#1>8912 10\else 9\fi \else 8% \fi \else \ifnum#1>3547 \ifnum#1>4466 7\else 6\fi \else 5% \fi \fi \else \ifnum#1>1412 % \ifnum#1>1777 \ifnum#1>2238 4\else 3\fi \else 2% \fi \else \ifnum#1>1121 1\else 0\fi \fi \fi .% }% \def\PML@ai #1.#2.% {\expandafter\PML@b\the\numexpr#2\@nameuse{PML@1@#1}.% )*774923109/1784326399+#100000000}% % \def\PML@b#1.{\expandafter\PML@bi\the\numexpr#1/1000000.#1.}% \def\PML@bi#1.{\expandafter\PML@bii \the\numexpr \ifnum#1>994 % \ifnum#1>1056 % \ifnum#1>1088 % \ifnum#1>1110 \ifnum#1>1121 12\else 11\fi \else \ifnum#1>1099 10\else 9\fi \fi \else \ifnum#1>1066 \ifnum#1>1077 8\else 7\fi \else 6% \fi \fi \else \ifnum#1>1024 % \ifnum#1>1035 \ifnum#1>1045 5\else 4\fi \else 3% \fi \else \ifnum#1>1004 \ifnum#1>1014 2\else 1\fi \else 0% \fi \fi \fi \else \ifnum#1>936 % \ifnum#1>965 % \ifnum#1>974 \ifnum#1>984 -1\else -2\fi \else -3% \fi \else \ifnum#1>945 \ifnum#1>955 -4\else -5\fi \else -6% \fi \fi \else \ifnum#1>908 % \ifnum#1>918 \ifnum#1>927 -7\else -8\fi \else -9% \fi \else \ifnum#1>890 \ifnum#1>899 -10\else -11\fi \else -12% \fi \fi \fi \fi .% }% \def\PML@bii#1.#2.% {\expandafter\PML@c\the\numexpr#2\@nameuse{PML@2@#1}.+#10000000}% % \def\PML@c#1.% {\expandafter\PML@ci\the\numexpr#1/1000000-1000.#1.}% \def\PML@ci#1.#2.% {\expandafter\PML@d\the\numexpr#2\@nameuse{PML@3@#1}.+#1000000}% % \def\PML@d#1.% {\expandafter\PML@di\the\numexpr#1/100000-10000.#1.}% \def\PML@di#1.#2.% {\expandafter\PML@e\the\numexpr#2\@nameuse{PML@4@#1}-1000000000.+#100000}% % we have reached % x = 1 + t/10^9 represented by t % log(x) represented by 10^9 times (t/10^9 (2.10^9 - t)/2.10^9) \def\PML@e #1.{(#1*(2000000000-#1)/2000000000+}% %% %% %% POWER OF TEN : \the\numexpr\PML@Pa ddddddddd.\relax %% %% Exactly 9 digits in input representing number 0.ddddddddd %% Goal is to compute 10^0.ddddddddd with 9 digits. %% \def\PML@Pa#1#2{\expandafter\PML@Pai\the\numexpr#1#2/10.#1#2}% \def\PML@Pai#1.#2.{% \expandafter\PML@Pb\the\numexpr(#2-#100000000)*2079839159/90326267.% \@nameuse{PML@P1@#1}% }% % problem with minus sign interfering with token count so simply fetch all % the -#1 is to re-use constants already defined for log \def\PML@Pb#1.{\expandafter\PML@Pbi\the\numexpr-#1/100000000.#1.}% \def\PML@Pbi#1.#2.% {\expandafter\PML@Pc\the\numexpr#2+#100000000.\@nameuse{PML@2@#1}}% % \pm 0.00d, d at most 5, 8 digits integer N for N/10^10 \def\PML@Pc#1.{\expandafter\PML@Pci\the\numexpr-#1/10000000.#1.}% \def\PML@Pci#1.#2.% {\expandafter\PML@Pd\the\numexpr#2+#10000000.\@nameuse{PML@3@#1}}% % \pm 0.000d, d at most 5, 7 digits \def\PML@Pd#1.{\expandafter\PML@Pdi\the\numexpr-#1/1000000.#1.}% \def\PML@Pdi#1.#2.% {\expandafter\PML@Pe\the\numexpr#2+#1000000.\@nameuse{PML@4@#1}}% % \pm 0.0000d, d at most 5, 6 digits integer N for N/10^10 % exp of that must fit in 10 digits, and there will be leading 1, hence % only 9 digits available for fitting x + x^2/2, x = Ne-10 % so we must compute via numexpr % 10^9*x*(1+x/2) = 10^9*N/10^10*(2.10^10+ N)/2.10^10 % with N in absolute value at most 500000. % N*(2.10^9+N/10)/2.10^10 which is about N/10 \def\PML@Pe#1.{(1000000000+#1*(200000000+#1/100)/2000000000)}% %% %% %% BASIC USER INTERFACE : \PMLogZ, \PMPowTen %% % Another way of inserting leading zeros is found in xint source code, % maybe faster. "Z" is for reminding that output has leading zeros. \def\PMLogZ#1% {% \romannumeral-`0\expandafter\@gobble % \PML@ never gives something negative, hopefully... \the\numexpr1000000000+\expandafter\PML@\romannumeral-`0#1.\relax }% \def\PMPowTen#1{\the\numexpr\expandafter\PML@Pa\romannumeral-`0#1.\relax}% \@tempa \endinput