diff options
author | Karl Berry <karl@freefriends.org> | 2008-01-28 19:32:04 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2008-01-28 19:32:04 +0000 |
commit | a898113387e9657ab658eb9cccb60988c3a3a2cc (patch) | |
tree | 71a6fccd47c26e89685cad790a5b5930f3dc0483 /Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty | |
parent | fd2cf1cc29725cf8ee1100cbd37655a0c8f51f0b (diff) |
new package pgfplots (26jan08)
git-svn-id: svn://tug.org/texlive/trunk@6435 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty b/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty new file mode 100644 index 00000000000..acb02e3b143 --- /dev/null +++ b/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty @@ -0,0 +1,443 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Package pgfmathlog.sty. +% +% This file provides the public functions +% +% \pgfmathnormalisedfloatingpoint#1\to#2\powten#3 +% like +% \pgfmathnormalisedfloatingpoint 412.02451e-5to\M\powten\E +% +% and +% \pgfmathlog +% \pgfmathlog@ +% which both assign \pgfmathresult to the natural number of a given +% number (without units). +% +% It is based on Till Tantaus pgfmath package which comes as part of +% the PGF bundle, but it provides its own number parsing routines to +% circumvent TeXs limited real number representations. +% +% Copyright 2007/2008 by Christian Feuersänger. +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\ProvidesPackage{pgfmathlog}[2008/26/01 Version 0.9.] +\RequirePackage{pgf}[2007/01/01] + +% Computes a normalised floating point representation for #1 of the +% form +% [+-]X.XXXXXXX*10^C +% where +% X.XXXXXX is a mantisse with first number != 0 +% and C is a count. +% +% This method does NOT use TeX Registers to represent the numbers! The +% computation is COMPLETELY STRING BASED. +% This allows numbers such at 10000000 or 5.23e-10 to be represented +% properly, although TeX-registers would produce overflow/underflow +% errors in these cases. +% +% It is to be used to compute logs, because log(X*10^Y) = log(X) + log(10)*Y +% +% Arguments: +% #1 a -possibly non-normalized- number representation. Accepted input +% format is +% [+-]XXXXX.XXXXXX +% [+-]XXXXX.XXXXXXeXXXX +% [+-]0.0000XXXXXX +% [+-]0.0000XXXXXXeXXXX +% NOT accepted input format is +% [+-]XXXXX [the period is missing] +% [+-]XXXXXe10 [the period is missing] +% [+-]0000.XXXXXX [leading zeros not supported] +% [+-]XXXXX.XXXXXXEXXXXX [E notation not yet implemented] +% #2 a macro name. \def#2{.....} will be used to assign the mantisse. +% #3 a macro name. \def#3{.....} will be used to assign the exponent (base 10). +% +% Example: +% \def\normalize#1{% +% \pgfmathnormalisedfloatingpoint#1\to\M\powten\E +% \[ #1 \mapsto \M\cdot 10^{\E} \] +% } +% \normalize{123.41251}% +% \normalize{3.26101452e-06}% +\def\pgfmathnormalisedfloatingpoint#1\to#2\powten#3{% + \pgfmathnormalisedfloatingpoint@impl@possibly@signed#1\to#2\powten{#3}% +} + +% first character MAY be + or -. This is checked, then +% \pgfmathnormalisedfloatingpoint@impl@positive will be called for the +% absolute value. The sign is inserted afterwards. +\def\pgfmathnormalisedfloatingpoint@impl@possibly@signed#1#2\to#3\powten#4{% + \def\pgfmathlogTMP{#1}% + \def\pgfmathlogTMPB{-}% + \if\pgfmathlogTMP\pgfmathlogTMPB + \pgfmathnormalisedfloatingpoint@impl@positive@possibly@noperiod#2.\to#3\powten{#4}% + \edef#3{-#3}% + \else + \def\pgfmathlogTMPB{+}% + \if\pgfmathlogTMP\pgfmathlogTMPB + \pgfmathnormalisedfloatingpoint@impl@positive@possibly@noperiod#2.\to#3\powten{#4}% + \else + \pgfmathnormalisedfloatingpoint@impl@positive@possibly@noperiod#1#2.\to#3\powten{#4}% + \fi + \fi +} + +% XXXX -> XXXX.0 +% XXXX.YYY -> XXXX.YYYY +\def\pgfmathnormalisedfloatingpoint@impl@positive@possibly@noperiod#1.#2\to#3\powten#4{% + %\tracingmacros=2\tracingcommands=2 + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + \pgfmathnormalisedfloatingpoint@impl@positive@noperiod@possibly@SCI#1e\to#3\powten{#4}% + \else + \expandafter\pgfmathnormalisedfloatingpoint@impl@positive\pgfmathlog@pop@last@of@two@dots#1.#2\to#3\powten{#4}% + \fi +} +\def\pgfmathlog@pop@last@of@two@dots#1.#2.{#1.#2}% + +\def\pgfmathnormalisedfloatingpoint@impl@positive@noperiod@possibly@SCI#1e#2\to#3\powten#4{% + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + % this case applies to + % 1234 -> 1234.0 + \pgfmathnormalisedfloatingpoint@impl@positive#1.0\to#3\powten{#4}% + \else + % this case applies to + % 1e1 -> 1.0e1 + % in this case, #1e#2 = 1e1e, so we have to discard a suffix 'e'. + \edef\pgfmathlogTMP{#1.0e\pgfmathlog@popsuffix@e@expansion#2}% + \expandafter\pgfmathnormalisedfloatingpoint@impl@positive\pgfmathlogTMP\to#3\powten{#4}% + \fi +} + +% XXXXX.XXXXX -> X.XXXXXXX * 10^4 +% 0.0000XXXXX -> X.XXXX * 10^{-5} +% +% or +% XXXX.XXXXXeYYY -> X.XXXXXX* 10^{3+YYY} +% 0.0000XXXXeYYY -> X.XXX* 10^{-5+YYY} +% +% this version does not accept a sign. A period is required. +\def\pgfmathnormalisedfloatingpoint@impl@positive#1#2.#3\to#4\powten#5{% +% \begingroup +% FIXME! restore variables!! + %\tracingmacros=2\tracingcommands=2 + %\tracingmacros=0\tracingcommands=0 + \pgfmathnormalisedfloatingpoint@positive@getexisting@exponent@e#3e\preexponentto\preexponentstring\exponenttocount\c@pgf@counta + % will \c@pgf@counta will be initialised in the line above + % \c@pgf@counta=0 + \ifnum#1=0 + % the case 0.0000XXXX + % does also handle 0.0000XXXXeXXX + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + \c@pgf@countb=0 + \expandafter\pgfmathlog@count@leading@zeros\preexponentstring\to\c@pgf@countb + \advance\c@pgf@countb by1 + \advance\c@pgf@counta by-\c@pgf@countb + \edef#5{\the\c@pgf@counta}% + \expandafter\pgfmathlog@assignmantisse\preexponentstring\to#4\countdownzerosfrom\c@pgf@countb + \else + % the case 000.0000XXXXX + % is not allowed and does not make sense. + \errmessage{INVALID NUMBER FORMAT: leading zeros 00*.* not supported yet}% + \fi + \else + % the case NXXXXX.XXXXXXX + % or NXXXXXX.XXXXXXeXXXX + % where N in [1-9] + \pgfmathlog@strlen#1#2\to\c@pgf@counta + \advance\c@pgf@counta by-1 + \edef#4{#1.#2\preexponentstring}% + \edef#5{\the\c@pgf@counta}% + \fi + %\tracingmacros=0\tracingcommands=0 +% \endgroup +} + +% parses scientific notation and returns the exponent and everything +% before the exponent like +% +% XXXXXXXeYYYY -> \def#2{XXXXXXX} #3=YYYY +% or +% XXXXXXXXe -> \def#2{XXXXXXXX} #3=0 +% +% Examples: +% - \pgfmathnormalisedfloatingpoint@exponent@e123456e\preexponentto\M\exponenttocount\acount +% \M->123456 +% \acount=0 +% Please note that the input was 123456e -> at least 'e' is expected! +% +% - \pgfmathnormalisedfloatingpoint@exponent@e123456e-10e\preexponentto\M\exponenttocount\acount +% \M->123456 +% \acount=-10 +% Again, the suffix 'e' is REQUIRED. This allows to reduce \ifs. +\def\pgfmathnormalisedfloatingpoint@positive@getexisting@exponent@e#1e#2\preexponentto#3\exponenttocount#4{% + \def#3{#1}% + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + #4=0 + \else + \pgfmathlog@popsuffix@e#2\tocount{#4}% + \fi +} + +% XXXXXe -> #2=XXXXX where X in [+-0-9]. +\def\pgfmathlog@popsuffix@e#1e\tocount#2{% + #2=#1 +} + +\def\pgfmathlog@popsuffix@e@expansion#1e{% + #1% +}% + +% 00000XXXXXX -> X.XXXXX +% Inputs: +% #1 = 00000XXXXXX +% #2 a macro name +% #3 a count in which the number of zeros plus one is contained (i.e. +% the number of shifts). +\def\pgfmathlog@assignmantisse#1\to#2\countdownzerosfrom#3{% + \toks0={#1}% + \loop + \ifnum#3=1 + \else + \expandafter\pgfmathlog@popfirst\the\toks0\to{\toks0}% + \advance#3 by-1 + \repeat + \edef\pgfmathlog@assignmantisseTMP{\the\toks0}% + \ifx\pgfmathlog@assignmantisseTMP\empty + % The case 0.0 * 10^0 + \def#2{0.0}% + \else + \expandafter\pgfmathlog@insertperiod\the\toks0\to{#2}% + \fi +} + +% XXXXXX -> X.XXXXX into #3 +\def\pgfmathlog@insertperiod#1#2\to#3{% + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + \def#3{#1.0}% + \else + \def#3{#1.#2}% + \fi +} + +% discards the first token. +\def\pgfmathlog@popfirst#1#2\to#3{% + #3={#2}% +} + +% adds the string length of #1#2 into the count register #3. +% +% The register won't be initialised to zero! +\def\pgfmathlog@strlen#1#2\to#3{% + \advance#3 by1 + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + \else + \pgfmathlog@strlen#2\to{#3}% + \fi +} + +% Adds the number of leadings zeros of #1#2 into the count register +% #3. +% +% The register won't be initialised to zero! +\def\pgfmathlog@count@leading@zeros#1#2\to#3{% + \ifnum#1=0 + \advance#3 by1 + \def\pgfmathlogTMP{#2}% + \ifx\pgfmathlogTMP\empty + \else + \pgfmathlog@count@leading@zeros#2\to{#3}% + \fi + \fi +} + +% Evaluates the natural logarithm, log(x) for 0.1<=x<=1. +% @see \pgfmathlog@ for the general method. +% NON ACCURATE ENOUGH! +\def\pgfmathlogzeroone#1{% + \begingroup% + \message{EVAL log(#1) STARTS:}% + \pgfmath@x=#1pt\relax + \pgfmath@y=\pgfmath@x + \advance\pgfmath@x by-1pt + \advance\pgfmath@y by 1pt + \pgfmathdivide{\pgfmath@x}{\pgfmath@y}% + % pgfmath@ya = tmp := (#1 -1)/ (#1+1) + \expandafter\pgfmath@ya\pgfmathresult pt + % pgfmath@xa := [ (#1 -1)/ (#1+1) ]^2 + \pgfmathmultiply{\pgfmathresult}{\pgfmathresult}% + \expandafter\pgfmath@xa\pgfmathresult pt + % returnvalue: + \pgfmath@y=0pt + % loop counter: + \c@pgfmath@counta=0 + % j: + \c@pgfmath@countb=1 + \loop + \ifnum\c@pgfmath@counta<6 + \let\multmp=\pgfmath@ya + \divide\pgfmath@ya by\c@pgfmath@countb + \advance\pgfmath@y by\pgfmath@ya + \let\pgfmath@ya=\multmp + \advance\c@pgfmath@countb by2 + \message{[tmp *= x*x tmp =\the\pgfmath@ya, x*x=\the\pgfmath@xa]}% + \pgfmathmultiply{\pgfmath@ya}{\pgfmath@xa}% + \expandafter\pgfmath@ya\pgfmathresult pt + \advance\c@pgfmath@counta by1 + \message{[cur/2 = \the\pgfmath@y]}% + \repeat + \multiply\pgfmath@y by2 + \message{fertiges Resultat fuer log(#1): \the\pgfmath@y}% + \pgfmath@returnone\pgfmath@y% + \endgroup% +} + + +% Computes a good guess for log(X.XXXX) where the input number should +% be between 0 < x < 10. +% +% If it is not in this range, the returned value will be bad. +% +% For use in the newton implementation of log(x). Please note that we +% first compute a normalized floating point representation of x, and +% the mantisse is always between 0 and 10. +\def\pgfmathlog@smaller@ten@newton@startval#1#2#3\to#4{% + \ifnum0<#1\relax + \def\axis@TMP{#2}% + \def\axis@TMPB{.}% + \ifx\axis@TMP\axis@TMPB + \ifcase#1 + \errmessage{pgfmathlog.sty: INTERNAL ERROR: should not happen! + [\#1=0 should have been caught before!]}% + \or#4=0.53062825106217pt + \or#4=0.993pt + \or#4=1.308pt + \or#4=1.5pt + \or#4=1.71pt + \or#4=1.872pt + \or#4=2.01pt + \or#4=2.145pt + \or#4=2.24pt + \fi +% \message{Newton: Start value \the#4 assigned}% + \else +% \message{Kein Komma an zweiter stelle (statt dessen: #2); Nehme standardstartwert.}% + #4=0.1pt + \fi + \else +% \message{Argument #1 <= 0. Nehme standardstartwert.}% + #4=0.1pt + \fi +} + +% Computes log(x) into \pgfmathresult. +% +% REMARK +% This method does NOT use TeX Registers to represent the numbers! The +% computation is COMPLETELY STRING BASED. +% This allows numbers such at 10000000 or 5.23e-10 to be represented +% properly, although TeX-registers would produce overflow/underflow +% errors in these cases. +% +% The natural logarithm is computed using log(X*10^Y) = log(X) + log(10)*Y +\def\pgfmathlog@#1{% + \pgfmathlog@newton{#1}% +} + +% Public interface method. This is expected to use \pgfmathparse but +% it DOESN'T do that. \pgfmathparse naturally can't handle numbers +% which exceed TeX's numerical capabilities. However, exponentials are +% typically either too large or too small for TeX. +% +% @see \pgfmathnormalisedfloatingpoint for how we parse arguments. +% @see \pgfmathlog@ +\def\pgfmathlog#1{% + \pgfmathlog@newton{#1}% +} + +\def\pgfmathlog@tonumber#1pt{#1} + +% Invokes command #1 with #2 without the 'pt' suffix. +\def\invokepgf@math@one#1#2{% + %\edef\pgfmath@resulttemp{\pgf@sys@tonumber{#2}}% + %\expandafter#1\expandafter{\pgfmath@resulttemp}% + \edef\pgfmath@resulttemp{{\pgf@sys@tonumber{#2}}}% + \expandafter#1\pgfmath@resulttemp% +} + +% Expands #2 using \edef and invokes #1 with the resulting string. +% +% Example: +% \pgfmath@y=7.9pt +% \pgfmathlog@invoke@expanded\pgfmathexp@{{\pgf@sys@tonumber{\pgfmath@y}}}% +% will invoke +% \pgfmathexp@{7.9} +\def\pgfmathlog@invoke@expanded#1#2{% + \edef\pgfmath@resulttemp{#2}% + \expandafter#1\pgfmath@resulttemp +} + +% This implementation of log(X) is done with a newton method applied to x-exp(y) = 0. +% The implementation \pgfmathexp is used for exp(y). +% +% see \pgfmathlog@ +\def\pgfmathlog@newton#1{% + \begingroup% + % compute #1 = M*10^E with normalised mantisse M = [+-]*[1-9].XXXXX + \pgfmathnormalisedfloatingpoint#1\to\newtoninput@mantisse\powten\newtoninput@exponent + % + % Now, compute log(#1) = log(M) + E*log(10) +% \message{EVAL log(#1) = log(\newtoninput@mantisse) + \newtoninput@exponent*log(10) mit newton STARTS:}% + % input argument into \pgfmath@x + \expandafter\pgfmath@x\newtoninput@mantisse pt + \ifdim\pgfmath@x>0pt + % return value: + \expandafter\pgfmathlog@smaller@ten@newton@startval\newtoninput@mantisse\to\pgfmath@y + % loop counter: + \c@pgfmath@counta=0 + \loop + %\message{Newton iter \#\the\c@pgfmath@counta: log(\newtoninput@mantisse) = \the\pgfmath@y }% + \ifnum\c@pgfmath@counta<2 + % \pgfmathexp\pgfmath@y% + \pgfmathlog@invoke@expanded\pgfmathexp@{{\pgf@sys@tonumber{\pgfmath@y}}}% + \let\tmp=\pgfmathresult + %\pgfmathdivide\pgfmath@x\tmp% + \pgfmathlog@invoke@expanded\pgfmathdivide@{{\pgf@sys@tonumber{\pgfmath@x}}{\tmp}}% + \expandafter\pgfmath@ya\pgfmathresult pt + \advance\pgfmath@y by\pgfmath@ya + \advance\pgfmath@y by-1pt + \advance\c@pgfmath@counta by1 + \repeat + \pgfmath@x=2.302585pt% = log(10) + \multiply\expandafter\pgfmath@x\newtoninput@exponent + \advance\pgfmath@y by\pgfmath@x +%\message{Newton final result: log(\newtoninput@mantisse)+\newtoninput@exponent*log(10) = \the\pgfmath@y [ nur \newtoninput@exponent * log(10) = \the\pgfmath@x]}% + \pgfmath@returnone\pgfmath@y% + \else + \global\let\pgfmathresult=\empty% + \fi + \endgroup% +} + |