summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2016-02-13 22:37:21 +0000
committerKarl Berry <karl@freefriends.org>2016-02-13 22:37:21 +0000
commit6aad496527f7643fd4ce0ec486e8204cab355281 (patch)
treefd76656717c7958282922af93a193ef6721e54fb
parent17a147917f94e99da6ae505ccb374b794db49117 (diff)
apnum (13feb16)
git-svn-id: svn://tug.org/texlive/trunk@39710 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Master/texmf-dist/doc/generic/apnum/README1
-rw-r--r--Master/texmf-dist/doc/generic/apnum/apnum.d106
-rw-r--r--Master/texmf-dist/doc/generic/apnum/apnum.pdfbin701961 -> 712774 bytes
-rw-r--r--Master/texmf-dist/tex/generic/apnum/apnum.tex127
4 files changed, 149 insertions, 85 deletions
diff --git a/Master/texmf-dist/doc/generic/apnum/README b/Master/texmf-dist/doc/generic/apnum/README
index 155b8e5d8f8..f926656cce0 100644
--- a/Master/texmf-dist/doc/generic/apnum/README
+++ b/Master/texmf-dist/doc/generic/apnum/README
@@ -25,3 +25,4 @@ Versions:
1.3 <Dec 2015> - many improvements, \SQRT, \LN, \EXP implemented
1.4 <Dec 2015> - \SIN, \COS, \TAN, \ASIN, \ACOS, \ATAN, \PI, \PIhalf added
1.5 <Jan 2016> - \eprint for printing evaluated expressions added.
+1.6 <Feb 2016> - \evalmdef introduced, \EXP improved.
diff --git a/Master/texmf-dist/doc/generic/apnum/apnum.d b/Master/texmf-dist/doc/generic/apnum/apnum.d
index f22485e578b..5698936330a 100644
--- a/Master/texmf-dist/doc/generic/apnum/apnum.d
+++ b/Master/texmf-dist/doc/generic/apnum/apnum.d
@@ -1,6 +1,6 @@
% apnum.tex -- Arbitrary Precision Numbers
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% The documentation, Petr Olsak, 2014
+% The documentation, Petr Olsak, 2014, 2015, 2016
% You can create the pdf version of this documentation by the command
% pdfcsplain apnum.d
@@ -10,7 +10,7 @@
\input utf8off \clearmubyte % use pdfcsplain
-\def\projectversion{1.5 Jan 2016}
+\def\projectversion{1.6 Feb 2016}
\def\headtitle{Arbitrary Precision Numbers}
\widowpenalty=10000
@@ -247,19 +247,21 @@ the text "1.234E-3" means ".001234". The decimal exponent (after the "E"
letter) have to be in the range $\pm\,2\,147\,483\,647$ because
we store this value in normal \TeX{} register.
-The "\evaldef<sequence>{<expression>}" operates by ``normal way'' if there are no operands
-with "E" syntax in the "<expression>". But if an operand is expressed in
-scientific form then "\evaldef" provide the calculation with the mantissa
-and the exponent separately. Only the mantissa of the result is found in the
-"<sequence>" and "\OUT" macros. The exponent of the result is stored in the "\apE"
-register. You can define the macro which shows the complete result of the
+The "\evaldef<sequence>{<expression>}" operates with mantissa and exponent
+separately if there are operands with scientific notation. It outputs the
+result in the scientific notation if the result have non-zero exponent.
+
+The \du{evalmdef}"\evalmdef<sequence>{<expression>}" does the same as "\evaldef"
+but only mantissa is saved in the output "<sequence>" and in the "\OUT" macro.
+The exponent is stored in the "\apE" register in such case.
+You can define the macro which shows the complete result after "\evalmdef"
calculation, for example:
\begtt
\def\showE#1{\message{#1\ifnum\apE=0 \else*10^\the\apE\fi}}
\endtt
-Suppose "\evaldef\foo{<expression>}" is processed and the complete result is
+Suppose "\evalmdef\foo{<expression>}" is processed and the complete result is
$R={}$"\foo*10^\apE". There are two possibilities how to save such complete
result $R$ to the "\foo" macro: use "\apEadd\foo" or "\apEnum\foo". Both
macros do nothing if "\apE=0". Else the \du{apEadd}"\apEadd<sequence>" macro adds
@@ -269,10 +271,10 @@ appends zeros. The "\apE" register is set to zero after the macro "\apEadd" or
"\apEnum" is finished. Example:
\begtt
-\evaldef\foo{ 3 * 4E9 } % \foo is 12, \apE=9
-\apEadd\foo % \foo is 12E+9
-\evaldef\foo{ 7E9 + 5E9 } % \foo is 12, \apE=9
-\apEnum\foo % \foo is 12000000000
+\evalmdef\foo{ 3 * 4E9 } % \foo is 12, \apE=9
+\apEadd\foo % \foo is 12E+9
+\evalmdef\foo{ 7E9 + 5E9 } % \foo is 12, \apE=9
+\apEnum\foo % \foo is 12000000000
\endtt
There are another usable macros for operations with scientific numbers.
@@ -319,12 +321,12 @@ Examples of "\apROUND" usage:
\def\A{12.3456}\apROUND\A{-4} % \A is "0", \XOUT is "00123456"
\endtt
-The following example saves the result of the "\evaldef" in scientific
+The following example saves the result of the "\evalmdef" in scientific
notation with the mantissa with maximal three digits after decimal point and one
digit before.
\begtt
-\evaldef\X{...}\apNORM\X{1}\apROUND\X{3}\apEadd\X
+\evalmdef\X{...}\apNORM\X{1}\apROUND\X{3}\apEadd\X
\endtt
The macros "\apEadd", "\apEnum", "\apROLL", "\apNORM" and "\apROUND" redefine the macro
@@ -334,7 +336,14 @@ The macro "<sequence>" must be the number in the format
"<simple sign><digits>.<digits>" where "<simple sign>" is one minus or none
and the rest of number has the format described in the first paragraph of
this documentation. The scientific notation isn't allowed here. This format
-of numbers is in accordance with the output of the "\evaldef" macro.
+of numbers is in accordance with the output of the "\evalmdef" macro.
+
+The build in function-like macros "\SGN", "\iDIV", \dots "\SIN", "\COS", "\ATAN" etc.\
+don't generate the result in scientific form regardless of its argument is in
+scientific form or not. But there are exceptions: "\ABS" and "\SQRT" returns
+scientific form if the argument is in this form. And "\EXP" returns scientific
+form if the result is greater than $10^{K+1}$ or less than $10^{-K-1}$ where
+$K={}$\du{apEX}"\apEX". The default value of this register is "\apEX=10".
\subsec [pgm] Notes for macro programmers
@@ -343,20 +352,30 @@ If you plan to create a ``function-like'' macro which can be used as an
operand in the "<expression>" then observe that first token in the
macro body must be "\relax". This tells to the "<expression>" scanner that
the calculation follows. The result of this calculation must be saved into
-the "\OUT" macro and into the "\apSIGN" and "\apE" registers.
+the "\OUT" macro and into the "\apSIGN" register.
Example. The "\ABS" macro for the absolute value is defined by:
+\ilabel [abs:eval] {evalmdef}
\ifirst{apnum.tex} {ABS}{^^B\cbrace}{+-}
\begtt
Usage: \evaldef\A{ 2 - \ABS{3-10} }% \A includes -5.
\endtt
-Note, that "\apSIGN" register is corrected by final routine of "\evaldef"
+Note, that "\apSIGN" register is corrected by final routine of the expression scanner
according the "\OUT" value. But setting "\apSIGN" in your macro is
recommended because user can use your macro directly outside of "\evaldef".
+If the result of the function-like macro needs to be expressed by scientific
+notation then you have two possibilities: use ``{\tt E}'' notation in the
+"\OUT" macro and keep "\apE" register zero. Or save the matissa only to the
+"\OUT" macro and set the value of the exponent into the "\apE" register. The
+second possibility is preferred and used by build in function-like macros.
+Note the "\ABS" definition above: the "\evalmdef" in the line~\cite[abs:eval]
+keeps only mantissa in
+the "\OUT" macro and the "\apE" register is set by "\evalmdef" itself.
+
The "\evaldef\foo{<expression>}" is processed in two steps. The
"<expression>" scanner converts the input to the macro call of the
\du{apPLUS}"\apPLUS", \du{apMINUS}"\apMINUS", \du{apMUL}"\apMUL",
@@ -598,7 +617,8 @@ We declare auxiliary counters and one Boolean variable.
\inext{newcount}{\empty}{+-}
-The counters \db apSIGN , \db apE , \db apTOT and \db apFRAC are declared here:
+The counters \db apSIGN , \db apE , \db apTOT, \db apFRAC and \db apEX
+are declared here:
\inext{newcount}{\empty}{+-}
@@ -655,19 +675,20 @@ push new couple ``operand, operator'' from the expression scanner.
In both cases try to execute the top of the stack again.
If the bottom of the stack is reached then the last operand is the result.
-The \db evaldef macro is protected by "\relax". It means that it can be used
+The \db evaldef and \db evalmdef macros are protected by
+"\relax". It means that it can be used
inside an "<expression>" as a ``function-like'' macro, but I don't imagine
any usual application of this. The "\apEVALa" is executed.
-\inext{apEVAL}{}{++}
+\inext{evaldef}{evalmdef}{++}
-The macro \db apEVALa "<sequence>{<expression>}" runs the evaluation of the
+The macro \db apEVALa "{<final-step>}<sequence>{<expression>}" runs the evaluation of the
expression in the group. The base priority is initialized by "\apnumA=0",
then "\apEVALb<expression>\limits" scans the expression and saves the
result in the form "\apPLUS{\A}{\apMUL{\B}{\C}}" (etc.) into the "\tmpb" macro. This
macro is executed. The group is finished by "\apEND" macro, which keeps the
-"\OUT", "\apSIGN" and "\apE" values unchanged. Finally the defined "<sequence>" is set
-equivalent to the \db OUT macro.
+"\OUT", "\apSIGN" and "\apE" values unchanged. Then "<final-step>" is executed and
+finally, the defined "<sequence>" is set equivalent to the \db OUT macro.
\inext{apEVALa}{}{++}
@@ -2368,16 +2389,25 @@ If $x\in(0,1)$ then this series converges relatively quickly.
The macro "\EXP" takes its argument. If it is negative, remember this fact,
remove minus sign and do "\OUT=1/\OUT" in final step. Now, the argument is
-positive always. If the argument is greater than~1, do argument = argument/2
+positive always. If the argument is ``big'' (greater or equal than 4,
+tested by "\testBig") then "\apEXPb" macro is used for evaluating.
+Else "\apEXPa" macro evaluates the exponential.
+
+\inext{EXP}{^^B\cbrace}{++}
+
+The \db apEXPa macro supposes input argument (saved in "\OUT" macro)
+in the interval $[0,4)$.
+If the argument is greater than~1, do argument = argument/2
and increase $K$ register. Do this step in the loop until argument${}<1$.
+Then calculate $e^x$ using Taylor series mentioned above.
After "\OUT" is calculated then we do "\OUT=\OUT"$^2$ in the loop $K$ times,
-because $e^{2x} = (e^x)^2$.
-Now we are ready to calculate the exponential of positive argument which is
-less than 1. This is done using loop of Taylor series. "\S" is total sum,
-"\Sn" is the new addition in the $n$-th step. If "\Sn" is zero (in
+because $e^{2x} = (e^x)^2$. Note that $K\le2$ in all cases.
+
+The Taylor series is processed using the folloving variables: "\S" is total
+sum, "\Sn" is the new addition in the $n$-th step. If "\Sn" is zero (in
accordance to the "\apFRAC" register) then we stop the calculation.
-\inext{EXP}{^^B\cbrace}{++}
+\inext{apEXPa}{^^B\cbrace}{++}
The macro \db apTAYLOR is ready for general usage in the form:
@@ -2390,7 +2420,21 @@ The macro \db apTAYLOR is ready for general usage in the form:
\apTAYLOR \iftrue \repeat % does S = S + Sn and finishes if Sn = 0
\endtt
-\inext{apTAYLOR}{\empty}{+-}
+\inext{apTAYLOR}{}{++}
+
+If the argument (saved i the "\OUT" macro) is greater or equal 4 then
+\db apEXPb macro is executed. The $d=\lfloor x/\ln 10\rfloor$ is
+calculated here.
+This is the number of decimal digits in the result before the decimal point.
+The result is in the form
+$$
+ e^x = e^{x\,-\,d\,\cdot\,\ln 10} \cdot 10^d.
+$$
+The argument of the exponential function is less than $\ln 10 \doteq 2.3$
+for this case, so we can call the "\EXP" macro recursively.
+And the result is returned in scientific form if $d\ge{}$"\apEX".
+
+\inext{apEXPb}{^^B\cbrace}{++}
{\bf The logarithm function} $\ln x$ (inverse to $e^x$) is implemented in
\db LN macro by Taylor series in the point zero of the $\arg\tanh$ function:
diff --git a/Master/texmf-dist/doc/generic/apnum/apnum.pdf b/Master/texmf-dist/doc/generic/apnum/apnum.pdf
index c40bf2c2d0e..e9ec9d35135 100644
--- a/Master/texmf-dist/doc/generic/apnum/apnum.pdf
+++ b/Master/texmf-dist/doc/generic/apnum/apnum.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/generic/apnum/apnum.tex b/Master/texmf-dist/tex/generic/apnum/apnum.tex
index e3a7bb53161..4c2e885904f 100644
--- a/Master/texmf-dist/tex/generic/apnum/apnum.tex
+++ b/Master/texmf-dist/tex/generic/apnum/apnum.tex
@@ -1,10 +1,10 @@
% Arbitrary precision numbers
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% 2014, 2015 Petr Olsak
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% 2014, 2015, 2016 Petr Olsak
% See the documentation apnum.pdf or apnum.d for more information
-\def\apVERSION{1.5 <Jan 2016>}
+\def\apVERSION{1.6 <Feb 2016>}
\message{The Arbitrary Precision Numbers, \apVERSION}
%%%%%%%%%%%% Internal registers, sec. 2.1 in apnum.pdf
@@ -20,13 +20,15 @@
\newcount\apE
\newcount\apTOT \apTOT=0
\newcount\apFRAC \apFRAC=20
+\newcount\apEX \apEX=10
\apnumZ=\catcode`\@ \catcode`\@=12
%%%%%%%%%%%% Evaluation of the expression, sec. 2.2 in apnum.pdf
-\def\evaldef{\relax \apEVALa}
-\def\apEVALa#1#2{\begingroup \apnumA=0 \apnumE=1 \apEVALb#2\limits \tmpb \apEND \let#1=\OUT}
+\def\evaldef{\relax \apEVALa{\apEadd\OUT}}
+\def\evalmdef{\relax \apEVALa{}}
+\def\apEVALa#1#2#3{\begingroup \apnumA=0 \apnumE=1 \apEVALb#3\limits \tmpb \apEND #1\let#2=\OUT}
\def\apEVALb{\def\tmpa{}\apEVALc}
\def\apEVALc#1{%
\ifx+#1\apEVALd \apEVALc \fi
@@ -111,7 +113,7 @@
%%%%%%%%%%%% Preparation of the parameter, sec. 2.3 in apnum.pdf
\def\apPPa#1#2{\expandafter\apPPb#2@#1}
-\def\apPPb{\def\tmpc{}\apSIGN=1 \apE=0 \apXfalse \expandafter\expandafter\expandafter\apPPc}
+\def\apPPb{\def\tmpc{}\apSIGN=1 \apE=0 \expandafter\expandafter\expandafter\apPPc}
\def\apPPc#1{%
\ifx+#1\apPPd \fi
\ifx-#1\apSIGN=-\apSIGN \apPPd \fi
@@ -119,8 +121,8 @@
\apPPg#1%
}
\def\apPPd#1\apPPg#2{\fi\expandafter\expandafter\expandafter\apPPc}
-\def\apPPe#1\apPPg#2#3@{\fi\apXtrue
- \begingroup#3% execution of the parameter in the group
+\def\apPPe#1\apPPg#2#3@{\fi
+ \begingroup\apE=0 #3% execution of the parameter in the group
\edef\tmpb{\apE=\the\apE\relax\noexpand\apPPf\OUT@}\expandafter\endgroup\tmpb
}
\def\apPPf#1{\ifx-#1\apSIGN=-\apSIGN \expandafter\apPPg\else\expandafter\apPPg\expandafter#1\fi}
@@ -133,7 +135,7 @@
\expandafter\apPPi\tmpc
}
\def\apPPh#1\apPPi\tmpc{\fi\apPPg}
-\def\apPPi{\ifapX \expandafter\apPPj \else \expandafter\apPPk \fi}
+\def\apPPi{\ifnum\apE=0 \expandafter\apPPk \else \expandafter\apPPj \fi}
\def\apPPj#1@#2{\def#2{#1}}
\def\apPPk#1@#2{\ifx@#1@\apSIGN=0 \def#2{0}\else \apPPl#1E@#2\fi}
\def\apPPl#1E#2@#3{%
@@ -702,7 +704,7 @@
%%%%%%%%%%%% Function-like macros, sec. 2.10 in apnum.pdf
\def\ABS#1{\relax % mandatory \relax for "function-like" macros
- \evaldef\OUT{#1}% % evaluation of the input parameter
+ \evalmdef\OUT{#1}% % evaluation of the input parameter
\ifnum\apSIGN<0 % if (input < 0)
\apSIGN=1 % sign = 1
\apREMfirst\OUT % remove first "minus" from OUT
@@ -710,33 +712,33 @@
}
\def\SGN#1{\relax \evaldef\OUT{#1}\edef\OUT{\the\apSIGN}\apE=0 }
\def\iDIV#1#2{\relax \apINIT % calculation in group
- \evaldef\apAparam{#1}\apEadd\apAparam
- \evaldef\apBparam{#2}\apEadd\apBparam % evaluation of the parameters
+ \evalmdef\apAparam{#1}\apEnum\apAparam
+ \evalmdef\apBparam{#2}\apEnum\apAparam % evaluation of the parameters
\apTOT=0 \apFRAC=0 \apDIV\apAparam\apBparam % integer division
\apEND % end of group
}
\def\iMOD#1#2{\relax \apINIT % calculation in group
- \evaldef\apAparam{#1}\apEadd\apAparam
- \evaldef\apBparam{#2}\apEadd\apBparam % evaluation of the parameters
+ \evalmdef\apAparam{#1}\apEnum\apAparam
+ \evalmdef\apBparam{#2}\apEnum\apBparam % evaluation of the parameters
\apTOT=0 \apFRAC=0 \apDIV\apAparam\apBparam % integer division
\let\OUT=\XOUT % remainder is the output
\apEND % end of group
}
-\def\iFLOOR#1{\relax \evaldef\OUT{#1}\apEnum\OUT \apROUND\OUT0%
+\def\iFLOOR#1{\relax \evalmdef\OUT{#1}\apEnum\OUT \apROUND\OUT0%
\ifnum\apSIGN<0 \ifx\XOUT\empty \else \apPLUS\OUT{-1}\fi\fi
\def\tmp{0}\ifx\tmp\OUT \apSIGN=0 \fi
}
\def\iFRAC#1{\relax
- \evaldef\OUT{#1}\apEnum\OUT \apROUND\OUT0% % preparing the parameter
- \ifx\XOUT\empty \def\OUT{0}\apSIGN=0 % empty fraction part means zero
+ \evalmdef\OUT{#1}\apEnum\OUT \apROUND\OUT0% % preparing the parameter
+ \ifx\XOUT\empty \def\OUT{0}\apSIGN=0 % empty fraction part means zero
\else \ifnum\apSIGN<0
- \edef\XOUT{-.\XOUT}\apPLUS1\XOUT % OUT = 1 - .\XOUT
- \else \edef\OUT{.\XOUT}\apSIGN=1 % else OUT = .\XOUT
+ \edef\XOUT{-.\XOUT}\apPLUS1\XOUT % OUT = 1 - .\XOUT
+ \else \edef\OUT{.\XOUT}\apSIGN=1 % else OUT = .\XOUT
\fi \fi
}
\def\FAC#1{\relax \apINIT % "function-like" in the group, FAC = factorial
- \evaldef\OUT{#1}\apEnum\OUT % preparing the parameter
+ \evalmdef\OUT{#1}\apEnum\OUT % preparing the parameter
\localcounts \N;% % local \newcount
\ifnum\apSIGN<0 \apERR{\string\FAC: argument {\OUT} cannot be negative}\apRETURN\fi
\let\tmp=\OUT \apROUND\tmp0% % test, if parameter is integer
@@ -748,8 +750,8 @@
\apEND % end of group
}
\def\BINOM#1#2{\relax \apINIT % BINOM = {#1 \choose #2} ...
- \evaldef\apAparam{#1}\apEnum\apAparam
- \evaldef\apBparam{#2}\apEnum\apBparam % preparation of the parameters
+ \evalmdef\apAparam{#1}\apEnum\apAparam
+ \evalmdef\apBparam{#2}\apEnum\apBparam % preparation of the parameters
\localcounts \A \B \C ;% % local \newcounts
\let\OUT=\apBparam \apROUND\OUT0% % test if B is integer
\ifx\XOUT\empty\else\apERR{\string\BINOM: second arg. {\apBparam} must be integer}\apRETURN\fi
@@ -775,7 +777,7 @@
\apEND
}
\def\SQRT#1{\relax \apINIT % OUT = SQRT(#1) ...
- \evaldef\A{#1}% % parameter preparation
+ \evalmdef\A{#1}% % parameter preparation
\localcounts \M \E ;% % local counters
\E=\apE \apE=0
\ifnum\apSIGN=0 \apRETURN\fi % SQRT(0) = 0 (OUT is set to 0 by previous \evaldef)
@@ -819,39 +821,53 @@
\edef\OUT{\expandafter\apNOPT\the\dimen0}% OUT = dimen0
}
\def\EXP#1{\relax\apINIT % OUT = EXP(#1) ...
- \evaldef\OUT{#1}\apEnum\OUT % OUT = #1
+ \evalmdef\OUT{#1}\apEnum\OUT % OUT = #1
\localcounts \N \K ;%
\ifnum\apSIGN=0 \def\OUT{1}\apSIGN=1 \apRETURN \fi
- \edef\digits{\the\apFRAC}\advance\apFRAC by3
+ \edef\digits{\the\apFRAC}\advance\apFRAC by4
\edef\signX{\the\apSIGN}%
\ifnum\apSIGN<0 \apSIGN=1 \apREMfirst\OUT \fi % remove "minus" sign
- \K=0 \N=0 % K = 0, N = 0
+ \def\testBig ##1##2##3\relax##4{\ifx##1.\apXfalse \else
+ \ifx##2.\ifnum##1<4 \apXfalse \else \apXtrue \fi \else \apXtrue
+ \fi \fi \ifapX}%
+ \expandafter\testBig \OUT.\relax
+ \iftrue \apEXPb \else \apEXPa \fi % OUT = e^OUT
+ \ifnum\signX<0 \K=-\apE \apDIV 1\OUT \apE=\K \fi % if (signX < 0) OUT = 1 / OUT
+ \apSIGN=1 % EXP is always positive
+ \apEND
+}
+\def\apEXPa{%
\def\testDot ##1##2\relax##3{\ifx##1.}%
- \loop \expandafter \testDot\OUT \relax % loop if (OUT >= 1)
- \iftrue \else % OUT = OUT/2
- \apDIV\OUT{2}% % K++
- \advance\K by1 % repeat
- \repeat % now: #1 = 2^K * OUT, OUT < 1
+ \K=0 \N=0 % K = 0, N = 0
+ \loop \expandafter \testDot\OUT \relax % loop if (OUT >= 1)
+ \iftrue \else % OUT = OUT/2
+ \apDIV\OUT{2}% % K++
+ \advance\K by1 % repeat
+ \repeat % oriOUT = 2^K * OUT, OUT < 1
\advance\apFRAC by\K
- \def\S{1}\def\Sn{1}\N=0 \let\X=\OUT % S = 1, Sn = 1, N = 0, X = OUT
- \loop \advance\N by1 % loop N++
- \do\Sn=\apDIV{\apMUL\Sn\X}{\the\N};% % Sn = Sn * X / N
- \apTAYLOR\iftrue \repeat % S = S + Sn (... Taylor)
+ \def\S{1}\def\Sn{1}\N=0 \let\X=\OUT % S = 1, Sn = 1, N = 0, X = OUT
+ \loop \advance\N by1 % loop N++
+ \do\Sn=\apDIV{\apMUL\Sn\X}{\the\N};% % Sn = Sn * X / N
+ \apTAYLOR\iftrue \repeat % S = S + Sn (... Taylor)
\N=0
- \loop \ifnum\N < \K % loop if (N < K)
- \apPOW\OUT{2}\apROUND\OUT\apFRAC % OUT = OUT^2
- \advance\N by1 \repeat % N++
- \ifnum\signX<0 \apDIV 1\OUT \fi % if (signX < 0) OUT = 1 / OUT
- \apROUND\OUT\digits \apSIGN=1 % EXP is always positive
- \apEND
+ \loop \ifnum\N < \K % loop if (N < K)
+ \apPOW\OUT{2}% % OUT = OUT^2
+ \advance\N by1 \repeat % N++
+ \apFRAC=\digits\relax \apROUND\OUT\apFRAC
}
\def\apTAYLOR#1{\ifnum\apSIGN=0 \let\OUT=\S \else \apPLUS\S\Sn \let\S=\OUT }
-
-\def\LN#1{\relax \apINIT % OUT = LN(#1) ...
- \evaldef\X{#1}% % X = #1
+\def\apEXPb{%
+ \let\X=\OUT \apLNtenexec \apDIV\X\apLNten \let\D=\OUT
+ \apROUND\D{0}% % D = floor( X/ln(X) )
+ \ifnum\D<\apEX \advance\apFRAC by\D \relax \apLNtenexec \fi
+ \EXP{\X-\D*\apLNten}% % mantissa = EXP(X-D*LN(10))
+ \ifnum\D<\apEX \apROLL\OUT\D \apE=0 \else \apE=\D \relax \fi
+ \apFRAC=\digits \apROUND\OUT\apFRAC % OUT = mantissa * 10^D
+}
+\def\LN#1{\relax \apINIT % OUT = LN(#1) ...
+ \evalmdef\X{#1}% % X = #1
\localcounts \M \N \E;%
\E=\apE
- \def\round{\apROUND\OUT\apFRAC}%
\edef\digits{\the\apFRAC}\advance\apFRAC by4
\ifnum\apSIGN>0 \else \apERR{\string\LN: argument {\X} is out of range}\apRETURN\fi
\apDIG\OUT\relax \M=\apnumD % find M: X = mantissa * 10^M
@@ -880,10 +896,10 @@
\apDIV{\apPLUS{\A}{-1}}{\apPLUS{\A}{1}}% % OUT = (A-1) / (A+1)
\ifnum\apSIGN=0 \def\OUT{0}\else % ln 1 = 0 else:
\let\Sn=\OUT \let\Kn=\OUT \let\S=\OUT % Sn = OUT, Kn = OUT, S = OUT
- \apPOW\OUT{2}\round \let\XX=\OUT % XX = OUT^2
+ \apPOW\OUT{2}\apROUND\OUT\apFRAC \let\XX=\OUT % XX = OUT^2
\N=1 % N = 1
\loop \advance\N by2 % loop N = N + 2
- \do\Kn=\apMUL\Kn\XX\round;% % Kn = Kn * XX
+ \do\Kn=\apMUL\Kn\XX\apROUND\OUT\apFRAC;% Kn = Kn * XX
\do\Sn=\apDIV\Kn{\the\N};% % Sn = Kn / N
\apTAYLOR\iftrue \repeat % S = S + Sn (Taylor)
\apMUL\S{2}% % OUT = 2 * OUT
@@ -965,7 +981,7 @@
\def\COS{\relax \let\apSINCOSx=\apCOSx \apSINCOSa}
\def\apSINCOSa#1{\apINIT
\advance\apFRAC by3
- \evaldef\X{#1}\apEnum\X
+ \evalmdef\X{#1}\apEnum\X
\def\signK{1}\apSINCOSo\apCOSx
\ifnum\apSIGN<0 \apREMfirst\X \def\sign{-}\else\def\sign{+}\fi
\ifx\apSINCOSx\apCOSx \def\sign{+}\fi
@@ -1013,7 +1029,7 @@
\def\apSINCOSo#1{\ifnum\apSIGN=0 \ifx#1\SCgo \apSIGN=\signK \let\OUT=\signK \fi \apRETURN\fi}
\def\TAN#1{\relax \apINIT
\advance\apFRAC by3
- \evaldef\X{#1}\apEnum\X
+ \evalmdef\X{#1}\apEnum\X
\advance\apFRAC by-3
\do\denom=\COS\X;%
\ifnum\apSIGN=0 \apERR{\string\TAN: argument {\X} is out of range}\apRETURN\fi
@@ -1023,7 +1039,7 @@
}
\def\ATAN#1{\relax \apINIT
\advance\apFRAC by3
- \evaldef\X{#1}\apEnum
+ \evalmdef\X{#1}\apEnum\X
\ifnum\apSIGN=0 \def\OUT{0}\apRETURN\fi
\ifnum\apSIGN<0 \def\sign{-}\apREMfirst\X \else\def\sign{}\fi
\let\tmp=\X \apDIG\tmp\relax
@@ -1053,7 +1069,7 @@
\apTAYLOR \iftrue \repeat
}
\def\ASIN#1{\relax \apINIT
- \evaldef\X{#1}\apEnum\X \edef\sign{\the\apSIGN}%
+ \evalmdef\X{#1}\apEnum\X \edef\sign{\the\apSIGN}%
\apPLUS 1{-\apPOW\X2}% OUT = 1 - X^2
\ifnum\apSIGN<0 \apERR{\string\ASIN: argument {\X} is out of range}\apRETURN\fi
\do\sqrt=\SQRT\OUT;% sqrt = SRQT {1 - X^1}
@@ -1138,7 +1154,7 @@
\let\SIGN=\apSIGN \let\ROUND=\apROUND \let\NORM=\apNORM \let\ROLL=\apROLL
\ifx\documentclass\undefined \else % please, don't remove this message
-\message{SORRY, you are using LaTeX. I don't recommend this. Petr Olsak}\fi
+\message{WARNING: the author of apnum package recommends: Never use LaTeX.}\fi
\catcode`\@=\apnumZ
\endinput
@@ -1167,8 +1183,11 @@
- \ATAN, \ASIN, \ACOS added
- \SIN, \COS, \TAN added
- \apTOT=0 by default
-1.4a \end -> \limits, internal change in \ebvaldef because LaTeX redefines \end
+1.4a \end -> \limits, internal change in \evaldef because LaTeX redefines \end
1.4b \apSINCOS: \ifx\OUT eq 0 added after \apROUND (bug fixed).
-1.5 <Jan 2015>
+1.5 <Jan 2016>
- \iROUND replaced by \iFLOOR, \iFRAC corrected (for negative numbers)
- \eprint introduced
+1.6 <Feb 2016>
+ - \evalmdef introduced
+ - \EXP for arg>=4 rewritten, \apEX register introduced