From 957aeb141e1e62fc19b0aedb3bc36ad058226250 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 18 Feb 2008 00:19:53 +0000 Subject: pgfplots update (17feb08) git-svn-id: svn://tug.org/texlive/trunk@6666 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/latex/pgfplots/liststructure.sty | 2 +- .../texmf-dist/tex/latex/pgfplots/pgfmathlog.sty | 262 +-- Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty | 2387 ++++++++++++++------ .../tex/latex/pgfplots/pgfplotshelpers.sty | 13 +- Master/texmf-dist/tex/latex/pgfplots/sciformat.sty | 861 +++++++ 5 files changed, 2559 insertions(+), 966 deletions(-) create mode 100644 Master/texmf-dist/tex/latex/pgfplots/sciformat.sty (limited to 'Master/texmf-dist/tex/latex/pgfplots') diff --git a/Master/texmf-dist/tex/latex/pgfplots/liststructure.sty b/Master/texmf-dist/tex/latex/pgfplots/liststructure.sty index 8a0a9568449..c5930374f7d 100644 --- a/Master/texmf-dist/tex/latex/pgfplots/liststructure.sty +++ b/Master/texmf-dist/tex/latex/pgfplots/liststructure.sty @@ -35,7 +35,7 @@ % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\ProvidesPackage{liststructure}[2008/26/01 Version 0.9] +\ProvidesPackage{liststructure}[2008/02/17 Version 0.9.4] \newtoks\TOKL@ta \newtoks\TOKL@tb diff --git a/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty b/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty index 81e252bbe27..9e9b57ea137 100644 --- a/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty +++ b/Master/texmf-dist/tex/latex/pgfplots/pgfmathlog.sty @@ -36,243 +36,14 @@ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\ProvidesPackage{pgfmathlog}[2008/26/01 Version 0.9.] +\ProvidesPackage{pgfmathlog}[2008/02/17 Version 0.9.4] \RequirePackage{pgf}[2007/01/01] +\RequirePackage{sciformat}[2008/02/17] +\RequirePackage{pgfplotshelpers}[2008/02/17] -\RequirePackage{pgfplotshelpers}[2008/31/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}% +% See \sciparse docs \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 + \sciparse#1\to#2\powten{#3}% } % Evaluates the natural logarithm, log(x) for 0.1<=x<=1. @@ -386,7 +157,7 @@ \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 + \sciparse#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:}% @@ -421,3 +192,24 @@ \endgroup% } +% Usage: +% \pgfmathapproxequalto@macro\argone\argtwo\result +% +% -> will set \resulttrue or \resultfalse +% -> check with \ifresult +\def\pgfmathlog@approxequalto@macro#1#2#3{% + \begingroup% + \expandafter\pgfmath@x#1pt\relax% + \expandafter\pgfmath@y#2pt\relax% + \advance\pgfmath@x-\pgfmath@y% + \ifdim\pgfmath@x<0pt + \multiply\pgfmath@x by-1 + \fi + \ifdim\pgfmath@x<0.0001pt\relax% + \expandafter\aftergroup\csname #3true\endcsname + \else% + \expandafter\aftergroup\csname #3false\endcsname + \fi% + \endgroup% +} + diff --git a/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty b/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty index 394cf16be6d..114db197b55 100644 --- a/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty +++ b/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty @@ -23,17 +23,33 @@ % along with this program. If not, see . % %-------------------------------------------- -\def\pgfplotsversion{0.92} -\ProvidesPackage{pgfplots}[2008/31/01 Version \pgfplotsversion] +\def\pgfplotsversion{0.92.4} +\ProvidesPackage{pgfplots}[2008/02/17 Version \pgfplotsversion] + +% ATTENTION: +% you MAY need one of +% \def\pgfsysdriver{pgfsys-dvipdfm.def} +% \def\pgfsysdriver{pgfsys-pdftex.def} +% \def\pgfsysdriver{pgfsys-dvips.def} +% +% BEFORE the first \usepackage{pgf}, \usepackage{tikz} or +% \usepackage{pgfplots}. +% Default is +% 'dvips' for 'latex' +% 'pdftex' for 'pdflatex' +% -> dvipdfm needs special attention. + \RequirePackage{xkeyval}[2006/11/18] \RequirePackage{ifthen} \RequirePackage{liststructure} \RequirePackage{tikz}[2007/06/07] +\RequirePackage{sciformat} \RequirePackage{pgfmathlog} \usetikzlibrary{plotmarks} \def\prefix{pgfplots} +% FIXME: reduce number of variables! \newcount\axisticknum \newcount\axis@tickposnum \newcount\axis@xmode @@ -46,14 +62,19 @@ \newdimen\axis@tmpa \newdimen\axis@tmpb \newif\ifaxis@isuniformtick +\newif\ifaxis@enlargelimits +\newif\ifaxis@enlargelimits@rel@thresh +\newif\ifaxis@enlargelimits@auto \let\axis@TMP=\empty \let\axis@TMPB=\empty +\let\axis@TMPC=\empty \def\axis@leftover{} \def\axis@rightover{} \def\axisdefaultwidth{240pt} \def\axisdefaultheight{207pt} \def\axisdefaulttickwidth{35}% the maximum space between adjacent ticks (in pt, but don't specify the unit 'pt') +\def\axisdefaulttryminticks{4} \listnew{\blackwhiteplotspeclist}{% mark options={fill=gray},mark=*\\% @@ -84,56 +105,6 @@ \listcopy\coloredplotspeclist\to\autoplotspeclist% %\listcopy\blackwhiteplotspeclist\to\autoplotspeclist% -%-------------------------------------------------- -% -% MARKERS: -% mark repeat=3,mark phase=2 -% mark options={color=blue,rotate=180} -% ball,ball color=blue -% {*} -% {x} -% {+} -% \usetikzlibrary{plotmarks} -% {-} -% {|} -% {o} -% {asterisk} -% {star} -% {oplus} -% {oplus*} -% {otimes} -% {otimes*} -% {square} -% {square*} -% {triangle} -% {triangle*} -% {diamond} -% {diamond*} -% {pentagon} -% {pentagon*} -% -% LINES: -% line width=2cm -% [snake=zigzag] -% [snake=brace] -% [snake=triangles] -% [snake=coil,segment length=4pt] -% [snake=coil,segment aspect=0] -% [snake=expanding waves,segment angle=7] -% style=solid -% style=dotted -% style=densely dotted -% style=loosely dotted -% style=dashed -% style=densely dashed -% style=loosely dashed -% dash pattern=on 2pt off 3pt on 4pt off 4pt -% dash phase=10pt -% Mit der 'double' und 'double distance' option gibts lustige effekte: -% \draw[draw=white,double=red,very thick] (0,1) -- (1,0); -% \draw[very thick,double distance=2pt] (1,0) arc (180:90:1cm); -%-------------------------------------------------- - \tikzstyle{every axis}=[] \tikzstyle{every axis plot}=[] \tikzstyle{every axis label}=[] @@ -142,6 +113,10 @@ \tikzstyle{every axis title}=[at={(0.5,1)},above,yshift=6pt] \tikzstyle{every tick}=[very thin,gray] \tikzstyle{every minor tick}=[] +\tikzstyle{every major tick}=[] +\tikzstyle{every axis grid}=[style=help lines] +\tikzstyle{every minor grid}=[] +\tikzstyle{every major grid}=[] \tikzstyle{every tick label}=[] \tikzstyle{every x tick label}=[] \tikzstyle{every y tick label}=[] @@ -163,6 +138,8 @@ % - \tikzstyle{every axis legend}+=[at={(1,0.5)},anchor=east,outer sep=0.5cm] % draws the legend INSIDE MIDDLE RIGHT, separated by 0.5cm from the axis. \tikzstyle{every axis legend}=[% + cells={anchor=center}, + inner xsep=3pt,inner ysep=2pt,nodes={inner sep=2pt,text depth=0.15em}, anchor=north east,% shape=rectangle,% fill=white,% @@ -173,32 +150,49 @@ % outer sep=0.1cm] -% -% xticklabel: -% im argument kann man '\axisticknum' und '\tick' verwenden. -% '\tick' ist der eintrag aus '\xtick', der gerade bearbeitet wird, -% '\axisticknum' seine nummer. -% -% yticklabel: -% analog zu xticklabel. -% -% xfilter/yfilter -% \def\meinxfilter#1\to#2{\def#2{1.4}} -% xfilter=\meinxfilter -% -% if the filtered coordinate is empty string, it will be skipped. \define@cmdkeys[\prefix]{axis}[axis@]{% xmin,xmax,xticklabel,xtick,xtickten,xlabel,% ymin,ymax,yticklabel,ytick,ytickten,ylabel,% - trimxmin,trimxmax,trimymin,trimymax,% subtickwidth,tickwidth,% xfilter,yfilter,% width,height,% title,% execute at begin plot,% execute at end plot,% + enlargelimits,% + legend columns,% x,y}% +\long\def\axis@foreach@to@list#1\to#2{% + \listnewempty\axis@TMP + \begingroup + \foreach \i in {#1} {% + \globaldefs=1 + \expandafter\listpushback\i\to\axis@TMP + \globaldefs=0 + }% + \endgroup + \listcopy\axis@TMP\to#2\relax +} + +\define@cmdkey[\prefix]{axis}[axis@]{xticklabels}{% + \expandafter\axis@foreach@to@list\axis@xticklabels\to\axis@xticklabels + %\expandafter\listnew\expandafter\axis@xticklabels\expandafter{\axis@xticklabels}% + \let\axis@xticklabel=\axis@user@ticklabel@list@x +} +\define@cmdkey[\prefix]{axis}[axis@]{yticklabels}{% + \expandafter\axis@foreach@to@list\axis@yticklabels\to\axis@yticklabels + %\expandafter\listnew\expandafter\axis@yticklabels\expandafter{\axis@yticklabels}% + \let\axis@yticklabel=\axis@user@ticklabel@list@y +} + +\define@cmdkey[\prefix]{axis}[axis@]{minor tick length}{% + \expandafter\let\expandafter\axis@subtickwidth\csname axis@minor tick length\endcsname +} +\define@cmdkey[\prefix]{axis}[axis@]{major tick length}{% + \expandafter\let\expandafter\axis@tickwidth\csname axis@major tick length\endcsname +} + % sets \axis@tickposnum to % left=0 % right=1 @@ -206,11 +200,75 @@ \define@choicekey[\prefix]{axis}{tickpos}[\val\nr]{left,right,both}{% \axis@tickposnum=\nr\relax } +\define@choicekey[\prefix]{axis}{legend plot pos}[\val\nr]{left,right,none}{% + \edef\axis@legend@plot@pos{\nr}% +} + +\define@choicekey[\prefix]{axis}{anchor}[\val\nr]{north,north west,west,south west,south,south east,east,north east,center}{% + \edef\axis@anchorchoicenum{\nr}% +} + +\define@choicekey[\prefix]{axis}{ticks}[\val\nr]{none,major,minor,both}{% + \expandafter\ifcase\nr\relax + \axis@xminorticksfalse + \axis@yminorticksfalse + \axis@xmajorticksfalse + \axis@ymajorticksfalse + \or + \axis@xminorticksfalse + \axis@yminorticksfalse + \axis@xmajortickstrue + \axis@ymajortickstrue + \or + \axis@xminortickstrue + \axis@yminortickstrue + \axis@xmajorticksfalse + \axis@ymajorticksfalse + \or + \axis@xminortickstrue + \axis@yminortickstrue + \axis@xmajortickstrue + \axis@ymajortickstrue + \fi +} +\define@choicekey[\prefix]{axis}{grid}[\val\nr]{none,major,minor,both}{% + \expandafter\ifcase\nr\relax + \axis@xminorgridsfalse + \axis@yminorgridsfalse + \axis@xmajorgridsfalse + \axis@ymajorgridsfalse + \or + \axis@xminorgridsfalse + \axis@yminorgridsfalse + \axis@xmajorgridstrue + \axis@ymajorgridstrue + \or + \axis@xminorgridstrue + \axis@yminorgridstrue + \axis@xmajorgridsfalse + \axis@ymajorgridsfalse + \or + \axis@xminorgridstrue + \axis@yminorgridstrue + \axis@xmajorgridstrue + \axis@ymajorgridstrue + \fi +} + + \define@boolkeys[\prefix]{axis}[axis@]{% xminorticks,% + xmajorticks,% yminorticks,% + ymajorticks,% + xminorgrids,% + xmajorgrids,% + yminorgrids,% + ymajorgrids,% disablelogfilter,% - enlargelimits}[true] + disabledatascaling,% + hide axis,% + scale only axis}[true] % sets \axis@xmode to % normal=0 @@ -226,63 +284,59 @@ \axis@ymode=\nr\relax } -% Options to legend: -% textwidth=auto -% textwidth=none -% textwidth=DIMENSION -\define@cmdkey[\prefix]{legend}[axis@legend@]{textwidth}[auto]{}% - -\define@cmdkey[\prefix]{legend}[axis@legend@]{font}[]{} - \long\def\axispreset#1{% \presetkeys[\prefix]{axis}{#1}{}% } \long\def\legendpreset#1{% - \presetkeys[\prefix]{legend}{#1}{}% + \errmessage{Sorry, legendpreset is now deprecated, along with the legend options text width and font. Legends are now TikZ-matrizes which provide better alignment and can be placed horizontally. See the manual for details.}% } \presetkeys[\prefix]{axis}{% xmode=normal, xmin=, xmax=, - trimxmin=, - trimxmax=, xlabel=, xtick=, xtickten=, xticklabel=, xminorticks=true, + xmajorticks=true, + xminorgrids=false, + xmajorgrids=false, ymode=normal, ymin=, ymax=, - trimymin=, - trimymax=, ylabel=, ytick=, ytickten=, yticklabel=, yminorticks=true, + ymajorticks=true, + yminorgrids=false, + ymajorgrids=false, + grid=none,% tickpos=both, xfilter=, yfilter=, title=, width=, height=, + anchor=south west, subtickwidth=0.1cm, tickwidth=0.15cm, + scale only axis=false, + hide axis=false, + legend columns=1, + legend plot pos=left, x=,% is implicitly set by 'width' and/or '\axisdefaultwidth' y=,% is implicitly set by 'height' and/or '\axisdefaultheight' execute at begin plot=,% execute at end plot=,% - enlargelimits=false, + enlargelimits=auto, disablelogfilter=false}{} -\presetkeys[\prefix]{legend}{% - textwidth=auto, - font=}{} - - -\def\logten{2.302585} +\def\logten{2.3025851} +\def\reciproc@logten{0.434294481903252} \newcommand{\logi}[1]{% \ifcase#1 @@ -300,7 +354,14 @@ \newcommand{\show@yticklabel}[2]{{% \let\ticknum=#1% - \def\tick{#2}% + \ifaxis@float@numerics@mode@y + % this here stores \\tick@S, \\tick@M, \\tick@E + \axis@inverse@datascaletrafo@y{#2}\to\tick + % .. and this here provides \tick as fixed point repr: + \scitofixedsingle\tick\tick + \else + \def\tick{#2}% + \fi \axis@yticklabel }} @@ -309,10 +370,26 @@ % #2: der x wert dafuer \newcommand{\show@xticklabel}[2]{{% \let\ticknum=#1% - \def\tick{#2}% + \ifaxis@float@numerics@mode@x + % this here stores \\tick@S, \\tick@M, \\tick@E + \axis@inverse@datascaletrafo@x{#2}\to\tick + % .. and this here provides \tick as fixed point repr: + \scitofixedsingle\tick\tick + \else + \def\tick{#2}% + \fi \axis@xticklabel }} +\def\axis@user@ticklabel@list@x{% + \listselect\ticknum\of\axis@xticklabels\to\tick + \tick +} +\def\axis@user@ticklabel@list@y{% + \listselect\ticknum\of\axis@yticklabels\to\tick + \tick +} + \newcommand{\axisdefaultticklabel}[0]{% $\prettyprintnumber{\tick}$% } @@ -344,147 +421,184 @@ % Y-Achsen und Achsenbeschriftung LOG: % 1: Ticks -\newcommand{\yachse}[1]{% +\newcommand{\axis@drawyaxis}[1]{% + \begingroup + \newif\ifneedsminorloop \axisticknum=0 - \foreach \y in {#1} { - %\pgfextracty{\axis@tmpa}{\pgfpointxy{0}{\logten*\y}}% - \pgfextracty{\axis@tmpa}{\pgfpointxy{0}{\y}}% - % - \ifdim\axis@tmpa<\axis@ycoordminTEX - \else - \ifdim\axis@tmpa>\axis@ycoordmaxTEX - \else - % Achsenbeschriftung: - \ifnum\axis@tickposnum=1 - \node at - (\axis@xcoordmaxTEX\axis@leftover,\axis@tmpa) - [right,style=every tick label,style=every y tick label] - {\show@yticklabel\axisticknum\y}; - \else - \node at - (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) - [left,style=every tick label,style=every y tick label] - {\show@yticklabel\axisticknum\y}; - \fi - \global\advance\axisticknum by1 - \fi - \fi - \begin{scope} - \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) - rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); - % Y-Achsenticks links und rechts - % in log: - % beachte: log( i*10^k ) = log\i + k\log10 -> male ticks für i=1..9 + \edef\axis@TMP{#1}% + \ifx\axis@TMP\empty + \else \ifaxis@yminorticks - \foreach \i in {1,...,9} { - \pgfextracty{\axis@tmpb}{\pgfpointxy{0}{\logi\i}}% - \advance\axis@tmpa by\axis@tmpb - \draw[style=every tick,style=every minor tick] + \needsminorlooptrue + \fi + \ifaxis@yminorgrids + \needsminorlooptrue + \fi + \def\axis@placecomputedtick##1[##2]{% + \draw[##2] \ifcase\axis@tickposnum (\axis@xcoordminTEX\axis@leftover, \axis@tmpa) - -- (\axis@xcoordminTEX+\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordminTEX+##1, \axis@tmpa) \or (\axis@xcoordmaxTEX\axis@rightover, \axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordmaxTEX-##1, \axis@tmpa) \or (\axis@xcoordminTEX\axis@leftover, \axis@tmpa) - -- (\axis@xcoordminTEX+\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordminTEX+##1, \axis@tmpa) (\axis@xcoordmaxTEX\axis@rightover, \axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordmaxTEX-##1, \axis@tmpa) \fi ; }% - \fi - \draw[style=every tick] - \ifcase\axis@tickposnum - (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) - -- (\axis@xcoordminTEX+\axis@tickwidth,\axis@tmpa) - \or - (\axis@xcoordmaxTEX\axis@rightover,\axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@tickwidth,\axis@tmpa) - \or - (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) - -- (\axis@xcoordminTEX+\axis@tickwidth,\axis@tmpa) - (\axis@xcoordmaxTEX\axis@rightover,\axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@tickwidth,\axis@tmpa) - \fi - ; - \end{scope} - } -} - -% X-Achsen und Achsenbeschriftung -% 1: Ticks -\newcommand{\xachse}[1]{% - \axisticknum=0 - \foreach \x in {#1} { - % \pgfextractx{\axis@tmpa}{\pgfpointxy{\logten*\x}{0}}% - \pgfextractx{\axis@tmpa}{\pgfpointxy{\x}{0}}% - % - \ifdim\axis@tmpa<\axis@xcoordminTEX - \else - \ifdim\axis@tmpa>\axis@xcoordmaxTEX + \def\placecomputedgridline[##1]{% + \draw[##1] + (\axis@xcoordminTEX\axis@leftover, \axis@tmpa) + -- (\axis@xcoordmaxTEX\axis@rightover, \axis@tmpa) + ; + }% + \foreach \y in {#1} { + \pgfextracty{\axis@tmpa}{\pgfpointxy{0}{\y}}% + % + \ifdim\axis@tmpa<\axis@ycoordminTEX \else - % Achsenbeschriftung: - \ifnum\axis@tickposnum=1 - \node at - (\axis@tmpa,\axis@ycoordmaxTEX\axis@leftover) - [above,style=every tick label,style=every x tick label] - {\show@xticklabel\axisticknum\x}; + \ifdim\axis@tmpa>\axis@ycoordmaxTEX \else - \node at - (\axis@tmpa,\axis@ycoordminTEX\axis@leftover) - [below,style=every tick label,style=every x tick label] - {\show@xticklabel\axisticknum\x}; + % Achsenbeschriftung: + \ifnum\axis@tickposnum=1 + \node at + (\axis@xcoordmaxTEX\axis@leftover,\axis@tmpa) + [right,style=every tick label,style=every y tick label] + {\show@yticklabel\axisticknum\y}; + \else + \node at + (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) + [left,style=every tick label,style=every y tick label] + {\show@yticklabel\axisticknum\y}; + \fi \fi - \global\advance\axisticknum by1 \fi - \fi + \global\advance\axisticknum by1 + \begin{scope} + \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) + rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); + % Y-ticks left and/or right + % in log: + % log( i*10^k ) = log\i + k\log10 -> draw ticks for i=1..9 + \ifneedsminorloop + \foreach \i in {1,...,9} { + % this code here is scoped inside of \foreach. + \pgfextracty{\axis@tmpb}{\pgfpointxy{0}{\logi\i}}% + \advance\axis@tmpa by\axis@tmpb + \ifaxis@yminorgrids + \placecomputedgridline[style=every axis grid,style=every minor grid]% + \fi + \ifaxis@yminorticks + \axis@placecomputedtick\axis@subtickwidth[style=every tick,style=every minor tick]% + \fi + }% + \fi + \ifaxis@ymajorgrids + \placecomputedgridline[style=every axis grid,style=every major grid]% + \fi + \ifaxis@ymajorticks + \axis@placecomputedtick\axis@tickwidth[style=every tick,style=every major tick]% + \fi + \end{scope} + }% + \fi + \endgroup +} - \begin{scope} - \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) - rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); - % Y-Achsenticks links und rechts - % in log: - % beachte: log( i*10^k ) = log\i + k\log10 -> male ticks für i=1..9 +% X-Achsen und Achsenbeschriftung +% 1: Ticks +\newcommand{\axis@drawxaxis}[1]{% + \begingroup + \axisticknum=0 + \newif\ifneedsminorloop + \edef\axis@TMP{#1}% + \ifx\axis@TMP\empty + \else \ifaxis@xminorticks - \foreach \i in {1,...,9} { - \pgfextractx{\axis@tmpb}{\pgfpointxy{\logi\i}{0}}% - \advance\axis@tmpa by\axis@tmpb - \draw[style=every tick,style=every minor tick] + \needsminorlooptrue + \fi + \ifaxis@xminorgrids + \needsminorlooptrue + \fi + \def\axis@placecomputedtick##1[##2]{% + \draw[##2] \ifcase\axis@tickposnum (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordminTEX+##1) \or (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordmaxTEX-##1) \or (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordminTEX+##1) (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordmaxTEX-##1) \fi ; }% - \fi - \draw[style=every tick] - \ifcase\axis@tickposnum - (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@tickwidth) - \or - (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@tickwidth) - \or - (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@tickwidth) - (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@tickwidth) - \fi - ; - \end{scope} - } + \def\placecomputedgridline[##1]{% + \draw[##1] + (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) + -- (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) + ; + }% + \foreach \x in {#1} { + \pgfextractx{\axis@tmpa}{\pgfpointxy{\x}{0}}% + % + \ifdim\axis@tmpa<\axis@xcoordminTEX + \else + \ifdim\axis@tmpa>\axis@xcoordmaxTEX + \else + % Achsenbeschriftung: + \ifnum\axis@tickposnum=1 + \node at + (\axis@tmpa,\axis@ycoordmaxTEX\axis@leftover) + [above,style=every tick label,style=every x tick label] + {\show@xticklabel\axisticknum\x}; + \else + \node at + (\axis@tmpa,\axis@ycoordminTEX\axis@leftover) + [below,style=every tick label,style=every x tick label] + {\show@xticklabel\axisticknum\x}; + \fi + \fi + \fi + \global\advance\axisticknum by1 + % + \begin{scope} + \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) + rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); + % X-Axis ticks bottom and top + % in log: + % log( i*10^k ) = log\i + k\log10 -> draw ticks for i=1..9 + \ifneedsminorloop + \foreach \i in {1,...,9} { + \pgfextractx{\axis@tmpb}{\pgfpointxy{\logi\i}{0}}% + \advance\axis@tmpa by\axis@tmpb + \ifaxis@xminorgrids + \placecomputedgridline[style=every axis grid,style=every minor grid]% + \fi + \ifaxis@xminorticks + \axis@placecomputedtick\axis@subtickwidth[style=every tick,style=every minor tick]% + \fi + }% + \fi + \ifaxis@xmajorgrids + \placecomputedgridline[style=every axis grid,style=every major grid]% + \fi + \ifaxis@xmajorticks + \axis@placecomputedtick\axis@tickwidth[style=every tick,style=every major tick]% + \fi + \end{scope} + }% + \fi + \endgroup } \def\axis@rememberplotspec#1{{% @@ -505,7 +619,7 @@ \advance\c@pgf@countb by-\c@pgf@counta \repeat \listselect\c@pgf@countb\of\autoplotspeclist\to#1 - %\message{pgfplots.sty: using \string\autoplotspeclist\ specification no\#\the\c@pgf@countb (of \the\c@pgf@counta): #1}% +%\message{pgfplots.sty: using \string\autoplotspeclist\ specification no\#\the\c@pgf@countb (of \the\c@pgf@counta): #1}% \fi } @@ -532,135 +646,297 @@ % % The linespec. will be used in the legend. \long\def\addplot{% - \@ifnextchar[{% - \axis@addplotimpl% - }{% + \@ifnextchar+{% \axis@getautoplotspec into\nextplotspec - % the space after ']' is required here: - % FIXME: - % - \addplot[]plot coordinates is NOT allowed!? - \expandafter\axis@addplotimpl\expandafter[\nextplotspec] + \axis@addplotimplAPPEND + }{% + \@ifnextchar[{% + \axis@addplotimpl% + }{% + \axis@getautoplotspec into\nextplotspec + % the space after ']' is required here: + % FIXME: + % - \addplot[]plot coordinates is NOT allowed!? + \expandafter\axis@addplotimpl\expandafter[\nextplotspec] + }% }% } +\long\def\axis@addplotimplAPPEND+[{% + \expandafter\axis@addplotimpl\expandafter[\nextplotspec, +} + \long\def\axis@addplotimpl[#1] #2;{% +%\tracingmacros=2\tracingcommands=2 % #2 = plot coordinates {...} \ifx\csname axis@execute at begin plot\endcsname\empty \else \csname axis@execute at begin plot\endcsname \fi - \axis@rememberplotspec{[#1]} + \axis@rememberplotspec{[#1]}% \ifaxis@filtercoords % FIXME : FREE THIS VARIABLE: - \axis@filtercoords#2\newplotcmdto\axis@filteredcoordinateplotcmd - \ifaxis@draw@at@end - \expandafter\axis@update@limits\axis@filteredcoordinateplotcmd;% - \fi - \def\axis@TMP{\axispath\draw[style=every axis plot,#1] }% - \expandafter\axis@TMP\axis@filteredcoordinateplotcmd;% - %\tracingmacros=2\tracingcommands=2 - %\tracingmacros=0\tracingcommands=0 + \axis@filtercoords@and@up@limits#2;\newplotcmdto\axis@filteredcoordinateplotcmd + \def\axis@TMP{\axispath@impl{\draw[style=every axis plot,#1]}}% + \expandafter\axis@TMP\axis@filteredcoordinateplotcmd% \else \ifaxis@draw@at@end - \axis@update@limits#2;% + \axis@update@limits{#2;}% \fi - \axispath\draw[style=every axis plot,#1] #2;% + \axispath@impl{\draw[style=every axis plot,#1]}#2;% \fi \ifx\csname axis@execute at end plot\endcsname\empty \else \csname axis@execute at end plot\endcsname \fi +%\tracingmacros=0\tracingcommands=0 }% -\long\def\axis@update@limits plot coordinates #1;{% -%\axis@update@limits@forpoint#1\axis@restinto\axis@TMP - \def\axis@TMP{#1}% - \def\axis@TMPB{ }% - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \loop - \ifx\axis@TMP\empty - \else - \expandafter\axis@update@limits@forpoint\axis@TMP\axis@restinto\axis@TMP - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \repeat +\long\def\axis@update@limits#1{% + \axis@foreach@plot@coord@do% + \axis@update@limits@for@one@point + \for + #1% + \EOI } -% #1: optional white spaces (will be ignored). FIXME is there a better -% way? I could not get \ignorespaces into this ... -\long\def\axis@update@limits@forpoint#1(#2,#3)#4\axis@restinto#5{% +% PRECONDITIONS: +% - 'floating point numerics active' +% => coordinate filtering is active +% => #1 and #2 are MACRO names +% => these macros are encoded with \scisetcomponents +% - no coordinate filters active +% => #1 and #2 MAY be macros, but they must be valid TeX +% length (without unit). +\long\def\axis@update@limits@for@one@point#1#2{% +%\tracingmacros=2\tracingcommands=2 +%\message{Updating limits for (#1,#2) ...}% \ifaxis@autocompute@xlim - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@xmin}{#2}}% - \let\axis@xmin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@xmax}{#2}}% - \let\axis@xmax=\pgfmathresult + \ifaxis@float@numerics@mode@x +%\scitofixedsingle\axis@xmin\axis@TMP +%\scitofixedsingle\axis@xmax\axis@TMPB +%\message{current limits: xmin=\axis@TMP, xmax=\axis@TMPB}% + \scigetcomponents#1\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scigetcomponents\axis@xmin\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmin% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@xmin\axis@lim@S\axis@lim@M\axis@lim@E + % + \scigetcomponents\axis@xmax\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmax% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@xmax\axis@lim@S\axis@lim@M\axis@lim@E +%\scitofixedsingle\axis@xmin\axis@TMP +%\scitofixedsingle\axis@xmax\axis@TMPB +%\message{updated limits: xmin=\axis@TMP, xmax=\axis@TMPB}% + \else + \pgfmathmin{\axis@xmin}{#1}% + \let\axis@xmin=\pgfmathresult + \pgfmathmax{\axis@xmax}{#1}% + \let\axis@xmax=\pgfmathresult + \fi \fi \ifaxis@autocompute@ylim - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@ymin}{#3}}% - \let\axis@ymin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@ymax}{#3}}% - \let\axis@ymax=\pgfmathresult + \ifaxis@float@numerics@mode@y +%\scitofixedsingle\axis@ymin\axis@TMP +%\scitofixedsingle\axis@ymax\axis@TMPB +%\message{current limits: ymin=\axis@TMP, ymax=\axis@TMPB}% + \scigetcomponents#2\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scigetcomponents\axis@ymin\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmin% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@ymin\axis@lim@S\axis@lim@M\axis@lim@E + % + \scigetcomponents\axis@ymax\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmax% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@ymax\axis@lim@S\axis@lim@M\axis@lim@E +%\scitofixedsingle\axis@ymin\axis@TMP +%\scitofixedsingle\axis@ymax\axis@TMPB +%\message{updated limits: ymin=\axis@TMP, ymax=\axis@TMPB}% + \else + \pgfmathmin{\axis@ymin}{#2}% + \let\axis@ymin=\pgfmathresult + \pgfmathmax{\axis@ymax}{#2}% + \let\axis@ymax=\pgfmathresult + \fi \fi - \def#5{#4}% \axis@limits@are@computedtrue +%\tracingmacros=0\tracingcommands=0 } % Filters coordinates and writes a new, modified 'plot coordinates' % command to macro #2. -\long\def\axis@filtercoords plot coordinates #1\newplotcmdto#2{% - %\edef#2{plot coordinates \verb|}|}% +\long\def\axis@filtercoords@and@up@limits#1\newplotcmdto#2{% \let#2=\empty - \def\axis@TMP{#1}% - \def\axis@TMPB{ }% - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \loop - \ifx\axis@TMP\empty - \else - \expandafter\axis@filter@point\axis@TMP\appendto#2\axis@restinto\axis@TMP - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \repeat - \edef#2{plot coordinates {#2}}% -} + \let\axis@filter@output=#2 + \axis@foreach@plot@coord@do% + \axis@filter@one@coord@pair + \for + #1% + \EOI + \edef#2{plot coordinates {\axis@filter@output};}% +}% -% #1: optional white spaces (will be ignored). FIXME is there a better -% way? I could not get \ignorespaces into this ... -\long\def\axis@filter@point#1(#2,#3)#4\appendto#5\axis@restinto#6{% +\def\axis@filter@one@coord@pair#1#2{% \ifx\axis@xfilter\empty - \def\axis@filter@tmpx{#2}% + \def\axis@filter@tmp@x{#1}% \else - \let\axis@filter@tmpx=\empty - \axis@xfilter#2\to\axis@filter@tmpx\relax + \let\axis@filter@tmp@x=\empty + \axis@xfilter#1\to\axis@filter@tmp@x \fi \ifx\axis@yfilter\empty - \def\axis@filter@tmpy{#3}% + \def\axis@filter@tmp@y{#2}% \else - \let\axis@filter@tmpy=\empty - \axis@yfilter#3\to\axis@filter@tmpy\relax + \let\axis@filter@tmp@y=\empty + \axis@yfilter#2\to\axis@filter@tmp@y \fi - \ifx\axis@filter@tmpx\empty - \message{NOTE: coordinate (#2,#3) has been dropped because of the x-coordinate filter.}% + \ifx\axis@filter@tmp@x\empty + \message{NOTE: coordinate (#1,#2) has been dropped because of the x-coordinate filter.}% \else - \ifx\axis@filter@tmpy\empty - \message{NOTE: coordinate (#2,#3) has been dropped because of the y-coordinate filter.}% + \ifx\axis@filter@tmp@y\empty + \message{NOTE: coordinate (#1,#2) has been dropped because of the y-coordinate filter.}% \else - \edef#5{#5 (\axis@filter@tmpx,\axis@filter@tmpy)}% + \ifaxis@draw@at@end + % update also axis limits: + \axis@update@limits@for@one@point{\axis@filter@tmp@x}{\axis@filter@tmp@y}% + \else + % apply data transformation directly. + \ifaxis@float@numerics@mode@x + \axis@datascaletrafo@x\axis@filter@tmp@x\to\axis@filter@tmp@x + \fi + \ifaxis@float@numerics@mode@y + \axis@datascaletrafo@y\axis@filter@tmp@y\to\axis@filter@tmp@y + \fi + \fi + % remind: + % \the\tokenregister + % will yield the contents of the token register, it will + % NOT expand recursively (like \expandafter)! + % + % Employ that here to maintain macros inside of + % \axis@filter@tmp[xy] + % (macros inside of those things are used by the floating + % point numerics to scale input data to TeX-lengths) + \pgfplots@toka=\expandafter{\axis@filter@output}% + \TOKL@ta=\expandafter{\axis@filter@tmp@x}% + \TOKL@tb=\expandafter{\axis@filter@tmp@y}% + \edef\axis@filter@output{\the\pgfplots@toka (\the\TOKL@ta,\the\TOKL@tb)}% +%\message{FILTERING: appended \axis@filter@tmp@x,\axis@filter@tmp@y}% -> results in \axis@filter@output}% \fi \fi - \def#6{#4}% } + +% A looping command to loop through plot coordinates. +% For every point, #3{X}{Y} will be invoked. +% +% No scoping is used during this operation, so you can access outer +% variables. +\long\def\axis@foreach@plot@coord@do#1\for plot coordinates #2;\EOI{% + \axis@foreach@plot@coord@ITERATE#1\n#2\EOI% +} + +\def\axis@foreach@plot@coord@ITERATE#1\n{% + \@ifnextchar;{% + \axis@foreach@plot@coord@FINISH@SEMICOLON% + }{% + \@ifnextchar\EOI{% + \axis@foreach@plot@coord@FINISH% + }{% + \axis@foreach@plot@coord@NEXT#1\n% + }% + }% +} + +\def\axis@foreach@plot@coord@NEXT#1\n(#2,#3){% + #1{#2}{#3}% + \axis@foreach@plot@coord@ITERATE#1\n +} + +\def\axis@foreach@plot@coord@FINISH\EOI{} +\def\axis@foreach@plot@coord@FINISH@SEMICOLON;\EOI{} + +% INPUT: +% a sequence of points (SMeE,SMeE) (terminated with ';') +% where S=sign, M=mantisse, E = exponent. +% Such input is generated in the case axis@float@numerics@modetrue +% by the coordinate filters. +% OUTPUT: +% proper sequence of fixed point coordinates which are the result of the +% data scaling transformation (\axis@datascaletrafo@x). +% +% The output will be written into the macro #1. +\long\def\axis@apply@data@scaletrafo@to@plot@data#1\to#2{% + \let#2=\empty + \let\axis@data@scaletrafo@result=\empty + \axis@foreach@plot@coord@do + \axis@apply@data@scaletrafo@to@one@point + \for + #1% + \EOI + \edef#2{plot coordinates {\axis@data@scaletrafo@result};}% + %\axis@apply@data@scaletrafo@to@plot@data@ITERATE\to#2 #1;% +} + +\def\axis@apply@data@scaletrafo@to@one@point#1#2{% + \ifaxis@float@numerics@mode@x + \axis@decode@filtered@float@numerics#1\to\axis@filter@tmp@x + \axis@datascaletrafo@x\axis@filter@tmp@x\to\axis@filter@tmp@x + \else + \def\axis@filter@tmp@x{#1}% + \fi + \ifaxis@float@numerics@mode@y + \axis@decode@filtered@float@numerics#2\to\axis@filter@tmp@y + \axis@datascaletrafo@y\axis@filter@tmp@y\to\axis@filter@tmp@y + \else + \def\axis@filter@tmp@y{#2}% + \fi + \edef\axis@data@scaletrafo@result{\axis@data@scaletrafo@result (\axis@filter@tmp@x,\axis@filter@tmp@y)}% +} + + +\def\axis@decode@filtered@float@numerics#1#2e#3\to#4{% + \scisetcomponents#4{#1}{#2}{#3}% +} + + \long\def\axispath#1;{% + \axispath@impl{}#1; +} + +% low-level \axispath implementation. +% #1: +% the command which is responsable for drawing. +% - If #1 is NOT '\empty', we expect #2 to contain only +% EXPANDABLE DATA. +% That's important for postponed floating point arithmetics in #2. +% - If #1='\empty', we don't make any assumption about #2 +% and process it as-is. +% +% #2: see above. +\long\def\axispath@impl#1#2;{% \ifaxis@draw@at@end - \listpushback{#1;}\to\axis@draw@stored@plots% + \listpushback{#1}\to\axis@stored@plot@cmds + \listpushback{#2;}\to\axis@stored@plot@data \else - #1;% + #1#2;% \fi } @@ -668,27 +944,14 @@ % Assigns a legend. % Syntax: % \legend{entry 1\\entry2\\entry3} -% or -% \legend[OPTIONS]{entry 1\\entry2\\} -% -% where OPTIONS is -% - textwidth=auto | DIMEN | none -% like -% \legend[textwidth=auto]{entry 1\\entry2\\} -% \legend[textwidth=2cm}{...} -% \legend[textwidth=none}{...} -% -% The option "textwidth=auto" chooses the correct width automatically; -% the option "textwidth=none" does not perform any line breaking and -% "textwidth=DIMEN" uses the fixed dimenion DIMEN for the (total) -% width of the legend. -% -% - font={...} -% \legend[font=\Huge}{...} \newcommand{\legend}[2][]{ {% \globaldefs=1% this will ONLY store the options and the legend into global variables - \setkeys[\prefix]{legend}{#1}% + \def\axis@TMP{#1}% + \ifx\axis@TMP\empty + \else + \errmessage{Sorry, legend are now deprecated. Legends are now TikZ-matrizes which provide better alignment and can be placed horizontally. See the manual for details.}% + \fi \def\axis@TMP{#2}% \ifx\axis@TMP\empty \else @@ -704,7 +967,7 @@ }% } -\def\getnextlegend{{% +\def\axis@pop@next@legend{{% \globaldefs=1 \listcheckempty\axis@plotspeclist \iflistempty @@ -722,116 +985,109 @@ \advance\axis@numplots by-1 }} -\def\axis@setlegendfont{% - \tikz@textfont - \axis@legend@font -} - -% Helper function for \axis@createlegend -% It assigns the TOTAL width of the legend node to -% the dimension register #1 and the option to #2 as macro. -% Arguments: -% #1 a temporary dimension register which will be filled with the -% width. -% #2 a macro name which will be filled with 'text width=XXXX'. -% WARNING: -% this function use the variables -% - \axis@legend@textwidth (from keyval, see above) -% - \axis@TMP -% - \legendCOORDC -% - \legendHSEP -\def\axis@legend@determinewidth\to#1\optionto#2{% - \def\axis@TMP{auto}% - \ifx\axis@legend@textwidth\axis@TMP - % OPTION - % \legend[textwidth=auto] +\long\def\axis@show@small@legendplots#1{ + \draw#1 + [mark repeat=2,mark phase=2] + plot coordinates { + (0cm,0cm) + (0.3cm,0cm) + (0.6cm,0cm)% + };% +} + +% Typesets a legend node. +% +% It will either typeset a previously computed legend (which needs to be +% stored in the macro \axis@already@computed@legend@node) +% +% or it creates a legend, stores the commands into the macro named +% above and typesets it. +\newcommand\axis@createlegend{% + \ifx\axis@already@computed@legend@node\empty + \listcheckempty\axis@legend + \iflistempty + \else % - % STEP 1: maximum width legend entries - #1=0cm + % \begingroup - \listforeach\axis@legend\as\axis@curlegend{% - \setbox0=\hbox{{% - \pgfutil@selectfont% RESTORE normal fonts (have been resetted by PGF) - \axis@setlegendfont - \axis@curlegend% - }}% - \ifdim\wd0>#1 - \global#1=\wd0 - \fi - }% + % assemble a + % \matrix { + % small plot & legend1\\ + % small plot & legend2\\ + % ... + % }; + % command [and using the 'legend columns' option] + % + % \TOKL@ta={ + % small plot & legend1\\ + % small plot & legend2\\ + % ... + % } + % ( I have allocated the token register in my simplelist.sty) + % + % \global\def\axis@TMP{ + % \matrix { + % \TOKL@TA + % }; + % } + % -> finally, \axis@TMP will contain the complete command. + \TOKL@ta={}% + \let\curcolumnNum=\c@pgf@counta + \let\maxcolumnCount=\c@pgf@countb + \let\legendplotpos=\c@pgf@countc + \legendplotpos\expandafter=\axis@legend@plot@pos + \curcolumnNum=0 + \maxcolumnCount\expandafter=\csname axis@legend columns\endcsname\relax + % + \loop + \ifnum0<\axis@numplots\relax + \axis@pop@next@legend + \ifx\axis@curlegend\empty + \else + \advance\curcolumnNum by1 + \edef\axis@TMP{% + \the\TOKL@ta + \ifcase\legendplotpos + % legend plot pos=left + \noexpand\axis@show@small@legendplots{\axis@curplotlist}% + \noexpand\pgfmatrixnextcell + \noexpand\node {\axis@curlegend}; + \or + % legend plot pos=right + \noexpand\node {\axis@curlegend}; + \noexpand\pgfmatrixnextcell + \noexpand\axis@show@small@legendplots{\axis@curplotlist}% + \or + % legend plot pos=none + \noexpand\node {\axis@curlegend}; + \fi + \ifnum\curcolumnNum=\maxcolumnCount + \noexpand\\ + \else + \ifnum\axis@numplots=0 + \noexpand\\ + \else + \noexpand\pgfmatrixnextcell + \fi + \fi + }% + \ifnum\curcolumnNum=\maxcolumnCount + \curcolumnNum=0 + \fi + \expandafter\TOKL@ta\expandafter{\axis@TMP}% + \fi + \repeat + \TOKL@tb={\matrix[style=every axis legend]}% + \xdef\axis@TMP{% + \the\TOKL@tb {% + \the\TOKL@ta + };% + }% \endgroup - % STEP 2: add plot spec width: - \expandafter\axis@tmpb\legendCOORDC - \advance#1 by\axis@tmpb - % STEP 3: hspace between plot spec and legend: - \advance#1 by\legendHSEP - %\advance#1 by1pt% FIXME I don't know why there was to few place!? - \def#2{text width=\the#1,}% - \else - \def\axis@TMP{none}% - \ifx\axis@legend@textwidth\axis@TMP - % OPTION - % \legend[textwidth=none] - % don't make a '\node[text width=XX]' option: - #1=0cm - \def#2{}% - \else - % OPTION - % \legend[textwidth=2cm] - % just use it: - \expandafter#1\axis@legend@textwidth - \def#2{text width=\the#1,}% + \let\axis@already@computed@legend@node=\axis@TMP \fi \fi - % -} - -\newcommand\axis@createlegend{% - \listcheckempty\axis@legend - \iflistempty - \else - % - \def\legendHSEP{5pt}% - \def\legendCOORDB{0.3cm}% - \def\legendCOORDC{0.6cm}% - % - \axis@legend@determinewidth\to\pgf@xa\optionto\axis@TMP - % - % - % This code here invokes - % \node[, - % ... - % ] - % where \axis@TMP contains a "text width=XXX" option. - %DEBUG: - %\draw[red] (0,0) rectangle (1,1); - \expandafter\node\expandafter[\axis@TMP% - style=every axis legend] - {% - \loop\ifnum0<\axis@numplots - \getnextlegend - \ifx\axis@curlegend\empty - \else - \vbox{% - \noindent - \begin{minipage}[c]{\legendCOORDC}% - \tikz - \expandafter\draw\axis@curplotlist - [mark repeat=2,mark phase=2] - plot coordinates { - (0cm,0cm) - (\legendCOORDB,0cm) - (\legendCOORDC,0cm)};% - \hss - \end{minipage} - %\expandafter\hskip\legendHSEP - \axis@setlegendfont - \axis@curlegend - }% - \fi - \repeat - }; - \fi + \axis@already@computed@legend@node } % Checks whether the argument to xtick or ytick is a UNIFORM tick @@ -857,18 +1113,19 @@ \begingroup \global\axis@isuniformticktrue \newif\ifisfirst + \newif\iftwo@are@equal \isfirsttrue \foreach \x in {#1}{% - \pgfmathlog@invoke@expanded\pgfmathdivide@{{\x}{\logten}}% + \pgfmathmultiply@\x\reciproc@logten \let\cur=\pgfmathresult % check whether % \cur - last == 1 (last = \axis@TMPB) \ifisfirst \global\isfirstfalse \else - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\cur}{\axis@TMPB}}% - \def\axis@TMP{1.0}% - \ifx\axis@TMP\pgfmathresult + \pgfmathsubtract@\cur\axis@TMPB% + \pgfmathlog@approxequalto@macro\pgfmathresult{1.0}{two@are@equal}% + \iftwo@are@equal \else \global\axis@isuniformtickfalse \breakforeach @@ -892,14 +1149,14 @@ } \def\logtologtentomacro#1#2{% - \pgfmathlog@invoke@expanded\pgfmathdivide@{{#1}{\logten}}% + \pgfmathmultiply@{#1}\reciproc@logten% \expandafter\skipsuffixzero\pgfmathresult|% \let#2=\pgfmathresult } % Expands to #1/log(10). It will also skip a suffix '.0' \def\logtologten#1{% - \pgfmathlog@invoke@expanded\pgfmathdivide@{{#1}{\logten}}% + \pgfmathmultiply@{#1}\reciproc@logten% \expandafter\skipsuffixzero\pgfmathresult|% \pgfmathresult } @@ -909,7 +1166,7 @@ \def\axis@compute@tick@times@logten#1\to#2{% \global\let#2=\empty \foreach \axis@TMPB in {#1} {% - \pgfmathlog@invoke@expanded\pgfmathmultiply@{{\axis@TMPB}{\logten}}% + \pgfmathmultiply@\axis@TMPB\logten% \ifx#2\empty \xdef#2{\pgfmathresult}% \else @@ -918,43 +1175,77 @@ }% } -\def\axis@enlarge@xlim{% - \ifcase\axis@xmode - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@xmin}{0.5}}% - \let\axis@xmin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@xmax}{0.5}}% - \let\axis@xmax=\pgfmathresult +\def\axis@init@enlarge@limit@booleans{% + \axis@enlargelimits@autofalse + \axis@enlargelimitsfalse + \axis@enlargelimits@rel@threshfalse + \edef\axis@TMP{\axis@enlargelimits}% + % + \def\axis@TMPB{true}% + \ifx\axis@TMP\axis@TMPB + \axis@enlargelimitstrue + \else + \def\axis@TMPB{false}% + \ifx\axis@TMP\axis@TMPB + \else + \def\axis@TMPB{auto}% + \ifx\axis@TMP\axis@TMPB + \axis@enlargelimits@autotrue + \else + \begingroup + % try to read it as number: + \expandafter\pgf@xa\axis@enlargelimits pt\relax + \endgroup + \axis@enlargelimitstrue + \axis@enlargelimits@rel@threshtrue + \fi + \fi + \fi +} + +\def\axis@enlarge@limit@for#1{% + \begingroup + \expandafter\let\expandafter\min\expandafter=\csname axis@#1min\endcsname + \expandafter\let\expandafter\max\expandafter=\csname axis@#1max\endcsname + \ifcase\csname axis@#1mode\endcsname + \ifaxis@enlargelimits@rel@thresh + \edef\enlargepercent{\axis@enlargelimits}% + \else + \def\enlargepercent{0.1}% FIXME : pack 10% as default into option 'enlargelimits' or so + \fi + \pgfmathsubtract@\max\min% + \expandafter\pgf@xa\pgfmathresult pt + \expandafter\pgf@xb\enlargepercent\pgf@xa + \ifdim\pgf@xb>0.001pt + % the case with + % enlargeabsolute ~= 0 + % means that \min ~= \max. + % It is handled in another method. + \edef\enlargeabsolute{\pgf@sys@tonumber{\pgf@xb}}% + % + % compute xmin := xmin - enlargeabsolute + \pgfmathsubtract@\min\enlargeabsolute% + \let\min=\pgfmathresult + \pgfmathadd@\max\enlargeabsolute% + \let\max=\pgfmathresult + \fi \or % compute - % \pgfmathsetmacro{\axis@xmin}{\axis@xmin - 0.5*\logten}% - % \pgfmathsetmacro{\axis@xmax}{\axis@xmax + 0.5*\logten}% + % \pgfmathsetmacro{\min}{\min - 0.5*\logten}% + % \pgfmathsetmacro{\max}{\max + 0.5*\logten}% % just a more efficiently (I hope so): \expandafter\pgfmath@x\logten pt \divide\pgfmath@x by2 - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@xmin}{\pgf@sys@tonumber{\pgfmath@x}}}% - \let\axis@xmin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@xmax}{\pgf@sys@tonumber{\pgfmath@x}}}% - \let\axis@xmax=\pgfmathresult - \fi -} -\def\axis@enlarge@ylim{% - \ifcase\axis@ymode - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@ymin}{0.5}}% - \let\axis@ymin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@ymax}{0.5}}% - \let\axis@ymax=\pgfmathresult - \or - % compute - % \pgfmathsetmacro{\axis@ymin}{\axis@ymin - 0.5*\logten}% - % \pgfmathsetmacro{\axis@ymax}{\axis@ymax + 0.5*\logten}% - % just a more efficiently (I hope so): - \expandafter\pgfmath@y\logten pt - \divide\pgfmath@y by2 - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@ymin}{\pgf@sys@tonumber{\pgfmath@y}}}% - \let\axis@ymin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@ymax}{\pgf@sys@tonumber{\pgfmath@y}}}% - \let\axis@ymax=\pgfmathresult + \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\min}{\pgf@sys@tonumber{\pgfmath@x}}}% + \let\min=\pgfmathresult + \pgfmathlog@invoke@expanded\pgfmathadd@{{\max}{\pgf@sys@tonumber{\pgfmath@x}}}% + \let\max=\pgfmathresult \fi + \xdef\axis@TMP{\min}% + \xdef\axis@TMPB{\max}% + \endgroup + \expandafter\let\csname axis@#1min\endcsname=\axis@TMP + \expandafter\let\csname axis@#1max\endcsname=\axis@TMPB } % Computes tick positions using the current axis limits. @@ -963,13 +1254,32 @@ % \axisdefaulttickwidth % Determines the maximum space which is not filled by at least one % tick label (approximate, there is some rounding internally) +% \axisdefaulttryminticks +% see manual +% +% Idea: +% We want ticks at each +% { i*H, i in \Z }. +% Of course, there shouldn't be TOO MUCH ticks. % -% Heuristics: -% Set desirednumticks = trunc(ACTUAL WIDTH / axisdefaulttickwidth) +1 +% Our heuristics is to set +% desirednumticks = round(ACTUAL WIDTH / axisdefaulttickwidth) +% and generate H = (axis range) / desirednumticks. % -% and generate STEPSIZE = (axis range)/ desirednumticks +% Since not all step sizes H look well, restrict H to a set of allowed +% step sizes such as +% { 1, 1/2, 1/5, 1/10 }, +% or, to be more precise: +% { 1*10^e, 2*10^e, 5*10^e } +% -> round to the nearest matching number! +% +% Then, the resulting tick is +% TICK={MIN,MIN+H,...,MAX} +% where +% MIN = I*H +% is chosen such that +% axis minimum limit = I*H + rest; |rest| < H. % -% We actually restrict STEPSIZE to { 1, 1/2, 1/5, 1/10 } % % PRECONDITION: % - limits are correct @@ -980,6 +1290,11 @@ % - \ifaxis@needs@check@uniformtick is set \def\axis@assign@default@tick@foraxis#1{% \begingroup + % Shortcut-names: + \expandafter\let\expandafter\ifaxis@is@datascaled\csname ifaxis@float@numerics@mode@#1\endcsname + \expandafter\let\expandafter\axis@data@scale@trafo\csname axis@datascaletrafo@#1\endcsname + \expandafter\let\expandafter\axis@data@scale@inverse@trafo\csname axis@inverse@datascaletrafo@#1\endcsname + % \let\desirednumticks=\c@pgf@countd \let\Wr=\pgf@xc \Wr=\csname axis@#1coordmaxTEX\endcsname @@ -988,48 +1303,89 @@ \expandafter\expandafter\divide\Wr\axisdefaulttickwidth \pgfmathsetcount{\desirednumticks}{\Wr}% \advance\desirednumticks by1 + \expandafter\ifnum\axisdefaulttryminticks>\desirednumticks + \expandafter\desirednumticks\axisdefaulttryminticks + \fi \ifcase\csname axis@#1mode\endcsname - % compute tick := MIN-h,MIN,....,MAX+h - % where h is a determined step size and MIN and MAX are - % (truncated) axis limits. - % - % The MIN-h and MAX+h is to support compatibility with the - % enlargelimits option - there should be ticks in the - % enlarged place. - \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1min\endcsname}% - %\pgfmathsetcount{\c@pgf@countb}{\csname axis@#1max\endcsname}% - \expandafter\ifdim\csname axis@#1min\endcsname pt<0pt - % the truncation round TOWARDS 0 which is not what I want. - \advance\c@pgf@counta by-1 - \fi + % compute tick := MIN,MIN+H,....,MAX \let\MINH=\pgf@xa \let\H=\pgf@xb \let\MAX=\axis@tmpa \let\MIN=\axis@tmpb - % compute step size 'h': + % compute step size 'H': \expandafter\MAX\csname axis@#1max\endcsname pt \advance\MAX by0.001pt% avoid round errors - \expandafter\MIN\the\c@pgf@counta pt + %\expandafter\MIN\the\c@pgf@counta pt + \expandafter\MIN\csname axis@#1min\endcsname pt \H=\MAX \advance\H by-\MIN \c@pgf@counta=\desirednumticks \advance\c@pgf@counta by-1 \divide\H by\c@pgf@counta - %\message{Wr\the\Wr, desirednumticks=\the\desirednumticks, H=\the\H}% - \ifdim\H<0.10001pt - \H=0.1pt +%\message{determining ticks for #1-axis: Wr := (width/max space between ticks) = \the\Wr, desirednumticks=max(\axisdefaulttryminticks, trunc(Wr)) = \the\desirednumticks, H=(axis range/(desirednumticks-1)) = \the\H}% + % + % SEARCH for the NEXT FEASABLE H. + % + \edef\Hmacro{\pgf@sys@tonumber\H}% + \ifaxis@is@datascaled + \expandafter\axis@data@scale@inverse@trafo\Hmacro\to\Hmacro + \else + \expandafter\sciparsesignsingle\expandafter{\Hmacro}\Hmacro + \fi + \scigetcomponents\Hmacro\H@S\H@M\H@E +%\message{Got T^{-1}(H) = [\H@S] \H@M * 10^\H@E}% + % modify the mantisse: + \expandafter\H\H@M pt + \ifdim\H<2pt + \ifdim\H<1.5pt + \def\H@M{1.0}% + \else + \def\H@M{2.0}% + \fi \else - \ifdim\H<0.20001pt - \H=0.2pt + \ifdim\H<4.9999pt + \ifdim\H<3.5pt + \def\H@M{2.0}% + \else + \def\H@M{5.0}% + \fi \else - \ifdim\H<0.5001pt - \H=0.5pt + \ifdim\H<7.5pt + \def\H@M{5.0}% \else - \H=1pt + \def\H@M{1.0}% + \expandafter\c@pgf@counta\H@E + \advance\c@pgf@counta by1 + \edef\H@E{\the\c@pgf@counta}% \fi \fi \fi - %\message{final H=\the\H}% + \scisetcomponents\Hmacro\H@S\H@M\H@E + \ifaxis@is@datascaled + \axis@data@scale@trafo\Hmacro\to\Hmacro + \else + \scitofixedsingle\Hmacro\Hmacro + \fi +%\message{I have computed H=\Hmacro}% + \expandafter\H\Hmacro pt +%\message{final H=\the\H}% + % + % Now, we want to activate the Tick set {i*H, i in \Z} + % compute I such that + % xmin = I * H + rest; |rest| < H + % -> I = round(xmin/H) + % -> MIN = I * H + \pgfmathlog@invoke@expanded\pgfmathdivide@{% + {\pgf@sys@tonumber\MIN}% + {\pgf@sys@tonumber\H}% + }% + \pgfmathsetcount{\c@pgf@counta}{\pgfmathresult}% + \ifdim\MIN<0pt + % the truncation rounds TOWARDS 0 which is not what I want. + \advance\c@pgf@counta by-1 + \fi + \MIN=\H + \multiply\MIN by\c@pgf@counta \MINH=\MIN \advance\MINH by\H \xdef\axis@TMP{\pgf@sys@tonumber{\MIN},\pgf@sys@tonumber{\MINH},...,\pgf@sys@tonumber{\MAX}}% @@ -1037,9 +1393,11 @@ \or \expandafter\ifx\csname axis@#1tickten\endcsname\empty % I want ticks at 10^k. So determine k_min and k_max. - \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1min\endcsname/\logten-1}% + % + % FIXME: optimize! + \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1min\endcsname*\reciproc@logten-1}% \pgfmathsetmacro{\tmp@min}{\c@pgf@counta*\logten}% - \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1max\endcsname/\logten}% + \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1max\endcsname*\reciproc@logten}% \pgfmathsetmacro{\tmp@max}{\c@pgf@counta*\logten}% \pgfmathadd\tmp@min\logten% \xdef\axis@TMP{\tmp@min,\pgfmathresult,...,\tmp@max}% @@ -1052,79 +1410,218 @@ \fi \endgroup \expandafter\let\csname axis@#1tick\endcsname=\axis@TMP - %\message{pgfplots.sty: #1tick set to \csname axis@#1tick\endcsname [#1mode=\the\csname axis@#1mode\endcsname, #1min=\csname axis@#1min\endcsname, #1max=\csname axis@#1max\endcsname].}% +%\message{pgfplots.sty: #1tick set to \csname axis@#1tick\endcsname [#1mode=\the\csname axis@#1mode\endcsname, #1min=\csname axis@#1min\endcsname, #1max=\csname axis@#1max\endcsname].}% } -\def\axis@determinedefaultvalues{% - % NOTIZ: - % - % wenn ich AUTOMATISCH aus (x_i,y_i) - % [xy]min und [xy]max ausrechnen will, muss ich - % ggf. - % xmin = min_{i} { untere_gaussklammer(log(x_i) / log10) } - % rechnen +% Helper method for +% \axis@apply@data@scale@trafo@to@options@for +% #1: the ticks +% #2: the trafo macro name (the form taking three args) +% #3: the output macro name +\long\def\axis@apply@data@scale@trafo@to@user@ticks#1#2\to#3{% + \let#3=\empty + \foreach \axis@TMPB in {#1} {% + \expandafter\sciparsesign\expandafter{\axis@TMPB}\sci@S\sci@M\sci@E + #2\sci@S\sci@M\sci@E\to\axis@TMPB + \ifx#3\empty + \xdef#3{\axis@TMPB}% + \else + \xdef#3{#3,\axis@TMPB}% + \fi + }% + % +}% + +% helper for \axis@apply@data@scale@trafo@to@options@for. +\def\axis@compute@number@order@for@trafo@isdimen#1\tocount#2{% + \edef\axis@TMP{\pgf@sys@tonumber{#1}}% + \expandafter\sciparsesign\expandafter{\axis@TMP}\S\M\E + \expandafter#2\E\relax + \advance#2 by1 +} + +% helper for \axis@apply@data@scale@trafo@to@options@for. +% +\def\axis@compute@number@order@for@trafo@isfloat#1\tocount#2{% + \scigetcomponents#1\S\M\E + \expandafter#2\E\relax + \advance#2 by1 +} + +% Initialises the data scale transformation and applies it to any +% user specified options. +% +% PRECONDITION: +% - all axis limits are available in float representation +% (i.e. with \scisetcomponents) +% - \axis@set@default@size@options has been called before +% POSTCONDITION: +% - the scaling transformation is set up, +% - all axis limits are transformed, +% - any user input (like ticks and tick labels) +% will reflect the changes. +\def\axis@apply@data@scale@trafo@to@options@for#1{% + % initialise data scale transformation + % T(x) = 10^{q-m} * x + % + \begingroup + \let\data@max@order=\c@pgf@counta + \let\data@cur@order=\c@pgf@countb + \let\data@dimen=\pgf@xa + \let\data@dimen@order=\c@pgf@countc + % + % Step 1: compute 'm', the data order + \expandafter\axis@compute@number@order@for@trafo@isfloat + \csname axis@#1min\endcsname + \tocount\data@cur@order + % + \data@max@order=\data@cur@order + % + \expandafter\axis@compute@number@order@for@trafo@isfloat + \csname axis@#1max\endcsname + \tocount\data@cur@order + % + \ifnum\data@cur@order>\data@max@order + \data@max@order=\data@cur@order + \fi % + % Step 2: compute 'q', the #1-size of the axis. + \expandafter\ifx\csname axis@#1\endcsname\empty + % We have 'width' or 'height'. + % + % Use the order of these parameters. + \def\axis@TMP{#1}% + \def\axis@TMPB{x}% + \ifx\axis@TMP\axis@TMPB + \expandafter\data@dimen\axis@width\relax + \else + \def\axis@TMPB{y}% + \ifx\axis@TMP\axis@TMPB + \expandafter\data@dimen\axis@height\relax + \fi + \fi + \axis@compute@number@order@for@trafo@isdimen + \data@dimen + \tocount\data@dimen@order + % This here is to avoid inaccuracies in the final + % axis rectangle size, see \axis@initsizes: + \advance\data@dimen@order by-1 + \else + % FIXME: + % we have either the 'x=1cm' or 'y=1cm' option! + % How should I initialise the trafo!? + \data@dimen@order=3 + \fi + % +%\message{Direction #1: data max order=\the\data@max@order; data dimen order=\the\data@dimen@order. }% + \advance\data@dimen@order by-\data@max@order + \xdef\axis@TMP{\the\data@dimen@order}% + \endgroup +%\message{Initialising the data scale transformation in direction #1 to \axis@TMP...}% + % COMPLETE INITIALISATION: + \ifaxis@EMERGENCY@FORCE@DATA@TRAFO@TO@IDENTITY + \message{WARNING: the automatic scaling of input data has been DISABLED to allow axispath commands [otherwise, axispath commands would not know of the pgfplots scalings - leading to wrong images). DISABLING THE DATA SCALING LIMITS THE DATA RANGE! I hope I can fix this issue as soon as possible. Please take a look at the manual for more information. If you get 'OVERFLOW' or 'UNDERFLOW' errors, you may need to disable the axispath.}% + \def\axis@TMP{0}% + \expandafter\let\csname axis@data@scale@trafo@SHIFT@#1\endcsname\axis@TMP + \else + \expandafter\let\csname axis@data@scale@trafo@SHIFT@#1\endcsname\axis@TMP + \fi + % + % ... and apply transformation to any user input + % + % Transform axis limits: + \expandafter\expandafter\csname axis@datascaletrafo@#1\endcsname\csname axis@#1min\endcsname\to\axis@TMP + \expandafter\let\csname axis@#1min\endcsname=\axis@TMP + % + \expandafter\expandafter\csname axis@datascaletrafo@#1\endcsname\csname axis@#1max\endcsname\to\axis@TMP + \expandafter\let\csname axis@#1max\endcsname=\axis@TMP + % + % Convert any user-specified ticks: + \edef\axis@TMP{\csname axis@#1tick\endcsname}% + % this here should also work with 'xtick=\empty', the "No tick" command. + \ifx\axis@TMP\empty + \else +%\message{Converting #1tick='\csname axis@#1tick\endcsname'}% + \pgfplots@toka=\expandafter{\csname axis@datascaletrafo@#1@three\endcsname}% + \edef\axis@TMP{{\csname axis@#1tick\endcsname}\the\pgfplots@toka}% + \expandafter\axis@apply@data@scale@trafo@to@user@ticks\axis@TMP\to\axis@TMPC + \expandafter\let\csname axis@#1tick\endcsname=\axis@TMPC + \fi + % + % Transform any explicit axis unit scalings: + \expandafter\ifx\csname axis@#1\endcsname\empty + \else +%\message{Converting #1 unit scale='\csname axis@#1\endcsname' ... }% + \expandafter\pgfmathparse\expandafter{\csname axis@#1\endcsname}% + \expandafter\expandafter\csname axis@inverse@datascaletrafo@tofixed@#1\endcsname\pgfmathresult\to\axis@TMP + \edef\axis@TMP{\axis@TMP pt}% + \expandafter\edef\csname axis@#1\endcsname{\axis@TMP}% +%\message{to #1='\csname axis@#1\endcsname'.}% + \fi +} + +\def\axis@determinedefaultvalues{% \ifx\axis@xmin\empty \errmessage{Sorry, the argument 'xmin=NUM' is mandatory to draw axes }% + \def\axis@xmin{0}% \fi \ifx\axis@xmax\empty \errmessage{Sorry, the argument 'xmax=NUM' is mandatory to draw axes }% + \def\axis@xmax{1}% \fi \ifx\axis@ymin\empty \errmessage{Sorry, the argument 'ymin=NUM' is mandatory to draw axes }% + \def\axis@ymin{0}% \fi \ifx\axis@ymax\empty \errmessage{Sorry, the argument 'ymax=NUM' is mandatory to draw axes }% + \def\axis@ymax{1}% \fi % + \axis@set@default@size@options % - \ifx\axis@trimxmin\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@xmin}{\axis@trimxmin}}% - \let\axis@xmin=\pgfmathresult + \ifaxis@float@numerics@mode@x + \axis@apply@data@scale@trafo@to@options@for x% \fi - \ifx\axis@trimxmax\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@xmax}{\axis@trimxmax}}% - \let\axis@xmax=\pgfmathresult - \fi - \ifx\axis@trimymin\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@ymin}{\axis@trimymin}}% - %\pgfmathmax\axis@ymin\axis@trimymin% - \let\axis@ymin=\pgfmathresult - \fi - \ifx\axis@trimymax\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@ymax}{\axis@trimymax}}% - %\pgfmathmin\axis@ymax\axis@trimymax% - \let\axis@ymax=\pgfmathresult + \ifaxis@float@numerics@mode@y + \axis@apply@data@scale@trafo@to@options@for y% \fi % - % \ifnum\axis@xmode=0 \axis@xminorticksfalse \fi \ifnum\axis@ymode=0 \axis@yminorticksfalse \fi + % + \axis@init@enlarge@limit@booleans \ifaxis@enlargelimits % relax the sizes. % % Idea: if the user chose his xmin,xmax tight to his data, % this here will look better. - \axis@enlarge@xlim - \axis@enlarge@ylim + \axis@enlarge@limit@for x + \axis@enlarge@limit@for y \else - % FIXME : this here should be user-configurable! - \ifaxis@autocompute@xlim - \axis@enlarge@xlim - \fi - \ifaxis@autocompute@ylim - \axis@enlarge@ylim + \ifaxis@enlargelimits@auto + \ifaxis@hide + % there is no axis, so skip this enlargement (unless + % the user explizitly requests it) + \else + % FIXME : this here should be user-configurable! + \ifaxis@autocompute@xlim + \axis@enlarge@limit@for x + \fi + \ifaxis@autocompute@ylim + \axis@enlarge@limit@for y + \fi + \fi \fi \fi % + \axis@avoid@empty@axis@range@for x% + \axis@avoid@empty@axis@range@for y% + % \axis@initsizes % \newif\ifaxis@xisuniform @@ -1187,6 +1684,7 @@ \fi } + % Helper method for initsizes. % % It computes a scaling such that \axis@width = SCALE * ACTUAL WIDTH. @@ -1208,7 +1706,14 @@ % -> \axis@tmpXscale = (X - c) / (x *(xmax-xmin)) % % \axis@tmpa := X-c: - \advance\axis@tmpa by-45pt% FIXME determine 'c' correctly! + \ifaxis@scale@only@axis + \else + \advance\axis@tmpa by-45pt% FIXME determine 'c' correctly! + \fi + \ifdim\axis@tmpa<0pt + \errmessage{Error: Plot width `\axis@width' is too small. This can't be realised while maintaining constant width for y-labels. Sorry, label width are only approximate. You will need to adjust your width.}% + \axis@tmpa=0pt + \fi % \axis@tmpb := x*(xmax-xmin): \axis@tmpb=\axis@xcoordmaxTEX \advance\axis@tmpb by-\axis@xcoordminTEX @@ -1217,13 +1722,11 @@ {\pgf@sys@tonumber\axis@tmpb}% }% \let#1=\pgfmathresult - %-------------------------------------------------- - % \message{pgfplots.sty: Computing 'x' such that 'width = c + x*(xmax-xmin)'; - % c=estimated, - % width-c =\the\axis@tmpa, - % x*(xmax[=\the\axis@xcoordmaxTEX] - xmin[=\the\axis@xcoordminTEX)]) = \the\axis@tmpb - % -> x-scale =#1 }% - %-------------------------------------------------- +%\message{pgfplots.sty: Computing 'x' such that 'width = c + x*(xmax-xmin)'; +% c=estimated, +% width-c =\the\axis@tmpa, +% x*(xmax[=\the\axis@xcoordmaxTEX] - xmin[=\the\axis@xcoordminTEX)]) = \the\axis@tmpb +% -> x-scale =#1 }% } % The same as \axis@initsizes@getXscale, just for the height. @@ -1235,7 +1738,14 @@ % -> \axis@tmpXscale = (X - c) / (x *(xmax-xmin)) % % \axis@tmpa := X-c: - \advance\axis@tmpa by-45pt% FIXME determine 'c' correctly! + \ifaxis@scale@only@axis + \else + \advance\axis@tmpa by-45pt\relax% FIXME determine 'c' correctly! + \fi + \ifdim\axis@tmpa<0pt + \errmessage{Error: Plot height `\axis@height' is too small. This can't be realised while maintaining constant height for x-labels. Sorry, label heights are only approximate. You will need to adjust your height.}% + \axis@tmpa=0pt + \fi % \axis@tmpb := x*(xmax-xmin): \axis@tmpb=\axis@ycoordmaxTEX \advance\axis@tmpb by-\axis@ycoordminTEX @@ -1244,28 +1754,110 @@ {\pgf@sys@tonumber\axis@tmpb}% }% \let#1=\pgfmathresult - %-------------------------------------------------- - % \message{pgfplots.sty: Computing 'y' such that 'height = c + y*(ymax-ymin)'; - % %height=\axis@height, - % c=estimated, - % height-c =\the\axis@tmpa, - % y*(ymax[=\the\axis@ycoordmaxTEX] - ymin[=\the\axis@ycoordminTEX)]) = \the\axis@tmpb - % -> y-scale =#1 }% - %-------------------------------------------------- -} - -% PRECONDITION: correct axis limits -% POSTCONDITION: the current x- and y unit vectors are changed; -% \axis@[xy]coord{min,max}TEX are set +%\message{pgfplots.sty: Computing 'y' such that 'height = c + y*(ymax-ymin)'; +% height=\axis@height, +% c=estimated, +% height-c =\the\axis@tmpa, +% y*(ymax[=\the\axis@ycoordmaxTEX] - ymin[=\the\axis@ycoordminTEX)]) = \the\axis@tmpb +% -> y-scale =#1 }% +} + + +% Checks whether axis limits in coordinate #1 are approximately equal. % -\def\axis@initsizes{% - % INIT. - % - % The axes 'x' and 'y' vectors will be scaled such that the total - % size is (\axisdefaultwidth, \axisdefaultheight). - % - % If the user specifies ONE of width OR height, - % the plot will be resized; keeping the aspect ratio. +% If that is the case, force a non-zero width of the range. +% +\def\axis@avoid@empty@axis@range@for#1{% + % Check if axis limits are empty: + \begingroup + \expandafter\let\expandafter\if@cur@is@scaled\csname ifaxis@float@numerics@mode@#1\endcsname + \expandafter\let\expandafter\min\csname axis@#1min\endcsname + \expandafter\let\expandafter\max\csname axis@#1max\endcsname + \let\min@d=\pgf@xa + \let\max@d=\pgf@xb + \let\diff=\pgf@xc + \newif\ifrange@is@approx@equal + \expandafter\min@d\min pt + \expandafter\max@d\max pt + \diff=\max@d + \advance\diff by-\min@d + % FIXME : I need a RELATIVE check here! + % but: real number point division is expensive + \if@cur@is@scaled + % this here should be sufficient because the axis + % has absolute values of order O( 10^3 ) or so. + \ifdim\diff<1pt + \range@is@approx@equaltrue + \fi + \else + % there is no data scaling, so I should be much more defensive + % with absolute thresholds... + \ifdim\diff<0.05pt + \range@is@approx@equaltrue + \fi + \fi + \ifrange@is@approx@equal +%\message{avoid range is approx equal for coord #1: MODIFYING (\min,\max)...}% + % the case \min ~= \max + % + % enlarge \max and shrink \min: + \ifdim\max@d<0pt + \ifdim\max@d<-1pt + \max@d=0.8\max@d + \min@d=1.2\min@d + \else + \advance\max@d by-1pt + \advance\min@d by1pt + \fi + \else + \ifdim\max@d>1pt + \max@d=1.2\max@d + \min@d=0.8\min@d + \else + \ifdim\max@d=0pt + \if@cur@is@scaled + % we can't simply add a constant in the + % transformed range. + % + % So: set limits to [-1,1] = [-1.0e0,+1.0e0] + \def\sci@S{2}% + \def\sci@M{1.0}% + \def\sci@E{0}% + \csname axis@datascaletrafo@#1@three\endcsname\sci@S\sci@M\sci@E\to\min + \def\sci@S{1}% + \def\sci@M{1.0}% + \def\sci@E{0}% + \csname axis@datascaletrafo@#1@three\endcsname\sci@S\sci@M\sci@E\to\max +%\message{[trafo shift = \csname axis@data@scale@trafo@SHIFT@#1\endcsname; setting limits -1:1]}% + \expandafter\min@d\min pt + \expandafter\max@d\max pt + \else + \advance\max@d by1pt + \advance\min@d by-1pt + \fi + \else + \advance\max@d by1pt + \advance\min@d by-1pt + \fi + \fi + \fi + \xdef\axis@TMP{\pgf@sys@tonumber{\min@d}}% + \xdef\axis@TMPB{\pgf@sys@tonumber{\max@d}}% +%\message{ -> #1 = \axis@TMP : \axis@TMPB;}% + \else + \global\let\axis@TMP=\min% + \global\let\axis@TMPB=\max% + \fi + \endgroup + \expandafter\let\csname axis@#1min\endcsname=\axis@TMP + \expandafter\let\csname axis@#1max\endcsname=\axis@TMPB +} + +% PRECONDITION: +% none +% POSTCONDITION: +% \axis@default@aspect@ratio is set. +\def\axis@compute@default@aspect@ratio{% \expandafter\pgfmath@x\axisdefaultwidth \expandafter\pgfmath@y\axisdefaultheight \pgfmathlog@invoke@expanded\pgfmathdivide@{% @@ -1273,52 +1865,70 @@ {\pgf@sys@tonumber{\pgfmath@y}}% }% \let\axis@default@aspect@ratio=\pgfmathresult +} + +\def\axis@set@default@size@options{% + % The axes 'x' and 'y' vectors will be scaled such that the total + % size is (\axisdefaultwidth, \axisdefaultheight). % - \pgfpointxy{\axis@xmin}{\axis@ymin}% - \axis@xcoordminTEX=\pgf@x - \axis@ycoordminTEX=\pgf@y - \pgfpointxy{\axis@xmax}{\axis@ymax}% - \axis@xcoordmaxTEX=\pgf@x - \axis@ycoordmaxTEX=\pgf@y - % - %----------------------------------------- - % PROCESS THE 'width' and 'height' options - %----------------------------------------- + % If the user specifies ONE of width OR height, + % the plot will be resized; keeping the aspect ratio. % - % FIXME: make these variables LOCAL: - \let\axis@tmpXscale=\empty% - \let\axis@tmpYscale=\empty% + \let\axis@default@aspect@ratio=\empty % CASES: % hasx := 'x' option non-empty % hasy := 'y' option non-empty % W := 'width' option non-empty % H := 'height' option non-empty % - % hasx hasy - % 0 0 -> work depend on W and H: - % W H - % 0 0 -> use \axisdefaultwidth and \axisdefaultheight - % 0 1 -> determine s:=\axis@tmpYscale and y*=s, x*=s (aspect ratio) - % 1 0 -> determine s:=\axis@tmpXscale and " " " - % 1 1 -> use specified width and height - % 0 1 -> use specified y vector, xscale by 'W' option (NO ASPECT RATIO) - % W - % 0 -> use \axisdefaultwidth - % 1 -> determine s:=\axis@tmpXscale - % 1 0 -> use specified x vector, yscale by 'H' option (NO ASPECT RATIO) - % H - % 0 -> use \axisdefaultheight - % 1 -> determine s:=\axis@tmpYscale - % 1 1 -> use specified x AND y vector (ignore W and H) + % hasx = 1 -> width is not interesting; we use 'x' option. + % hasx = 0 -> determine final width: + % W H + % 0 0 -> \axisdefaultwidth + % 0 1 -> determine width out of H and the default aspect ratio + % 1 X -> ok, use the user parameter. + % + % hasy = 1 -> height is not interesting, we use 'y' option. + % hasy = 0 -> determine final height: + % W H + % 0 0 -> \axisdefaultheight + % X 1 -> ok, use the user parameter + % 1 0 -> determine height out of W and the default aspect ratio % \ifx\axis@x\empty \ifx\axis@y\empty - % The case hasx=0, hasy=0, W=0 H=0: - % the other cases for hasx=0, hasy=0 follow below. - \ifx\axis@width\empty\ifx\axis@height\empty - \let\axis@width=\axisdefaultwidth - \let\axis@height=\axisdefaultheight - \fi\fi + % hasx=0, hasy=0 + % + % -> KEEP ASPECT RATIO if just one W, or H is given! + \ifx\axis@width\empty + \ifx\axis@height\empty + % The case hasx=0, hasy=0, W=0 H=0: + \let\axis@width=\axisdefaultwidth + \let\axis@height=\axisdefaultheight + \else + % The case hasx=0, hasy=0, W=0 H=1: + \axis@compute@default@aspect@ratio + \expandafter\pgfmath@y\axis@height + \pgfmathlog@invoke@expanded\pgfmathmultiply@{% + {\pgf@sys@tonumber{\pgfmath@y}}% + {\axis@default@aspect@ratio}% + }% + \edef\axis@width{\pgfmathresult pt}% + \fi + \else + \ifx\axis@height\empty + % The case hasx=0, hasy=0, W=1 H=0: + \axis@compute@default@aspect@ratio + \expandafter\pgfmath@x\axis@width + \pgfmathlog@invoke@expanded\pgfmathdivide@{% + {\pgf@sys@tonumber{\pgfmath@x}}% + {\axis@default@aspect@ratio}% + }% + \edef\axis@height{\pgfmathresult pt}% + \else + % The case hasx=0, hasy=0, W=1 H=1: + \fi + \fi \else % hasx=0, hasy=1, W=0: \ifx\axis@width\empty @@ -1333,12 +1943,43 @@ \fi \fi \fi +} + +% PRECONDITION: +% - final axis limits are given in transformed range +% - \axis@set@default@size@options has been invoked before +% POSTCONDITION: +% - the current x- and y unit vectors are changed; +% - \axis@[xy]coord{min,max}TEX are set +% +\def\axis@initsizes{% + % INIT. + % + % + \pgfpointxy{\axis@xmin}{\axis@ymin}% + \axis@xcoordminTEX=\pgf@x + \axis@ycoordminTEX=\pgf@y + \pgfpointxy{\axis@xmax}{\axis@ymax}% + \axis@xcoordmaxTEX=\pgf@x + \axis@ycoordmaxTEX=\pgf@y + % + % + %----------------------------------------- + % PROCESS THE 'width' and 'height' options + %----------------------------------------- + % + % FIXME: make these variables LOCAL: + % + \let\axis@rectangle@width=\empty + \let\axis@rectangle@height=\empty % - % common code for the cases if one of W,H is 1: \ifx\axis@x\empty \ifx\axis@width\empty - \else - \axis@initsizes@getXscale\into\axis@tmpXscale + \errmessage{INTERNAL LOGIC ERROR! WIDTH NOT SET}% + \fi + \axis@initsizes@getXscale\into\axis@tmpXscale + \ifaxis@scale@only@axis + \let\axis@rectangle@width=\axis@width \fi \else \def\axis@tmpXscale{1}% @@ -1346,45 +1987,18 @@ % \ifx\axis@y\empty \ifx\axis@height\empty - \else - \axis@initsizes@getYscale\into\axis@tmpYscale + \errmessage{INTERNAL LOGIC ERROR! HEIGHT NOT SET}% + \fi + \axis@initsizes@getYscale\into\axis@tmpYscale + \ifaxis@scale@only@axis + \let\axis@rectangle@height=\axis@height \fi \else \def\axis@tmpYscale{1}% \fi % - \ifx\axis@x\empty\ifx\axis@y\empty - % hasx=0, hasy=0 and ... - % - % -> KEEP ASPECT RATIO! - % - % CASE W=0 H=1: - \ifx\axis@width\empty - \ifx\axis@height\empty - \else - \expandafter\pgfmath@y\axis@height - \pgfmathlog@invoke@expanded\pgfmathmultiply@{% - {\pgf@sys@tonumber{\pgfmath@y}}% - {\axis@default@aspect@ratio}% - }% - \edef\axis@width{\pgfmathresult pt}% - \axis@initsizes@getXscale\into\axis@tmpXscale - \fi - \else% CASE W=1 H=0: - \ifx\axis@height\empty - \expandafter\pgfmath@x\axis@width - \pgfmathlog@invoke@expanded\pgfmathdivide@{% - {\pgf@sys@tonumber{\pgfmath@x}}% - {\axis@default@aspect@ratio}% - }% - \edef\axis@height{\pgfmathresult pt}% - \axis@initsizes@getYscale\into\axis@tmpYscale - \fi - \fi - \fi\fi - % IMPLEMENTATION NOTE: - % if(Xscale=empty or Yscale=empty) - % -> LOGIC ERROR above. + % + % assert( \axis@tmpXscale != \empty && \axis@tmpYscale != \empty ) % % Apply scaling: \pgfpointxy{\axis@tmpXscale}{\axis@tmpYscale}% @@ -1401,34 +2015,127 @@ \pgfsetyvec{\pgfpoint{0pt}{\axis@y}}% \fi % + % Determine final rectangle dimensions. + % There are the following cases: + % 1. the user really wants a fixed dimension, + % i.e. he used 'scale only axis'. + % Then, we have to work to get the correct dimension! + % + % Up to now, the scaling mechanism looses to many significant + % digits such that the final width/height differs by 1-2 pt. + % + % If I am not mistaken, this does ONLY affect the final size, + % not the relative plot precision. + % + % FIXME : really compute the plot precision! + % + % 2. The use specified width and/or height, but not 'scale only + % axis'. Accept inaccurate final widths/heights (see above). + % + % 3. The user supplied 'x' and or 'y'. Simply use them, its + % accurate. + % \pgfpointxy{\axis@xmin}{\axis@ymin}% \axis@xcoordminTEX=\pgf@x \axis@ycoordminTEX=\pgf@y \pgfpointxy{\axis@xmax}{\axis@ymax}% - \axis@xcoordmaxTEX=\pgf@x - \axis@ycoordmaxTEX=\pgf@y - %----------------------------------------- + \ifx\axis@rectangle@width\empty + \axis@xcoordmaxTEX=\pgf@x + \else + % this 'if' here should only make a difference of about + % 1-2pt, not more. + % + % and I am quite sure that this inaccuracy (and this + % work-around) only affects the + % final size, not the relative plot accuracy. + \axis@xcoordmaxTEX=\axis@xcoordminTEX + \expandafter\advance\expandafter\axis@xcoordmaxTEX\axis@width + \fi + \ifx\axis@rectangle@height\empty + \axis@ycoordmaxTEX=\pgf@y + \else + \axis@ycoordmaxTEX=\axis@ycoordminTEX + \expandafter\advance\expandafter\axis@ycoordmaxTEX\axis@height + \fi +%-------------------------------------------------- +% \begingroup +% \pgf@x=\axis@xcoordmaxTEX\advance\pgf@x by-\axis@xcoordminTEX +% \pgf@y=\axis@ycoordmaxTEX\advance\pgf@y by-\axis@ycoordminTEX +% \message{Axis scaling x=\axis@tmpXscale, y=\axis@tmpYscale\ yields lower-left-corner (\axis@xmin,\axis@ymin) = (\the\axis@xcoordminTEX,\the\axis@ycoordminTEX) and upper right (\axis@xmax,\axis@ymax) = (\the\axis@xcoordmaxTEX,\the\axis@ycoordmaxTEX). Axis dimensions are width=\the\pgf@x, height=\the\pgf@y.}% +% \endgroup +%-------------------------------------------------- } \def\axis@BEGIN@init@and@draw@axis{% \axis@determinedefaultvalues - % X-Achsenbeschriftung: - % LADE DIE \axis@xtick -variable REIN - \expandafter\xachse\expandafter{\axis@xtick} - % - % Y-Achsen und Achsenbeschriftung: - \expandafter\yachse\expandafter{\axis@ytick}% - - % Äußerer Rahmen: - \draw - (\axis@xcoordminTEX, \axis@ycoordminTEX) - rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + % move the anchor to (0,0): + \expandafter\ifcase\axis@anchorchoicenum + % north: + \begin{scope}[ + yshift=-\axis@ycoordmaxTEX, + xshift=-0.5\axis@xcoordminTEX-0.5\axis@xcoordmaxTEX + ] + \or% north west: + \begin{scope}[ + yshift=-\axis@ycoordmaxTEX, + xshift=-\axis@xcoordminTEX + ] + \or% west: + \begin{scope}[ + yshift=-0.5\axis@ycoordminTEX-0.5\axis@ycoordmaxTEX, + xshift=-\axis@xcoordminTEX + ] + \or% south west: + \begin{scope}[ + yshift=-\axis@ycoordminTEX, + xshift=-\axis@xcoordminTEX + ] + \or% south: + \begin{scope}[ + yshift=-\axis@ycoordminTEX, + xshift=-0.5\axis@xcoordminTEX-0.5\axis@xcoordmaxTEX + ] + \or% south east: + \begin{scope}[ + yshift=-\axis@ycoordminTEX, + xshift=-\axis@xcoordmaxTEX + ] + \or% east: + \begin{scope}[ + yshift=-0.5\axis@ycoordminTEX-0.5\axis@ycoordmaxTEX, + xshift=-\axis@xcoordmaxTEX + ] + \or% north east: + \begin{scope}[ + yshift=-\axis@ycoordmaxTEX, + xshift=-\axis@xcoordmaxTEX + ] + \or% center + \begin{scope}[ + yshift=-0.5\axis@ycoordminTEX-0.5\axis@ycoordmaxTEX, + xshift=-0.5\axis@xcoordminTEX-0.5\axis@xcoordmaxTEX + ] + \fi \begin{scope} - \clip - (\axis@xcoordminTEX, \axis@ycoordminTEX) - rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + \ifaxis@hide + \clip + (\axis@xcoordminTEX, \axis@ycoordminTEX) + rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + \else + + % X-Achsenbeschriftung: + % LADE DIE \axis@xtick -variable REIN + \expandafter\axis@drawxaxis\expandafter{\axis@xtick} + % + % Y-Achsen und Achsenbeschriftung: + \expandafter\axis@drawyaxis\expandafter{\axis@ytick}% + \draw[clip] + (\axis@xcoordminTEX, \axis@ycoordminTEX) + rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + + \fi } \def\axis@END@init@and@draw@axis{% @@ -1448,6 +2155,34 @@ }% } +\tikzdeclarecoordinatesystem{axis}{\axis@evalute@tikz@coord@system@interface#1\axis@coord@end} + + +% Assigns \pgfmathresult := canvas coordinate (#2) for axis #1. +\long\def\axis@evalute@tikz@coord@system@interface@for#1#2{% + \expandafter\let\expandafter\if@datascaled@cur\csname ifaxis@float@numerics@mode@#1\endcsname + \expandafter\ifcase\csname axis@#1mode\endcsname + \if@datascaled@cur + \csname axis@datascaletrafo@fromfixed@#1\endcsname#2\to\pgfmathresult + \else + \def\pgfmathresult{#2}% + \fi + \or + \pgfmathlog@{#2}% + \fi +} + +\long\def\axis@evalute@tikz@coord@system@interface#1,#2\axis@coord@end{% + \begingroup + \axis@evalute@tikz@coord@system@interface@for{x}{#1}% + \let\axis@evaluate@tikz@coord@x=\pgfmathresult + \axis@evalute@tikz@coord@system@interface@for{y}{#2}% + \xdef\axis@TMP{\axis@evaluate@tikz@coord@x pt}% + \xdef\axis@TMPB{\pgfmathresult pt}% + \endgroup + \pgfpointxy{\axis@TMP}{\axis@TMPB}% +} + % In case of (semi-) logplots, this command will % - assign a filter which invokes \pgfmathlog@{} for each coordinate % - replace any user-specified coordinate by its log. @@ -1455,105 +2190,285 @@ % All subsequent commands will then work with logarithmic coordinates. % % @see pgfmathlog.sty for details about the implementation of log(). -\def\axis@preparelog@filtering{% - \ifnum\axis@xmode=1 - % any user-specified axis limits: - \ifx\axis@xmin\empty - \else - \expandafter\pgfmathlog@\expandafter{\axis@xmin}% - \let\axis@xmin=\pgfmathresult - \fi - \ifx\axis@xmax\empty +% +% PRECONDITION: +% - The user input options have been set correctly, +% - the option processing has not yet begun +% +% POSTCONDITION: +% - any user input for log-axis has been replaced by its log +% - coordinate filters to compute logs are installed +% +% See also: +% \axis@apply@data@scale@trafo@to@options@for +\def\axis@prepare@coord@filtering@for#1{% + \expandafter\ifcase\csname axis@#1mode\endcsname + \ifaxis@disabledatascaling + \csname axis@float@numerics@mode@#1false\endcsname + \axis@float@numerics@modefalse \else - \expandafter\pgfmathlog@\expandafter{\axis@xmax}% - \let\axis@xmax=\pgfmathresult + \csname axis@float@numerics@mode@#1true\endcsname + \axis@float@numerics@modetrue \fi - % - % any user specified axis ticks: - \ifx\axis@xtick\empty - \else - \expandafter\axis@filter@input@ticks@with@log\expandafter{\axis@xtick}% - \edef\axis@xtick{\axis@TMP}% + \ifaxis@float@numerics@mode + % Install coordinate filters that + % - read input as normalised floating point numbers, + % - return [SIGN][MANTISSE]eEXPONENT + % Motivation: + % 1. we can compute axis limits using such data + % 2. we can remember the floating point representation for + % the data scaling transformation. + % ATTENTION: + % this here is a preprocessing step! You will need to + % apply the data scaling later! + % see + % \axis@apply@data@scaletrafo@to@plot@data + \expandafter\let\expandafter\axis@TMP\csname axis@#1filter\endcsname + \ifx\axis@TMP\empty + \expandafter\def\csname addplot@float@numerics@#1filter\endcsname##1\to##2{% + \sciparsesign{##1}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scisetcomponents{##2}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \edef##2{\axis@tmp@S\axis@tmp@M e\axis@tmp@E}% + }% + \else + \expandafter\let\csname axis@#1filter@orig\endcsname=\axis@TMP + \expandafter\def\csname addplot@float@numerics@#1filter\endcsname##1\to##2{% + \csname axis@#1filter@orig\endcsname##1\to##2\relax + \ifx##2\empty + \else + \expandafter\sciparsesign\expandafter{##2}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scisetcomponents{##2}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \edef##2{\axis@tmp@S\axis@tmp@M e\axis@tmp@E}% + \fi + }% + \fi + \expandafter\let\expandafter\axis@TMP\csname addplot@float@numerics@#1filter\endcsname + \expandafter\let\csname axis@#1filter\endcsname\axis@TMP + % + % Check for any existing axis limits: + \expandafter\let\expandafter\axis@TMP\csname axis@#1min\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\sciparsesign\expandafter{\axis@TMP}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \expandafter\scisetcomponents\csname axis@#1min\endcsname\axis@tmp@S\axis@tmp@M\axis@tmp@E + \fi + \expandafter\let\expandafter\axis@TMP\csname axis@#1max\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\sciparsesign\expandafter{\axis@TMP}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \expandafter\scisetcomponents\csname axis@#1max\endcsname\axis@tmp@S\axis@tmp@M\axis@tmp@E + \fi \fi - \ifx\axis@xfilter\empty - \def\addplot@log@compute@xfilter##1\to##2{% - \pgfmathlog@{##1}% - \let##2=\pgfmathresult - }% + \or + \ifaxis@disablelogfilter \else - \let\axis@xfilter@orig=\axis@xfilter - \def\addplot@log@compute@xfilter##1\to##2{% - \pgfmathlog@{##1}% - \ifx\pgfmathresult\empty - \let##2=\empty - \else - \expandafter\axis@xfilter@orig\pgfmathresult\to##2\relax - \fi - }% + % any user-specified axis limits: + \expandafter\let\expandafter\axis@TMP\csname axis@#1min\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\pgfmathlog@\expandafter{\axis@TMP}% + \expandafter\let\csname axis@#1min\endcsname=\pgfmathresult + \fi + \expandafter\let\expandafter\axis@TMP\csname axis@#1max\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\pgfmathlog@\expandafter{\axis@TMP}% + \expandafter\let\csname axis@#1max\endcsname=\pgfmathresult + \fi + % + % any user specified axis ticks: + \expandafter\let\expandafter\axis@TMP\csname axis@#1tick\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\axis@filter@input@ticks@with@log\expandafter{\axis@TMP}% + \expandafter\edef\csname axis@#1tick\endcsname{\axis@TMP}% + \fi + % + \expandafter\let\expandafter\axis@TMP\csname axis@#1filter\endcsname + \ifx\axis@TMP\empty + \expandafter\def\csname addplot@log@compute@#1filter\endcsname##1\to##2{% + \pgfmathlog@{##1}% + \let##2=\pgfmathresult + }% + \else + \expandafter\let\csname axis@#1filter@orig\endcsname=\axis@TMP + \expandafter\def\csname addplot@log@compute@#1filter\endcsname##1\to##2{% + \pgfmathlog@{##1}% + \ifx\pgfmathresult\empty + \let##2=\empty + \else + \expandafter\expandafter\csname axis@#1filter@orig\endcsname\pgfmathresult\to##2\relax + \fi + }% + \fi + \expandafter\let\expandafter\axis@TMP\csname addplot@log@compute@#1filter\endcsname + \expandafter\let\csname axis@#1filter\endcsname\axis@TMP \fi - \def\axis@xfilter{\addplot@log@compute@xfilter}% \fi - % - \ifnum\axis@ymode=1 - % any user-specified axis limits: - \ifx\axis@ymin\empty - \else - \expandafter\pgfmathlog@\expandafter{\axis@ymin}% - \let\axis@ymin=\pgfmathresult - \fi - \ifx\axis@ymax\empty - \else - \expandafter\pgfmathlog@\expandafter{\axis@ymax}% - \let\axis@ymax=\pgfmathresult - \fi - % - % any user specified axis ticks: - \ifx\axis@ytick\empty +} + +\def\axis@create@axis@descriptions{% + \ifaxis@hide + \else + \ifx\axis@xlabel\empty \else - \expandafter\axis@filter@input@ticks@with@log\expandafter{\axis@ytick}% - \edef\axis@ytick{\axis@TMP}% + \axisshowxlabel \fi - \ifx\axis@yfilter\empty - \def\addplot@log@compute@yfilter##1\to##2{% - \pgfmathlog@{##1}% - \let##2=\pgfmathresult - }% + \ifx\axis@ylabel\empty \else - \let\axis@yfilter@orig=\axis@yfilter - \def\addplot@log@compute@yfilter##1\to##2{% - \pgfmathlog@{##1}% - \ifx\pgfmathresult\empty - \let##2=\empty - \else - \expandafter\axis@yfilter@orig\pgfmathresult\to##2\relax - \fi - }% + \axisshowylabel \fi - \def\axis@yfilter{\addplot@log@compute@yfilter}% \fi + \ifx\axis@title\empty + \else + \axisshowtitle + \fi + \axis@createlegend +} + +% DATA TRANSFORMATION T(x) = X +% +% Input: +% a number in the original data range, given in **floating** point representation +% Output: +% a fixed point number in transformed range +% @see +% \axis@datascaletrafo@x@three +% \axis@datascaletrafo@fromfixed@x +\def\axis@datascaletrafo@x#1\to#2{% + \scigetcomponents#1\axis@tmp@S\axis@tmp@M\axis@tmp@E + \axis@datascaletrafo@x@three\axis@tmp@S\axis@tmp@M\axis@tmp@E\to#2 +} + +% Overloaded function. +% Input: +% The same as above, but with Sign, Mantisse, Exponent. +% #1,#2 and #3 are expected to be MACRO NAMES. +\def\axis@datascaletrafo@x@three#1#2#3\to#4{% + \def\axis@TMP{\scimathshift{#1}{#2}{#3}}% + \expandafter\axis@TMP\expandafter{\axis@data@scale@trafo@SHIFT@x}% + \scitofixed{#1}{#2}{#3}{#4}% +} + +% Overloaded function. +% Input: +% a FIXED point number instead of a floating point one. +% @see \axis@datascaletrafo@x +\def\axis@datascaletrafo@fromfixed@x#1\to#2{% + \begingroup + \sciparsesign{#1}\axis@S\axis@M\axis@E + \axis@datascaletrafo@x@three\axis@S\axis@M\axis@E\to{#2}% + \global\let\axis@TMP=#2\relax + \endgroup + \let#2=\axis@TMP +} + +\def\axis@datascaletrafo@y#1\to#2{% + \scigetcomponents#1\axis@tmp@S\axis@tmp@M\axis@tmp@E + \axis@datascaletrafo@y@three\axis@tmp@S\axis@tmp@M\axis@tmp@E\to#2 +} +\def\axis@datascaletrafo@y@three#1#2#3\to#4{% + \def\axis@TMP{\scimathshift{#1}{#2}{#3}}% + \expandafter\axis@TMP\expandafter{\axis@data@scale@trafo@SHIFT@y}% + \scitofixed{#1}{#2}{#3}{#4}% +} +\def\axis@datascaletrafo@fromfixed@y#1\to#2{% + \begingroup + \sciparsesign{#1}\axis@S\axis@M\axis@E + \axis@datascaletrafo@y@three\axis@S\axis@M\axis@E\to{#2}% + \global\let\axis@TMP=#2\relax + \endgroup + \let#2=\axis@TMP +} + +% INVERSE transformation x = T^{-1}( X ) +% Input: +% a fixed point number in transformed domain +% Output: +% a number in the data domain, given in floating point +% representation +\def\axis@inverse@datascaletrafo@x#1\to#2{% + \expandafter\sciparsesignsingle\expandafter{#1}#2 + \edef\axis@TMP{\noexpand#2{-\axis@data@scale@trafo@SHIFT@x}}% + \expandafter\scimathshiftsingle\axis@TMP +} + +\def\axis@inverse@datascaletrafo@y#1\to#2{% + \expandafter\sciparsesignsingle\expandafter{#1}#2 + \edef\axis@TMP{\noexpand#2{-\axis@data@scale@trafo@SHIFT@y}}% + \expandafter\scimathshiftsingle\axis@TMP +} + +% Overloaded function. +% +% In contrast to \axis@inverse@datascaletrafo@x, this method +% returns a number in FIXED point representation. +% @see \axis@inverse@datascaletrafo@x +\def\axis@inverse@datascaletrafo@tofixed@x#1\to#2{% + \axis@inverse@datascaletrafo@x#1\to{#2}% + \scitofixedsingle{#2}{#2}% +} +\def\axis@inverse@datascaletrafo@tofixed@y#1\to#2{% + \axis@inverse@datascaletrafo@y#1\to{#2}% + \scitofixedsingle{#2}{#2}% } \newenvironment{axis}[1][]{% \begingroup - \begin{scope}[style=every axis] +% \def\axis@setkeys{\setkeys*[\prefix]{axis}}% +%\tracingmacros=2\tracingcommands=2 +% \message{Der every-axis-style ist gerade \csname tikz@st@every axis\endcsname}% +%\tracingmacros=0\tracingcommands=0 +% \expandafter\expandafter\expandafter\axis@setkeys + % \expandafter\expandafter\expandafter{\csname tikz@st@every axis\endcsname}% + \begin{scope}[style=every axis,% + x=1pt,y=1pt% see below + ] + % The explicit specification of 'x' and 'y' as 1pt is to avoid + % numeric overflow/underflow during scale computations: + % + % The scaling (i.e. proper values for 'x' and 'y') will be + % determined later-on, dependend on the axis limits. Since axis + % limits are implicitly in units of 1pt, it is reasonable to use + % '1pt' here as well. + % + % %-------------------------------------------------- % \draw[very thin,color=gray,xstep=1,ystep=\logten] % (\xcoordmin\axis@leftover,\ycoordmin) % grid (\xcoordmax\axis@rightover,\ycoordmax); %-------------------------------------------------- \setkeys[\prefix]{axis}{#1}% - \setkeys[\prefix]{legend}{}% % + % -------------------- + % Allocations: + % -------------------- \listnewempty\axis@plotspeclist \listnewempty\axis@legend - \listnewempty\axis@draw@stored@plots + \listnewempty\axis@stored@plot@cmds + \listnewempty\axis@stored@plot@data + \newif\ifaxis@autocompute@xlim + \newif\ifaxis@autocompute@ylim + \newif\ifaxis@filtercoords + \newif\ifaxis@float@numerics@mode@x + \newif\ifaxis@float@numerics@mode@y + \newif\ifaxis@float@numerics@mode + % rename '\ifaxis@hide axis' to mask the white space: + \expandafter\let\expandafter\ifaxis@hide\csname ifaxis@hide axis\endcsname + % the same for other options with white spaces: + \expandafter\let\expandafter\ifaxis@scale@only@axis\csname ifaxis@scale only axis\endcsname + \newif\ifaxis@draw@at@end + \newif\ifaxis@limits@are@computed + \newif\ifaxis@EMERGENCY@FORCE@DATA@TRAFO@TO@IDENTITY + \axis@numplots=0 + \let\axis@already@computed@legend@node=\empty % - \ifaxis@disablelogfilter - \else - \axis@preparelog@filtering - \fi + % -------------------- + % Option preprocessing + % -------------------- + \axis@prepare@coord@filtering@for x + \axis@prepare@coord@filtering@for y % - \newif\ifaxis@filtercoords \ifx\axis@xfilter\empty \else \axis@filtercoordstrue @@ -1562,46 +2477,66 @@ \else \axis@filtercoordstrue \fi - % - \axis@numplots=0 - % - \newif\ifaxis@autocompute@xlim - \newif\ifaxis@autocompute@ylim - \newif\ifaxis@draw@at@end - \newif\ifaxis@limits@are@computed - \axis@limits@are@computedtrue + % \ifx\axis@xmin\empty \axis@autocompute@xlimtrue \def\axis@xmin{16300}% + \ifaxis@float@numerics@mode@x + \scisetcomponents\axis@xmin{1}{1.0}{324}% + \fi \fi \ifx\axis@xmax\empty \axis@autocompute@xlimtrue \def\axis@xmax{-16300}% + \ifaxis@float@numerics@mode@x + \scisetcomponents\axis@xmax{2}{1.0}{324}% + \fi \fi \ifx\axis@ymin\empty \axis@autocompute@ylimtrue \def\axis@ymin{16300}% + \ifaxis@float@numerics@mode@y + \scisetcomponents\axis@ymin{1}{1.0}{324}% + \fi \fi \ifx\axis@ymax\empty \axis@autocompute@ylimtrue \def\axis@ymax{-16300}% + \ifaxis@float@numerics@mode@y + \scisetcomponents\axis@ymax{2}{1.0}{324}% + \fi \fi % \ifaxis@autocompute@xlim \axis@draw@at@endtrue \axis@limits@are@computedfalse + \else + \axis@limits@are@computedtrue \fi \ifaxis@autocompute@ylim \axis@draw@at@endtrue \axis@limits@are@computedfalse + \else + \axis@limits@are@computedtrue \fi % % + % -------------------- + % Start axis: + % either postponed to \end or directly. + % -------------------- + % \ifaxis@draw@at@end \else \axis@BEGIN@init@and@draw@axis \fi }{% + %\end{axis}: + % -------------------- + % All plotting commands + % have been done. + % -> apply postponed drawing commands! + % -------------------- \ifaxis@draw@at@end \ifaxis@limits@are@computed \else @@ -1612,7 +2547,20 @@ \def\axis@ymax{1}% \fi \axis@BEGIN@init@and@draw@axis - \listforeach\axis@draw@stored@plots\as\plotcmd{\plotcmd}% + \listforeach\axis@stored@plot@cmds\as\plotcmd{% + \listpopfront\axis@stored@plot@data\to\plotdata + \ifaxis@float@numerics@mode + \ifx\plotcmd\empty + \plotdata + \else + % Apply the data scaling transformation + \expandafter\axis@apply@data@scaletrafo@to@plot@data\plotdata\to\plotdata + \expandafter\plotcmd\plotdata + \fi + \else + \expandafter\plotcmd\plotdata + \fi + }% \fi \axis@END@init@and@draw@axis % @@ -1622,20 +2570,9 @@ x={\axis@xcoordmaxTEX-\axis@xcoordminTEX}, y={\axis@ycoordmaxTEX-\axis@ycoordminTEX} ]% - \ifx\axis@xlabel\empty - \else - \axisshowxlabel - \fi - \ifx\axis@ylabel\empty - \else - \axisshowylabel - \fi - \ifx\axis@title\empty - \else - \axisshowtitle - \fi - \axis@createlegend + \axis@create@axis@descriptions \end{scope}% + \end{scope}% this scope starts inside of \axis@BEGIN@init@and@draw@axis % \end{scope}% \endgroup diff --git a/Master/texmf-dist/tex/latex/pgfplots/pgfplotshelpers.sty b/Master/texmf-dist/tex/latex/pgfplots/pgfplotshelpers.sty index 203f16379ee..304448fbef4 100644 --- a/Master/texmf-dist/tex/latex/pgfplots/pgfplotshelpers.sty +++ b/Master/texmf-dist/tex/latex/pgfplots/pgfplotshelpers.sty @@ -22,7 +22,9 @@ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\ProvidesPackage{pgfplotshelpers}[2008/31/01 Version 0.9] +\ProvidesPackage{pgfplotshelpers}[2008/02/17 Version 0.9.4] + +\newtoks\pgfplots@toka \def\prettyprintnumberprecision{2} @@ -54,10 +56,11 @@ % It uses \prettyprintnumberprecision digits after the comma. \def\prettyprintnumber#1{% \begingroup -%\tracingmacros=2\tracingcommands=2 - \edef\argument{#1}% - \expandafter\prettyprintnumber@impl\argument.\END -%\tracingmacros=0\tracingcommands=0 +% \edef\argument{#1}% +% \expandafter\prettyprintnumber@impl\argument.\END + \edef\argument{#1\noexpand\prec\prettyprintnumberprecision}% + \expandafter\fixedpointround\argument\to\result + \result \endgroup } diff --git a/Master/texmf-dist/tex/latex/pgfplots/sciformat.sty b/Master/texmf-dist/tex/latex/pgfplots/sciformat.sty new file mode 100644 index 00000000000..493aca948d1 --- /dev/null +++ b/Master/texmf-dist/tex/latex/pgfplots/sciformat.sty @@ -0,0 +1,861 @@ +%-------------------------------------------- +% +% Package sciformat.sty +% +% Provides support for floating point number representations of the +% form +% +% S * M * 10^e +% +% with S in [-,+,0], 0. +% +%-------------------------------------------- +\ProvidesPackage{sciformat}[2008/02/17 v.0.9.4] +\RequirePackage{pgf}[2007/01/01] +\RequirePackage{pgfplotshelpers}[2008/02/17] + +% 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 +% [+-]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{% +% \sciparse#1\to\M\powten\E +% \[ #1 \mapsto \M\cdot 10^{\E} \] +% } +% \normalize{123.41251}% +% \normalize{3.26101452e-06}% +% +% REMARKS: +% - the mantisse will ALWAYS have a period and one following number. +% - Special case: the number +- 0 will always have the mantisse 0.0. The sign and +% the exponent is undefined. +\def\sciparse#1\to#2\powten#3{% + \begingroup + \sciparse@impl@possibly@signed#1\to#2\powten{#3}% + \xdef\sciparseTMP{% + \noexpand\def\noexpand#2{#2}% + \noexpand\def\noexpand#3{#3}% + }% + \endgroup + \sciparseTMP +} + +% Overloaded scientific parser. +% +% In addition to '\sciparse', this method checks for '+- 0' cases +% and sets #2 accordingly. +% +% \S #2: will be \def'ed to one of [0,1,2] with +% 0 == '0', ( \def#2{0} ) +% 1 == '+', +% 2 == '-', +% -> can be used with \ifcase +% \M #3: will be filled with a positive mantisse (undefined in case \S=0). +% \E #4: the exponent basis 10 (an integer). Undefined in case \S = 0. +% +% Example: +% \sciparsesign141.212\S\M\E +% -> \S = 1, \M = 1.41212, \E =2 +% +\def\sciparsesign#1#2#3#4{% + \begingroup + \sciparsesign@impl@possibly@signed#1\S#2\M#3\E{#4}% + \def\sciparseTMP{0}% + \ifx\sciparseTMP#2\relax + \def#4{0}% + \fi + \xdef\sciparseTMP{% + \noexpand\def\noexpand#2{#2}% + \noexpand\def\noexpand#3{#3}% + \noexpand\def\noexpand#4{#4}% + }% + \endgroup + \sciparseTMP +} + +\def\sciparsesignsingle#1#2{% + \begingroup + \sciparsesign{#1}\sci@S\sci@M\sci@E + \xdef\sciparseTMP{\noexpand\scisetcomponents{\noexpand#2}{\sci@S}{\sci@M}{\sci@E}}% + \endgroup + \sciparseTMP +} + +% Compares +% x = Sign(#1) #2 * 10^#3 +% with +% y = Sign(#4) #5 * 10^#6 +% +% example: +% \scimathlessthan\S\M\E\and\SS\MM\EE +% \ifscimathlessthan +% is smaller! +% \else +% is not smaller. +% \fi +% +% and sets the boolean +% \ifscimathlessthan := (x (x y >0) + \ifnum1=\S@second + \aftergroup\scimathlessthantrue + \fi + \or + % x > 0 -> (x ( y > 0 && |x| < |y|) ) + \ifnum1=\S@second + % y>0: + \scimathlessthan@positive\M#2\E#3\MM#5\EE{#6}% + \fi + \or + % x < 0 -> (x (y >= 0 || |x| > |y|) ) + \ifnum2=\S@second + % 'y<0': + \scimathlessthan@positive\M#5\E#6\MM#2\EE{#3}% + \else + \aftergroup\scimathlessthantrue + \fi + \fi + \endgroup +} + +\def\scimathmax#1#2#3\and#4#5#6\to#7#8#9{% + \scimathlessthan#1#2#3\and#4#5#6\relax + \ifscimathlessthan + \let#7=#4 + \let#8=#5 + \let#9=#6 + \else + \let#7=#1 + \let#8=#2 + \let#9=#3 + \fi +} + +\def\scimathmin#1#2#3\and#4#5#6\to#7#8#9{% + \scimathlessthan#1#2#3\and#4#5#6\relax + \ifscimathlessthan + \let#7=#1 + \let#8=#2 + \let#9=#3 + \else + \let#7=#4 + \let#8=#5 + \let#9=#6 + \fi +} + +% Takes \S, \M and \E as sign, mantisse and exponent and computes a +% fixed point representation for that number. +% +% example: +% \S=1 +% \M=4.2 +% \E=1 +% \scitofixed\S\M\E\result +% -> 42.0 +\def\scitofixed#1#2#3#4{% + \begingroup + \let\sci@sign=\c@pgf@counta + \sci@sign\expandafter=#1\relax + \ifnum0=\sci@sign + \xdef\sciparseTMP{0.0}% + \else + \expandafter\scitofixed@impl#2\E#3\END + \ifnum2=\sci@sign + \xdef\sciparseTMP{-\sciparseTMP}% + \fi + \fi + \endgroup + \let#4=\sciparseTMP +} + +% Single macro SCI-representation to #2. +\def\scitofixedsingle#1#2{% + \begingroup + \scigetcomponents{#1}\sci@S\sci@M\sci@E + \scitofixed\sci@S\sci@M\sci@E{#2}% + \global\let\sciparseTMP=#2% + \endgroup + \let#2=\sciparseTMP +} + +% Takes a SINGLE macro representing a floating point and extracts +% sign, mantisse and exponent. +% #1: the name of the single macro. +% The expansion of #1 is COMPLETELY independend of associated +% floating point number. You can even use \def#1{foo bar} +% so change the meaning of #1 without affecting the number. +% #2: will be set to #1's sign +% #3: will be set to #1's mantisse +% #4: will be set to #1's exponent +% +% @see scisetcomponents +\def\scigetcomponents#1#2#3#4{% + \expandafter\let\expandafter#2\csname\string#1@S\endcsname + \expandafter\let\expandafter#3\csname\string#1@M\endcsname + \expandafter\let\expandafter#4\csname\string#1@E\endcsname +} + +% Assigns sign #2, mantisse #3 and exponent #4 to a single macro +% representing the floating point. +% +% #1: the target name. Will create macros #1@S, #1@M and #1@E +% which will be filled with #2, #3 and #4. +% +% Remark: +% It is perfectly save to use the macro name #1 for other uses since +% only the '@{S,M,E}' - macros are used to maintain the numerical +% information. +% +% @see scigetcomponents +\def\scisetcomponents#1#2#3#4{% + \expandafter\edef\csname\string#1@S\endcsname{#2}% + \expandafter\edef\csname\string#1@M\endcsname{#3}% + \expandafter\edef\csname\string#1@E\endcsname{#4}% +} + +% Divides or multiplies the input number by 10^#4 using an arithmetic +% left/right shift. +% +% Input: +% #1 Sign macro +% #2 Mantisse macro +% #3 exponent macro +% #4 a positive or negative integer number denoting the shift. +% +% Example: +% \scimathshift\S\M\E4 +\def\scimathshift#1#2#3#4{% + \begingroup + \c@pgf@counta\expandafter=#3\relax + \advance\c@pgf@counta by#4\relax + \xdef\sciparseTMP{\the\c@pgf@counta}% + \endgroup + \let#3=\sciparseTMP +} + +\def\scimathshiftsingle#1#2{% + \begingroup + \expandafter\let\expandafter\E\csname\string#1@E\endcsname + \c@pgf@counta\expandafter=\E\relax + \advance\c@pgf@counta by#2\relax + \xdef\sciparseTMP{\the\c@pgf@counta}% + \endgroup + \expandafter\let\csname\string#1@E\endcsname\sciparseTMP% +} + + +% Rounds a fixed point number #1 to #2 digits precision and returns +% the result into macro #3. +% +% This method is PURELY text based and can work with arbirtrary +% precision (well, limited to TeX's stack size and integer size). +\def\fixedpointround#1\prec#2\to#3{% + \begingroup + \pgfplots@toka={}% + \let\fp@round@next=\empty + \let\fp@round@prec=\c@pgf@countb + \let\fp@offsetbehindperiod=\c@pgf@counta + \let\fp@round@lastzeros=\c@pgf@countc + \let\fp@round@trg=#3\relax + \def\fp@round@input{#1}% + \fp@round@prec=#2\relax + \fp@round@lastzeros=0 + \fp@offsetbehindperiod=-1 % means: no period found so far + \fixedpointround@impl@ITERATE@NODOT #1\fp@round@EOI + \xdef\sciparseTMP{\fp@round@trg}% + \endgroup + \let#3=\sciparseTMP +} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% IMPL +% +%%%%%%%%%%%%%%%%%%%%%%%%%% + +% \fixedpointround implementation in WORDS: +% +% coarse idea: +% 1. collect all digits/sign BEFORE the first period in REVERSE order +% 2. then, collect UP TO \prec digits after the period in REVERSE order +% Steps 1. and 2. lead to the digit [sign] sequence +% "x_{-p} x_{-p+1} ... x_{-2} x_{-1} '.' x_0 ... x_r" +% where 'r' is the total number of digits. The integer 'p' denotes the +% ACTUALLY collected number of digits behind the period. +% +% Let 'k' be the desired precision. +% +% There are exactly TWO cases: +% 1. The case with p<=k and x_{-p-1} = end of input. +% 2. The case with p=k and x_{-p-1} is a further, next character. +% +% Then, we do in case 1.) +% discard any unused zeros at the tail of our number (possibly +% including the period) +% +% and in case 2.) +% if NEXT DIGIT < 5: +% do exactly the same as in case 1.) above and discard any +% following digits. +% else +% let q := -p +% while(x_q = 9 and q<=r ) +% if q>=0 +% set x_q = '0' +% else +% discard digit x_q='9' +% fi +% ++q +% if q=0 +% discard the period +% fi +% end while +% if q = r+1 +% insert a '1' +% else +% set x_q = x_q + 1 +% fi +% fi +% +% All these loops have been implemented in spaghetti-code below. +% Sorry, I fear its hard to understand. In principle, everything is +% realised using more or less finite state machines (with some number +% counting logic). +% +% Some comments: +% - The token register \pgfplots@toka is used to accumulate the REVERSED input number. +% - \fp@round@EOI always denotes 'END OF INPUT'. +% - in the second stage, we need to reverse \pgfplots@toka. +% This is -again- done with \pgfplots@toka. + +\def\fixedpointround@impl@discard@period#1.#2\fp@round@EOI{% + \def\fp@round@trg{#1}% +} + +\def\fixedpointround@impl@gobble@rest@and@start#1\fp@round@EOI{% + \fixedpointround@impl@start +} +\def\fixedpointround@impl@gobble@and@start\fp@round@EOI{% + \fixedpointround@impl@start +} +\def\fixedpointround@impl@gobble\fp@round@EOI{}% + +\def\fixedpointround@impl@start{% + \ifx\fp@round@next\empty + \ifnum\fp@offsetbehindperiod<0 + \edef\fp@round@trg{\fp@round@input}% + \else + \ifnum\fp@offsetbehindperiod>\fp@round@prec + \errmessage{Internal logic error in fixedpointround at [I] - should not have happened!?}% + \fi + \fixedpointround@impl@discard@suffix@zeros + \fi + \else + \ifnum\fp@offsetbehindperiod=\fp@round@prec + \else + \errmessage{Internal logic error in fixedpointround at [II] - should not have happened!? I have offsetbehindperiod=\the\fp@offsetbehindperiod and prec = \the\fp@round@prec}% + \fi + \expandafter\ifnum\fp@round@next<5 + \fixedpointround@impl@discard@suffix@zeros + \else + \multiply\fp@offsetbehindperiod by-1 + %\edef\fp@round@trg{B\the\pgfplots@toka B}% + \expandafter\fixedpointround@impl@ADD@ONE\the\pgfplots@toka\fp@round@EOI + \fi + \fi +} + +\def\fixedpointround@impl@ADD@ONE{% + \pgfplots@toka={}% + \fixedpointround@impl@ADD@ONE@ITERATE +} +\def\fixedpointround@impl@ADD@ONE@ITERATE{% + \@ifnextchar\fp@round@EOI{% + \edef\fp@round@trg{1\the\pgfplots@toka}% + \fixedpointround@impl@gobble + }{% + \@ifnextchar.{% + \fixedpointround@impl@ADD@ONE@NEXT@COLLECT + }{% + \@ifnextchar+{% + \fixedpointround@impl@ADD@ONE@NEXT@COLLECT + }{% + \@ifnextchar-{% + \fixedpointround@impl@ADD@ONE@NEXT@COLLECT + }{% + \fixedpointround@impl@ADD@ONE@NEXT + }% + }% + }% + }% +} + +\def\fixedpointround@impl@ADD@ONE@ITERATE@gobble@dot.{% + \fixedpointround@impl@ADD@ONE@ITERATE +} + +\def\fixedpointround@impl@ADD@ONE@NEXT@COLLECT#1{% + \pgfplots@toka=\expandafter{\expandafter#1\the\pgfplots@toka}% + \fixedpointround@impl@ADD@ONE@ITERATE +} +\def\fixedpointround@impl@ADD@ONE@NEXT#1{% + \ifnum#1=9 + \ifnum\fp@offsetbehindperiod<0 + % silently DROP digit + \else + \pgfplots@toka=\expandafter{\expandafter0\the\pgfplots@toka}% + \fi + \advance\fp@offsetbehindperiod by1 + \ifnum\fp@offsetbehindperiod=0 + \def\fp@round@nextcmd{\fixedpointround@impl@ADD@ONE@ITERATE@gobble@dot}% + \else + \def\fp@round@nextcmd{\fixedpointround@impl@ADD@ONE@ITERATE}% + \fi + \else + % re-use this counter: + \fp@round@lastzeros=#1 + \advance\fp@round@lastzeros by1 + \edef\fp@round@trg{\the\fp@round@lastzeros\the\pgfplots@toka}% + \pgfplots@toka=\expandafter{\fp@round@trg}% + \def\fp@round@nextcmd{\fixedpointround@impl@REVERSE@ITERATE}% + \fi + \fp@round@nextcmd +} + + +\def\fixedpointround@impl@discard@suffix@zeros{% + \ifnum\fp@round@lastzeros=\fp@offsetbehindperiod + \expandafter\fixedpointround@impl@discard@period\fp@round@input\fp@round@EOI + \else + \ifnum\fp@round@lastzeros=0 + \expandafter\fixedpointround@impl@REVERSE\the\pgfplots@toka\fp@round@EOI + \else + \expandafter\fixedpointround@impl@discard@suffix@zeros@ITERATE\the\pgfplots@toka\fp@round@EOI + \fi + \fi +} + +% PRECONDITION: +% \fp@round@lastzeros > 0 +\def\fixedpointround@impl@discard@suffix@zeros@ITERATE#1{% + \advance\fp@round@lastzeros by-1 + \ifnum\fp@round@lastzeros=0 + \def\fp@round@nextcmd{\fixedpointround@impl@REVERSE}% + \else + \def\fp@round@nextcmd{\fixedpointround@impl@discard@suffix@zeros@ITERATE}% + \fi + \fp@round@nextcmd +} + +\def\fixedpointround@impl@REVERSE{% + \pgfplots@toka={}% + \fixedpointround@impl@REVERSE@ITERATE +} + +\def\fixedpointround@impl@REVERSE@ITERATE{% + \@ifnextchar\fp@round@EOI{% + \edef\fp@round@trg{\the\pgfplots@toka}% + \fixedpointround@impl@gobble + }{% + \fixedpointround@impl@REVERSE@NEXT + }% +} + +\def\fixedpointround@impl@REVERSE@NEXT#1{% + \pgfplots@toka=\expandafter{\expandafter#1\the\pgfplots@toka}% + \fixedpointround@impl@REVERSE@ITERATE +} + +\def\fixedpointround@impl@BEGIN@DOT.{% + \pgfplots@toka=\expandafter{\expandafter.\the\pgfplots@toka}% + \fp@offsetbehindperiod=0 + \fixedpointround@impl@ITERATE@DOT +} +\def\fixedpointround@impl@ITERATE@DOT{% + \@ifnextchar\fp@round@EOI{% + % finished. + \fixedpointround@impl@gobble@and@start + }{% + \fixedpointround@impl@NEXT@DOT + }% +} +\def\fixedpointround@impl@NEXT@DOT#1{% + \ifnum\fp@offsetbehindperiod=\fp@round@prec + \def\fp@round@next{#1}% + \def\fp@round@nextcmd{\fixedpointround@impl@gobble@rest@and@start}% + \else + \advance\fp@offsetbehindperiod by1 + \ifnum#1=0 + \advance\fp@round@lastzeros by1 + \else + \fp@round@lastzeros=0 + \fi + \pgfplots@toka=\expandafter{\expandafter#1\the\pgfplots@toka}% + \def\fp@round@nextcmd{\fixedpointround@impl@ITERATE@DOT}% + \fi + \fp@round@nextcmd +}% + +\def\fixedpointround@impl@ITERATE@NODOT{% + \@ifnextchar\fp@round@EOI{% + \fixedpointround@impl@gobble@and@start + }{% + \@ifnextchar.{% + \fixedpointround@impl@BEGIN@DOT + }{% + \fixedpointround@impl@NEXT@NODOT + }% + }% +} +\def\fixedpointround@impl@NEXT@NODOT#1{% + \pgfplots@toka=\expandafter{\expandafter#1\the\pgfplots@toka}% + \fixedpointround@impl@ITERATE@NODOT +}% + +%-------------------------------------------- +% END of fixedpointround implementation. +%-------------------------------------------- + +\newif\ifscimathlessthan + +% first character MAY be + or -. This is checked, then +% \sciparse@impl@positive will be called for the +% absolute value. The sign is inserted afterwards. +\def\sciparse@impl@possibly@signed#1#2\to#3\powten#4{% + \def\sciparseTMP{#1}% + \def\sciparseTMPB{-}% + \if\sciparseTMP\sciparseTMPB + \sciparse@impl@positive@possibly@noperiod#2.\to#3\powten#4\S\sciparseTMPB% + \edef#3{-#3}% + \else + \def\sciparseTMPB{+}% + \if\sciparseTMP\sciparseTMPB + \sciparse@impl@positive@possibly@noperiod#2.\to#3\powten#4\S\sciparseTMPB% + \else + \sciparse@impl@positive@possibly@noperiod#1#2.\to#3\powten#4\S\sciparseTMPB% + \fi + \fi +} + +% the same as above, only the return value is different. +\def\sciparsesign@impl@possibly@signed#1#2\S#3\M#4\E#5{% + \def\sciparseTMP{#1}% + \def\sciparseTMPB{-}% + \if\sciparseTMP\sciparseTMPB + \def#3{2}% + \sciparse@impl@positive@possibly@noperiod#2.\to#4\powten#5\S#3% + \else + \def#3{1}% + \def\sciparseTMPB{+}% + \if\sciparseTMP\sciparseTMPB + \sciparse@impl@positive@possibly@noperiod#2.\to#4\powten#5\S#3% + \else + \sciparse@impl@positive@possibly@noperiod#1#2.\to#4\powten#5\S#3% + \fi + \fi +} + +% XXXX -> XXXX.0 +% XXXX.YYY -> XXXX.YYYY +\def\sciparse@impl@positive@possibly@noperiod#1.#2\to#3\powten#4\S#5{% +%\tracingmacros=2\tracingcommands=2 + \def\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + \sciparse@impl@positive@noperiod@possibly@SCI#1e\to#3\powten#4\S{#5}% + \else + \expandafter\sciparse@impl@positive\sciformat@pop@last@of@two@dots#1.#2\to#3\powten#4\S{#5}% + \fi +} +\def\sciformat@pop@last@of@two@dots#1.#2.{#1.#2}% + +\def\sciparse@impl@positive@noperiod@possibly@SCI#1e#2\to#3\powten#4\S#5{% + \def\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + % this case applies to + % 1234 -> 1234.0 + \sciparse@impl@positive#1.0\to#3\powten#4\S{#5}% + \else + % this case applies to + % 1e1 -> 1.0e1 + % in this case, #1e#2 = 1e1e, so we have to discard a suffix 'e'. + \edef\sciparseTMP{#1.0e\sciformat@popsuffix@e@expansion#2}% + \expandafter\sciparse@impl@positive\sciparseTMP\to#3\powten#4\S{#5}% + \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. +% +% The return value #6 will be \def'ed to '0' if the resulting mantisse is '0'. +% Won't be touched otherwise. +\def\sciparse@impl@positive#1#2.#3\to#4\powten#5\S#6{% +% \begingroup +% FIXME! restore variables!! +%\tracingmacros=2\tracingcommands=2 +%\tracingmacros=0\tracingcommands=0 + \sciparse@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\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + \c@pgf@countb=0 + \expandafter\sciformat@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\sciformat@assignmantisse\preexponentstring\to#4\countdownzerosfrom\c@pgf@countb\S{#6}% + \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] + \sciformat@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: +% - \sciparse@exponent@e123456e\preexponentto\M\exponenttocount\acount +% \M->123456 +% \acount=0 +% Please note that the input was 123456e -> at least 'e' is expected! +% +% - \sciparse@exponent@e123456e-10e\preexponentto\M\exponenttocount\acount +% \M->123456 +% \acount=-10 +% Again, the suffix 'e' is REQUIRED. This allows to reduce \ifs. +\def\sciparse@positive@getexisting@exponent@e#1e#2\preexponentto#3\exponenttocount#4{% + \def#3{#1}% + \def\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + #4=0 + \else + \sciformat@popsuffix@e#2\tocount{#4}% + \fi +} + +% XXXXXe -> #2=XXXXX where X in [+-0-9]. +\def\sciformat@popsuffix@e#1e\tocount#2{% + #2=#1 +} + +\def\sciformat@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). +% #4 a macro name which will be \def'ed to '0' if the resulting +% mantisse is 0. Won't be touched otherwise. +\def\sciformat@assignmantisse#1\to#2\countdownzerosfrom#3\S#4{% + \pgfplots@toka={#1}% + \loop + \ifnum#3=1 + \else + \expandafter\sciformat@popfirst\the\pgfplots@toka\to{\pgfplots@toka}% + \advance#3 by-1 + \repeat + \edef\sciformat@assignmantisseTMP{\the\pgfplots@toka}% + \ifx\sciformat@assignmantisseTMP\empty + % The case 0.0 * 10^0 + \def#2{0.0}% + \def#4{0}% + \else + \expandafter\sciformat@insertperiod\the\pgfplots@toka\to{#2}% + \fi +} + +% XXXXXX -> X.XXXXX into #3 +\def\sciformat@insertperiod#1#2\to#3{% + \def\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + \def#3{#1.0}% + \else + \def#3{#1.#2}% + \fi +} + +% discards the first token. +\def\sciformat@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\sciformat@strlen#1#2\to#3{% + \advance#3 by1 + \def\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + \else + \sciformat@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\sciformat@count@leading@zeros#1#2\to#3{% + \ifnum#1=0 + \advance#3 by1 + \def\sciparseTMP{#2}% + \ifx\sciparseTMP\empty + \else + \sciformat@count@leading@zeros#2\to{#3}% + \fi + \fi +} + + + + + + +\def\scimathlessthan@positive\M#1\E#2\MM#3\EE#4{% + \c@pgf@counta\expandafter=#2\relax + \c@pgf@countb\expandafter=#4\relax + \ifnum\c@pgf@counta<\c@pgf@countb + \aftergroup\scimathlessthantrue + \else + \ifnum\c@pgf@counta=\c@pgf@countb\relax + \pgfmath@xa\expandafter=#1 pt\relax + \pgfmath@xb\expandafter=#3 pt\relax + \ifdim\pgfmath@xa<\pgfmath@xb + \aftergroup\scimathlessthantrue + \fi + \fi + \fi +} + +\def\scitofixed@impl#1.#2\E#3\END{% + \let\scitofixed@exponent=\c@pgf@countb + \scitofixed@exponent\expandafter=#3\relax + \ifnum\scitofixed@exponent<0 + \pgfplots@toka={0.}% + \loop + \ifnum\scitofixed@exponent<-1 + \pgfplots@toka=\expandafter{\the\pgfplots@toka 0}% + \advance\scitofixed@exponent by1 + \repeat + \def\sciparseTMPB{#2}% + \def\sciparseTMPC{0}% + \ifx\sciparseTMPB\sciparseTMPC + \xdef\sciparseTMP{\the\pgfplots@toka #1}% + \else + \xdef\sciparseTMP{\the\pgfplots@toka #1#2}% + \fi + \else + \ifnum\scitofixed@exponent=0 + \xdef\sciparseTMP{#1.#2}% + \else + \pgfplots@toka={#1}% + \scitofixed@impl@collectmantisse#2\count\scitofixed@exponent + \xdef\sciparseTMP{\the\pgfplots@toka}% + \fi + \fi +} + +\def\scitofixed@impl@collectmantisse#1#2\count#3{% + \pgfplots@toka=\expandafter{\the\pgfplots@toka #1}% + \advance\scitofixed@exponent by-1 + \def\sciparseTMPB{#2}% + \ifx\sciparseTMPB\empty + \loop + \ifnum\scitofixed@exponent>0 + \pgfplots@toka=\expandafter{\the\pgfplots@toka 0}% + \advance\scitofixed@exponent by-1 + \repeat + \else + \ifnum\scitofixed@exponent=0 + \pgfplots@toka=\expandafter{\the\pgfplots@toka .#2}% + \else + \scitofixed@impl@collectmantisse#2\count#3% + \fi + \fi +} -- cgit v1.2.3