diff options
author | Karl Berry <karl@freefriends.org> | 2015-01-31 21:37:06 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-01-31 21:37:06 +0000 |
commit | 84e0e95868a845e531157a1cb94f622da016e6a5 (patch) | |
tree | f880703d39c15193369f6e82eaa169755ae54e22 | |
parent | 13673a964ccd149c582585f4df887a11457a430a (diff) |
pgfplots (31jan15)
git-svn-id: svn://tug.org/texlive/trunk@36178 c570f23f-e606-0410-a88d-b1316a301751
51 files changed, 6872 insertions, 695 deletions
diff --git a/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.pdf b/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.pdf Binary files differindex 15657ee25b4..29de02daaee 100644 --- a/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.pdf +++ b/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.pdf diff --git a/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.tuc b/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.tuc new file mode 100644 index 00000000000..dc35d5f87c6 --- /dev/null +++ b/Master/texmf-dist/doc/context/third/pgfplots/pgfplotsexample-context.tuc @@ -0,0 +1,206 @@ +local utilitydata = { } + +utilitydata.comment={ + ["escape"]="[===[ ... ]===]", + ["file"]="pgfplotsexample-context", + ["format"]="cont-en", + ["stamp"]="2014.05.21 22:04", + ["version"]=1.25, +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.variables then utilitydata.job.variables = { } end + +utilitydata.job.variables.checksums={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.variables then utilitydata.job.variables = { } end + +utilitydata.job.variables.collected={ + ["randomseed"]=0.044282636625824, +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.passes then utilitydata.job.passes = { } end + +utilitydata.job.passes.collected={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.datasets then utilitydata.job.datasets = { } end + +utilitydata.job.datasets.collected={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.pagestates then utilitydata.job.pagestates = { } end + +utilitydata.job.pagestates.collected={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.structure then utilitydata.job.structure = { } end + +utilitydata.job.structure.collected={ + ["branches"]={}, + ["name"]="pgfplotsexample-context", + ["type"]="text", +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.specials then utilitydata.structures.specials = { } end + +utilitydata.structures.specials.collected={ +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.counters then utilitydata.structures.counters = { } end + +utilitydata.structures.counters.collected={ + ["chemical"]={ + { 0 }, + }, + ["combination"]={ + { 0 }, + }, + ["endnote"]={ + { 0 }, + }, + ["figure"]={ + { 0 }, + }, + ["footnote"]={ + { 0 }, + }, + ["formula"]={ + { 0 }, + }, + ["graphic"]={ + { 0 }, + }, + ["intermezzo"]={ + { 0 }, + }, + ["itemgroup:itemize"]={ + { 0 }, + }, + ["linenote"]={ + { 0 }, + }, + ["paragraph"]={ + { 0 }, + }, + ["realpage"]={ + { 1 }, + }, + ["subpage"]={ + { 0 }, + }, + ["table"]={ + { 0 }, + }, + ["userpage"]={ + { 1 }, + }, +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.lists then utilitydata.structures.lists = { } end + +utilitydata.structures.lists.collected={ +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.pages then utilitydata.structures.pages = { } end + +utilitydata.structures.pages.collected={ + { + ["block"]="bodypart", + ["number"]=1, + ["numberdata"]=1, + ["prefixdata"]=2, + ["state"]="start", + ["viewerprefix"]="", + }, +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.references then utilitydata.structures.references = { } end + +utilitydata.structures.references.collected={ +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.references then utilitydata.structures.references = { } end + +utilitydata.structures.references.referred={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.positions then utilitydata.job.positions = { } end + +utilitydata.job.positions.collected={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.objects then utilitydata.job.objects = { } end + +utilitydata.job.objects.collected={ +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.synonyms then utilitydata.structures.synonyms = { } end + +utilitydata.structures.synonyms.collected={ +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.registers then utilitydata.structures.registers = { } end + +utilitydata.structures.registers.collected={ +} + +if not utilitydata.structures then utilitydata.structures = { } end +if not utilitydata.structures.blocks then utilitydata.structures.blocks = { } end + +utilitydata.structures.blocks.collected={ +} + +if not utilitydata.job then utilitydata.job = { } end +if not utilitydata.job.files then utilitydata.job.files = { } end + +utilitydata.job.files.collected={ +} + +if not utilitydata.publications then utilitydata.publications = { } end + +utilitydata.publications.collected={ +} + +utilitydata.job.packed={ + ["index"]={ + { + ["conversionset"]="pagenumber", + }, + { + ["connector"]="–", + ["prefix"]="no", + ["set"]="part", + }, + }, + ["keys"]={ + ["directives"]=true, + ["metadata"]=true, + ["numberdata"]=true, + ["numbers"]=true, + ["pagedata"]=true, + ["prefixdata"]=true, + ["processors"]=true, + ["sectiondata"]=true, + ["specification"]=true, + }, + ["version"]=1.02, +} + +return utilitydata
\ No newline at end of file diff --git a/Master/texmf-dist/doc/generic/pgfplots/README b/Master/texmf-dist/doc/generic/pgfplots/README index b62eab9cb1b..ac023d64411 100644 --- a/Master/texmf-dist/doc/generic/pgfplots/README +++ b/Master/texmf-dist/doc/generic/pgfplots/README @@ -40,6 +40,42 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. HISTORY: + +1.12: scalability + performance +- scalability: reduced TeX memory consumption for huge inline tables +- scalability: lualatex allows bigger 3d graphics +- scalability: lualatex now reduces compilation time for huge 3d graphics + (requires \pgfplotsset{compat=newest} at the time of this writing) + surf shader=faceted: time reduced to 61% of pdflatex + (\addplot3[surf,samples=70] {exp(-x^2-y^2 +x*y)}) + + surf shader=interp: time reduced to 25% of pdflatex + (\addplot3[surf,shader=interp,samples=70] {exp(-x^2-y^2 +x*y)}) + + surf shader=interp, parametric: time reduced to 36% of pdflatex + (\addplot3[surf,shader=interp,z buffer=sort, samples=50,domain=-1:0,y domain=0:2*pi] ({sqrt(1-x^2) * cos(deg(y))}, {sqrt( 1-x^2 ) * sin(deg(y))}, x);) + + surf shader=faceted, parametric: time reduced to 40% of pdflatex + (\addplot3[surf,z buffer=sort, samples=50,domain=-1:0,y domain=0:2*pi] ({sqrt(1-x^2) * cos(deg(y))}, {sqrt( 1-x^2 ) * sin(deg(y))}, x);) + +- scalability: lualated now reduces compilation time for boxplots. + 10000 input points from table: time reduced to 23% of pdflatex +- fixed bug: 3d axes where all axes used log scale produced compile failure +- fixed bug: axis equal did not respect "disabledatascaling" +- fixed bug: mesh legend was confused by color input=explicit +- fixed bug: colorbar style did not reset zmin/zmax +- fixed bug: memory allocation in FPU consumed too much memory +- fixed bug: boxplots: removed compilation error due to spurious spaces in options list +- fixed bug: boxplots: now uses standard quantile estimators: has all 9 estimators of R and uses the same as in Excel as default (as of compat=1.12) +- fixed bug: boxplots: sometimes failed to compute boxplot statistics for special inputs +- fixed bug: boxplots: now, it sets 'mark=*' for outliers if there is no mark (compat=1.12) +- fixed regression: compat=1.11 broke arcs inside of axis +- new feature: ensured that arcs inside of axis make use of 'axis cs' and 'axis direction cs' automatically +- new feature: ensured that (0:1) is evaluated with axis cs +- fixed bug: precision of transformation cartesian to polar was too low (added atan2 to fpu) +- fixed bug: z buffer caused 'mesh legend' to produce a compile error +- new feature: added 'y filter/.expression={y==3 ? nan : y}' to simplify coordinate filters + 1.11: usability + bug fixes. - new feature: "hide obscured x ticks=false" to disable the feature which hides ticks - simplified UI for symbolic coords: now, it accepts unexpandable diff --git a/Master/texmf-dist/doc/latex/pgfplots/TeX-programming-notes.pdf b/Master/texmf-dist/doc/latex/pgfplots/TeX-programming-notes.pdf Binary files differindex 43145f0b4aa..5d4e91d251d 100644 --- a/Master/texmf-dist/doc/latex/pgfplots/TeX-programming-notes.pdf +++ b/Master/texmf-dist/doc/latex/pgfplots/TeX-programming-notes.pdf diff --git a/Master/texmf-dist/doc/latex/pgfplots/pgfplots.doc.src.tar.bz2 b/Master/texmf-dist/doc/latex/pgfplots/pgfplots.doc.src.tar.bz2 Binary files differindex 8dcde4e6c31..7cf1ee93af6 100644 --- a/Master/texmf-dist/doc/latex/pgfplots/pgfplots.doc.src.tar.bz2 +++ b/Master/texmf-dist/doc/latex/pgfplots/pgfplots.doc.src.tar.bz2 diff --git a/Master/texmf-dist/doc/latex/pgfplots/pgfplots.pdf b/Master/texmf-dist/doc/latex/pgfplots/pgfplots.pdf Binary files differindex e1e8017d8fa..b6bed36c3fd 100644 --- a/Master/texmf-dist/doc/latex/pgfplots/pgfplots.pdf +++ b/Master/texmf-dist/doc/latex/pgfplots/pgfplots.pdf diff --git a/Master/texmf-dist/doc/latex/pgfplots/pgfplotsexample.pdf b/Master/texmf-dist/doc/latex/pgfplots/pgfplotsexample.pdf Binary files differindex 04e8a04ebbe..839f2c5418e 100644 --- a/Master/texmf-dist/doc/latex/pgfplots/pgfplotsexample.pdf +++ b/Master/texmf-dist/doc/latex/pgfplots/pgfplotsexample.pdf diff --git a/Master/texmf-dist/doc/latex/pgfplots/pgfplotstable.pdf b/Master/texmf-dist/doc/latex/pgfplots/pgfplotstable.pdf Binary files differindex 3751dcafabb..b23c7e2d74c 100644 --- a/Master/texmf-dist/doc/latex/pgfplots/pgfplotstable.pdf +++ b/Master/texmf-dist/doc/latex/pgfplots/pgfplotstable.pdf diff --git a/Master/texmf-dist/doc/latex/pgfplots/pgfplotstodo.pdf b/Master/texmf-dist/doc/latex/pgfplots/pgfplotstodo.pdf Binary files differindex 8f182ea1895..fdf88fd8810 100644 --- a/Master/texmf-dist/doc/latex/pgfplots/pgfplotstodo.pdf +++ b/Master/texmf-dist/doc/latex/pgfplots/pgfplotstodo.pdf diff --git a/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.pdf b/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.pdf Binary files differindex 9818c6c130f..c0aea225d31 100644 --- a/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.pdf +++ b/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.pdf diff --git a/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.tex b/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.tex index c32e14522bd..3ef5373e11f 100644 --- a/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.tex +++ b/Master/texmf-dist/doc/plain/pgfplots/pgfplotsexample-plain.tex @@ -2,7 +2,7 @@ \def\pgfsysdriver{pgfsys-pdftex.def} \input pgfplots.tex -\pgfplotsset{compat=1.8}% <-- moves axis labels near ticklabels (respects tick label widths) +\pgfplotsset{compat=1.12}% <-- moves axis labels near ticklabels (respects tick label widths) Using plain-\TeX. diff --git a/Master/texmf-dist/source/context/third/pgfplots/pgfplotstests.context.tar.bz2 b/Master/texmf-dist/source/context/third/pgfplots/pgfplotstests.context.tar.bz2 Binary files differindex c44718e3711..e0d3cd38d5b 100644 --- a/Master/texmf-dist/source/context/third/pgfplots/pgfplotstests.context.tar.bz2 +++ b/Master/texmf-dist/source/context/third/pgfplots/pgfplotstests.context.tar.bz2 diff --git a/Master/texmf-dist/source/latex/pgfplots/pgfplotstests.tar.bz2 b/Master/texmf-dist/source/latex/pgfplots/pgfplotstests.tar.bz2 Binary files differindex a6121a0d0e9..bc2fba1a454 100644 --- a/Master/texmf-dist/source/latex/pgfplots/pgfplotstests.tar.bz2 +++ b/Master/texmf-dist/source/latex/pgfplots/pgfplotstests.tar.bz2 diff --git a/Master/texmf-dist/tex/context/third/pgfplots/t-pgfplots.tex b/Master/texmf-dist/tex/context/third/pgfplots/t-pgfplots.tex index 0c8ac83f33f..426d07282d0 100644 --- a/Master/texmf-dist/tex/context/third/pgfplots/t-pgfplots.tex +++ b/Master/texmf-dist/tex/context/third/pgfplots/t-pgfplots.tex @@ -28,6 +28,7 @@ \unprotect +\input pgfplots.revision.tex \startmodule [pgfplots] \usemodule[tikz] diff --git a/Master/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.code.tex b/Master/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.code.tex index 4f414535eec..7ab01a3b03e 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/libs/pgfplotslibrary.code.tex @@ -39,7 +39,7 @@ \expandafter\pgfkeys@spdef\expandafter\pgf@temp\expandafter{\pgf@temp}% \ifx\pgf@temp\pgfutil@empty \else - \expandafter\ifx\csname pgfp@library@\pgf@temp @loaded\endcsname\relax% + \pgfplotsiflibraryloaded{\pgf@temp}{}{% \expandafter\global\expandafter\let\csname pgfp@library@\pgf@temp @loaded\endcsname=\pgfutil@empty% \expandafter\edef\csname tikz@library@#1@atcode\endcsname{\the\catcode`\@} \expandafter\edef\csname tikz@library@#1@barcode\endcsname{\the\catcode`\|} @@ -50,11 +50,45 @@ \input pgflibrarypgfplots.\pgf@temp.code.tex}% \catcode`\@=\csname tikz@library@#1@atcode\endcsname \catcode`\|=\csname tikz@library@#1@barcode\endcsname - \fi% + \expandafter\ifx\csname pgfp@library@#1@loadoptions\endcsname\relax + \else + \expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfp@library@\pgf@temp @loadoptions\endcsname + \expandafter\pgfplotsset\expandafter{\pgfplots@glob@TMPa}% + \fi + }% \fi }% } +\pgfkeys{ + % #1: library name + % #2: compatiblity presets which are controlled by the + % compatibility system but which belong to the library. + % + % FIXME : now as I wrote it, it might have been better to reverse + % the dependency... !? + /pgfplots/compat/library hook/.code 2 args={% + \pgfplotsiflibraryloaded{#1}{% + \pgfkeysalso{#2}% + }{% + \expandafter\ifx\csname pgfp@library@#1@loadoptions\endcsname\relax + \expandafter\def\csname pgfp@library@#1@loadoptions\endcsname{#2}% + \else + \t@pgfplots@toka=\expandafter\expandafter\expandafter{\csname pgfp@library@#1@loadoptions\endcsname}% + \t@pgfplots@tokb={#2}% + \expandafter\edef\csname pgfp@library@#1@loadoptions\endcsname{\the\t@pgfplots@toka,\the\t@pgfplots@tokb}% + \fi + }% + }, +} + +\def\pgfplotsiflibraryloaded#1#2#3{% + \expandafter\ifx\csname pgfp@library@#1@loaded\endcsname\relax% + #3\relax + \else + #2\relax + \fi% +}% % Default loaded libraries: % Currently none diff --git a/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.dateplot.code.tex b/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.dateplot.code.tex index 146153fca9b..55d8da81154 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.dateplot.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.dateplot.code.tex @@ -90,6 +90,39 @@ }% \def\pgfplotslibdateplot@discard@zero@dot 0.#1\to#2{\def#2{#1}}% +%-------------------------------------------------- +%This here extends it to SECONDS, but the precision is too low +% \def\pgfplotslibdateplot@map@time#1 #2:#3:#4\dateto#5\timeto#6{% +% \pgf@xa=#2pt +% \divide\pgf@xa by24 +% % +% \pgf@xb=#3pt +% \divide\pgf@xb by1440 +% \advance\pgf@xa by\pgf@xb +% % +% \def\pgfplots@loc@TMPc{#4}% +% \ifx\pgfplots@loc@TMPc\pgfutil@empty +% \else +% \edef\pgfplots@loc@TMPc{\pgfplotslibdateplot@discard@trailing@colon #4}% +% \pgf@xb=\pgfplots@loc@TMPc pt +% \divide\pgf@xb by1440 +% \divide\pgf@xb by60 +% \advance\pgf@xa by\pgf@xb +% \fi +% % +% \ifdim\pgf@xa<0pt +% \pgf@xa=0pt +% \else +% \ifdim\pgf@xa>1pt +% \pgf@xa=1pt +% \fi +% \fi +% \def#5{#1}% +% \edef#6{\pgf@sys@tonumber\pgf@xa}% +% }% +% \def\pgfplotslibdateplot@discard@trailing@colon#1:{#1}% +%-------------------------------------------------- + \pgfplotsset{ /pgfplots/date ZERO/.code={% \begingroup diff --git a/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.polar.code.tex b/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.polar.code.tex index 2cf8ef5235d..6697ab0f4ad 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.polar.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.polar.code.tex @@ -72,6 +72,9 @@ } \def\pgfplots@polaraxis@activate{% + % FIXME : activating it results in strange output: + \pgfplots@LUA@backend@supportedfalse + % \let\pgfplotsqpointxy@cart=\pgfplotsqpointxy \let\pgfplotsqpointxy=\pgfplotsqpointxy@polaraxis \let\pgfplotsqpointxy@orthogonal=\pgfplotsqpointxy diff --git a/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.statistics.code.tex b/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.statistics.code.tex index 8ccf4abf610..7fbf4f5ea44 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.statistics.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.statistics.code.tex @@ -19,24 +19,41 @@ % %-------------------------------------------- +\catcode`\;=12 +\catcode`\"=12 \newif\ifpgfplotsplothandlerboxplot@variable@width +\ifpgfplots@LUA@supported + \directlua{require("pgfplots.statistics")}% +\fi + +\newif\ifpgfplots@boxplot@ensure@plot@mark +\def\pgfplots@boxplot@ensure@plot@mark{% + \ifpgfplots@boxplot@ensure@plot@mark + \pgfplots@if@has@plot@marks{}{% + \tikzset{mark=*}% + }% + \fi +}% + \pgfplotsset{ boxplot/.code={% \def\tikz@plot@handler{\pgfplotsplothandlerboxplot}% - \pgfkeysalso{% + \pgfplotsset{% /pgfplots/every boxplot, - /pgfplots/boxplot/.cd, + /pgfplots/boxplot/.cd,% #1% }% + \pgfplots@boxplot@ensure@plot@mark }, boxplot prepared/.code={% \def\tikz@plot@handler{\pgfplotsplothandlerboxplotprepared}% - \pgfkeysalso{% + \pgfplotsset{% /pgfplots/every boxplot, - /pgfplots/boxplot/.cd, + /pgfplots/boxplot/.cd,% #1% }% + \pgfplots@boxplot@ensure@plot@mark }, boxplot/data value/.code =\pgfplots@set@source@for{boxplot/data}{#1}{0},% boxplot/data/.code =\pgfplots@set@source@for{boxplot/data}{#1}{1},% @@ -57,6 +74,53 @@ boxplot/upper whisker/.initial=auto, boxplot/average/.initial=, % + % mainly used for compatibility. + boxplot/ensure mark/.is if=pgfplots@boxplot@ensure@plot@mark, + % + boxplot/estimator/.is choice, + boxplot/estimator/legacy/.code={\def\pgfplots@boxplot@estimator{legacy}}, + % + boxplot/estimator/legacy*/.code={\def\pgfplots@boxplot@estimator{legacy*}}, + boxplot/estimator/R1/.code={\def\pgfplots@boxplot@estimator{R1}}, + boxplot/estimator/SAS3/.code={\def\pgfplots@boxplot@estimator{R1}}, + boxplot/estimator/Maple1/.code={\def\pgfplots@boxplot@estimator{R1}}, + % + boxplot/estimator/R2/.code={\def\pgfplots@boxplot@estimator{R2}}, + boxplot/estimator/SAS5/.code={\def\pgfplots@boxplot@estimator{R2}}, + boxplot/estimator/Maple2/.code={\def\pgfplots@boxplot@estimator{R2}}, + % + boxplot/estimator/R3/.code={\def\pgfplots@boxplot@estimator{R3}}, + boxplot/estimator/SAS2/.code={\def\pgfplots@boxplot@estimator{R3}}, + % + boxplot/estimator/R4/.code={\def\pgfplots@boxplot@estimator{R4}}, + boxplot/estimator/SAS1/.code={\def\pgfplots@boxplot@estimator{R4}}, + boxplot/estimator/SciPy0-1/.code={\def\pgfplots@boxplot@estimator{R4}}, + boxplot/estimator/Maple3/.code={\def\pgfplots@boxplot@estimator{R4}}, + % + boxplot/estimator/R5/.code={\def\pgfplots@boxplot@estimator{R5}}, + boxplot/estimator/SciPy12-12/.code={\def\pgfplots@boxplot@estimator{R5}}, + boxplot/estimator/Maple4/.code={\def\pgfplots@boxplot@estimator{R5}}, + % + boxplot/estimator/R6/.code={\def\pgfplots@boxplot@estimator{R6}}, + boxplot/estimator/SAS4/.code={\def\pgfplots@boxplot@estimator{R6}}, + boxplot/estimator/SciPy0-0/.code={\def\pgfplots@boxplot@estimator{R6}}, + boxplot/estimator/Maple5/.code={\def\pgfplots@boxplot@estimator{R6}}, + % + boxplot/estimator/R7/.code={\def\pgfplots@boxplot@estimator{R7}}, + boxplot/estimator/Excel/.code={\def\pgfplots@boxplot@estimator{R7}}, + boxplot/estimator/SciPy1-1/.code={\def\pgfplots@boxplot@estimator{R7}}, + boxplot/estimator/Maple6/.code={\def\pgfplots@boxplot@estimator{R7}}, + % + boxplot/estimator/R8/.code={\def\pgfplots@boxplot@estimator{R8}}, + boxplot/estimator/SciPy13-13/.code={\def\pgfplots@boxplot@estimator{R8}}, + boxplot/estimator/Maple7/.code={\def\pgfplots@boxplot@estimator{R8}}, + % + boxplot/estimator/R9/.code={\def\pgfplots@boxplot@estimator{R9}}, + boxplot/estimator/SciPy38-38/.code={\def\pgfplots@boxplot@estimator{R9}}, + boxplot/estimator/Maple8/.code={\def\pgfplots@boxplot@estimator{R9}}, + % + boxplot/estimator=legacy, + % boxplot/lower quartile off/.initial=0.25, boxplot/upper quartile off/.initial=0.75, boxplot/whisker range/.initial=1.5, @@ -188,6 +252,19 @@ \let\pgfplotsplothandlersurveypoint=\pgfplotsplothandlersurveypoint@boxplot \let\pgfplotsplothandlersurveystart=\pgfplotsplothandlersurveystart@boxplot \let\pgfplotsplothandlersurveyend=\pgfplotsplothandlersurveyend@boxplot + \def\pgfplotsplothandlerLUAfactory{% + function(axis, pointmetainputhandler) + return pgfplots.BoxPlotPlothandler.new( + pgfplots.BoxPlotRequest.new( + "\pgfkeysvalueof{/pgfplots/boxplot/lower quartile off}", + "\pgfkeysvalueof{/pgfplots/boxplot/upper quartile off}", + "\pgfkeysvalueof{/pgfplots/boxplot/whisker range}", + pgfplots.getPercentileEstimator("\pgfplots@boxplot@estimator")), + "\pgfkeysvalueof{/pgfplots/boxplot/draw direction}", + "\pgfkeysvalueof{/pgfplots/boxplot/draw position}", + axis, pointmetainputhandler) + end + }% } @@ -202,18 +279,7 @@ % \def\b@pgfplotsplothandlerboxplot@issorted{1}% % - % FIXME : the decision to store the input points into a SINGLY - % LINKED LIST is based on the observation that huge TeX arrays - % (with one macro per index) run into out-of-memory easily. - % The list does not: it does not need that many macros and uses a - % different memory limit... - % - % However, the linked-list is bought off for a high price... the - % statistics computation takes linear time instead of constant. - % But we have linear time anyway, so it does not destroy the - % asymptotics... and it appears to be better to get it into main - % memory (?) - \pgfplotsapplistXnewempty\pgfp@boxplot@@ + \pgfplotsarraynewempty\pgfp@boxplot@@ \def\c@pgfplotsplothandlerboxplot@num{0}% \c@pgfplots@coordindex=0 }% @@ -221,11 +287,11 @@ \def\pgfplotsplothandlersurveyend@boxplot{% \pgfplots@curplot@threedimfalse % - \pgfplotsapplistXlet\pgfplots@boxplot@data=\pgfp@boxplot@@ - \pgfplotsapplistXnewempty\pgfp@boxplot@@ - % - \if0\b@pgfplotsplothandlerboxplot@issorted - \pgfplotsplothandlersurveyend@boxplot@sort + \ifpgfplots@LUA@backend@supported + \else + \if0\b@pgfplotsplothandlerboxplot@issorted + \pgfplotsplothandlersurveyend@boxplot@sort + \fi \fi % % @@ -246,9 +312,11 @@ % \pgfplotsplothandlersurveystart % - % this will report outliers as point stream: - \pgfplotsplothandlersurveyend@boxplot@computestats - \let\pgfplots@boxplot@data=\relax + \ifpgfplots@LUA@backend@supported + \else + % this will report outliers as point stream: + \pgfplotsplothandlersurveyend@boxplot@computestats + \fi % \let\pgfplotsplothandlerboxplotprepared@normalize@values=\pgfplotsplothandlerboxplotprepared@normalize@values@@ \pgfplotsplothandlerboxplotprepared@normalize@values @@ -258,40 +326,8 @@ }% \def\pgfplotsplothandlersurveyend@boxplot@sort{% - % how bad. we have to convert to array, sort, convert back to - % list... it would have been better if we had worked with arrays - % right away! But see the docs in front of the line - % '\pgfplotsapplistXnewempty\pgfp@boxplot@@' somewhere in this - % file... - % - \begingroup - \pgfplotsarraynewempty{P}% - \pgfplotsarrayresize{P}{\c@pgfplots@coordindex}% - % - \c@pgfplots@coordindex=0 - \let\pgfplotsplothandlersurveyend@boxplot@computestats@=\pgfplots@boxplot@fillarray - \expandafter\pgfplotsplothandlersurveyend@boxplot@computestats@loop\pgfplots@boxplot@data\pgfplots@EOI - % - \pgfkeysdef{/pgfplots/array/unscope pre}{% - \pgfplotsapplistXnewempty\pgfp@boxplot@@ - \pgfplotsarrayforeachungrouped{##1}\as\elem{% - \edef\elem{{\elem}}% - \expandafter\pgfplotsapplistXpushback\expandafter{\elem}\to\pgfp@boxplot@@ - }% - \pgfplotsapplistXlet\pgfplots@boxplot@data=\pgfp@boxplot@@ - \global\let\pgfplots@glob@boxplot@TMPd=\pgfplots@boxplot@data - }% - \pgfkeysdef{/pgfplots/array/unscope post}{% - }% - % - %\message{[}\pgfplotsarrayforeach{P}\as\elem{\message{\elem,}}\message{]^^J}% - % \pgfkeys{/pgfplots/float <}% - \pgfplotsarraysort{P}% - % - \endgroup - \let\pgfplots@boxplot@data=\pgfplots@glob@boxplot@TMPd - %\message{-> \meaning\pgfplots@boxplot@data^^J}% + \pgfplotsarraysort{\pgfp@boxplot@@}% }% \def\pgfplots@boxplot@fillarray{% @@ -301,47 +337,228 @@ %%%% -% -% OUTPUT: -% \pgfplotsretval: the result of #1 * #2 as integer -% \pgfplotsretvalb = 1 iff #1 * #2 is an integer (without loss) -\def\pgfplots@boxplot@get@quantile@offset#1#2{% - \pgfplotscoordmath{float}{parsenumber}{#2}% - \pgfplotscoordmath{float}{op}{multiply}{{\pgfmathresult}{#1}}% - \pgfplotscoordmath{float}{tofixed}{\pgfmathresult}% - \afterassignment\pgfplots@boxplot@get@quantile@remainder - \c@pgf@countd=\pgfmathresult\relax - \edef\pgfplotsretval{\the\c@pgf@countd}% +\def\pgfplotsplothandler@boxplot@init@percentile@estimator{% + \def\pgfplots@loc@TMPb{legacy}% + \ifx\pgfplots@loc@TMPb\pgfplots@boxplot@estimator + \let\pgfplotsplothandler@boxplot@percentile@estimator@=\pgfplotsplothandler@boxplot@percentile@estimator@legacy + \else + \def\pgfplots@loc@TMPb{legacy*}% + \ifx\pgfplots@loc@TMPb\pgfplots@boxplot@estimator + \let\pgfplotsplothandler@boxplot@percentile@estimator@=\pgfplotsplothandler@boxplot@percentile@estimator@legacy@bad + \else + % first, strip 'R' and store the integer number into \pgfplotsretval: + \def\pgfplots@loc@TMPb##1##2{% + \def\pgfplotsretval{##2}% + }% + \expandafter\pgfplots@loc@TMPb\pgfplots@boxplot@estimator + \ifcase\pgfplotsretval\relax + % 0: + \pgfplots@error{illegal argument 'estimator=\pgfplots@boxplot@estimator' encountered.}% + \or + % R1: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{##1*##2}% + \let\h=\pgfmathresult + \pgfmathparse{ceil(\h)}% + \pgfmathfloattoint\pgfmathresult + \let\offset@low=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@low}{##2}% + } + % FIXME : implement 'ceil' in the FPU! + \pgfplots@error{The argument 'estimator=\pgfplots@boxplot@estimator' is only available in conjunction with 'lua backend' and lualatex.}% + \or + % R2: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{##1*##2 + 0.5}% + \let\h=\pgfmathresult + % + \pgfmathparse{ceil(\h-0.5)}% + \pgfmathfloattoint\pgfmathresult + \let\offset@low=\pgfmathresult + % + \pgfmathparse{floor(\h+0.5)}% + \pgfmathfloattoint\pgfmathresult + \let\offset@high=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@low}{##2}% + \let\x@low=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@high}{##2}% + \let\x@high=\pgfmathresult + \pgfmathparse{0.5*(\x@low + \x@high)}% + } + % FIXME : implement 'ceil' in the FPU! + \pgfplots@error{The argument 'estimator=\pgfplots@boxplot@estimator' is only available in conjunction with 'lua backend' and lualatex.}% + \or + % R3: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{##1*##2}% + \let\h=\pgfmathresult + \pgfmathparse{round(\h)}% + \pgfmathfloattoint\pgfmathresult + \let\offset@low=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@low}{##2}% + } + \or + % R4: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{##1*##2}% + \let\h=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@std@lookup{##2}% + } + \or + % R5: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{##1*##2 + 0.5}% + \let\h=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@std@lookup{##2}% + } + \or + % R6: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{##1*(##2+1)}% + \let\h=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@std@lookup{##2}% + } + \or + % R7: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{(##2-1) * ##1 + 1}% + \let\h=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@std@lookup{##2}% + } + \or + % R8: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{(##2 + 1/3) * ##1 + 1/3}% + \let\h=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@std@lookup{##2}% + } + \or + % R9: + \def\pgfplotsplothandler@boxplot@percentile@estimator@##1##2{% + \pgfmathparse{(##2 + 1/4) * ##1 + 3/8}% + \let\h=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@std@lookup{##2}% + } + \else + \pgfplots@error{illegal argument 'estimator=\pgfplots@boxplot@estimator' encountered.}% + \fi + \fi + \fi }% -\def\pgfplots@boxplot@get@quantile@remainder#1\relax{% - \ifdim #1pt>0.001pt - \def\pgfplotsretvalb{0}% +% #1: the percentile in question (like 0.5 for the median) +% #2: the number of data points in the array \pgfp@boxplot@@ +% POSTCONDITION: \pgfmathresult contains the result. +\def\pgfplotsplothandler@boxplot@percentile@estimator#1#2{% + \begingroup + \pgfkeys{/pgf/fpu}% + \pgfplotsplothandler@boxplot@percentile@estimator@{#1}{#2}% + \pgfmath@smuggleone\pgfmathresult + \endgroup +}% + +% #1: the index +% #2: the number of data points in the array \pgfp@boxplot@@ +% +% POSTCONDITION: \pgfmathresult contains the result. +\def\pgfplotsplothandler@boxplot@percentile@estimator@getIndex#1#2{% + \c@pgf@countd=#1\relax + \advance\c@pgf@countd by-1 % we have 0-based indices + \ifnum\c@pgf@countd<0 \c@pgf@countd=0 \fi + \ifnum\c@pgf@countd<#2\relax \else \c@pgf@countd=#2\relax \advance\c@pgf@countd by-1 \fi + \pgfplotsarrayselect\c@pgf@countd\of\pgfp@boxplot@@\to\pgfmathresult +}% + +% #1: the index +% #2: the number of data points in the array \pgfp@boxplot@@ +% +% POSTCONDITION: \pgfmathresult contains the result. +\def\pgfplotsplothandler@boxplot@percentile@estimator@getIndex@legacy@bad#1#2{% + \c@pgf@countd=#1\relax + %\advance\c@pgf@countd by-1 % we have 0-based indices + \ifnum\c@pgf@countd<0 \c@pgf@countd=0 \fi + \ifnum\c@pgf@countd<#2\relax \else \c@pgf@countd=#2\relax \advance\c@pgf@countd by-1 \fi + \pgfplotsarrayselect\c@pgf@countd\of\pgfp@boxplot@@\to\pgfmathresult +}% + +\def\pgfplotsplothandler@boxplot@percentile@estimator@#1#2{% + \pgfplots@error{The estimator is uninitialized in this context. Call \string\pgfplotsplothandler@boxplot@init@percentile@estimator\space first.}% +} + +% computes x_low + (h - h_low) * (x_up - x_low) +% #1: the number of data points in the array \pgfp@boxplot@@ +\def\pgfplotsplothandler@boxplot@percentile@estimator@std@lookup#1{% + \pgfmathparse{floor(\h)}% + \let\h@low=\pgfmathresult + \pgfmathfloattoint\pgfmathresult + \let\offset@low=\pgfmathresult + \c@pgf@countd=\offset@low\relax + \advance\c@pgf@countd by1 % + \edef\offset@high{\the\c@pgf@countd}% + % + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@low}{#1}% + \let\x@low=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@high}{#1}% + \let\x@high=\pgfmathresult + \pgfmathparse{\x@low + (\h - \h@low) * (\x@high - \x@low)}% +}% + +% implements 'estimator=legacy' +\def\pgfplotsplothandler@boxplot@percentile@estimator@legacy#1#2{% + \pgfmathparse{#1*#2}% + \let\h=\pgfmathresult + \pgfmathparse{floor(\h)}% + \pgfmathfloattoint\pgfmathresult + \let\offset@low=\pgfmathresult + % + \pgfmathparse{\h > \offset@low}% + \ifpgfmathfloatcomparison + \def\b@is@int{0}% \else - \def\pgfplotsretvalb{1}% + \def\b@is@int{1}% \fi -}% + % + \c@pgf@countd=\offset@low\relax + \advance\c@pgf@countd by1 % + \edef\offset@high{\the\c@pgf@countd}% + % + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@low}{#2}% + \if0\b@is@int + \let\temp=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex{\offset@high}{#2}% + \pgfmathparse{0.5*(\temp + \pgfmathresult)}% + \fi +} +\def\pgfplotsplothandler@boxplot@percentile@estimator@legacy@bad#1#2{% + \pgfmathparse{#1*(#2-1)}% + \let\h=\pgfmathresult + \pgfmathparse{floor(\h)}% + \pgfmathfloattoint\pgfmathresult + \let\offset@low=\pgfmathresult + % + \pgfmathparse{\h > \offset@low}% + \ifpgfmathfloatcomparison + \def\b@is@int{0}% + \else + \def\b@is@int{1}% + \fi + % + \c@pgf@countd=\offset@low\relax + \advance\c@pgf@countd by1 % + \edef\offset@high{\the\c@pgf@countd}% + % + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex@legacy@bad{\offset@low}{#2}% + \if0\b@is@int + \let\temp=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator@getIndex@legacy@bad{\offset@high}{#2}% + \pgfmathparse{0.5*(\temp + \pgfmathresult)}% + \fi +} + \def\pgfplotsplothandlersurveyend@boxplot@computestats{ % - % compute TMPa := float(\numcoords - 1) - \pgfplotscoordmath{float}{one}% - \let\pgfplots@loc@TMPa=\pgfmathresult - \pgfplotscoordmath{float}{parsenumber}{\numcoords}% - \let\pgfplots@boxplot@numcoords=\pgfmathresult - \pgfplotscoordmath{float}{op}{subtract}{{\pgfmathresult}{\pgfplots@loc@TMPa}}% - \let\pgfplots@boxplot@numcoords@minus@one=\pgfmathresult - % - % compute the indices into the coordinate arrays: - \pgfplots@boxplot@get@quantile@offset{\pgfplots@boxplot@numcoords@minus@one}{\pgfplotsboxplotvalue{lower quartile off}}% - \let\c@pgfplotsplothandlerboxplot@lowerquartile=\pgfplotsretval - \let\b@pgfplotsplothandlerboxplot@lowerquartile@isint=\pgfplotsretvalb - \pgfplots@boxplot@get@quantile@offset{\pgfplots@boxplot@numcoords@minus@one}{0.5}% - \let\c@pgfplotsplothandlerboxplot@median=\pgfplotsretval - \let\b@pgfplotsplothandlerboxplot@median@isint=\pgfplotsretvalb - \pgfplots@boxplot@get@quantile@offset{\pgfplots@boxplot@numcoords@minus@one}{\pgfplotsboxplotvalue{upper quartile off}}% - \let\c@pgfplotsplothandlerboxplot@upperquartile=\pgfplotsretval - \let\b@pgfplotsplothandlerboxplot@upperquartile@isint=\pgfplotsretvalb + \pgfplotsplothandler@boxplot@init@percentile@estimator % % hm. I once had the idea to support quartile-based whisker % definitions... but I did not implement them. @@ -357,15 +574,16 @@ \let\pgfplotsplothandlerboxplot@upperquartile=\pgfutil@empty \let\pgfplotsplothandlerboxplot@upperwhisker=\pgfutil@empty % - \c@pgfplots@coordindex=0 % - \def\pgfplots@boxplot@@next@target{lowerquartile}% - \def\pgfplots@boxplot@next@@lowerquartile{median}% - \def\pgfplots@boxplot@next@@median{upperquartile}% - \def\pgfplots@boxplot@next@@upperquartile{}% - \let\pgfplotsplothandlersurveyend@boxplot@computestats@=\pgfplotsplothandlersurveyend@boxplot@computestats@quantile - \expandafter\pgfplotsplothandlersurveyend@boxplot@computestats@loop\pgfplots@boxplot@data\pgfplots@EOI + \pgfplotsplothandler@boxplot@percentile@estimator{\pgfkeysvalueof{/pgfplots/boxplot/lower quartile off}}{\numcoords}% + \let\pgfplotsplothandlerboxplot@lowerquartile=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator{\pgfkeysvalueof{/pgfplots/boxplot/upper quartile off}}{\numcoords}% + \let\pgfplotsplothandlerboxplot@upperquartile=\pgfmathresult + \pgfplotsplothandler@boxplot@percentile@estimator{0.5}{\numcoords}% + \let\pgfplotsplothandlerboxplot@median=\pgfmathresult % % + \pgfplotscoordmath{float}{parsenumber}{\numcoords}% + \let\pgfplots@boxplot@numcoords=\pgfmathresult \pgfplotscoordmath{float}{op}{divide}{{\pgfplotsplothandlerboxplot@sum}{\pgfplots@boxplot@numcoords}}% \let\pgfplotsplothandlerboxplot@average=\pgfmathresult % @@ -395,9 +613,9 @@ \pgfplotscoordmath{float}{op}{subtract}{{\pgfplotsplothandlerboxplot@lowerquartile}{\pgfplots@boxplot@whisker@width}}% \let\pgfplotsplothandlerboxplot@lowerwhisker@value=\pgfmathresult % - \c@pgfplots@coordindex=0 % - \let\pgfplotsplothandlersurveyend@boxplot@computestats@=\pgfplotsplothandlersurveyend@boxplot@computestats@valuebased - \expandafter\pgfplotsplothandlersurveyend@boxplot@computestats@loop\pgfplots@boxplot@data\pgfplots@EOI + \pgfplotsarrayforeachungrouped\pgfp@boxplot@@\as\pgfplots@current@point@data{% + \pgfplotsplothandlersurveyend@boxplot@computestats@valuebased + }% % \pgfplotsplothandlersurveyend@boxplot@set{lower whisker}{\pgfplotsplothandlerboxplot@lowerwhisker}% \pgfplotsplothandlersurveyend@boxplot@set{upper whisker}{\pgfplotsplothandlerboxplot@upperwhisker}% @@ -412,6 +630,8 @@ % % The "replaced by #2" means to set the value right away and to modify % the plot's option list to reflect the new value. +% +% ---- NOTE: this routine is also invoked from the LUA BACKEND. \def\pgfplotsplothandlersurveyend@boxplot@set#1#2{% \pgfkeysgetvalue{/pgfplots/boxplot/#1}\pgfplots@loc@TMPa \edef\pgfplots@loc@TMPa{\pgfplots@loc@TMPa}% @@ -423,10 +643,15 @@ \pgfplotscoordmath{float}{tostring}{#2}% \edef\pgfplots@loc@TMPb{\noexpand\pgfplotsplothandlersurveyaddoptions{/pgfplots/boxplot/#1={\pgfmathresult}}}% \pgfplots@loc@TMPb + \pgfplotsplothandlersurveyend@boxplot@log{#1}{\pgfmathresult}% \fi \fi }% +\def\pgfplotsplothandlersurveyend@boxplot@log#1#2{% + \pgfplots@log3{boxplot: got #1=#2}% +}% + \def\pgfplotsplothandlersurveyend@boxplot@get#1#2{% \pgfkeysgetvalue{/pgfplots/boxplot/#2}\pgfplots@loc@TMPa \edef\pgfplots@loc@TMPa{\pgfplots@loc@TMPa}% @@ -441,79 +666,6 @@ \fi } - -% Assuming that the input coordinates are in a LIST, we have to loop -% over that list. -\def\pgfplotsplothandlersurveyend@boxplot@computestats@loop#1{% - \def\pgfplots@loc@TMPa{#1}% - \ifx\pgfplots@loc@TMPa\pgfplots@EOI - \else - % - \let\pgfplots@current@point@data=\pgfplots@loc@TMPa - \pgfplotsplothandlersurveyend@boxplot@computestats@ - % - \advance\c@pgfplots@coordindex by1 % - \expandafter\pgfplotsplothandlersurveyend@boxplot@computestats@loop - \fi -}% - -% Really computes stats. -% -% This method computes ALL quantiles (one after the other). These are 0.25, -% 0.5, and 0.75. Perhaps I add quantile-based whiskers eventually. -% -% XXX : this method is quite inefficient because it iterates through a -% loop for what would be 3 arrays lookups otherwise. If I would have enough -% courage to store the points into an array, both this and the -% whisker-loop would be more efficient. But in TeX, arrays are not -% necessarily that efficient ... they run out of memory easily! -% -% The data is in \pgfplots@current@point@data. -\def\pgfplotsplothandlersurveyend@boxplot@computestats@quantile{% - % - \c@pgf@countd=\csname c@pgfplotsplothandlerboxplot@\pgfplots@boxplot@@next@target\endcsname\relax - \expandafter\let\expandafter\pgfplots@loc@TMPa\csname pgfplotsplothandlerboxplot@\pgfplots@boxplot@@next@target\endcsname - % - \ifnum\c@pgf@countd=\c@pgfplots@coordindex\relax - % Ah - we found the occurence of the current search target! - \expandafter\let\csname pgfplotsplothandlerboxplot@\pgfplots@boxplot@@next@target\endcsname=\pgfplots@current@point@data - % - \expandafter\let\expandafter\pgfplots@loc@TMPb\csname b@pgfplotsplothandlerboxplot@\pgfplots@boxplot@@next@target @isint\endcsname - \if 1\pgfplots@loc@TMPb - % accept the match! - % ... and search for the next search target. - \expandafter\let\expandafter\pgfplots@boxplot@@next@target\csname pgfplots@boxplot@next@@\pgfplots@boxplot@@next@target\endcsname - \else - % ... continue searching for the same target in order to - % compute the mean. - \fi - \else - \ifx\pgfplots@loc@TMPa\pgfutil@empty - \else - % Ah! this can *only* happen if we have to compute a - % mean between the previous and this data point. - % - % The current search target is 0.5 * (value + next): - \pgfplotscoordmath{float}{op}{add}{{\pgfplots@current@point@data}{\pgfplots@loc@TMPa}}% - \let\pgfplots@loc@TMPb=\pgfmathresult - \pgfplotscoordmath{float}{parsenumber}{0.5}% - \pgfplotscoordmath{float}{op}{multiply}{{\pgfmathresult}{\pgfplots@loc@TMPb}}% - % - \expandafter\let\csname pgfplotsplothandlerboxplot@\pgfplots@boxplot@@next@target\endcsname - =\pgfmathresult - % - % ... and search for the next search target. - \expandafter\let\expandafter\pgfplots@boxplot@@next@target\csname pgfplots@boxplot@next@@\pgfplots@boxplot@@next@target\endcsname - % - \fi - \fi - % - \ifx\pgfplots@boxplot@@next@target\pgfutil@empty - % stop searching. - \let\pgfplotsplothandlersurveyend@boxplot@computestats@=\relax - \fi -} - \def\pgfplotsplothandlersurveyend@boxplot@computestats@valuebased{% \ifx\pgfplotsplothandlerboxplot@lowerwhisker\pgfutil@empty \pgfplotscoordmath{float}{if less than}{\pgfplots@current@point@data}{\pgfplotsplothandlerboxplot@lowerwhisker@value}{% @@ -524,6 +676,8 @@ }% \fi % + % FIXME : optimize this! We have an array so we COULD check it in + % reverse order! % it would be so cool if we could simply check the list in reverse % order. but not if it really is a singly-linked list... \pgfplotscoordmath{float}{if less than}{\pgfplotsplothandlerboxplot@upperwhisker@value}{\pgfplots@current@point@data}{% @@ -556,12 +710,19 @@ \else \pgfplotscoordmath{float}{if is bounded}{\pgfplots@current@point@data}{% % - \pgfplotsplothandlersurveypoint@boxplot@ + \ifpgfplots@LUA@backend@supported + \pgfplotsplothandlerboxplot@LUA@survey@point + \else + \pgfplotsplothandlersurveypoint@boxplot@ + \fi }{% }% \fi }% +\def\pgfplotsplothandlerboxplot@LUA@survey@point{% + \directlua{pgfplots.texBoxPlotSurveyPoint("\pgfplots@current@point@data")}% +}% \def\pgfplotsplothandlersurveypoint@boxplot@{% \pgfplotsutil@advancestringcounter\c@pgfplotsplothandlerboxplot@num % @@ -577,8 +738,8 @@ \let\pgfplotsplothandlerboxplot@sum=\pgfmathresult % % store parsed result. - \edef\pgfmathresult{{\pgfplots@current@point@data}}% - \expandafter\pgfplotsapplistXpushback\expandafter{\pgfmathresult}\to\pgfp@boxplot@@ + \edef\pgfmathresult{\pgfplots@current@point@data}% + \expandafter\pgfplotsarraypushback\expandafter{\pgfmathresult}\to\pgfp@boxplot@@ % \let\pgfplotsplothandlerboxplot@last=\pgfplots@current@point@data % @@ -1054,4 +1215,7 @@ \pgfplots@boxplot@cs@decompose{#1}% \pgfplotsboxplotpointabwhisker{\pgfplots@boxplotcs@a}{\pgfplots@boxplotcs@b}% }% + +\catcode`\;=\pgfplots@oldcatcodesemicolon +\catcode`\"=\pgfplots@oldcatcodedoublequote \endinput diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots.lua index dcb8ea94007..23aeaab2a84 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots.lua +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots.lua @@ -1,37 +1,45 @@ -pgfplotsGetLuaBinaryStringFromCharIndicesChunkSize = 7000; +require("pgfplots.binary") -if unpack == nil then - -- LUA 0.76 renamed unpack to table.unpack - pgfplotsUnpack = table.unpack; +-- all classes/globals will be added to this table: +pgfplots = {} + +-- will be set by TeX: +pgfplots.pgfplotsversion = nil + +if _VERSION == "Lua 5.1" or _VERSION == "Lua 5.0" then + texio.write("pgfplots: setting 'lua support=false': the lua version on this system is " .. _VERSION .. "; expected at least 'Lua 5.2'. Use a more recent TeX distribution to benefit from LUA in pgfplots.\n") + + -- the entire lua backend will be switched off if this is false: + tex.sprint("\\pgfplotsset{lua support=false}") + return else - pgfplotsUnpack = unpack; + -- well, 5.2 is what this stuff has been written for. + -- Is there a good reason why it shouldn't work on 5.1 !? No, I guess not. Except that it took me a long time + -- to figure out that 5.2 broke compatibility in lots of ways - and it was difficult enough to get it up and running. + -- If someone wants (and needs) to run it in 5.1 - I would accept patches. end --- Takes a table containing an arbitrary number of integers in the range 0..255 and converts it --- into a binary stream of the corresponding binary chars. --- --- @param charIndices a table containing 0...N arguments; each in the range 0..255 --- --- @return a string containing binary content, one byte for each input integer. -function pgfplotsGetLuaBinaryStringFromCharIndices(charIndices) - -- unpack extracts only the indices (we can't provide a table to string.char). - -- note that pdf.immediateobj has been designed to avoid sanity checking for invalid UTF strings - - -- in other words: it accepts binary strings. - -- - -- unfortunately, this here fails for huge input tables: - -- pgfplotsretval=string.char(unpack(charIndices)); - -- we have to create it incrementally using chunks: - local len = #charIndices; - local chunkSize = pgfplotsGetLuaBinaryStringFromCharIndicesChunkSize; - local buf = {}; - -- ok, append all full chunks of chunkSize first: - local numFullChunks = math.floor(len/chunkSize); - for i = 0, numFullChunks-1, 1 do - table.insert(buf, string.char(pgfplotsUnpack(charIndices, 1+i*chunkSize, (i+1)*chunkSize))); - end - -- append the rest: - table.insert(buf, string.char(pgfplotsUnpack(charIndices, 1+numFullChunks*chunkSize))); - return table.concat(buf); +require("pgfplots.pgfplotsutil") + +-- see pgfrcs.code.tex -- all versions after 3.0.0 (excluding 3.0.0) will set this version: +if not pgf or not pgf.pgfversion then + pgfplots.log("log", "pgfplots.lua: loading complementary lua code for your pgf version...\n") + pgfplots.pgfluamathfunctions = require("pgfplotsoldpgfsupp.luamath.functions") + pgfplots.pgfluamathparser = require("pgfplotsoldpgfsupp.luamath.parser") +else + pgfplots.pgfluamathparser = require("pgf.luamath.parser") + pgfplots.pgfluamathfunctions = require("pgf.luamath.functions") end +pgfplots.pgftonumber = pgfplots.pgfluamathfunctions.tonumber +pgfplots.tostringfixed = pgfplots.pgfluamathfunctions.tostringfixed +pgfplots.toTeXstring = pgfplots.pgfluamathfunctions.toTeXstring + + +require("pgfplots.plothandler") +require("pgfplots.meshplothandler") +require("pgfplots.colormap") +require("pgfplots.streamer") +-- hm. perhaps this here should become a separate module: +require("pgfplots.pgfplotstexio") diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/binary.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/binary.lua new file mode 100644 index 00000000000..704778440bc --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/binary.lua @@ -0,0 +1,41 @@ + +-- Attention: functions in this file are part of the backend driver. +-- They are supposed to work back with Lua 5.1 . +-- Note that most of the 'lua backend' requires Lua 5.2 (currently) + +pgfplotsGetLuaBinaryStringFromCharIndicesChunkSize = 7000; + +if unpack == nil then + -- LUA 0.76 renamed unpack to table.unpack + pgfplotsUnpack = table.unpack; +else + pgfplotsUnpack = unpack; +end + +-- Takes a table containing an arbitrary number of integers in the range 0..255 and converts it +-- into a binary stream of the corresponding binary chars. +-- +-- @param charIndices a table containing 0...N arguments; each in the range 0..255 +-- +-- @return a string containing binary content, one byte for each input integer. +function pgfplotsGetLuaBinaryStringFromCharIndices(charIndices) + -- unpack extracts only the indices (we can't provide a table to string.char). + -- note that pdf.immediateobj has been designed to avoid sanity checking for invalid UTF strings - + -- in other words: it accepts binary strings. + -- + -- unfortunately, this here fails for huge input tables: + -- pgfplotsretval=string.char(unpack(charIndices)); + -- we have to create it incrementally using chunks: + local len = #charIndices; + local chunkSize = pgfplotsGetLuaBinaryStringFromCharIndicesChunkSize; + local buf = {}; + -- ok, append all full chunks of chunkSize first: + local numFullChunks = math.floor(len/chunkSize); + for i = 0, numFullChunks-1, 1 do + table.insert(buf, string.char(pgfplotsUnpack(charIndices, 1+i*chunkSize, (i+1)*chunkSize))); + end + -- append the rest: + table.insert(buf, string.char(pgfplotsUnpack(charIndices, 1+numFullChunks*chunkSize))); + return table.concat(buf); +end + diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/colormap.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/colormap.lua new file mode 100644 index 00000000000..28fd6ddd56b --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/colormap.lua @@ -0,0 +1,98 @@ +-- +-- This file contains parts of pgfplotscolormap.code.tex +-- + +local math=math +local pgfplotsmath = pgfplots.pgfplotsmath +local io=io +local type=type +local tostring=tostring +local error=error +local table=table + +do +-- all globals will be read from/defined in pgfplots: +local _ENV = pgfplots +----------------------------------- + +ColorSpace = newClass() +function ColorSpace:constructor(numComponents) + self.numComponents=numComponents +end + +rgb = ColorSpace.new(3) +cmyk = ColorSpace.new(4) +gray = ColorSpace.new(1) + + +ColorMap = newClass() + +ColorMap.range =1000 + +-- h: mesh width between adjacent values +-- colorspace: an instance of ColorSpace +-- values: an array (1-based table) with color components. Each color component is supposed to be a table with K entries where K is colorspace:numComponents +function ColorMap:constructor( h, colorspace, values) + if not h or not colorspace or not values then error("arguments must not be nil")end + + self.name = name + self.h = h + self.invh = 1/h + self.colorspace = colorspace + self.values = values + + local numComponents = self.colorspace.numComponents + for i = 1,#self.values do + local value = self.values[i] + if #value ~= numComponents then + error("Some value has an unexpected number of color components, expected " .. self.colorspace.numComponents .. " but was ".. #value); + end + end +end + +function ColorMap:findPrecomputed(inMin, inMax, x) + local transformed + if inMin == 0 and inMax == ColorMap.range then + transformed = x + else + local scale = ColorMap.range / (inMax - inMin) + + transformed = (x - inMin) * scale + end + transformed = math.max(0, transformed) + transformed = math.min(ColorMap.range, transformed) + + local divh = transformed * self.invh + local intervalno = math.floor(divh) + local factor = divh - intervalno + local factor_two = 1-factor + + + -- Step 2: interpolate the desired RGB value using vector valued interpolation on the identified interval + if intervalno+1 == #self.values then + -- ah- we are at the right end! + return self.values[#self.values] + end + + local left = self.values[intervalno+1] + local right = self.values[intervalno+2] + if not left or not right then error("Internal error: the color map does not have enough values for interval no " .. intervalno )end + + local result = {} + for i = 1,self.colorspace.numComponents do + local result_i = factor_two * left[i] + factor * right[i] + + result[i] = result_i + end + + return result +end + +----------------------------------- + +-- global registry of all colormaps. +-- Key: colormap name +-- Value: an instance of ColorMap +ColorMaps = {} + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/meshplothandler.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/meshplothandler.lua new file mode 100644 index 00000000000..a3b492a5296 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/meshplothandler.lua @@ -0,0 +1,294 @@ +-- This file has dependencies to BOTH, the TeX part of pgfplots and the LUA part. +-- It is the only LUA component with this property. +-- +-- Its purpose is to encapsulate the communication between TeX and LUA in a central LUA file + +local pgfplotsmath = pgfplots.pgfplotsmath +local error=error +local table=table +local string=string +local tostring=tostring +local type=type +local io=io + +do +-- all globals will be read from/defined in pgfplots: +local _ENV = pgfplots + + +------------------------------------------------------- +-- A patch type. +-- @see \pgfplotsdeclarepatchclass + +PatchType = newClass() + +function PatchType:constructor(name, numVertices) + self.name = name + self.numVertices = numVertices +end + +function PatchType:__tostring() + return self.name +end + +function PatchType:newPatch(coords) + return Patch.new(self,coords) +end + +LinePatchType = newClassExtends(PatchType) + +function LinePatchType:constructor() + PatchType.constructor(self, "line", 2) +end + +TrianglePatchType = newClassExtends(PatchType) + +function TrianglePatchType:constructor() + PatchType.constructor(self, "triangle", 3) +end + + +RectanglePatchType = newClassExtends(PatchType) + +function RectanglePatchType:constructor() + PatchType.constructor(self, "rectangle", 4) +end + +------------------------------------------------------- +-- +-- a single patch. +-- @see \pgfplotsdeclarepatchclass + +Patch = newClass() + +function Patch:constructor(patchtype, coords) + if not patchtype or not coords then error("arguments must not be nil") end + if #coords ~= patchtype.numVertices then error("Unexpected number of coordinates provided; expected " .. tostring(patchtype.numVertices) .. " but got " .. tostring(#coords)) end + + self.patchtype = patchtype + self.coords = coords +end + +------------------------------------------------------- +-- Replicates \pgfplotsplothandlermesh (to some extend) +MeshPlothandler = newClassExtends(Plothandler) + +function MeshPlothandler:constructor(axis, pointmetainputhandler) + Plothandler.constructor(self,"mesh", axis, pointmetainputhandler) +end + +-- see \pgfplot@apply@zbuffer +function MeshPlothandler:reverseScanline(scanLineLength) + local coords = self.coords + local tmp + local scanlineOff + local numScanLines = #coords / scanLineLength + for scanline = 0,numScanLines-1,1 do + scanlineOff = scanline * scanLineLength + local reverseindex = scanlineOff + scanLineLength + for i = 0,scanLineLength/2-1,1 do + tmp = coords[1+scanlineOff+i] + coords[1+scanlineOff+i] = coords[reverseindex] + coords[reverseindex] = tmp + + reverseindex = reverseindex-1 + end + end +end + +-- see \pgfplot@apply@zbuffer +function MeshPlothandler:reverseTransposed(scanLineLength) + local coords = self.coords + local tmp + local scanlineOff + local numScanLines = #coords / scanLineLength + local reverseScanline = numScanLines-1 + for scanline = 0,numScanLines/2-1,1 do + scanlineOff = 1+scanline * scanLineLength + reverseScanlineOff = 1+reverseScanline * scanLineLength + for i = 0,scanLineLength-1 do + tmp = coords[scanlineOff+i] + coords[scanlineOff+i] = coords[reverseScanlineOff+i] + coords[reverseScanlineOff+i] = tmp + end + + reverseScanline = reverseScanline-1 + end +end + +-- see \pgfplot@apply@zbuffer +function MeshPlothandler:reverseStream() + local coords = self.coords + local tmp + local reverseindex = #coords + for i = 1,#coords/2 do + tmp = coords[i] + coords[i] = coords[reverseindex] + coords[reverseindex] = tmp + reverseindex = reverseindex-1 + end +end + + + +------------------------------------------------------- +-- +-- The (LUA!) visualizer for patch plots. It prepares stuff such that TeX only needs to work with lowlevel driver (PGF) streams. +-- + +MeshVisualizer = newClassExtends(PlotVisualizer) + +local COORDINATE_VALUE_OF_JUMPS = -16000 +local meshVisualizerTagEmptyCoordinates = function(pt) + pt.pgfXY= { COORDINATE_VALUE_OF_JUMPS, COORDINATE_VALUE_OF_JUMPS } + pt.x = { COORDINATE_VALUE_OF_JUMPS, COORDINATE_VALUE_OF_JUMPS, COORDINATE_VALUE_OF_JUMPS } +end + +function MeshVisualizer:constructor(sourcePlotHandler, patchType, rows, cols, isXVariesOrdering, isMatrixInput, isMatrixOutput, isZBufferSort) + PlotVisualizer.constructor(self,sourcePlotHandler) + self.patchType = patchType + self.isMatrixInput = isMatrixInput + self.isMatrixOutput = isMatrixOutput + self.isZBufferSort = isZBufferSort + self.rows = rows + self.cols = cols + self.isXVariesOrdering =isXVariesOrdering + + self.isOneDimMode= false + self.scanLineLength =-1 + if isMatrixInput then + -- isOneDimMode is ONLY interesting for matrix input + if cols <= 1 or rows <=1 then + self.isOneDimMode = true + self.patchType = LinePatchType.new() + -- this is not yet implemented (and cannot happen since the TeX call does catch this) + error("UNSUPPORTED OPERATION EXCEPTION") + end + + if isXVariesOrdering then + -- x varies (=rowwise) + self.scanLineLength = cols + else + -- y varies (=colwise) + self.scanLineLength = rows + end + + self.notifyJump = meshVisualizerTagEmptyCoordinates + else + -- disable any special handling + self.isXVariesOrdering = true + end + + -- log("initialized MeshVisualizer with " .. tostring(sourcePlotHandler) .. ", " .. tostring(patchType) .. ", isMatrixInput = " .. tostring(isMatrixInput) .. ", isMatrixOutput = " .. tostring(isMatrixOutput) .. ", isZBufferSort = " .. tostring(isZBufferSort) .. " rows = " ..tostring(rows) .. " cols = " ..tostring(cols) .. " is x varies=" .. tostring(isXVariesOrdering)) +end + +function MeshVisualizer:getVisualizationOutput() + local result = PlotVisualizer.getVisualizationOutput(self) + + if self.isMatrixInput and not self.isMatrixOutput then + result = self:decodeIntoPatches(result) + end + + if self.isZBufferSort then + result = self:applyZBufferSort(result) + end + + return result +end + +-- @param coords an array of Coord +function MeshVisualizer:applyZBufferSort(coords) + -- in order to sort this thing, we need to compute the sort key (view depth) for each coord. + -- furthermore, each list entry must be single patch... that means we need a (huge?) temporary table. + + local patchType = self.patchType + local numVertices = patchType.numVertices + + if (#coords % numVertices) ~= 0 then error("Got an unexpected number of input coordinates: each patch has " .. tostring(numVertices) .. " vertices, but the number of coords " .. tostring(#coords) .. " is no multiple of this number") end + local numPatches = #coords / numVertices + + -- STEP 1: compute an array of patches. + local patches = {} + local off=1 + for i = 1,numPatches do + local patchCoords = {} + for j = 1,numVertices do + local pt = coords[off] + off = off+1 + patchCoords[j] = pt + end + local patch = patchType:newPatch(patchCoords) + patches[i] = patch + end + if off ~= 1+#coords then error("Internal error: not all coordinates are part of patches (got " .. tostring(off) .. "/" .. tostring(#coords) ..")") end + + -- STEP 2: assign the sort key: the "element depth". + -- + -- the "element depth" is defined to be the MEAN of all + -- vertex depths. + -- And since the mean is 1/n * sum_{i=1}^n V_i, we can + -- directly omit the 1/n --- it is the same for every + -- vertex anyway, and we only want to compare the depth + -- values. + local axis = self.axis + local getVertexDepth = axis.getVertexDepth + for i=1,numPatches do + local patch = patches[i] + local patchcoords = patch.coords + + local sumOfVertexDepth = 0 + for j = 1,numVertices do + local vertex = patchcoords[j] + + local vertexDepth = getVertexDepth(axis,vertex) + + sumOfVertexDepth = sumOfVertexDepth + vertexDepth + end + patch.elementDepth = sumOfVertexDepth + end + + -- STEP 3: SORT. + local comparator = function(patchA, patchB) + return patchA.elementDepth > patchB.elementDepth + end + table.sort(patches, comparator) + + -- STEP 4: convert back into a list (in-place). + local off = 1 + for i=1,numPatches do + local patch = patches[i] + local patchcoords = patch.coords + for j = 1,numVertices do + coords[off] = patchcoords[j] + off = off+1 + end + end + if off ~= 1+#coords then error("Internal error: not all coordinates are part of patches (got " .. tostring(off) .. "/" .. tostring(#coords) ..")") end + + return coords +end + +function MeshVisualizer:decodeIntoPatches(coords) + local result = {} + + local scanLineLength = self.scanLineLength + local length = #coords + + local i = scanLineLength + while i < length do + local im = i-scanLineLength + + for j = 2,scanLineLength do + table.insert(result, coords[im+j-1]) -- (i-1,j-1) + table.insert(result, coords[im+j]) -- (i-1,j ) + table.insert(result, coords[i+j]) -- (i ,j ) + table.insert(result, coords[i+j-1]) -- (i ,j-1) + end + + i = i + scanLineLength + end + + return result +end + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/pgfplotstexio.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/pgfplotstexio.lua new file mode 100644 index 00000000000..ca8b894a7c3 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/pgfplotstexio.lua @@ -0,0 +1,464 @@ +-- This file has dependencies to BOTH, the TeX part of pgfplots and the LUA part. +-- It is the only LUA component with this property. +-- +-- Its purpose is to encapsulate the communication between TeX and LUA in a central LUA file +-- +-- +-- Here is the idea how the TeX backend communicates with the LUA backend: +-- +-- * TeX can call LUA methods in order to "do something". The reverse direction is not true: LUA cannot call TeX methods. +-- +-- * the only way that LUA can read TeX input values or write TeX output values is the top layer (at the time of this writing: only pgfplotstexio.lua ). +-- +-- * The LUA backend has one main purpose: scalability and performance. +-- Its purpose is _not_ to run a standalone visualization. +-- +-- The precise meaning of "scalability" is: the LUA backend should do as much +-- as possible which is done for single coordinates. Coordinates constitute +-- "scalability": the number of coordinates can become arbitrarily large. +-- +-- "Performance" is related to scalability. But it is more: some dedicated +-- utility function might have a TeX backend and will be invoked whenever it +-- is needed. Candidates are colormap functions, z buffer arithmetics etc. +-- +-- Thus, the best way to ensure "scalability" is to move _everything_ which is to be done for a single coordinate to LUA. +-- +-- Sometimes, this will be impossible or too expensive. +-- Here, "Performance" might still be optimized by some dedicated LUA function. +-- +-- +-- Unfortunately, the LUA backend does not simplify the code base - it makes it more complicated. +-- This is due to the way it is used: one needs to know when the TeX backend +-- delegates all its work to LUA. It is also due to the fact that it +-- duplicates code: the same code is present in TeX and in LUA. I chose to keep +-- the two code bases close to each other. This has a chance to simplify maintenance: if I know +-- how something works in TeX, and I find some entry point in LUA, it will +-- hopefully be closely related. +-- +-- +-- It follows an overview over entry points into the LUA backend: +-- +-- * \begin{axis}. It invokes \pgfplots@prepare@LUA@api . +-- The purpose is to define the global pgfplots.gca "_g_et _c_urrent _a_xis" and to transfer some key presets. +-- +-- Log message: "lua backend=true: Activating LUA backend for axis." +-- +-- * \end{axis}. It invokes \pgfplots@LUA@visualization@update@axis . +-- The purpose is to transfer results of the survey phase to LUA; in particular axis properties like +-- the view direction, data scale transformations, axis wide limits and some related properties. +-- This has nothing to do with coordinates; the survey phase of coordinates is handled in a different way (see below). +-- +-- Eventually, \pgfplots@LUA@cleanup will clear the global pgfplots.gca . +-- +-- * \addplot . This has much to do with scalability, so much of its functionality is done in the LUA backend. +-- +-- Keep in mind that \addplot is part of the survey phase: it collects coordinates and updates axis limits. +-- Afterwards, it stores the survey results in the current axis. +-- +-- The survey phase currently has two different ways to communicate with the LUA backend: +-- +-- 1. PARTIAL MODE. In this mode, the coordinate stream comes from TeX: +-- some TeX code generates the coordinates. Whenever the stream is ready, +-- it will invoke \pgfplots@LUA@survey@point . This, in turn, calls the +-- LUA backend in order to complete the survey (which boils down to +-- pgfplots.texSurveyPoint). PARTIAL MODE saves lots of time, but its +-- scalability is limited due to the intensive use of TeX, it is less +-- powerful than COMPLETE MODE. +-- +-- 2. COMPLETE MODE. In this mode, the entire coordinate stream is on the +-- LUA side. The TeX code will merely call start the survey phase, call +-- LUA, and end the survey phase. This is the most efficient +-- implementation. At the time of this writing, it is limited to `\addplot +-- expression`: the code for `\addplot expression` tries to transfer the +-- entire processing to the LUA backend. If it succeeds, it will do +-- nothing on the TeX side. +-- +-- Both PARTIAL MODE and COMPLETE MODE call +-- \pgfplots@LUA@survey@start : transfer plot type and current axis arguments to LUA +-- and +-- \pgfplots@LUA@survey@end : copy LUA axis arguments back to TeX. +-- +-- Eventually, the axis will initiate the visualization phase for each plot. This is done by +-- a) \pgfplots@LUA@visualization@init : it calls pgfplots.texVisualizationInit() and results in the log message +-- "lua backend=true: Activating partial LUA backend for visualization of plot 0". +-- b) \pgfplots@LUA@visualization@of@current@plot : it transfers control +-- to LUA (pgfplots.texVisualizePlot) and does as much with the +-- coordinates as possible. Eventually, it streams the result back to +-- TeX which will visualize the stream by means of PGF's plot streams. +-- This is somewhat complicated since it modifies the TeX streaming. +local pgfplotsmath = pgfplots.pgfplotsmath +local tex=tex +local tostring=tostring +local error=error +local table=table +local string=string +local pairs=pairs +local pcall=pcall +local type=type +local lpeg = require("lpeg") +local math = math + +do +-- all globals will be read from/defined in pgfplots: +local _ENV = pgfplots + +local pgftonumber = pgfluamathfunctions.tonumber + +-- will be assigned by pgfplots at boot time. +LOAD_TIME_CATCODETABLE = nil + +-- Called during \addplot, i.e. during the survey phase. It is only called in PARTIAL MODE (see above). +function texSurveyPoint(x,y,z,meta) + local pt = Coord.new() + pt.x[1] = x + pt.x[2] = y + pt.x[3] = z + pt.meta = meta + + gca.currentPlotHandler:surveypoint(pt) +end + +-- Copies survey results of the current plot back to TeX. It prints a couple of executable TeX statements as result. +-- @see \pgfplots@LUA@survey@end +function texSurveyEnd() + local result = gca:surveyToPgfplots(gca.currentPlotHandler, true) + --log("returning " .. result .. "\n\n") + + tex.sprint(LOAD_TIME_CATCODETABLE, result); + gca.currentPlotHandler=nil +end + +-- A performance optimization: point meta transformation is done on the LUA side. +-- +-- expands to the transformed point meta +function texPerpointMetaTrafo(metaStr) + local meta = pgftonumber(metaStr) + local transformed = gca.currentPlotHandler:visualizationTransformMeta(meta); + tex.sprint(LOAD_TIME_CATCODETABLE, tostringfixed(transformed)); +end + +-- Called at the beginning of each plot visualization. +-- +-- expands to '1' if LUA is available for this plot and '0' otherwise. +-- @see texVisualizePlot +function texVisualizationInit(plotNum, plotIs3d) + if not plotNum or plotIs3d==nil then error("arguments must not be nil") end + + local currentPlotHandler = gca.plothandlers[plotNum+1] + gca.currentPlotHandler = currentPlotHandler; + if currentPlotHandler then + currentPlotHandler.plotIs3d = plotIs3d + currentPlotHandler:visualizationPhaseInit(); + tex.sprint("1") + else + -- ok, this plot has no LUA support. + tex.sprint("0") + end +end + +local pgfXyCoordSerializer = function(pt) + -- FIXME : it is unsure of whether this here really an improvement - or if it would be faster to compute that stuff in TeX... + if pt.pgfXY ~=nil then + return "{" .. tostringfixed(pt.pgfXY[1]) .. "}{" .. tostringfixed(pt.pgfXY[2]) .. "}" + else + return "{0}{0}" + end +end + +-- Actually does as much of the visualization of the current plot: it transforms all coordinates to some point where the TeX visualization mode continues. +-- +-- It expands to the resulting coordinates. Note that these coordinates are already mapped somehow (typically: to fixed point) +-- @see texVisualizationInit +function texVisualizePlot(visualizerFactory) + if not visualizerFactory then error("arguments must not be nil") end + if type(visualizerFactory) ~= "function" then error("arguments must be a function (a factory)") end + + local currentPlotHandler = gca.currentPlotHandler + if not currentPlotHandler then error("Illegal state: The current plot has no LUA plot handler!") end + + local visualizer = visualizerFactory(currentPlotHandler) + + local result = visualizer:getVisualizationOutput() + local result_str = currentPlotHandler:getCoordsInTeXFormat(gca, result, pgfXyCoordSerializer) + --log("returning " .. result_str .. "\n\n") + tex.sprint(LOAD_TIME_CATCODETABLE, result_str) +end + +-- Modifies the Surveyed coordinate list. +-- Expands to nothing +function texApplyZBufferReverseScanline(scanLineLength) + local currentPlotHandler = gca.currentPlotHandler + if not currentPlotHandler then error("This function cannot be used in the current context") end + + currentPlotHandler:reverseScanline(scanLineLength) +end + +-- Modifies the Surveyed coordinate list. +-- Expands to nothing +function texApplyZBufferReverseTransposed(scanLineLength) + local currentPlotHandler = gca.currentPlotHandler + if not currentPlotHandler then error("This function cannot be used in the current context") end + + currentPlotHandler:reverseTransposed(scanLineLength) +end + +-- Modifies the Surveyed coordinate list. +-- Expands to nothing +function texApplyZBufferReverseStream() + local currentPlotHandler = gca.currentPlotHandler + if not currentPlotHandler then error("This function cannot be used in the current context") end + + currentPlotHandler:reverseStream(scanLineLength) +end + +-- Modifies the Surveyed coordinate list. +-- +-- Note that this is UNRELATED to mesh/surface plots! They have their own (patch-based) z buffer. +-- +-- Expands to nothing +function texApplyZBufferSort() + local currentPlotHandler = gca.currentPlotHandler + if not currentPlotHandler then error("This function cannot be used in the current context") end + + currentPlotHandler:sortCoordinatesByViewDepth() +end + +-- Modifies the Surveyed coordinate list. +-- Expands to the resulting coordinates +function texGetSurveyedCoordsToPgfplots() + local currentPlotHandler = gca.currentPlotHandler + if not currentPlotHandler then error("This function cannot be used in the current context") end + + tex.sprint(LOAD_TIME_CATCODETABLE, currentPlotHandler:surveyedCoordsToPgfplots(gca)) +end + +-- Performance optimization: computes the colormap lookup. +function texColorMapPrecomputed(mapName, inMin, inMax, x) + local colormap = ColorMaps[mapName]; + if colormap then + local result = colormap:findPrecomputed( + pgftonumber(inMin), + pgftonumber(inMax), + pgftonumber(x)) + + local str = "" + for i = 1,#result do + if i>1 then str = str .. "," end + str = str .. tostringfixed(result[i]) + end + tex.sprint(LOAD_TIME_CATCODETABLE, str) + end +end + +local function isStripPrefixOrSuffixChar(char) + return char == ' ' or char == '{' or char == "}" +end + +-- Expressions can be something like +-- ( {(6+(sin(3*(x+3*y))+1.25)*cos(x))*cos(y)}, +-- {(6+(sin(3*(x+3*y))+1.25)*cos(x))*sin(y)}, +-- {((sin(3*(x+3*y))+1.25)*sin(x))} ); +-- +-- These result in expressions = { " {...}", " {...}", " {...} " } +-- -> this function removes the surrounding braces and the white spaces. +local function removeSurroundingBraces(expressions) + for i=1,#expressions do + local expr = expressions[i] + local startIdx + local endIdx + startIdx=1 + while startIdx<#expr and isStripPrefixOrSuffixChar(string.sub(expr,startIdx,startIdx)) do + startIdx = startIdx+1 + end + endIdx = #expr + while endIdx > 0 and isStripPrefixOrSuffixChar(string.sub(expr,endIdx,endIdx)) do + endIdx = endIdx-1 + end + + expr = string.sub(expr, startIdx, endIdx ) + expressions[i] = expr + end +end + +------------- +-- A parser for foreach statements - at least those which are supported in this LUA backend. +-- +local samplesAtToDomain +do + local P = lpeg.P + local C = lpeg.C + local V = lpeg.V + local match = lpeg.match + local space_pattern = P(" ")^0 + + local Exp = V"Exp" + local comma = P"," * space_pattern + -- this does not catch balanced braces. Ok for now... ? + local argument = C( ( 1- P"," )^1 ) * space_pattern + local grammar = P{ "initialRule", + initialRule = space_pattern * Exp * -1, + Exp = lpeg.Ct(argument * comma * argument * comma * P"..." * space_pattern * comma *argument ) + } + + -- Converts very simple "samples at" values to "domain=A:B, samples=N" + -- + -- @param foreachString something like -5,-4,...,5 + -- @return a table where + -- [0] = domain min + -- [1] = domain max + -- [2] = samples + -- It returns nil if foreachString is no "very simple value of 'samples at'" + samplesAtToDomain = function(foreachString) + local matches = match(grammar,foreachString) + + if not matches or #matches ~= 3 then + return nil + else + local arg1 = matches[1] + local arg2 = matches[2] + local arg3 = matches[3] + arg1= pgfluamathparser.pgfmathparse(arg1) + arg2= pgfluamathparser.pgfmathparse(arg2) + arg3= pgfluamathparser.pgfmathparse(arg3) + + if not arg1 or not arg2 or not arg3 then + return nil + end + + if arg1 > arg2 then + return nil + end + + local domainMin = arg1 + local h = arg2-arg1 + local domainMax = arg3 + + -- round to the nearest integer (using +0.5, should be ok) + local samples = math.floor((domainMax - domainMin)/h + 0.5) + 1 + + return domainMin, domainMax, samples + end + end +end + +-- This is the code which attempts to transfer control from `\addplot expression' to LUA. +-- +-- If it succeeds, the entire plot stream and the entire survey phase has been done in LUA. +-- +-- generates TeX output '1' on success and '0' on failure +-- @param debugMode one of a couple of strings: "off", "verbose", or "compileerror" +function texAddplotExpressionCoordinateGenerator( + is3d, + xExpr, yExpr, zExpr, + sampleLine, + domainxmin, domainxmax, + domainymin, domainymax, + samplesx, samplesy, + variablex, variabley, + samplesAt, + debugMode +) + local plothandler = gca.currentPlotHandler + local coordoutputstream = SurveyCoordOutputStream.new(plothandler) + + if samplesAt and string.len(samplesAt) >0 then + -- "samples at" has higher priority than domain. + -- Use it! + + domainxmin, domainxmax, samplesx = samplesAtToDomain(samplesAt) + if not domainxmin then + -- FAILURE: could not convert "samples at". + -- Fall back to a TeX based survey. + log("log", "LUA survey failed: The value of 'samples at= " .. tostring(samplesAt) .. "' is unsupported by the LUA backend (currently, only 'samples at={a,b,...,c}' is supported).\n") + tex.sprint("0") + return + end + + else + domainxmin= pgftonumber(domainxmin) + domainxmax= pgftonumber(domainxmax) + samplesx= pgftonumber(samplesx) + end + + local expressions + local domainMin + local domainMax + local samples + local variableNames + + -- allow both, even if sampleLine=1. We may want to assign a dummy value to y. + variableNames = { variablex, variabley } + + if sampleLine==1 then + domainMin = { domainxmin } + domainMax = { domainxmax } + samples = { samplesx } + else + local domainymin = pgftonumber(domainymin) + local domainymax = pgftonumber(domainymax) + local samplesy = pgftonumber(samplesy) + + domainMin = { domainxmin, domainymin } + domainMax = { domainxmax, domainymax } + samples = { samplesx, samplesy } + end + if is3d then + expressions = {xExpr, yExpr, zExpr} + else + expressions = {xExpr, yExpr} + end + removeSurroundingBraces(expressions) + + local generator = AddplotExpressionCoordinateGenerator.new( + coordoutputstream, + expressions, + domainMin, domainMax, + samples, + variableNames) + + local messageOnFailure + local compileErrorOnFailure + if debugMode == "compileerror" then + compileErrorOnFailure = true + messageOnFailure = true + elseif debugMode == "off" or debugMode == "verbose" then + messageOnFailure = true + compileErrorOnFailure = false + elseif debugMode == "off and silent" then + messageOnFailure = false + compileErrorOnFailure = false + else + error("Got unknown debugMode = " .. debugMode ) + end + + local success + if compileErrorOnFailure then + success = generator:generateCoords() + else + local resultOfGenerator + success, resultOfGenerator = pcall(generator.generateCoords, generator) + if success then + -- AH: "pcall" returned 'true'. In this case, 'success' is the boolean returned by generator + success = resultOfGenerator + end + + if messageOnFailure and not success and type(resultOfGenerator) ~= "boolean" then + log("log", "LUA survey failed: " .. resultOfGenerator .. ". Use \\pgfplotsset{lua debug} to see more.\n") + end + end + + if not type(success) == 'boolean' then error("Illegal state: expected boolean result") end + + if success then + tex.sprint("1") + else + tex.sprint("0") + end +end + +-- Creates the default plot visualizer factory. It simply applies data scale trafos. +function defaultPlotVisualizerFactory(plothandler) + return PlotVisualizer.new(plothandler) +end + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/pgfplotsutil.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/pgfplotsutil.lua new file mode 100644 index 00000000000..b3b09fea688 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/pgfplotsutil.lua @@ -0,0 +1,139 @@ +local math=math +local string=string +local type=type +local tostring = tostring +local tonumber = tonumber +local setmetatable = setmetatable +local getmetatable = getmetatable +local print=print +local pairs = pairs +local table=table +local texio=texio + +do +local _ENV = pgfplots +--------------------------------------- +-- + +log=texio.write_nl + +local stringfind = string.find +local stringsub = string.sub +local tableinsert = table.insert + +-- Splits 'str' at delimiter and returns a table of strings +function stringsplit( str, delimiter ) + if not str or not delimiter then error("arguments must not be nil") end + local result = { } + local start = 1 + local findStart, findEnd = stringfind( str, delimiter, start ) + while findStart do + tableinsert( result, stringsub( str, start, findStart-1 ) ) + start = findEnd + 1 + findStart, findEnd = stringfind( str, delimiter, start ) + end + tableinsert( result, stringsub( str, start ) ) + return result +end + +function stringOrDefault(str, default) + if str == nil or type(str) == 'string' and string.len(str) == 0 then + return default + end + return tostring(str) +end + + +pgfplotsmath = {} + +function pgfplotsmath.isfinite(x) + if pgfplotsmath.isnan(x) or x == pgfplotsmath.infty or x == -pgfplotsmath.infty then + return false + end + return true +end + +local isnan = function(x) + return x ~= x +end + +pgfplotsmath.isnan = isnan + +local infty = 1/0 +pgfplotsmath.infty = infty + +local nan = math.sqrt(-1) +pgfplotsmath.nan = nan + +--------------------------------------- +-- + + +-- Creates and returns a new class object. +-- +-- Usage: +-- complexclass = newClass() +-- function complexclass:constructor() +-- self.re = 0 +-- self.im = 0 +-- end +-- +-- instance = complexclass.new() +-- +function newClass() + local result = {} + + -- we need this such that *instances* (which will have 'result' as meta table) + -- will "inherit" the class'es methods. + result.__index = result + local allocator= function (...) + local self = setmetatable({}, result) + self:constructor(...) + return self + end + result.new = allocator + return result +end + + + +-- Create a new class that inherits from a base class +-- +-- base = pgfplots.newClass() +-- function base:constructor() +-- self.variable= 'a' +-- end +-- +-- sub = pgfplots.newClassExtends(base) +-- function sub:constructor() +-- -- call super constructor. +-- -- it is ABSOLUTELY CRUCIAL to use <baseclass>.constructor here - not :constructor! +-- base.constructor(self) +-- end +-- +-- instance = base.new() +-- +-- instance2 = sub.new() +-- +-- @see newClass +function newClassExtends( baseClass ) + if not baseClass then error "baseClass must not be nil" end + + local new_class = newClass() + + -- The following is the key to implementing inheritance: + + -- The __index member of the new class's metatable references the + -- base class. This implies that all methods of the base class will + -- be exposed to the sub-class, and that the sub-class can override + -- any of these methods. + -- + local mt = {} -- getmetatable(new_class) + mt.__index = baseClass + setmetatable(new_class,mt) + + return new_class +end + + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/plothandler.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/plothandler.lua new file mode 100644 index 00000000000..e3fc089e25d --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/plothandler.lua @@ -0,0 +1,962 @@ +-- +-- This file contains parts of pgfplotscoordprocessing.code.tex and pgfplotsplothandlers.code.tex . +-- +-- It contains +-- +-- pgfplots.Axis +-- pgfplots.Coord +-- pgfplots.Plothandler +-- +-- and some related classes. + +local math=math +local pgfplotsmath = pgfplots.pgfplotsmath +local type=type +local tostring=tostring +local error=error +local table=table +local pgfmathparse = pgfplots.pgfluamathparser.pgfmathparse + +do +-- all globals will be read from/defined in pgfplots: +local _ENV = pgfplots +----------------------------------- + +local pgftonumber =pgfluamathfunctions.tonumber + +Coord = newClass() + +function Coord:constructor() + self.x = { nil, nil, nil } + self.unboundedDir = nil + self.meta= nil + self.metatransformed = nil -- assigned during vis phase only + self.unfiltered = nil + self.pgfXY = nil -- assigned during visphase only + return self +end + +function Coord:copy(other) + for i = 1,#other.x do self.x[i] = other.x[i] end + self.meta = other.meta + self.metatransformed = other.metatransformed + self.unfiltered = nil -- not needed +end + +function Coord:__tostring() + local result = '(' .. stringOrDefault(self.x[1], "--") .. + ',' .. stringOrDefault(self.x[2], "--") .. + ',' .. stringOrDefault(self.x[3], "--") .. + ') [' .. stringOrDefault(self.meta, "--") .. ']' + + if not self.x[1] and self.unfiltered then + result = result .. "(was " .. tostring(self.unfiltered) .. ")" + end + return result +end + +local stringToFunctionMap = pgfluamathfunctions.stringToFunctionMap + +-- a reference to a Coord which is returned by math expressions involving 'x', 'y', or 'z' +-- see surveystart() +local pseudoconstant_pt = nil +local function pseudoconstant_x() return pseudoconstant_pt.x[1] end +local function pseudoconstant_y() return pseudoconstant_pt.x[2] end +local function pseudoconstant_z() return pseudoconstant_pt.x[3] end +local function pseudoconstant_rawx() return pgftonumber(pseudoconstant_pt.unfiltered.x[1]) end +local function pseudoconstant_rawy() return pgftonumber(pseudoconstant_pt.unfiltered.x[2]) end +local function pseudoconstant_rawz() return pgftonumber(pseudoconstant_pt.unfiltered.x[3]) end +local function pseudoconstant_meta() return pseudoconstant_pt.meta end + +-- @return the old value +local function updatePseudoConstants(pt) + local old = pseudoconstant_pt + pseudoconstant_pt = pt + return old +end + +------------------------------------------------------- + +LinearMap = newClass() + +-- A map such that +-- [inMin,inMax] is mapped linearly to [outMin,outMax] +-- +function LinearMap:constructor(inMin, inMax, outMin, outMax) + if not inMin or not inMax or not outMin or not outMax then error("arguments must not be nil") end + if inMin == inMax then + self.map = function (x) return inMin end + else + if inMin > inMax then error("linear map received invalid input domain " .. tostring(inMin) .. ":" .. tostring(inMax)) end + self.offset = outMin - (outMax-outMin)*inMin/(inMax-inMin) + self.scale = (outMax-outMin)/(inMax-inMin) + end +end + +function LinearMap:map(x) + return x*self.scale + self.offset +end + +PointMetaMap = newClass() + +function PointMetaMap:constructor(inMin,inMax, warnForfilterDiscards) + if not inMin or not inMax or warnForfilterDiscards == nil then error("arguments must not be nil") end + self._mapper = LinearMap.new(inMin,inMax, 0, 1000) + self.warnForfilterDiscards = warnForfilterDiscards +end + +function PointMetaMap:map(meta) + if pgfplotsmath.isfinite(meta) then + local result = self._mapper:map(meta) + result = math.max(0, result) + result = math.min(1000, result) + return result + else + if self.warnForfilterDiscards then + log("The per point meta data '" .. tostring(meta) .. " (and probably others as well) is unbounded - using the minimum value instead.\n") + self.warnForfilterDiscards=false + end + return 0 + end +end + + + +------------------------------------------------------- + +-- Abstract base class of all plot handlers. +-- It offers basic functionality for the survey phase. +Plothandler = newClass() + +-- @param name the plot handler's name (a string) +-- @param axis the parent axis +-- @param pointmetainputhandler an instance of PointMetaHandler or nil if there is none +function Plothandler:constructor(name, axis, pointmetainputhandler) + if not name or not axis then + error("arguments must not be nil") + end + self.axis = axis + self.config = PlothandlerConfig.new() + self.name = name + self.coordindex = 0 + self.metamin = math.huge + self.metamax = -math.huge + self.autocomputeMetaMin = true + self.autocomputeMetaMax = true + self.coords = {} + self.pointmetainputhandler = pointmetainputhandler + self.pointmetamap = nil -- will be set later + self.filteredCoordsAway = false + self.plotHasJumps = false + -- will be set before the visualization phase starts. At least. + self.plotIs3d = false + return self +end + +function Plothandler:__tostring() + return 'plot handler ' .. self.name +end + +-- @see \pgfplotsplothandlersurveybeforesetpointmeta +function Plothandler:surveyBeforeSetPointMeta() +end + +-- @see \pgfplotsplothandlersurveyaftersetpointmeta +function Plothandler:surveyAfterSetPointMeta() +end + +-- PRIVATE +-- +-- appends a fully surveyed point +function Plothandler:addSurveyedPoint(pt) + table.insert(self.coords, pt) + -- log("addSurveyedPoint(" .. tostring(pt) .. ") ...\n") +end + +-- PRIVATE +-- +-- assigns the point meta value by means of the PointMetaHandler +function Plothandler:setperpointmeta(pt) + if pt.meta == nil and self.pointmetainputhandler ~= nil then + self.pointmetainputhandler:assign(pt) + end +end + +-- PRIVATE +-- +-- updates point meta limits +function Plothandler:setperpointmetalimits(pt) + if pt.meta ~= nil then + if not type(pt.meta) == 'number' then error("got unparsed input "..tostring(pt)) end + if self.autocomputeMetaMin then + self.metamin = math.min(self.metamin, pt.meta ) + end + + if self.autocomputeMetaMax then + self.metamax = math.max(self.metamax, pt.meta ) + end + end +end + +-- @see \pgfplotsplothandlersurveystart +function Plothandler:surveystart() + stringToFunctionMap["x"] = pseudoconstant_x + stringToFunctionMap["y"] = pseudoconstant_y + stringToFunctionMap["z"] = pseudoconstant_z + stringToFunctionMap["rawx"] = pseudoconstant_rawx + stringToFunctionMap["rawy"] = pseudoconstant_rawy + stringToFunctionMap["rawz"] = pseudoconstant_rawz + stringToFunctionMap["meta"] = pseudoconstant_meta +end + +-- @see \pgfplotsplothandlersurveyend +-- returns executable TeX code to communicate return values. +function Plothandler:surveyend() + -- empty by default. + return "" +end + +-- @see \pgfplotsplothandlersurveypoint +function Plothandler:surveypoint(pt) + updatePseudoConstants(nil) + + local updateLimits = self.config.updateLimits + local current = self.axis:parsecoordinate(pt, self.config.filterExpressionByDir) + + -- this here defines the math functions for x, y, or z. + -- FIXME: are there any hidden callers which rely on these constants in parsecoordinate!? + updatePseudoConstants(current) + + if current.x[1] ~= nil then + current = self.axis:preparecoordinate(current) + if updateLimits then + self.axis:updatelimitsforcoordinate(current) + end + end + self.axis:datapointsurveyed(current, self) + + self.coordindex = self.coordindex + 1; +end + +-- PUBLIC +-- +-- @return a string containing all surveyed coordinates in the format which is accepted \pgfplotsaxisdeserializedatapointfrom +function Plothandler:surveyedCoordsToPgfplots(axis) + return self:getCoordsInTeXFormat(axis, self.coords) +end + +-- PUBLIC +-- +-- @return a string containing all coordinates in the format which is accepted \pgfplotsaxisdeserializedatapointfrom +-- @param extraSerializer a function which takes an instance of Coord and returns a string. can be nil. +function Plothandler:getCoordsInTeXFormat(axis, coords, extraSerializer) + if not axis then error("arguments must not be nil") end + local result = {} + for i = 1,#coords,1 do + local pt = coords[i] + local ptstr = self:serializeCoordToPgfplots(pt) + local axisPrivate = axis:serializeCoordToPgfplotsPrivate(pt) + if extraSerializer then + axisPrivate = extraSerializer(pt) .. "{" .. axisPrivate .. "}" + end + local serialized = "{" .. axisPrivate .. ";" .. ptstr .. "}" + table.insert(result, serialized) + end + return table.concat(result) +end + +-- PRIVATE +-- +-- does the same as \pgfplotsplothandlerserializepointto +function Plothandler:serializeCoordToPgfplots(pt) + return + toTeXstring(pt.x[1]) .. "," .. + toTeXstring(pt.x[2]) .. "," .. + toTeXstring(pt.x[3]) +end + +function Plothandler:visualizationPhaseInit() + if self.pointmetainputhandler ~=nil then + local rangeMin + local rangeMax + if self.config.pointmetarel == PointMetaRel.axiswide then + rangeMin = self.axis.axiswidemetamin + rangeMax = self.axis.axiswidemetamax + else + rangeMin = self.metamin + rangeMax = self.metamax + end + self.pointmetamap = PointMetaMap.new(rangeMin, rangeMax, self.config.warnForfilterDiscards) + end +end + +-- PRECONDITION: visualizationPhaseInit() has been called some time before. +function Plothandler:visualizationTransformMeta(meta) + if meta == nil then + log("could not access the 'point meta' (used for example by scatter plots and color maps). Maybe you need to add '\\addplot[point meta=y]' or something like that?\n") + return 1 + else + return self.pointmetamap:map(meta) + end +end + +-- Modifies coords inplace. +-- @return nothing. +-- see \pgfplots@apply@zbuffer@sort@coordinates +function Plothandler:sortCoordinatesByViewDepth() + local coords = self.coords + + local axis = self.axis + local viewdir = axis.viewdir + + -- Step 1: compute view depth for every coordinate + local getVertexDepth = axis.getVertexDepth + for i=1,#coords do + local vertexDepth = getVertexDepth(axis,coords[i]) + coords[i].vertexDepth = vertexDepth + end + + -- Step 2: sort (inplace) + local comparator = function(ptA, ptB) + return ptA.vertexDepth > ptB.vertexDepth + end + table.sort(coords, comparator) + + -- Step 3: cleanup: do not leave 'vertexDepth' inside of the array + for i=1,#coords do + coords[i].vertexDepth = nil + end +end + +------------------------------------------------------- +-- Generic plot handler: one which has the default survey phase +-- It is actually the same as Plothandler... + +GenericPlothandler = newClassExtends(Plothandler) + +function GenericPlothandler:constructor(name, axis, pointmetainputhandler) + Plothandler.constructor(self,name, axis, pointmetainputhandler) +end + + +------------------------------------------------------- + +UnboundedCoords = { discard="d", jump="j" } + +PointMetaRel = { axiswide = 0, perplot =1 } + + +-- contains static configuration entities. +PlothandlerConfig = newClass() + +function PlothandlerConfig:constructor() + self.unboundedCoords = UnboundedCoords.discard + self.warnForfilterDiscards=true + self.pointmetarel = PointMetaRel.axiswide + self.updateLimits = true + self.filterExpressionByDir = {"", "", ""} + return self +end + +------------------------------------------------------- +-- a PlotVisualizer takes an input Plothandler and visualizes its results. +-- +-- "Visualize" can mean +-- * apply the plot handler's default visualization phase +-- * visualize just plot marks at each of the collected coordinates +-- * visualize just error bars at each collected coordinate +-- * ... +-- + +-- this class offers basic visualization support. "Basic" means that it will merely transform and finalize input coordinates. +PlotVisualizer = newClass() +-- @param sourcePlotHandler an instance of Plothandler +function PlotVisualizer:constructor(sourcePlotHandler) + if not sourcePlotHandler then error("arguments must not be nil") end + self.axis = sourcePlotHandler.axis + self.sourcePlotHandler=sourcePlotHandler + if sourcePlotHandler.plotIs3d then + self.qpointxyz = self.axis.qpointxyz + else + self.qpointxyz = self.axis.qpointxy + end +end + +-- Visualizes the results. +-- +-- @return any results. The format of the results is currently a list of Coord, but I am unsure of whether it will stay this way. +-- +-- Note that a PlotVisualizer does _not_ modify self.sourcePlotHandler.coords +function PlotVisualizer:getVisualizationOutput() + local result = {} + local coords = self.sourcePlotHandler.coords + + -- standard z buffer choices (not mesh + sort) is currently handled in TeX + -- as well as other preparations + + -- FIXME : stacked plots? + -- FIXME : error bars? + + for i = 1,#coords do + local result_i + local result_i = Coord.new() + result_i:copy(coords[i]) + + if result_i.x[1] ~= nil then + self:visphasegetpoint(result_i) + else + self:notifyJump(result_i) + end + + result[i] = result_i + end + + return result +end + +-- PROTECTED +-- resembles \pgfplotsplothandlervisualizejump -- or at least that part which can be done in LUA. +-- It does not visualize anything, but it can be used to modify the coordinate +function PlotVisualizer:notifyJump(pt) + -- do nothing. +end + +function PlotVisualizer:visphasegetpoint(pt) + pt.untransformed = {} + for j = 1,#pt.x do + pt.untransformed[j] = pt.x[j] + end + + self.axis:visphasetransformcoordinate(pt) + + -- FIXME : prepare data point (only for stacked) + + pt.pgfXY = self.qpointxyz(pt.x) +end + + + +------------------------------------------------------- + +-- An abstract base class for a handler of point meta. +-- @see \pgfplotsdeclarepointmetasource +PointMetaHandler = newClass() + +-- @param isSymbolic +-- expands to either '1' or '0' +-- A numeric source will be processed numerically in float +-- arithmetics. Thus, the output of the @assign routine should be +-- a macro \pgfplots@current@point@meta in float format. +-- +-- The output of a numeric point meta source will result in meta +-- limit updates and the final map to [0,1000] will be +-- initialised automatically. +-- +-- A symbolic input routine won't be processed. +-- Default is '0' +-- +-- @param explicitInput +-- expands to either +-- '1' or '0'. In case '1', it expects explicit input from the +-- coordinate input routines. For example, 'plot file' will look for +-- further input after the x,y,z coordinates. +-- Default is '0' +-- +function PointMetaHandler:constructor(isSymbolic, explicitInput) + self.isSymbolic =isSymbolic + self.explicitInput = explicitInput + return self +end + +-- During the survey phase, this macro is expected to assign +-- \pgfplots@current@point@meta +-- if it is a numeric input method, it should return a +-- floating point number. +-- It is allowed to return an empty string to say "there is no point +-- meta". +-- PRECONDITION for '@assign': +-- - the coordinate input method has already assigned its +-- '\pgfplots@current@point@meta' (probably as raw input string). +-- - the other input coordinates are already read. +-- POSTCONDITION for '@assign': +-- - \pgfplots@current@point@meta is ready for use: +-- - EITHER a parsed floating point number +-- - OR an empty string, +-- - OR a symbolic string (if the issymbolic boolean is true) +-- The default implementation is +-- \let\pgfplots@current@point@meta=\pgfutil@empty +-- +function PointMetaHandler.assign(pt) + error("This instance of PointMetaHandler is not implemented") +end + + +-- A PointMetaHandler which merely acquires values of either x,y, or z. +CoordAssignmentPointMetaHandler = newClassExtends( PointMetaHandler ) +function CoordAssignmentPointMetaHandler:constructor(dir) + PointMetaHandler.constructor(self, false,false) + if not dir then error "nil argument for 'dir' is unsupported." end + self.dir=dir +end + +function CoordAssignmentPointMetaHandler:assign(pt) + if not pt then error("arguments must not be nil") end + pt.meta = pgftonumber(pt.x[self.dir]) +end + +XcoordAssignmentPointMetaHandler = CoordAssignmentPointMetaHandler.new(1) +YcoordAssignmentPointMetaHandler = CoordAssignmentPointMetaHandler.new(2) +ZcoordAssignmentPointMetaHandler = CoordAssignmentPointMetaHandler.new(3) + +-- A class of PointMetaHandler which takes the 'Coord.meta' as input +ExplicitPointMetaHandler = newClassExtends( PointMetaHandler ) +function ExplicitPointMetaHandler:constructor() + PointMetaHandler.constructor(self, false,true) +end + +function ExplicitPointMetaHandler:assign(pt) + if pt.unfiltered ~= nil and pt.unfiltered.meta ~= nil then + pt.meta = pgftonumber(pt.unfiltered.meta) + end +end + +-- a point meta handler which evaluates a math expression. +-- ATTENTION: the expression cannot depend on TeX macro values +ExpressionPointMetaHandler = newClassExtends( PointMetaHandler ) + +-- @param expression an expression. It can rely on functions which are only available in plot context (in plot expression, x and y are typically defined) +function ExpressionPointMetaHandler:constructor(expression) + PointMetaHandler.constructor(self, false,false) + self.expression = expression +end + +function ExpressionPointMetaHandler:assign(pt) + pt.meta = pgfmathparse(self.expression) + if not pt.meta then + error("point meta=" .. self.expression .. ": expression has been rejected.") + end +end + + +------------------------------------------------------- + +DatascaleTrafo = newClass() + +function DatascaleTrafo:constructor(exponent, shift) + self.exponent=exponent + self.shift=shift + self.scale = math.pow(10, exponent) +end + +function DatascaleTrafo:map(x) + return self.scale * x - self.shift +end + + +------------------------------------------------------- + +-- An axis. +Axis = newClass() + +function Axis:constructor() + self.is3d = false + self.clipLimits = true + self.autocomputeAllLimits = true -- FIXME : redundant!? + self.autocomputeMin = { true, true, true } + self.autocomputeMax = { true, true, true } + self.isLinear = { true, true, true } + self.min = { math.huge, math.huge, math.huge } + self.max = { -math.huge, -math.huge, -math.huge } + self.datamin = { math.huge, math.huge, math.huge } + self.datamax = { -math.huge, -math.huge, -math.huge } + self.axiswidemetamin = { math.huge, math.huge } + self.axiswidemetamax = { -math.huge, -math.huge } + -- will be populated by the TeX code: + self.plothandlers = {} + -- needed during visualization phase: + self.datascaleTrafo={} + -- needed during visualization phase: a vector of 3 elements, each is a vector of 2 elements. + -- self.unitvectors[1] is (\pgf@xx,\pgf@xy) + self.unitvectors={} + -- needed during visualization phase -- but only for 3d! + self.viewdir = {} + return self +end + +function Axis:getVertexDepth(pt) + local vertexDepth = 0 + local vertex = pt.x + local viewdir = self.viewdir + if vertex[1] == nil then + -- an empty coordinate. Get rid of it. + return 0 + end + + if #vertex ~=3 then + error("Cannot compute vertex depth of " .. tostring(pt) .. ": expected a 3d point but got " .. tostring(#vertex)) + end + if not viewdir or #viewdir~=3 then error("got unexpected view dir " ..tostring(viewdir) ) end + + for k = 1,3 do + local component = vertex[k] + vertexDepth = vertexDepth + component*viewdir[k] + end + + return vertexDepth +end + +function Axis:setunitvectors(unitvectors) + if not unitvectors or #unitvectors ~= 3 then error("got illegal arguments " .. tostring(unitvectors)) end + self.unitvectors = unitvectors + + local pgfxx = unitvectors[1][1] + local pgfxy = unitvectors[1][2] + local pgfyx = unitvectors[2][1] + local pgfyy = unitvectors[2][2] + local pgfzx = unitvectors[3][1] + local pgfzy = unitvectors[3][2] + + self.qpointxyz = function(xyz) + local result = {} + result[1] = xyz[1] * pgfxx + xyz[2] * pgfyx + xyz[3] * pgfzx + result[2] = xyz[1] * pgfxy + xyz[2] * pgfyy + xyz[3] * pgfzy + return result + end + + if pgfxy==0 and pgfyx ==0 then + self.qpointxy = function(xy) + local result = {} + result[1] = xy[1] * pgfxx + result[2] = xy[2] * pgfyy + return result + end + else + self.qpointxy = function(xyz) + local result = {} + result[1] = xyz[1] * pgfxx + xyz[2] * pgfyx + result[2] = xyz[1] * pgfxy + xyz[2] * pgfyy + return result + end + end +end + +-- PRIVATE +-- +-- applies user transformations and logs +-- +-- @see \pgfplots@prepared@xcoord +function Axis:preparecoord(dir, value) + -- FIXME : user trafos, logs (switches off LUA backend) + return value +end + +function Axis:filtercoord(dir, ptCoords, filterExpressionByDir) + if not dir or not ptCoords or not filterExpressionByDir then error("Arguments must not be nil") end + local result = ptCoords.x[dir] + if filterExpressionByDir[dir]:len() > 0 then + + for j = 1,#ptCoords.x do + ptCoords.x[j] = pgftonumber(ptCoords.x[j]) + end + local old = updatePseudoConstants(ptCoords) + + result = pgfmathparse(filterExpressionByDir[dir]) + + updatePseudoConstants(old) + end + return result +end + +-- PRIVATE +-- @see \pgfplotsaxisserializedatapoint@private +function Axis:serializeCoordToPgfplotsPrivate(pt) + return toTeXstring(pt.meta) +end + + +-- PRIVATE +-- +function Axis:validatecoord(dir, point) + if not dir or not point then error("arguments must not be nil") end + local result = pgftonumber(point.x[dir]) + + if result == nil then + result = nil + elseif result == pgfplotsmath.infty or result == -pgfplotsmath.infty or pgfplotsmath.isnan(result) then + result = nil + point.unboundedDir = dir + end + + point.x[dir] = result +end + +-- PRIVATE +-- +-- @see \pgfplotsaxisparsecoordinate +function Axis:parsecoordinate(pt, filterExpressionByDir) + -- replace empty strings by 'nil': + for i = 1,3 do + pt.x[i] = stringOrDefault(pt.x[i], nil) + end + pt.meta = stringOrDefault(pt.meta) + + if pt.x[3] ~= nil then + self.is3d = true + end + + local result = Coord.new() + + local unfiltered = Coord.new() + unfiltered.x = {} + unfiltered.meta = pt.meta + for i = 1,3 do + unfiltered.x[i] = pt.x[i] + end + result.unfiltered = unfiltered + + -- copy values such that filtercoord can access them in the same order as the TeX impl. + for i = 1,self:loopMax() do + result.x[i] = pt.x[i] + end + + -- FIXME : self:prefilter(pt[i]) + for i = 1,self:loopMax() do + result.x[i] = self:preparecoord(i, pt.x[i]) + result.x[i] = self:filtercoord(i, result, filterExpressionByDir) + end + -- FIXME : result.x = self:xyzfilter(result.x) + + for i = 1,self:loopMax() do + self:validatecoord(i, result) + end + + local resultIsBounded = true + for i = 1,self:loopMax() do + if result.x[i] == nil then + resultIsBounded = false + end + end + + if not resultIsBounded then + result.x = { nil, nil, nil} + end + + return result +end + +-- PROTECTED +-- +-- @see \pgfplotsaxispreparecoordinate +function Axis:preparecoordinate(pt) + -- the default "preparation" is to return it as is (no number parsing) + -- + -- FIXME : data cs! Stacking! + return pt +end + +-- PRIVATE +-- +-- returns either 2 if this axis is 2d or 3 otherwise +-- +-- FIXME : shouldn't this depend on the current plot handler!? +function Axis:loopMax() + if self.is3d then return 3 else return 2 end +end + +-- PRIVATE: +-- +-- updates axis limits for pt +-- @param pt an instance of Coord +function Axis:updatelimitsforcoordinate(pt) + local isClipped = false + if self.clipLimits then + for i = 1,self:loopMax(),1 do + if not self.autocomputeMin[i] then + isClipped = isClipped or pt.x[i] < self.min[i] + end + if not self.autocomputeMax[i] then + isClipped = isClipped or pt.x[i] > self.max[i] + end + end + end + + if not isClipped then + for i = 1,self:loopMax(),1 do + if self.autocomputeMin[i] then + self.min[i] = math.min(pt.x[i], self.min[i]) + end + + if self.autocomputeMax[i] then + self.max[i] = math.max(pt.x[i], self.max[i]) + end + end + end + + -- Compute data range: + if self.autocomputeAllLimits then + -- the data range will be acquired simply from the axis + -- range, see below! + else + for i = 1,self:loopMax(),1 do + self.datamin[i] = math.min(pt.x[i], self.min[i]) + self.datamax[i] = math.max(pt.x[i], self.max[i]) + end + end +end + +-- PRIVATE +-- +-- unfinished, see its fixmes +function Axis:addVisualizationDependencies(pt) + -- FIXME : 'visualization depends on' + -- FIXME : 'execute for finished point' + return pt +end + +-- PROTECTED +-- +-- indicates that a data point has been surveyed by the axis and that it can be consumed +function Axis:datapointsurveyed(pt, plothandler) + if not pt or not plothandler then error("arguments must not be nil") end + if pt.x[1] ~= nil then + plothandler:surveyBeforeSetPointMeta() + plothandler:setperpointmeta(pt) + plothandler:setperpointmetalimits(pt) + plothandler:surveyAfterSetPointMeta() + + -- FIXME : error bars + -- FIXME: collect first plot as tick + + -- note that that TeX code would also remember the first/last coordinate in a stream. + -- This is unnecessary here. + + local serialized = self:addVisualizationDependencies(pt) + plothandler:addSurveyedPoint(serialized) + else + -- COORDINATE HAS BEEN FILTERED AWAY + if plothandler.config.unboundedCoords == UnboundedCoords.discard then + plothandler.filteredCoordsAway = true + if plothandler.config.warnForfilterDiscards then + local reason + if pt.unboundedDir == nil then + reason = "of a coordinate filter." + else + reason = "it is unbounding (in " .. tostring(pt.unboundedDir) .. ")." + end + log("NOTE: coordinate " .. tostring(pt) .. " has been dropped because " .. reason .. "\n") + end + elseif plothandler.config.unboundedCoords == UnboundedCoords.jump then + if pt.unboundedDir == nil then + plothandler.filteredCoordsAway = true + if plothandler.config.warnForfilterDiscards then + local reason = "of a coordinate filter." + log("NOTE: coordinate " .. tostring(pt) .. " has been dropped because " .. reason .. "\n") + end + else + plothandler.plotHasJumps = true + + local serialized = self:addVisualizationDependencies(pt) + plothandler:addSurveyedPoint(serialized) + end + end + end + + -- note that the TeX variant would increase the coord index here. + -- We do it it surveypoint. +end + +local function axisLimitToTeXString(name, value) + if value == math.huge or value == -math.huge then + return "" + end + return "\\gdef" .. name .. "{" .. toTeXstring(value) .. "}" +end + +local function toTeXxyzCoord(namePrefix, pt ) + local x = toTeXstring(pt.x[1]) + local y = toTeXstring(pt.x[2]) + local z = toTeXstring(pt.x[3]) + return + "\\gdef" .. namePrefix .. "@x{" .. x .. "}" .. + "\\gdef" .. namePrefix .. "@y{" .. y .. "}" .. + "\\gdef" .. namePrefix .. "@z{" .. z .. "}"; +end + +local function findFirstValidCoord(coords) + for i=1,#coords do + local pt = coords[i] + if pt.x[1] ~=nil then + return pt + end + end + return nil +end + +local function findLastValidCoord(coords) + for i=#coords,1,-1 do + local pt = coords[i] + if pt.x[1] ~=nil then + return pt + end + end + return nil +end + +-- PUBLIC +-- +-- @return a set of (private) key-value pairs such that the TeX code of pgfplots can +-- access survey results of the provided plot handler +-- +-- @param plothandler an instance of Plothandler +function Axis:surveyToPgfplots(plothandler) + local plothandlerResult = plothandler:surveyend() + local firstCoord = findFirstValidCoord(plothandler.coords) or Coord.new() + local lastCoord = findLastValidCoord(plothandler.coords) or Coord.new() + + local result = + plothandlerResult .. + toTeXxyzCoord("\\pgfplots@currentplot@firstcoord", firstCoord) .. + toTeXxyzCoord("\\pgfplots@currentplot@lastcoord", lastCoord) .. + axisLimitToTeXString("\\pgfplots@metamin", plothandler.metamin) .. + axisLimitToTeXString("\\pgfplots@metamax", plothandler.metamax) .. + "\\c@pgfplots@coordindex=" .. tostring(plothandler.coordindex) .. " " .. + axisLimitToTeXString("\\pgfplots@xmin", self.min[1]) .. + axisLimitToTeXString("\\pgfplots@ymin", self.min[2]) .. + axisLimitToTeXString("\\pgfplots@xmax", self.max[1]) .. + axisLimitToTeXString("\\pgfplots@ymax", self.max[2]); + if self.is3d then + result = result .. + axisLimitToTeXString("\\pgfplots@zmin", self.min[3]) .. + axisLimitToTeXString("\\pgfplots@zmax", self.max[3]) .. + "\\global\\pgfplots@threedimtrue "; + end + if plothandler.plotHasJumps then + result = result .. + "\\def\\pgfplotsaxisplothasjumps{1}" + else + result = result .. + "\\def\\pgfplotsaxisplothasjumps{0}" + end + if plothandler.filteredCoordsAway then + result = result .. + "\\def\\pgfplotsaxisfilteredcoordsaway{1}" + else + result = result .. + "\\def\\pgfplotsaxisfilteredcoordsaway{0}" + end + + return result +end + +-- resembles \pgfplotsaxisvisphasetransformcoordinate +function Axis:visphasetransformcoordinate(pt) + for i = 1,#pt.x do + pt.x[i] = self.datascaleTrafo[i]:map( pt.x[i] ) + end +end + +-- will be set by TeX code (in \begin{axis}) +gca = nil + + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/statistics.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/statistics.lua new file mode 100644 index 00000000000..57350254b30 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/statistics.lua @@ -0,0 +1,400 @@ +-- This file has dependencies to BOTH, the TeX part of pgfplots and the LUA part. +-- It is the only LUA component with this property. +-- +-- Its purpose is to encapsulate the communication between TeX and LUA in a central LUA file + +local pgfplotsmath = pgfplots.pgfplotsmath +local error=error +local table=table +local string=string +local tostring=tostring +local type=type +local io=io +local mathfloor=math.floor +local mathceil=math.ceil +local pgfmathparse = pgfplots.pgfluamathparser.pgfmathparse + +do +-- all globals will be read from/defined in pgfplots: +local _ENV = pgfplots + +local pgftonumber =pgfluamathfunctions.tonumber + +function texBoxPlotSurveyPoint(data) + gca.currentPlotHandler:semiSurveyedValue(data) +end + +------------------------------------------------------- + +PercentileEstimator = newClass() + +function PercentileEstimator:constructor() +end + +function PercentileEstimator:getIndex(data, i) + local idx = i + if idx < 1 then idx = 1 end + if idx > #data then idx = #data end + + local result = data[idx] + if not result then + error("Box plot percentile estimator '" .. tostring(self) .." accessed illegal array index " .. tostring(idx) .. " in array of length " .. tostring(#data)) + end + return result +end + + +-- @param percentile the requested percentile. Use 0.5 for the median, 0.25 for the first quartile, 0.95 for the 95% percentile etc. +function PercentileEstimator:getValue(percentile, data) + error("Use implementation of PercentileEstimator, not interface") +end + +-- LegacyPgfplotsPercentileEstimator is a minimally repaired percentile estimator as it has been shipped with pgfplots.10 . +-- I decided to mark it as deprecated because it is non-standard and not comparable with other programs. +LegacyPgfplotsPercentileEstimator = newClassExtends(PercentileEstimator) +function LegacyPgfplotsPercentileEstimator:constructor() +end +function LegacyPgfplotsPercentileEstimator:__tostring() + return "estimator=legacy"; +end +function LegacyPgfplotsPercentileEstimator:getValue(percentile, data) + if not percentile or not data then error("Arguments must not be nil") end + local numCoords = #data + local h = numCoords * percentile + + local offset_low = mathfloor(h) + local isInt = ( h==offset_low ) + + local offset_high = offset_low+1 + + local x_low = self:getIndex(data, offset_low) + local x_up = self:getIndex(data, offset_high) + local res = x_low + if not isInt then + res = 0.5 * (res + x_up) + end + return res +end + +-- LegacyBadPgfplotsPercentileEstimator is _the_ percentile estimator as it has been shipped with pgfplots 1.10. +-- It has bugs and is non-standard. Don't use it. +LegacyBadPgfplotsPercentileEstimator = newClassExtends(PercentileEstimator) +function LegacyBadPgfplotsPercentileEstimator:constructor() +end +function LegacyBadPgfplotsPercentileEstimator:__tostring() + return "estimator=legacy*"; +end +function LegacyBadPgfplotsPercentileEstimator:getValue(percentile, data) + if not percentile or not data then error("Arguments must not be nil") end + local numCoords = #data + local h = (numCoords-1) * percentile + + local offset_low = mathfloor(h) + local isInt = ( h==offset_low ) + + local offset_high = offset_low+1 + + local x_low = self:getIndex(data, offset_low+1) + local x_up = self:getIndex(data, offset_high+1) + local res = x_low + if not isInt then + res = 0.5 * (res + x_up) + end + return res +end +---------------- + +ParameterizedPercentileEstimator = newClassExtends(PercentileEstimator) + +function ParameterizedPercentileEstimator:__tostring() + return "estimator=" .. tostring(self.typeFlag) ; +end + +function ParameterizedPercentileEstimator:constructor( typeFlag ) + -- http://en.wikipedia.org/wiki/Quantile + self.typeFlag = typeFlag + + local getIndex = self.getIndex + + local stdLookup = function(data, h ) + local h_low = mathfloor(h) + local x_low = getIndex(self, data, h_low ) + local x_up = getIndex(self, data, h_low +1 ) + return x_low + (h - h_low) * (x_up - x_low) + end + + if typeFlag == 1 then + -- R1 + self.getValue = function(self, percentile, data) + local h= #data * percentile + return getIndex(self, data, mathceil(h) ) + end + elseif typeFlag == 2 then + -- R2 + self.getValue = function(self, percentile, data) + local h= #data * percentile + 0.5 + return 0.5*(getIndex(self, data, mathceil(h-0.5)) + getIndex(self, data, mathfloor(h+0.5) ) ) + end + elseif typeFlag == 3 then + -- R3 + self.getValue = function(self, percentile, data) + local h= #data * percentile + return getIndex(self, data, pgfluamathfunctions.round(h) ) + end + elseif typeFlag == 4 then + -- R4 + self.getValue = function(self, percentile, data) + local h= #data * percentile + return stdLookup(data,h) + end + elseif typeFlag == 5 then + -- R5 + self.getValue = function(self, percentile, data) + local h= #data * percentile + 0.5 + return stdLookup(data,h) + end + elseif typeFlag == 6 then + -- R6 + self.getValue = function(self, percentile, data) + local h= (#data +1) * percentile + return stdLookup(data,h) + end + elseif typeFlag == 7 then + -- R7 (Excel) + self.getValue = function(self, percentile, data) + local h= (#data -1) * percentile + 1 + return stdLookup(data,h) + end + elseif typeFlag == 8 then + -- R8 + self.getValue = function(self, percentile, data) + local h= (#data + 1/3) * percentile + 1/3 + return stdLookup(data,h) + end + elseif typeFlag == 9 then + -- R9 + self.getValue = function(self, percentile, data) + local h= (#data + 1/4) * percentile + 3/8 + return stdLookup(data,h) + end + else + error("Got unsupported type '" .. tostring(typeFlag) .. "'") + end +end + + +getPercentileEstimator = function(estimatorName) + if estimatorName == "legacy" then + return LegacyPgfplotsPercentileEstimator.new() + elseif estimatorName == "legacy*" then + return LegacyBadPgfplotsPercentileEstimator.new() + elseif estimatorName == "R1" then + return ParameterizedPercentileEstimator.new(1) + elseif estimatorName == "R2" then + return ParameterizedPercentileEstimator.new(2) + elseif estimatorName == "R3" then + return ParameterizedPercentileEstimator.new(3) + elseif estimatorName == "R4" then + return ParameterizedPercentileEstimator.new(4) + elseif estimatorName == "R5" then + return ParameterizedPercentileEstimator.new(5) + elseif estimatorName == "R6" then + return ParameterizedPercentileEstimator.new(6) + elseif estimatorName == "R7" then + return ParameterizedPercentileEstimator.new(7) + elseif estimatorName == "R8" then + return ParameterizedPercentileEstimator.new(8) + elseif estimatorName == "R9" then + return ParameterizedPercentileEstimator.new(9) + end + + error("Unknown estimator '" .. tostring(estimatorName) .. "'") +end + +BoxPlotRequest = newClass() + +-- @param lowerQuartialPercent: typically 0.25 +-- @param upperQuartialPercent: typically 0.75 +-- @param whiskerRange: typically 1.5 +-- @param estimator: an instance of PercentileEstimator +-- @param morePercentiles: either nil or an array of percentiles to compute +function BoxPlotRequest:constructor(lowerQuartialPercent, upperQuartialPercent, whiskerRange, estimator, morePercentiles) + if not lowerQuartialPercent or not upperQuartialPercent or not whiskerRange or not estimator then error("Arguments must not be nil") end + self.lowerQuartialPercent = pgftonumber(lowerQuartialPercent) + self.upperQuartialPercent = pgftonumber(upperQuartialPercent) + self.whiskerRange = pgftonumber(whiskerRange) + self.estimator = estimator + if not morePercentiles then + self.morePercentiles = {} + else + self.morePercentiles = morePercentiles + end +end + +------------------------------------------------------- + +BoxPlotResponse = newClass() + +function BoxPlotResponse:constructor() + self.lowerWhisker = nil + self.lowerQuartile = nil + self.median = nil + self.upperQuartile = nil + self.upperWhisker = nil + self.average = nil + self.morePercentiles = {} + self.outliers = {} +end + +-- @param boxPlotRequest an instance of BoxPlotRequest +-- @param data an indexed array with float values +-- @return an instance of BoxPlotResponse +function boxPlotCompute(boxPlotRequest, data) + if not boxPlotRequest or not data then error("Arguments must not be nil") end + + for i = 1,#data do + local data_i = data[i] + if data_i == nil or type(data_i) ~= "number" then + error("Illegal input array at index " .. tostring(i) .. ": " .. tostring(data_i)) + end + end + + table.sort(data) + + local sum = 0 + for i = 1,#data do + sum = sum + data[i] + end + + local numCoords = #data + + local lowerWhisker + local lowerQuartile = boxPlotRequest.estimator:getValue(boxPlotRequest.lowerQuartialPercent, data) + local median = boxPlotRequest.estimator:getValue(0.5, data) + local upperQuartile = boxPlotRequest.estimator:getValue(boxPlotRequest.upperQuartialPercent, data) + + local morePercentileValues = {} + for i = 1,#boxPlotRequest.morePercentiles do + morePercentileValues[i] = boxPlotRequest.estimator:getValue(boxPlotRequest.morePercentiles[i], data) + end + + local upperWhisker + local average = sum / numCoords + + local whiskerRange = boxPlotRequest.whiskerRange + local whiskerWidth = whiskerRange*(upperQuartile - lowerQuartile) + local upperWhiskerValue = upperQuartile + whiskerWidth + local lowerWhiskerValue = lowerQuartile - whiskerWidth + + local outliers = {} + for i = 1,numCoords do + local current = data[i] + if current < lowerWhiskerValue then + table.insert(outliers, current) + else + lowerWhisker = current + break + end + end + + for i = numCoords,1,-1 do + local current = data[i] + if upperWhiskerValue < current then + table.insert(outliers, current) + else + upperWhisker = current + break + end + end + + local result = BoxPlotResponse.new() + result.lowerWhisker = lowerWhisker + result.lowerQuartile = lowerQuartile + result.median = median + result.upperQuartile = upperQuartile + result.upperWhisker = upperWhisker + result.average = average + result.morePercentiles = morePercentileValues + result.outliers = outliers + + return result +end + +------------------------------------------------------- +-- Replicates the survey phase of \pgfplotsplothandlerboxplot +BoxPlotPlothandler = newClassExtends(Plothandler) + +-- drawDirection : either "x" or "y". +function BoxPlotPlothandler:constructor(boxPlotRequest, drawDirection, drawPosition, axis, pointmetainputhandler) + if not boxPlotRequest or not drawDirection or not drawPosition then error("Arguments must not be nil") end + Plothandler.constructor(self,"boxplot", axis, pointmetainputhandler) + self.boxPlotRequest = boxPlotRequest + + local function evaluateDrawPosition() + local result = pgfmathparse(drawPosition) + return result + end + + if drawDirection == "x" then + self.boxplotsetxy = function (a,b) return a,evaluateDrawPosition() + b end + elseif drawDirection == "y" then + self.boxplotsetxy = function (a,b) return evaluateDrawPosition() + b,a end + else + error("Illegal argument drawDirection="..tostring(drawDirection) ) + end +end + +function BoxPlotPlothandler:surveystart() + self.boxplotInput = {} + self.boxplotSurveyMode = true +end + + +function BoxPlotPlothandler:surveyend() + self.boxplotSurveyMode = false + + local computed = boxPlotCompute( self.boxPlotRequest, self.boxplotInput ) + + local texResult = + "\\pgfplotsplothandlersurveyend@boxplot@set{lower whisker}{" .. toTeXstring(computed.lowerWhisker) .. "}" .. + "\\pgfplotsplothandlersurveyend@boxplot@set{lower quartile}{" .. toTeXstring(computed.lowerQuartile) .. "}" .. + "\\pgfplotsplothandlersurveyend@boxplot@set{median}{" .. toTeXstring(computed.median) .. "}" .. + "\\pgfplotsplothandlersurveyend@boxplot@set{upper quartile}{" .. toTeXstring(computed.upperQuartile) .. "}" .. + "\\pgfplotsplothandlersurveyend@boxplot@set{upper whisker}{" .. toTeXstring(computed.upperWhisker) .. "}" .. + "\\pgfplotsplothandlersurveyend@boxplot@set{sample size}{" .. toTeXstring(# self.boxplotInput) .. "}" + + self.boxplotInput = nil + Plothandler.surveystart(self) + + local outliers = computed.outliers + for i =1,#outliers do + local outlier = outliers[i] + local pt = Coord.new() + -- this here resembles \pgfplotsplothandlersurveypoint@boxplot@prepared when it is invoked during boxplot: + local X,Y = self.boxplotsetxy(outlier, 0) + pt.x = { X, Y, nil } + Plothandler.surveypoint(self,pt) + end + Plothandler.surveyend(self) + + return texResult +end + +function BoxPlotPlothandler:semiSurveyedValue(data) + local result = pgftonumber(data) + if result then + table.insert( self.boxplotInput, result ) + end +end + +function BoxPlotPlothandler:surveypoint(pt) + if self.boxplotSurveyMode then + error("Unsupported Operation encountered: box plot survey in LUA are only in PARTIAL mode (i.e. only if almost all has been prepared in TeX. Use 'lua backend=false' to get around this.") + else + Plothandler.surveypoint(self,pt) + end +end + +------------------------------------------------------- + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/streamer.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/streamer.lua new file mode 100644 index 00000000000..ab5b605d6d1 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplots/streamer.lua @@ -0,0 +1,193 @@ +-- Contains coordinate streamers, i.e. classes which generate coordinates and stream them to some output stream + +local math=math +local pgfplotsmath = pgfplots.pgfplotsmath +local type=type +local tostring=tostring +local error=error +local table=table + +do +-- all globals will be read from/defined in pgfplots: +local _ENV = pgfplots +----------------------------------- + +CoordOutputStream = newClass() + +function CoordOutputStream:constructor() +end + +-- @param pt an instance of Coord +function CoordOutputStream:coord(pt) +end + +----------------------------------- + +SurveyCoordOutputStream = newClassExtends(CoordOutputStream) + +function SurveyCoordOutputStream:constructor(targetPlothandler) + if not targetPlothandler then error("arguments must not be nil") end + self.plothandler= targetPlothandler +end + +function SurveyCoordOutputStream:coord(pt) + self.plothandler:surveypoint(pt) +end + +------------- +-- This is a partial reimplementation of \addplot expression: it samples points -- but entirely in LUA. Only the results are serialized back to TeX. + +AddplotExpressionCoordinateGenerator = newClass() + +function AddplotExpressionCoordinateGenerator:constructor(coordoutputstream, expressionsByDimension, domainMin, domainMax, samples, variableNames) + if not coordoutputstream or not expressionsByDimension or not domainMin or not domainMax or not samples or not variableNames then error("arguments must not be nil") end + if #variableNames ~= 2 then error("Expected 2 variableNames") end + self.coordoutputstream = coordoutputstream + self.is3d = #expressionsByDimension == 3 + self.expressions = expressionsByDimension + self.domainMin = domainMin + self.domainMax = domainMax + self.samples = samples + self.variableNames = variableNames + + -- log("initialized " .. tostring(self) .. "\n") +end + +-- @return true on success or false if the operation cannot be carried out. +-- this method is a replicate of \pgfplots@addplotimpl@expression@@ +function AddplotExpressionCoordinateGenerator:generateCoords() + local stringToFunctionMap = pgfluamathfunctions.stringToFunctionMap + -- create a backup of the 'x' and 'y' math expressions which + -- have been defined in \pgfplots@coord@stream@start: + local old_global_function_x = stringToFunctionMap["x"] + local old_global_function_y = stringToFunctionMap["y"] + + local coordoutputstream = self.coordoutputstream + local is3d = self.is3d + local expressions = self.expressions + local xExpr = expressions[1] + local yExpr = expressions[2] + local zExpr = expressions[3] + + local domainMin = self.domainMin + local domainMax = self.domainMax + local samples = self.samples + local h = {} + for i = 1,#domainMin do + h[i] = (domainMax[i] - domainMin[i]) / (samples[i]-1) + end + + local variableNames = self.variableNames + + local x,y + local sampleLine = #samples==1 + + local function pseudoconstantx() return x end + local pseudoconstanty + if sampleLine then + if yExpr ~= variableNames[2] then + -- suppress the warning - we want to allow (x,y,x^2) in this case. + pseudoconstanty = function() return 0 end + else + local didWarn = false + pseudoconstanty = function() + if not didWarn then + log("Sorry, you can't use 'y' in this context. PGFPlots expected to sample a line, not a mesh. Please use the [mesh] option combined with [samples y>0] and [domain y!=0:0] to indicate a twodimensional input domain\n") + didWarn = true + end + return 0 + end + end + else + pseudoconstanty = function() return y end + end + + local pgfmathparse = pgfluamathparser.pgfmathparse + local prepareX + if xExpr == variableNames[1] then + prepareX = function() return x end + else + prepareX = function() return pgfmathparse(xExpr) end + end + + local prepareY + if yExpr == variableNames[2] then + prepareY = function() return y end + else + prepareY = function() return pgfmathparse(yExpr) end + end + + local function computeXYZ() + stringToFunctionMap[variableNames[1]] = pseudoconstantx + stringToFunctionMap[variableNames[2]] = pseudoconstanty + local X = prepareX() + local Y = prepareY() + local Z = nil + if is3d then + Z = pgfmathparse(zExpr) + end + + local pt = Coord.new() + pt.x = { X, Y, Z} + + -- restore 'x' and 'y' + -- FIXME : defining the resulting x/y coordinates as 'x' and 'y' constants was a really really bad idea in the first place :-( + stringToFunctionMap["x"] = old_global_function_x + stringToFunctionMap["y"] = old_global_function_y + + coordoutputstream:coord(pt) + end + + if not sampleLine then + local xmin = domainMin[1] + local ymin = domainMin[2] + local hx = h[1] + local hy = h[2] + local max_i = samples[1]-1 + local max_j = samples[2]-1 + -- samples twodimensionally (a lattice): + for j = 0,max_j do + -- FIXME : pgfplots@plot@data@notify@next@y + y = ymin + j*hy + -- log("" .. j .. "\n") + for i = 0,max_i do + -- FIXME : pgfplots@plot@data@notify@next@x + x = xmin + i*hx + computeXYZ() + end + -- FIXME : \pgfplotsplothandlernotifyscanlinecomplete + end + else + local xmin = domainMin[1] + local hx = h[1] + local max_i = samples[1]-1 + for i = 0,max_i do + -- FIXME : pgfplots@plot@data@notify@next@x + x = xmin + i*hx + computeXYZ() + end + end + + stringToFunctionMap[variableNames[1]] = nil + stringToFunctionMap[variableNames[2]] = nil + return true +end + +function AddplotExpressionCoordinateGenerator:__tostring() + local result = "AddplotExpressionCoordinateGenerator[\n" + result = result .. "\n variable(s)=" .. self.variableNames[1] .. " " .. self.variableNames[2] + result = result .. "\n expressions=" + for i = 1,#self.expressions do + result = result .. self.expressions[i] ..", " + end + result = result .. "\n domain=" .. self.domainMin[1] .. ":" .. self.domainMax[1] + result = result .. "\n samples=" .. self.samples[1] + if #self.domainMin == 2 then + result = result .. "\n domain y=" .. self.domainMin[2] .. ":" .. self.domainMax[2] + result = result .. "\n samples y=" .. self.samples[2] + end + result = result .. "]" + return result +end + +end diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplotsoldpgfsupp/luamath/functions.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplotsoldpgfsupp/luamath/functions.lua new file mode 100644 index 00000000000..e5573f26f64 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplotsoldpgfsupp/luamath/functions.lua @@ -0,0 +1,649 @@ +-------------------------------------------------------------------------------------------------- +------ This file is a copy of some part of PGF/Tikz. +------ It has been copied here to provide : +------ - compatibility with older PGF versions +------ - availability of PGF contributions by Christian Feuersaenger +------ which are necessary or helpful for pgfplots. +------ +------ For reasons of simplicity, I have copied the whole file, including own contributions AND +------ PGF parts. The copyrights are as they appear in PGF. +------ +------ Note that pgfplots has compatible licenses. +------ +------ This copy has been modified in the following ways: +------ - nested \input commands have been updated +------ +-- +-- Support for the contents of this file will NOT be done by the PGF/TikZ team. +-- Please contact the author and/or maintainer of pgfplots (Christian Feuersaenger) if you need assistance in conjunction +-- with the deployment of this patch or partial content of PGF. Note that the author and/or maintainer of pgfplots has no obligation to fix anything: +-- This file comes without any warranty as the rest of pgfplots; there is no obligation for help. +---------------------------------------------------------------------------------------------------- +-- Date of this copy: Mi 14. Jan 21:15:32 CET 2015 --- + + + +-- Copyright 2011 by Christophe Jorssen +-- +-- This file may be distributed and/or modified +-- +-- 1. under the LaTeX Project Public License and/or +-- 2. under the GNU Public License. +-- +-- See the file doc/generic/pgf/licenses/LICENSE for more details. +-- +-- $Id: functions.lua,v 1.2 2015/01/14 20:15:13 cfeuersaenger Exp $ +-- + +local pgfluamathfunctions = pgfluamathfunctions or {} + +-- Maps function names to their function. +-- +-- Note that this allows to register functions which are not in pgfluamathfunctions. +-- +-- Note that the string keys are not necessarily the same as the function +-- names. In particular, the math expression "not(1,1)" will execute notPGF(1,1) +-- +-- Note that each function which is added to pgfluamathfunctions will _automatically_ be inserted into this map, see __newindex. +-- (I fear it will not be erased directly...) +pgfluamathfunctions.stringToFunctionMap = {} + +local newFunctionAllocatedCallback = function(table,key,value) + local keyName = tostring(key):gsub("PGF","") + if not value then + stringToFunctionMap[keyName] = nil + elseif type(value) == 'function' then + -- remember it, and strip PGF suffix (i.e. remember 'not' instead of 'notPGF') + pgfluamathfunctions.stringToFunctionMap[keyName] = value + end + rawset(table,key,value) +end + +setmetatable(pgfluamathfunctions, { __newindex = newFunctionAllocatedCallback }) + +local mathabs, mathacos, mathasin = math.abs, math.acos, math.asin +local mathatan, mathceil = math.atan, math.ceil +local mathcos, mathdeg = math.cos, math.deg +local mathexp, mathfloor, mathfmod = math.exp, math.floor, math.fmod +local mathlog, mathmax = math.log, math.max +local mathmin, mathpi = math.min, math.pi +local mathrad, mathrandom = math.rad, math.random +local mathrandomseed, mathsin = math.randomseed, math.sin +local mathsqrt = math.sqrt +local mathtan = math.tan + +local trigFormatToRadians = mathrad + +local radiansToTrigFormat = mathdeg + +pgfluamathfunctions.TrigFormat = { 'deg', 'rad' } +pgfluamathfunctions.stringToFunctionMap["TrigFormat"] = nil + +-- choice is one of the valid choices in TrigFormat. +function pgfluamathfunctions.setTrigFormat(choice) + if choice == 'deg' then + trigFormatToRadians = mathrad + radiansToTrigFormat = mathdeg + elseif choice == 'rad' then + local identity = function(x) return x end + trigFormatToRadians = identity + radiansToTrigFormat = identity + else + error("The argument '" .. tostring(choice) .. "' is no valid choice for setTrigFormat.") + end +end +pgfluamathfunctions.stringToFunctionMap["setTrigFormat"] = nil + +pgfluamathfunctions.setRandomSeed = mathrandomseed +pgfluamathfunctions.stringToFunctionMap["setRandomSeed"] = nil + +------------------------------------------- + +function pgfluamathfunctions.add(x,y) + return x+y +end + +function pgfluamathfunctions.subtract(x,y) + return x-y +end + +function pgfluamathfunctions.neg(x) + return -x +end + +function pgfluamathfunctions.multiply(x,y) + return x*y +end + +function pgfluamathfunctions.veclen(x,y) + return mathsqrt(x*x+y*y) +end + +function pgfluamathfunctions.divide(x,y) + return x/y +end + +function pgfluamathfunctions.div(x,y) + return mathfloor(x/y) +end + +function pgfluamathfunctions.pow(x,y) + -- do not use math.pow -- it is deprecated as of LUA 5.3 + return x^y +end + +function pgfluamathfunctions.factorial(x) +-- TODO: x must be an integer + if x == 0 then + return 1 + else + return x * pgfluamathfunctions.factorial(x-1) + end +end + +function pgfluamathfunctions.ifthenelse(x,y,z) + if x~= 0 then + return y + else + return z + end +end + +function pgfluamathfunctions.equal(x,y) + if x == y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.greater(x,y) + if x > y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.less(x,y) + if x < y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.min(x,y) + return mathmin(x,y) +end + +function pgfluamathfunctions.max(x,y) + return mathmax(x,y) +end + +function pgfluamathfunctions.notequal(x,y) + if x ~= y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.notless(x,y) + if x >= y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.notgreater(x,y) + if x <= y then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.andPGF(x,y) + if (x ~= 0) and (y ~= 0) then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.orPGF(x,y) + if (x ~= 0) or (y ~= 0) then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.notPGF(x) + if x == 0 then + return 1 + else + return 0 + end +end + +function pgfluamathfunctions.pi() + return mathpi +end + +function pgfluamathfunctions.e() + return mathexp(1) +end + +function pgfluamathfunctions.abs(x) + return mathabs(x) +end + +function pgfluamathfunctions.floor(x) + return mathfloor(x) +end + +function pgfluamathfunctions.ceil(x) + return mathceil(x) +end + +function pgfluamathfunctions.exp(x) + return mathexp(x) +end + +function pgfluamathfunctions.ln(x) + return mathlog(x) +end + +local logOf10 = mathlog(10) +function pgfluamathfunctions.log10(x) + return mathlog(x) / logOf10 +end + +local logOf2 = mathlog(2) +function pgfluamathfunctions.log2(x) + return mathlog(x) / logOf2 +end + +function pgfluamathfunctions.sqrt(x) + return mathsqrt(x) +end + +function pgfluamathfunctions.sign(x) + if x < 0 then + return -1.0 + elseif x == 0 then + return 0.0 + else + return 1.0 + end +end +function pgfluamathfunctions.real(x) + -- "ensure that x contains a decimal point" is kind of a no-op here, isn't it!? + return x +end + +function pgfluamathfunctions.rnd() + return mathrandom() +end + +function pgfluamathfunctions.rand() + return -1 + mathrandom() *2 +end + +function pgfluamathfunctions.random(x,y) + if x == nil and y == nil then + return mathrandom() + elseif y == nil then + return mathrandom(x) + else + return mathrandom(x,y) + end +end + +function pgfluamathfunctions.deg(x) + return mathdeg(x) +end + +function pgfluamathfunctions.rad(x) + return mathrad(x) +end + +function pgfluamathfunctions.round(x) + if x<0 then + return -mathfloor(mathabs(x)+0.5) + else + return mathfloor(x + 0.5) + end +end + +function pgfluamathfunctions.gcd(a, b) + if b == 0 then + return a + else + return pgfluamathfunctions.gcd(b, a%b) + end +end + +function pgfluamathfunctions.isprime(a) + local ifisprime = true + if a == 1 then + ifisprime = false + elseif a == 2 then + ifisprime = true +-- if a > 2 then + else + local i, imax = 2, mathceil(mathsqrt(a)) + 1 + while ifisprime and (i < imax) do + if pgfluamathfunctions.gcd(a,i) ~= 1 then + ifisprime = false + end + i = i + 1 + end + end + if ifisprime then + return 1 + else + return 0 + end +end + + +function pgfluamathfunctions.split_braces_to_explist(s) + -- (Thanks to mpg and zappathustra from fctt) + -- Make unpack available whatever lua version is used + -- (unpack in lua 5.1 table.unpack in lua 5.2) + local unpack = table.unpack or unpack + local t = {} + for i in s:gmatch('%b{}') do + table.insert(t, tonumber(i:sub(2, -2))) + end + return unpack(t) +end + +function pgfluamathfunctions.split_braces_to_table(s) + local t = {} + for i in s:gmatch('%b{}') do + table.insert(t, tonumber(i:sub(2, -2))) + end + return t +end + +function pgfluamathfunctions.mathtrue() + return 1.0 +end +pgfluamathfunctions.stringToFunctionMap["true"] = pgfluamathfunctions.mathtrue + +function pgfluamathfunctions.mathfalse() + return 0.0 +end +pgfluamathfunctions.stringToFunctionMap["false"] = pgfluamathfunctions.mathfalse + +function pgfluamathfunctions.frac(a) + -- should be positive, apparently + return mathabs(a - pgfluamathfunctions.int(a)) +end + +function pgfluamathfunctions.int(a) + if a < 0 then + return -mathfloor(mathabs(a)) + else + return mathfloor(a) + end +end + +function pgfluamathfunctions.iseven(a) + if (a % 2) == 0 then + return 1.0 + else + return 0.0 + end +end + +function pgfluamathfunctions.isodd(a) + if (a % 2) == 0 then + return 0.0 + else + return 1.0 + end +end + +function pgfluamathfunctions.mod(x,y) + if x/y < 0 then + return -(mathabs(x)%mathabs(y)) + else + return mathabs(x)%mathabs(y) + end +end + +function pgfluamathfunctions.Mod(x,y) + local tmp = pgfluamathfunctions.mod(x,y) + if tmp < 0 then + tmp = tmp + y + end + return tmp +end + +function pgfluamathfunctions.Sin(x) + return mathsin(trigFormatToRadians(x)) +end +pgfluamathfunctions.sin=pgfluamathfunctions.Sin + + +function pgfluamathfunctions.cosh(x) + -- math.cosh is deprecated as of LUA 5.3 . reimplement it: + return 0.5* (mathexp(x) + mathexp(-x)) +end +function pgfluamathfunctions.sinh(x) + -- math.sinh is deprecated as of LUA 5.3 . reimplement it: + return 0.5* (mathexp(x) - mathexp(-x)) +end + +local sinh = pgfluamathfunctions.sinh +local cosh = pgfluamathfunctions.cosh +function pgfluamathfunctions.tanh(x) + -- math.tanh is deprecated as of LUA 5.3 . reimplement it: + return sinh(x)/cosh(x) +end + +function pgfluamathfunctions.Cos(x) + return mathcos(trigFormatToRadians(x)) +end +pgfluamathfunctions.cos=pgfluamathfunctions.Cos + +function pgfluamathfunctions.Tan(x) + return mathtan(trigFormatToRadians(x)) +end +pgfluamathfunctions.tan=pgfluamathfunctions.Tan + +function pgfluamathfunctions.aSin(x) + return radiansToTrigFormat(mathasin(x)) +end +pgfluamathfunctions.asin=pgfluamathfunctions.aSin + +function pgfluamathfunctions.aCos(x) + return radiansToTrigFormat(mathacos(x)) +end +pgfluamathfunctions.acos=pgfluamathfunctions.aCos + +function pgfluamathfunctions.aTan(x) + return radiansToTrigFormat(mathatan(x)) +end +pgfluamathfunctions.atan=pgfluamathfunctions.aTan + +local mathatan2 +if math.atan2 == nil then + -- math.atan2 has been deprecated since LUA 5.3 + mathatan2 = function (y,x) return mathatan(y,x) end +else + mathatan2 = math.atan2 +end + +function pgfluamathfunctions.aTan2(y,x) + return radiansToTrigFormat(mathatan2(y,x)) +end +pgfluamathfunctions.atan2=pgfluamathfunctions.aTan2 +pgfluamathfunctions.atantwo=pgfluamathfunctions.aTan2 + +function pgfluamathfunctions.cot(x) + return pgfluamathfunctions.cos(x) / pgfluamathfunctions.sin(x) +end +function pgfluamathfunctions.sec(x) + return 1 / pgfluamathfunctions.cos(x) +end +function pgfluamathfunctions.cosec(x) + return 1 / pgfluamathfunctions.sin(x) +end + +function pgfluamathfunctions.pointnormalised (pgfx, pgfy) + local pgfx_normalised, pgfy_normalised + if pgfx == 0. and pgfy == 0. then + -- Orginal pgf macro gives this result + tex.dimen['pgf@x'] = "0pt" + tex.dimen['pgf@y'] = "1pt" + else + pgfx_normalised = pgfx/math.sqrt(pgfx^2 + pgfy^2) + pgfx_normalised = pgfx_normalised - pgfx_normalised%0.00001 + pgfy_normalised = pgfy/math.sqrt(pgfx^2 + pgfy^2) + pgfy_normalised = pgfy_normalised - pgfy_normalised%0.00001 + tex.dimen['pgf@x'] = tostring(pgfx_normalised) .. "pt" + tex.dimen['pgf@y'] = tostring(pgfy_normalised) .. "pt" + end + return nil +end + +local isnan = function(x) + return x ~= x +end + +pgfluamathfunctions.isnan = isnan + +local infty = 1/0 +pgfluamathfunctions.infty = infty + +local nan = math.sqrt(-1) +pgfluamathfunctions.nan = nan + +local stringlen = string.len +local globaltonumber = tonumber +local stringsub=string.sub +local stringformat = string.format +local stringsub = string.sub + +-- like tonumber(x), but it also accepts nan, inf, infty, and the TeX FPU format +function pgfluamathfunctions.tonumber(x) + if type(x) == 'number' then return x end + if not x then return x end + + local len = stringlen(x) + local result = globaltonumber(x) + if not result then + if len >2 and stringsub(x,2,2) == 'Y' and stringsub(x,len,len) == ']' then + -- Ah - some TeX FPU input of the form 1Y1.0e3] . OK. transform it + local flag = stringsub(x,1,1) + if flag == '0' then + -- ah, 0.0 + result = 0.0 + elseif flag == '1' then + result = globaltonumber(stringsub(x,3, len-1)) + elseif flag == '2' then + result = globaltonumber("-" .. stringsub(x,3, len-1)) + elseif flag == '3' then + result = nan + elseif flag == '4' then + result = infty + elseif flag == '5' then + result = -infty + end + else + local lower = x:lower() + if lower == 'nan' then + result = nan + elseif lower == 'inf' or lower == 'infty' then + result = infty + elseif lower == '-inf' or lower == '-infty' then + result = -infty + end + end + end + + return result +end + +local stringlen = string.len +local globaltonumber = tonumber +local stringformat = string.format +local stringsub = string.sub +local stringfind = string.find +local stringbyte = string.byte +local NULL_CHAR = string.byte("0",1) + +local function discardTrailingZeros(x) + local result = x + -- printf is too stupid: I would like to have + -- 1. a fast method + -- 2. a reliable method + -- 3. full precision of x + -- 4. a fixed point representation + -- the 'f' modifier has trailing zeros (stupid!) + -- the 'g' modified can switch to scientific notation (no-go!) + local periodOff = stringfind(result, '.',1,true) + if periodOff ~= nil then + -- strip trailing zeros + local chars = { stringbyte(result,1,#result) }; + local lastNonZero = #chars + for i = #chars, periodOff, -1 do + if chars[i] ~= NULL_CHAR then lastNonZero=i; break; end + end + if lastNonZero ~= #chars then + -- Ah: we had at least one trailing zero. + -- discard all but the last. + lastNonZero = mathmax(periodOff+1,lastNonZero) + end + result = stringsub(result, 1, lastNonZero) + end + return result; +end + +local function discardTrailingZerosFromMantissa(x) + local mantissaStart = stringfind(x, "e") + + local mantissa = stringsub(x,1,mantissaStart-1) + local exponent = stringsub(x,mantissaStart) + + return discardTrailingZeros(mantissa) .. exponent +end + + +-- a helper function which has no catcode issues when communicating with TeX: +function pgfluamathfunctions.tostringfixed(x) + if x == nil then + return "" + end + + return discardTrailingZeros(stringformat("%f", x)) +end + +-- converts an input number to a string which is accepted by the TeX FPU +function pgfluamathfunctions.toTeXstring(x) + local result = "" + if x ~= nil then + if x == infty then result = "4Y0.0e0]" + elseif x == -infty then result = "5Y0.0e0]" + elseif isnan(x) then result = "3Y0.0e0]" + elseif x == 0 then result = "0Y0.0e0]" + else + result = discardTrailingZerosFromMantissa(stringformat("%.10e", x)) + if x > 0 then + result = "1Y" .. result .. "]" + else + result = "2Y" .. stringsub(result,2) .. "]" + end + end + end + return result +end + +return pgfluamathfunctions diff --git a/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplotsoldpgfsupp/luamath/parser.lua b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplotsoldpgfsupp/luamath/parser.lua new file mode 100644 index 00000000000..cc9663f145f --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/lua/pgfplotsoldpgfsupp/luamath/parser.lua @@ -0,0 +1,495 @@ +-------------------------------------------------------------------------------------------------- +------ This file is a copy of some part of PGF/Tikz. +------ It has been copied here to provide : +------ - compatibility with older PGF versions +------ - availability of PGF contributions by Christian Feuersaenger +------ which are necessary or helpful for pgfplots. +------ +------ For reasons of simplicity, I have copied the whole file, including own contributions AND +------ PGF parts. The copyrights are as they appear in PGF. +------ +------ Note that pgfplots has compatible licenses. +------ +------ This copy has been modified in the following ways: +------ - nested \input commands have been updated +------ +-- +-- Support for the contents of this file will NOT be done by the PGF/TikZ team. +-- Please contact the author and/or maintainer of pgfplots (Christian Feuersaenger) if you need assistance in conjunction +-- with the deployment of this patch or partial content of PGF. Note that the author and/or maintainer of pgfplots has no obligation to fix anything: +-- This file comes without any warranty as the rest of pgfplots; there is no obligation for help. +---------------------------------------------------------------------------------------------------- +-- Date of this copy: Mi 14. Jan 21:15:32 CET 2015 --- + + + +-- Copyright 2011 by Christophe Jorssen and Mark Wibrow +-- Copyright 2014 by Christian Feuersaenger +-- +-- This file may be distributed and/or modified +-- +-- 1. under the LaTeX Project Public License and/or +-- 2. under the GNU Public License. +-- +-- See the file doc/generic/pgf/licenses/LICENSE for more details. +-- +-- $Id: parser.lua,v 1.1 2014/12/27 14:11:49 cfeuersaenger Exp $ +-- +-- usage: +-- +-- pgfluamathparser = require("pgfplotsoldpgfsupp.luamath.parser") +-- +-- local result = pgfluamathparser.pgfmathparse("1+ 2*4^2") +-- +-- This LUA class has a direct backend in \pgfuselibrary{luamath}, see the documentation of that TeX package. + +local pgfluamathparser = pgfluamathparser or {} + +pgfluamathfunctions = require("pgfplotsoldpgfsupp.luamath.functions") + +-- lpeg is always present in luatex +local lpeg = require("lpeg") + +local S, P, R = lpeg.S, lpeg.P, lpeg.R +local C, Cc, Ct = lpeg.C, lpeg.Cc, lpeg.Ct +local Cf, Cg, Cs = lpeg.Cf, lpeg.Cg, lpeg.Cs +local V = lpeg.V +local match = lpeg.match + +local space_pattern = S(" \n\r\t")^0 +local tex_unit = + P('pt') + P('mm') + P('cm') + P('in') + + -- while valid units, the font-depending ones need special attention... move them to the TeX side. For now. + -- P('ex') + P('em') + + P('bp') + P('pc') + + P('dd') + P('cc') + P('sp'); + +local one_digit_pattern = R("09") +local positive_integer_pattern = one_digit_pattern^1 +-- FIXME : it might be a better idea to remove '-' from all number_patterns! Instead, rely on the prefix operator 'neg' to implement negative numbers. +-- Is that wise? It is certainly less efficient... +local integer_pattern = S("+-")^-1 * positive_integer_pattern +-- Valid positive decimals are |xxx.xxx|, |.xxx| and |xxx.| +local positive_integer_or_decimal_pattern = positive_integer_pattern * ( P(".") * one_digit_pattern^0)^-1 + + (P(".") * one_digit_pattern^1) +local integer_or_decimal_pattern = S("+-")^-1 * positive_integer_or_decimal_pattern +local fpu_pattern = R"15" * P"Y" * positive_integer_or_decimal_pattern * P"e" * P("-")^-1 * R("09")^1 * P"]" +local unbounded_pattern = P"inf" + P"INF" + P"nan" + P"NaN" + P"Inf" +local number_pattern = C(unbounded_pattern + fpu_pattern + integer_or_decimal_pattern * (S"eE" * integer_pattern + C(tex_unit))^-1) + +local underscore_pattern = P("_") + +local letter_pattern = R("az","AZ") +local alphanum__pattern = letter_pattern + one_digit_pattern + underscore_pattern + +local identifier_pattern = letter_pattern^1 * alphanum__pattern^0 + +local openparen_pattern = P("(") * space_pattern +local closeparen_pattern = P(")") +local opencurlybrace_pattern = P("{") +local closecurlybrace_pattern = P("}") +local openbrace_pattern = P("[") +local closebrace_pattern = P("]") + +-- hm. what about '\\' or '\%' ? +-- accept \pgf@x, \count0, \dimen42, \c@pgf@counta, \wd0, \ht0, \dp 0 +local controlsequence_pattern = P"\\" * C( (R("az","AZ") + P"@")^1) * space_pattern* C( R"09"^0 ) + +-- local string = P('"') * C((1 - P('"'))^0) * P('"') + +local comma_pattern = P(",") * space_pattern + + +---------------- +local TermOp = C(S("+-")) * space_pattern +local RelationalOp = C( P"==" + P"!=" + P"<=" + P">=" + P"<" + P">" ) * space_pattern +local FactorOp = C(S("*/")) * space_pattern + +-- Grammar +local Exp, Term, Factor = V"Exp", V"Term", V"Factor" +local Prefix = V"Prefix" +local Postfix = V"Postfix" + + + +local function eval (v1, op, v2) + if (op == "+") then return v1 + v2 + elseif (op == "-") then return v1 - v2 + elseif (op == "*") then return v1 * v2 + elseif (op == "/") then return v1 / v2 + else + error("This function must not be invoked for operator "..op) + end +end + +local pgfStringToFunctionMap = pgfluamathfunctions.stringToFunctionMap +local function function_eval(name, ... ) + local f = pgfStringToFunctionMap[name] + if not f then + error("Function '" .. name .. "' is undefined (did not find pgfluamathfunctions."..name .." (looked into pgfluamathfunctions.stringToFunctionMap))") + end + -- FIXME: validate signature + return f(...) +end + + +local func = + (C(identifier_pattern) * space_pattern * openparen_pattern * Exp * (comma_pattern * Exp)^0 * closeparen_pattern) / function_eval; + +local functionWithoutArg = identifier_pattern / function_eval + +-- this is what can occur as exponent after '^'. +-- I have the impression that the priorities could be implemented in a better way than this... but it seems to work. +local pow_exponent = + -- allows 2^-4, 2^1e4, 2^2 + -- FIXME : why not 2^1e2 ? + Cg(C(integer_or_decimal_pattern) + -- 2^pi, 2^multiply(2,2) + + Cg(func+functionWithoutArg) + -- 2^(2+2) + + openparen_pattern * Exp * closeparen_pattern ) + +local function prefix_eval(op, x) + if op == "-" then + return pgfluamathfunctions.neg(x) + elseif op == "!" then + return pgfluamathfunctions.notPGF(x) + else + error("This function must not be invoked for operator "..op) + end +end + + +local prefix_operator = C( S"-!" ) +local prefix_operator_pattern = (prefix_operator * space_pattern * Cg(Prefix) ) / prefix_eval + +-- apparently, we need to distinghuish between <expr> ! and <expr> != <expr2>: +local postfix_operator = C( S"r!" - P"!=" ) + C(P"^") * space_pattern * pow_exponent + + +local ternary_eval = pgfluamathfunctions.ifthenelse + +local factorial_eval = pgfluamathfunctions.factorial +local deg = pgfluamathfunctions.deg +local pow_eval = pgfluamathfunctions.pow + +-- @param prefix the argument before the postfix operator. +-- @param op either nil or the postfix operator +-- @param arg either nil or the (mandatory) argument for 'op' +local function postfix_eval(prefix, op, arg) + local result + if op == nil then + result = prefix + elseif op == "r" then + if arg then error("parser setup error: expected nil argument") end + result = deg(prefix) + elseif op == "!" then + if arg then error("parser setup error: expected nil argument") end + result = factorial_eval(prefix) + elseif op == "^" then + if not arg then error("parser setup error: ^ with its argument") end + result = pow_eval(prefix, arg) + else + error("Parser setup error: " .. tostring(op) .. " unexpected in this context") + end + return result +end + +local function relational_eval(v1, op, v2) + local fct + if (op == "==") then fct = pgfluamathfunctions.equal + elseif (op == "!=") then fct = pgfluamathfunctions.notequal + elseif (op == "<") then fct = pgfluamathfunctions.less + elseif (op == ">") then fct = pgfluamathfunctions.greater + elseif (op == ">=") then fct = pgfluamathfunctions.notless + elseif (op == "<=") then fct = pgfluamathfunctions.notgreater + else + error("This function must not be invoked for operator "..op) + end + return fct(v1,v2) +end + +-- @return either the box property or nil +-- @param cs "wd", "ht", or "dp" +-- @param intSuffix some integer +local function get_tex_box(cs, intSuffix) + -- assume get_tex_box is only called when a dimension is required. + local result + pgfluamathparser.units_declared = true + local box =tex.box[tonumber(intSuffix)] + if not box then error("There is no box " .. intSuffix) end + if cs == "wd" then + result = box.width / 65536 + elseif cs == "ht" then + result = box.height / 65536 + elseif cs == "dp" then + result = box.depth / 65536 + else + result = nil + end + return result +end + + +local function controlsequence_eval(cs, intSuffix) + local result + if intSuffix and #intSuffix >0 then + if cs == "count" then + result= pgfluamathparser.get_tex_count(intSuffix) + elseif cs == "dimen" then + result= pgfluamathparser.get_tex_dimen(intSuffix) + else + result = get_tex_box(cs,intSuffix) + if not result then + -- this can happen - we cannot expand \chardef'ed boxes here. + -- this will be done by the TeX part + error('I do not know/support the TeX register "\\' .. cs .. '"') + end + end + else + result = pgfluamathparser.get_tex_register(cs) + end + return result +end + +pgfluamathparser.units_declared = false +function pgfluamathparser.get_tex_register(register) + -- register is a string which could be a count or a dimen. + if pcall(tex.getcount, register) then + return tex.count[register] + elseif pcall(tex.getdimen, register) then + pgfluamathparser.units_declared = true + return tex.dimen[register] / 65536 -- return in points. + else + error('I do not know the TeX register "' .. register .. '"') + return nil + end + +end + +function pgfluamathparser.get_tex_count(count) + -- count is expected to be a number + return tex.count[tonumber(count)] +end + +function pgfluamathparser.get_tex_dimen(dimen) + -- dimen is expected to be a number + pgfluamathparser.units_declared = true + return tex.dimen[tonumber(dimen)] / 65536 +end + +function pgfluamathparser.get_tex_sp(dimension) + -- dimension should be a string + pgfluamathparser.units_declared = true + return tex.sp(dimension) / 65536 +end + + +local initialRule = V"initial" + +local Summand = V"Summand" +local Relational = V"Relational" +local LogicalOr = V"LogicalOr" +local LogicalAnd = V"LogicalAnd" + +local pgftonumber = pgfluamathfunctions.tonumber +local tonumber_withunit = pgfluamathparser.get_tex_sp +local function number_optional_units_eval(x, unit) + if not unit then + return pgftonumber(x) + else + return tonumber_withunit(x) + end +end + +-- @param scale the number. +-- @param controlsequence either nil in which case just the number must be returned or a control sequence +-- @see controlsequence_eval +local function scaled_controlsequence_eval(scale, controlsequence, intSuffix) + if controlsequence==nil then + return scale + else + return scale * controlsequence_eval(controlsequence, intSuffix) + end +end + +-- Grammar +-- +-- for me: +-- - use '/' to evaluate all expressions which contain a _constant_ number of captures. +-- - use Cf to evaluate expressions which contain a _dynamic_ number of captures +-- +-- see unittest_luamathparser.tex for tons of examples +local G = P{ "initialRule", + initialRule = space_pattern* Exp * -1; + -- ternary operator (or chained ternary operators): + -- FIXME : is this chaining a good idea!? + Exp = Cf( Relational * Cg(P"?" * space_pattern * Relational * P":" *space_pattern * Relational )^0, ternary_eval) ; + -- FIXME : do we really allow something like " 1 == 1 != 2" ? I would prefer (1==1) != 2 !? + Relational = Cf(LogicalOr * Cg(RelationalOp * LogicalOr)^0, relational_eval); + LogicalOr = Cf(LogicalAnd * (P"||" * space_pattern * LogicalAnd)^0, pgfluamathfunctions.orPGF); + LogicalAnd = Cf(Summand * (P"&&" * space_pattern * Summand)^0, pgfluamathfunctions.andPGF); + Summand = Cf(Term * Cg(TermOp * Term)^0, eval) ; + Term = Cf(Prefix * Cg(FactorOp * Prefix)^0, eval); + Prefix = prefix_operator_pattern + Postfix; + -- this calls 'postfix_eval' with nil arguments if it is no postfix operation.. but that does not hurt (right?) + Postfix = Factor * (postfix_operator * space_pattern)^-1 / postfix_eval; + Factor = + ( + number_pattern / number_optional_units_eval * + -- this construction will evaluate number_pattern with 'number_optional_units_eval' FIRST. + -- also accept '0.5 \pgf@x' here: + space_pattern *controlsequence_pattern^-1 / scaled_controlsequence_eval + + func + + functionWithoutArg + + openparen_pattern * Exp * closeparen_pattern + + controlsequence_pattern / controlsequence_eval + ) *space_pattern + ; +} + +-- does not reset units_declared. +local function pgfmathparseinternal(str) + local result = match(G,str) + if result == nil then + error("The string '" .. str .. "' is no valid PGF math expression. Please check for syntax errors.") + end + return result +end + + +-- This is the math parser function in this module. +-- +-- @param str a string like "1+1" which is accepted by the PGF math language +-- @return the result of the expression. +-- +-- Throws an error if the string is no valid expression. +function pgfluamathparser.pgfmathparse(str) + pgfluamathparser.units_declared = false + + return pgfmathparseinternal(str) +end + +local pgfmathparse = pgfluamathparser.pgfmathparse +local tostringfixed = pgfluamathfunctions.tostringfixed +local tostringfpu = pgfluamathfunctions.toTeXstring + +local tmpFunctionArgumentPrefix = "tmpVar" +local stackOfLocalFunctions = {} + +-- This is a backend for PGF's 'declare function'. +-- \tikzset{declare function={mu(\x,\i)=\x^\i;}} +-- will boil down to +-- pgfluamathparser.declareExpressionFunction("mu", 2, "#1^#2") +-- +-- The local function will be pushed on a stack of known local functions and is +-- available until popLocalExpressionFunction() is called. TeX will call this using +-- \aftergroup. +-- +-- @param name the name of the new function +-- @param numArgs the number of arguments +-- @param expression an expression containing #1, ... #n where n is numArgs +-- +-- ATTENTION: local functions behave DIFFERENTLY in LUA! +-- In LUA, local variables are not expanded whereas TeX expands them. +-- The difference is +-- +-- declare function={mu1(\x,\i)=\x^\i;} +-- \pgfmathparse{mu1(-5,2)} --> -25 +-- \pgfluamathparse{mu1(-5,2)} --> 25 +-- +-- x = -5 +-- \pgfmathparse{mu1(x,2)} --> 25 +-- \pgfluamathparse{mu1(x,2)} --> 25 +-- +-- In an early prototype, I simulated TeX's expansion to fix the first case (successfully). +-- BUT: that "simulated expansion" broke the second case because LUA will evaluate "x" and hand -5 to the local function. +-- I decided to keep it as is. Perhaps we should fix PGF's expansion approach in TeX (which is ugly anyway) +function pgfluamathparser.pushLocalExpressionFunction(name, numArgs, expression) + -- now we have "tmpVar1^tmpVar2" instead of "#1^#2" + local normalizedExpr = expression:gsub("#", tmpFunctionArgumentPrefix) + local restores = {} + local tmpVars = {} + for i=1,numArgs do + local tmpVar = tmpFunctionArgumentPrefix .. tostring(i) + tmpVars[i] = tmpVar + end + + local newFunction = function(...) + local args = table.pack(...) + + -- define "tmpVar1" ... "tmpVarN" to return args[i]. + -- Of course, we need to restore "tmpVar<i>" after we return! + for i=1,numArgs do + local tmpVar = tmpVars[i] + local value = args[i] + restores[i] = pgfStringToFunctionMap[tmpVar] + pgfStringToFunctionMap[tmpVar] = function () return value end + end + + -- parse our expression. + + -- FIXME : this here is an attempt to mess around with "units_declared". + -- It would be better to call pgfmathparse and introduce some + -- semaphore to check if pgfmathparse is a nested call-- in this case, it should + -- not reset units_declared. But there is no "finally" block and pcall is crap (looses stack trace). + local success,result = pcall(pgfmathparseinternal, normalizedExpr) + + -- remove 'tmpVar1', ... from the function table: + for i=1,numArgs do + local tmpVar = tmpVars[i] + pgfStringToFunctionMap[tmpVar] = restores[i] + end + + if success==false then error(result) end + return result + end + table.insert(stackOfLocalFunctions, name) + pgfStringToFunctionMap[name] = newFunction +end + +function pgfluamathparser.popLocalExpressionFunction() + local name = stackOfLocalFunctions[#stackOfLocalFunctions] + pgfStringToFunctionMap[name] = nil + -- this removes the last element: + table.remove(stackOfLocalFunctions) +end + + +-- A Utility function which simplifies the interaction with the TeX code +-- @param expression the input expression (string) +-- @param outputFormatChoice 0 if the result should be a fixed point number, 1 if it should be in FPU format +-- @param showErrorMessage (boolean) true if any error should be displayed, false if errors should simply result in an invocation of TeX's parser (the default) +-- +-- it defines \pgfmathresult and \ifpgfmathunitsdeclared +function pgfluamathparser.texCallParser(expression, outputFormatChoice, showErrorMessage) + local success, result + if showErrorMessage then + result = pgfmathparse(expression) + success = true + else + success, result = pcall(pgfmathparse, expression) + end + + if success and result then + local result_str + if outputFormatChoice == 0 then + -- luamath/output format=fixed + result_str = tostringfixed(result) + else + -- luamath/output format=fixed + result_str = tostringfpu(result) + end + tex.sprint("\\def\\pgfmathresult{" .. result_str .. "}") + if pgfluamathparser.units_declared then + tex.sprint("\\pgfmathunitsdeclaredtrue") + else + tex.sprint("\\pgfmathunitsdeclaredfalse") + end + else + tex.sprint("\\def\\pgfmathresult{}") + tex.sprint("\\pgfmathunitsdeclaredfalse") + end +end + +return pgfluamathparser diff --git a/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstableshared.code.tex b/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstableshared.code.tex index cfd13a74a58..8d470b6c6f5 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstableshared.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstableshared.code.tex @@ -296,7 +296,24 @@ % Invokes #2 if '#1' is an already loaded table and #3 if not. \long\def\pgfplotstable@isloadedtable#1#2#3{% - \pgfplotsutil@ifdefinedui@withsuffix{#1}{@@table@name}{#2}{#3}% + \ifcase\pgfplotstableread@ROWSEP@CASE\relax + % row sep=newline + \let\pgfplots@loc@TMPa=\pgfplotstableread@NL@other% + \or + % row sep=crcr + \def\pgfplots@loc@TMPa{\\}% + \fi + % + \expandafter\pgfutil@in@\expandafter{\pgfplots@loc@TMPa}{#1}% + \ifpgfutil@in@ + % Hah! it contains the row separator! This is NO macro name! + % -> it is an inline table definition. Don't try to + % assemble a macro name (may run into out-of-memory) + #3\relax% + \else + % ok, the early-out was not met. Make check: + \pgfplotsutil@ifdefinedui@withsuffix{#1}{@@table@name}{#2}{#3}% + \fi }% % If the colum name `#1' is a `create on use' speicifcation, #2 is @@ -785,6 +802,7 @@ }% \begingroup \catcode`\^^M=12\relax% +\gdef\pgfplotstableread@NL@other{^^M}% \long\gdef\pgfplotstableread@checkinlineformat@NL@#1^^M#2\pgfplotstable@EOI{% \def\pgfplotstable@loc@TMPa{#2}% \ifx\pgfplotstable@loc@TMPa\pgfutil@empty% @@ -831,6 +849,14 @@ \pgfplotstableread@inlinefalse \fi % + \ifpgfplotstableread@inline + \else + \if1\pgfplotstableread@ROWSEP@CASE + % row sep=crcr + \pgfplotsthrow{unsupported operation}{Sorry, the choice 'row sep=crcr' is currently only available for inline tables, not for external files}\pgfeov + \fi + \fi + % % optimizations: \pgfkeysgetvalue{/pgfplots/table/comment chars}\pgfplots@loc@TMPd \ifx\pgfplots@loc@TMPd\pgfutil@empty diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_loader.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_loader.code.tex index 8b5a3eaa055..ced1ab3c95b 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_loader.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_loader.code.tex @@ -17,6 +17,7 @@ }% }% + \def\pgfmathfloatrounddisplaystyle@shared@impl@WRONG#1#2{% {\toks0={#1}% \toks1=\expandafter{\pgfmathfloatrounddisplaystyle@e@mark #2}% @@ -60,9 +61,10 @@ }% }% -\pgfutil@ifundefined{pgfmathdeclarepseudoconstant}{ +\pgfutil@ifundefined{pgfmathfloatatan2}{ \immediate\write16{Package pgfplots: loading complementary arithmetics for your pgf version...} \input pgfplotsoldpgfsupp_pgflibraryfpu.code.tex + \input pgfplotsoldpgfsupp_pgfmathfloat.code.tex } {}% @@ -88,5 +90,57 @@ }% }{}% +\ifpgfplots@LUA@supported + \def\PATCH@pgfmath@local@function@body#1;{% + \def\pgfmath@local@body{#1}% + \begingroup% + \c@pgf@counta=0\relax% + \ifx\pgfmath@local@args\pgfmath@empty% + \expandafter\pgfmath@toks\expandafter=\expandafter{\pgfmath@local@body}% + \else% + \pgfmath@toks={}% + \expandafter\pgfmath@local@function@@body\pgfmath@local@args,,% + \fi% + \xdef\pgfmath@local@temp{% + \noexpand\pgfmathnotifynewdeclarefunction{\pgfmath@local@name}{\the\c@pgf@counta}% + {\the\pgfmath@toks}% + }% + \endgroup% + \pgfmath@local@temp% + } + % #1: the name + % #2: the number of arguments <n> + % #3: a math expression containing '#1', '#2', ... ,'#'<n> + % This callback is overwritten by pgflibraryluamath. + \def\PATCH@pgfmathnotifynewdeclarefunction#1#2#3{% + \pgfmathdeclarefunction{#1}{#2}{\pgfmathparse{#3}}% + }% + % + % currently, pgfplots does NOT call directly call any TeX macros + % from this library - but it relies on the fact that "trig + % format", \pgfmathsetseed and other configuration macros also + % mirror their values in LUA. + % And this mirroring is done in library luamath: + \def\pgfplots@glob@TMPa{3.0.0}% + \ifx\pgfversion\pgfplots@glob@TMPa + % 3.0.0 does not have the (correct) luamath library. + \let\pgfmathnotifynewdeclarefunction=\PATCH@pgfmathnotifynewdeclarefunction + \let\pgfmath@local@function@body=\PATCH@pgfmath@local@function@body + \pgfplotsusecompatibilityfile{pgflibraryluamath.code.tex} + \else + \pgfutil@IfFileExists{pgflibraryluamath.code.tex}{% + % ah - we have a very recent version of PGF. + % Well, it will hopefully come with a suitable version of the + % luamath library! Use it. + \usepgflibrary{luamath}% + }{% + % hm. PGF 2.10 ? + % + % FIXME + %\pgfplots@LUA@supportedfalse + }% + \fi +\fi + \endinput diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_patches.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_patches.code.tex deleted file mode 100644 index 698769ec1e5..00000000000 --- a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_patches.code.tex +++ /dev/null @@ -1,18 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% This file contains patches on top of PGF/Tikz. -%%% -%%% It has been copied here to provide : -%%% - compatibility with older PGF versions -%%% - availability of PGF contributions by Christian Feuersaenger -%%% which are necessary or helpful for pgfplots. -%%% -%%% For reasons of simplicity, I have copied the whole file, including own contributions AND -%%% PGF parts. The copyrights are as they appear in PGF. -%%% -%%% Note that pgfplots has compatible licenses. -%%% -%%% This copy has been modified in the following ways: -%%% - nested \input commands have been updated -%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryfpu.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryfpu.code.tex index c45a35f60c8..8b5784c1172 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryfpu.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryfpu.code.tex @@ -19,7 +19,7 @@ % with the deployment of this patch or partial content of PGF. Note that the author and/or maintainer of pgfplots has no obligation to fix anything: % This file comes without any warranty as the rest of pgfplots; there is no obligation for help. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% Date of this copy: Di 25. Dez 18:14:20 CET 2012 %%% +%%% Date of this copy: So 11. Jan 18:03:19 CET 2015 %%% @@ -182,24 +182,13 @@ \expandafter\let\expandafter#1\csname pgfmathfloat@backup@\string#1\endcsname% }% } -\def\pgfmathfloat@prepareuninstallcmd@csname#1{% - % and store backup information (globally - I don't want to do that - % all the time when the FPU is used!): - {% - \globaldefs=1 - \pgfutil@namelet{pgfmathfloat@backup@#1}{#1}% - \expandafter\gdef\expandafter\pgfmathfloat@uninstall\expandafter{\pgfmathfloat@uninstall - \pgfutil@namelet{#1}{pgfmathfloat@backup@#1}% - }% - }% -} \def\pgfmathfloat@install#1=#2{% \pgfmathfloat@prepareuninstallcmd{#1}% \let#1=#2% } \def\pgfmathfloat@install@csname#1#2{% - \pgfmathfloat@prepareuninstallcmd@csname{#1}% + \expandafter\pgfmathfloat@prepareuninstallcmd\csname #1\endcsname% \pgfutil@namelet{#1}{#2}% } \def\pgfmathfloat@install@unimplemented#1{% @@ -238,6 +227,7 @@ \pgfmathfloat@install\pgfmathmultiply@=\pgfmathfloatmultiply@% \pgfmathfloat@install\pgfmathdivide@=\pgfmathfloatdivide@% \pgfmathfloat@install\pgfmathabs@=\pgfmathfloatabs@% + \pgfmathfloat@install\pgfmathsign@=\pgfmathfloatsign@% \pgfmathfloat@install\pgfmathround@=\pgfmathfloatround@% \pgfmathfloat@install\pgfmathfloor@=\pgfmathfloatfloor@% \pgfmathfloat@install\pgfmathmod@=\pgfmathfloatmod@% @@ -293,13 +283,13 @@ \pgfmathfloat@install\pgfmathcosh@=\pgfmathfloatcosh@ \pgfmathfloat@install\pgfmathsinh@=\pgfmathfloatsinh@ \pgfmathfloat@install\pgfmathtanh@=\pgfmathfloattanh@ + \expandafter\pgfmathfloat@install\csname pgfmathatan2@\endcsname=\pgfmathfloatatantwo@ \pgfmathfloat@install@unimplemented{ceil}% \pgfmathfloat@install@unimplemented{frac}% \pgfmathfloat@install@unimplemented{random}% \pgfmathfloat@install@unimplemented{setseed}% \pgfmathfloat@install@unimplemented{Mod}% \pgfmathfloat@install@unimplemented{real}% -% \pgfmathfloat@install@unimplemented{atan2}% % \pgfmathfloat@install@unimplemented{height}% % % @@ -333,6 +323,21 @@ \pgfmathfloat@install\pgfmath@parse@exponent=\pgfmathfloat@parse@float@or@exponent % \pgfmathfloat@install\pgfmathparse=\pgfmathfloatparse% + %\pgfmathfloat@install\pgfmathparse@trynumber@token=\pgfmathfloat@parse@trynumber@token + \pgfmathfloat@install\pgfmathparse@expression@is@number=\pgfmathfloat@parse@expression@is@number +}% + +% This here might bring speed improvements... if implemented +% correctly. +% However, this heuristics might fail in cases like "1+1" vs "1e+1" ... +%\def\pgfmathfloat@parse@trynumber@token{numericfpu} +%\pgfmath@tokens@make{numericfpu}{eE+-Y.0123456789} + +\def\pgfmathfloat@parse@expression@is@number{% + \pgfmathfloatparsenumber{\pgfmath@expression}% + \pgfmath@smuggleone\pgfmathresult% + \endgroup + \ignorespaces }% \def\pgfmathfloat@defineadapter@for@pgf@two@null@null@ONEARG#1{% @@ -1018,7 +1023,7 @@ \if#2+% \pgfmathfloatifflags{#1}{1}{#3}{#4}% \else - \pgfmathfloatgetflagstomacro#1\pgfmathfloat@loc@TMPa + \pgfmathfloatgetflagstomacro{#1}\pgfmathfloat@loc@TMPa \if#2u% \ifnum\pgfmathfloat@loc@TMPa>2 #3\relax @@ -1501,7 +1506,34 @@ \pgfmath@smuggleone\pgfmathresult \endgroup }% -\let\pgfmathfloatabs=\pgfmathfloatabs@ +% +% Defines \pgfmathresult to be sign(#1) +\def\pgfmathfloatsign@#1{% + \begingroup + \expandafter\pgfmathfloat@decompose@tok#1\relax\pgfmathfloat@a@S\pgfmathfloat@a@Mtok\pgfmathfloat@a@E + \ifcase\pgfmathfloat@a@S + % 0: + \pgfmathfloatcreate{0}{0.0}{0}% + \or + % +: ok, is positive. + \pgfmathfloatcreate{1}{1.0}{0}% + \or + % -: + \pgfmathfloatcreate{2}{1.0}{0}% + \or + % nan: do nothing. + \pgfmathfloatcreate{\the\pgfmathfloat@a@S}{\the\pgfmathfloat@a@Mtok}{\the\pgfmathfloat@a@E}% + \or + % +infty:. + \pgfmathfloatcreate{1}{1.0}{0}% + \or + % -infty: + \pgfmathfloatcreate{2}{1.0}{0}% + \fi + \pgfmath@smuggleone\pgfmathresult + \endgroup +}% +\let\pgfmathfloatsign=\pgfmathfloatsign@ % Computes the absolute error |#1 - #2| into \pgfmathresult. \def\pgfmathfloatabserror@#1#2{% @@ -1519,8 +1551,8 @@ \let\pgfmathresult=\pgfmathfloat@subtract }{% \pgfmathfloatdivide@{\pgfmathfloat@subtract}{#2}% - \pgfmathfloatabs@{\pgfmathresult}% }% + \pgfmathfloatabs@{\pgfmathresult}% }% \let\pgfmathfloatrelerror=\pgfmathfloatrelerror@ @@ -1592,14 +1624,27 @@ % % #1 is a one-argument macro which assigns \pgfmathresult. \def\pgfmathfloatTRIG@#1#2{% - \expandafter\ifx\csname pgfmathfloatTRIG@NUM\endcsname\relax% - % Lazy evaluation: - \pgfmathfloatcreate{1}{3.6}{2}% - \global\let\pgfmathfloatTRIG@NUM=\pgfmathresult - \pgfmathfloatcreate{1}{2.77777777777778}{-3}% - \global\let\pgfmathfloatTRIG@NUM@INV=\pgfmathresult + \if0\pgfmath@trig@format@choice + % trig format=deg + \expandafter\ifx\csname pgfmathfloatTRIG@NUM\endcsname\relax% + % Lazy evaluation: + \pgfmathfloatcreate{1}{3.6}{2}% + \global\let\pgfmathfloatTRIG@NUM=\pgfmathresult + \pgfmathfloatcreate{1}{2.77777777777778}{-3}% + \global\let\pgfmathfloatTRIG@NUM@INV=\pgfmathresult + \fi + \pgfmathfloatmodknowsinverse@{#2}{\pgfmathfloatTRIG@NUM}{\pgfmathfloatTRIG@NUM@INV}% + \else + % trig format=rad + \expandafter\ifx\csname pgfmathfloatTRIG@rad@NUM\endcsname\relax% + % Lazy evaluation: + \pgfmathfloatcreate{1}{6.28318530717959}{0}% + \global\let\pgfmathfloatTRIG@rad@NUM=\pgfmathresult + \pgfmathfloatcreate{1}{1.59154943091895}{-1}% + \global\let\pgfmathfloatTRIG@rad@NUM@INV=\pgfmathresult + \fi + \pgfmathfloatmodknowsinverse@{#2}{\pgfmathfloatTRIG@rad@NUM}{\pgfmathfloatTRIG@rad@NUM@INV}% \fi - \pgfmathfloatmodknowsinverse@{#2}{\pgfmathfloatTRIG@NUM}{\pgfmathfloatTRIG@NUM@INV}% \pgfmathfloattofixed@{\pgfmathresult}% \expandafter#1\expandafter{\pgfmathresult}% \pgfmathfloatparsenumber{\pgfmathresult}% @@ -1643,11 +1688,19 @@ \fi \pgfmathfloatgreaterthan@{#1}{\pgfmathfloatatan@TMP}% \ifpgfmathfloatcomparison - \pgfmathfloatcreate{1}{9.0}{1}% + \pgfmathiftrigonometricusesdeg{% + \pgfmathfloatcreate{1}{9.0}{1}% + }{% + \pgfmathfloatcreate{1}{1.570796326794}{0}% + }% \else \pgfmathfloatlessthan{#1}{\pgfmathfloatatan@TMPB}% \ifpgfmathfloatcomparison - \pgfmathfloatcreate{2}{9.0}{1}% + \pgfmathiftrigonometricusesdeg{% + \pgfmathfloatcreate{2}{9.0}{1}% + }{% + \pgfmathfloatcreate{2}{1.570796326794}{0}% + }% \else \pgfmathfloattofixed@{#1}% \expandafter\pgfmath@basic@atan@\expandafter{\pgfmathresult}% @@ -1659,6 +1712,75 @@ }% \let\pgfmathfloatatan=\pgfmathfloatatan@ +\def\pgfmathfloatatantwo#1#2{% + % Note: first parameter is y (!), second is x (!) + \begingroup% + \let\pgfmath@trig@format@choice@@=\pgfmath@trig@format@choice + \def\pgfmath@trig@format@choice{0}% + % + \expandafter\pgfmathfloat@decompose@tok#1\relax\pgfmathfloat@a@S\pgfmathfloat@a@Mtok\pgfmathfloat@a@E + \expandafter\pgfmathfloat@decompose#2\relax\pgfmathfloat@b@S\pgfmathfloat@b@M\pgfmathfloat@b@E + \ifnum\pgfmathfloat@a@S=0 + \pgfmathfloat@a@E=-16 % + \fi + % + \ifnum\pgfmathfloat@a@E<-3 % + \ifnum\pgfmathfloat@b@S=2 % + % #2 < 0 + \pgfmathfloatcreate{1}{1.8}{2}% +180 + \else + \ifnum\pgfmathfloat@b@S=1 % + % #2 >0 + \pgfmathfloatcreate{0}{0.0}{0}% + \else + % + or - 90, just use the sign of #1: + \pgfmathfloatcreate{\the\pgfmathfloat@a@S}{9.0}{1}% + \fi + \fi + \else% + \pgfmathfloatabs@{#1}\let\pgfmath@tempa\pgfmathresult% + \pgfmathfloatabs@{#2}\let\pgfmath@tempb\pgfmathresult% + \pgfmathfloatgreaterthan@{\pgfmath@tempa}{\pgfmath@tempb}% + \ifpgfmathfloatcomparison + \pgfmathfloatdivide@{#2}{\pgfmath@tempa}% + \expandafter\pgfmathfloatatan@\expandafter{\pgfmathresult}% + \let\pgfmath@tempa=\pgfmathresult + \pgfmathfloatcreate{1}{9.0}{1}% + \let\pgfmath@tempb=\pgfmathresult + \pgfmathfloatsubtract@{\pgfmath@tempb}{\pgfmath@tempa}% + \else% + \pgfmathfloatdivide@{\pgfmath@tempa}{#2}% + \expandafter\pgfmathfloatatan@\expandafter{\pgfmathresult}% + \expandafter\pgfmathfloatifflags\expandafter{\pgfmathresult}{2}{% + \let\pgfmath@tempa=\pgfmathresult + \pgfmathfloatcreate{1}{1.8}{2}% + \let\pgfmath@tempb=\pgfmathresult + \pgfmathfloatadd@{\pgfmath@tempa}{\pgfmath@tempb}% + }{}% + \fi% + % + \pgfmathfloatifflags{#1}{-}{% + % #1 < 0: + \pgfmathfloatmultiplyfixed@{\pgfmathresult}{-1}% + }{}% + \fi% + \if1\pgfmath@trig@format@choice@@ + % trig format=rad + \pgfmathfloat@scale@deg@to@rad\pgfmathresult + \fi + \pgfmath@smuggleone\pgfmathresult% + \endgroup% +}% +\let\pgfmathfloatatantwo@=\pgfmathfloatatantwo +\expandafter\let\csname pgfmathfloatatan2\endcsname=\pgfmathfloatatantwo +\expandafter\let\csname pgfmathfloatatan2@\endcsname=\pgfmathfloatatantwo@ + +\def\pgfmathfloat@scale@deg@to@rad#1{% + \edef\pgfmathfloat@loc@TMPb{#1}% + \pgfmathfloatcreate{1}{1.74532925199433}{-2}% = pi / 180 + \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@loc@TMPb}% +}% + \def\pgfmathfloatsec@#1{\pgfmathfloatTRIG@\pgfmath@basic@cos@{#1}\pgfmathfloatreciprocal@{\pgfmathresult}} \let\pgfmathfloatsec=\pgfmathfloatsec@ \def\pgfmathfloatcosec@#1{\pgfmathfloatTRIG@\pgfmath@basic@sin@{#1}\pgfmathfloatreciprocal@{\pgfmathresult}} @@ -1905,12 +2027,25 @@ \divide\c@pgfmath@counta by2\relax% \repeatpgfmathloop% \else - % employ #1^#2 = exp( #2 * ln(#1) ) - \pgfmathfloatln@{#1}% - \let\pgfmathfloat@loc@TMPa=\pgfmathresult - \edef\pgfmathfloat@loc@TMPb{#2}% - \pgfmathfloatmultiply@{\pgfmathfloat@loc@TMPa}{\pgfmathfloat@loc@TMPb}% - \pgfmathfloatexp@{\pgfmathresult}% + \pgfmathfloatgetflags{#1}\c@pgfmath@counta + \ifnum0=\c@pgfmath@counta + % ah: 0^x + \pgfmathfloatgetflags{#2}\c@pgfmath@counta + \ifnum0=\c@pgfmath@counta + % ah: 0^0 + \pgfmathfloatcreate{1}{1.0}{0}% + \else + % ah: 0^x with x!=0: + \pgfmathfloatcreate{0}{0.0}{0}% + \fi + \else + % employ #1^#2 = exp( #2 * ln(#1) ) + \pgfmathfloatln@{#1}% + \let\pgfmathfloat@loc@TMPa=\pgfmathresult + \edef\pgfmathfloat@loc@TMPb{#2}% + \pgfmathfloatmultiply@{\pgfmathfloat@loc@TMPa}{\pgfmathfloat@loc@TMPb}% + \pgfmathfloatexp@{\pgfmathresult}% + \fi \fi } diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryluamath.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryluamath.code.tex new file mode 100644 index 00000000000..28de0607b25 --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgflibraryluamath.code.tex @@ -0,0 +1,540 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% This file is a copy of some part of PGF/Tikz. +%%% It has been copied here to provide : +%%% - compatibility with older PGF versions +%%% - availability of PGF contributions by Christian Feuersaenger +%%% which are necessary or helpful for pgfplots. +%%% +%%% For reasons of simplicity, I have copied the whole file, including own contributions AND +%%% PGF parts. The copyrights are as they appear in PGF. +%%% +%%% Note that pgfplots has compatible licenses. +%%% +%%% This copy has been modified in the following ways: +%%% - nested \input commands have been updated +%%% +% +% Support for the contents of this file will NOT be done by the PGF/TikZ team. +% Please contact the author and/or maintainer of pgfplots (Christian Feuersaenger) if you need assistance in conjunction +% with the deployment of this patch or partial content of PGF. Note that the author and/or maintainer of pgfplots has no obligation to fix anything: +% This file comes without any warranty as the rest of pgfplots; there is no obligation for help. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Date of this copy: Do 1. Jan 22:31:46 CET 2015 %%% + + + +% Copyright 2011 by Christophe Jorssen and Mark Wibrow +% Copyright 2014 by Christian Feuersänger +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Public License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. +% +% $Id: pgflibraryluamath.code.tex,v 1.19 2014/12/27 14:11:49 cfeuersaenger Exp $ +% +% !!! Warning: this library does not work with fpu!!! +% +% +% This is a library for a LUA math parser and LUA math operations. +% Advantage compared to its TeX pendant: it is FASTER and has HIGHER +% ACCURACY. +% Disadvantage: any function declared by means of +% \pgfmathdeclarefunction is NOT automatically transported to the LUA +% side (at the time of this writing). +% LUA functions need to be defined by means of LUA code +% +% function pgfluamathfunctions.myoperation(a,b) +% return a*2*b +% end +% +% this will automatically set up 'myoperation' for use in +% \pgfluamathparse{myoperation(4,2)} +% +% The library has TWO use-cases which are more or less distinct: one +% is to use LUA for all math function, but not for math expression +% parsing -- this was still under control of the TeX math parser. +% This approach works like the 'fpu' library. +% +% The second approach is to use LUA to parse all math expressions - +% but if someone calls \pgfmathadd@{1}{2}, it would use the TeX +% command. This approach is relatively lightweight because it does not +% need to substitute all \pgfmath* macros. +% +% One can mix both modes. + +% ******************************************************************* +% Some luatex stuff. Should be put elsewhere (e.g. in +% pgfutil-luatex-engine). + +\edef\pgfliblua@oldcatcodedoublequote{\the\catcode`\"}% +\catcode`\"=12 + +% We assume luatex version > 0.39: +% - \directlua <general text> will work +% - \directlua is the only luatex primitive that we can assume +% accessible without being prefixed by the format via +% tex.enableprimitives. +% Ideas taken from the ifluatex package (Heiko Oberdiek) +\let\pgfutil@ifluatex\iffalse +\begingroup\expandafter\expandafter\expandafter\endgroup +\expandafter\ifx\csname directlua\endcsname\relax +\else + \expandafter\let\csname pgfutil@ifluatex\expandafter\endcsname + \csname iftrue\endcsname +\fi + +\pgfutil@ifluatex + \let\pgfutil@directlua\directlua + \pgfutil@directlua{% + tex.enableprimitives('pgfutil@',{'luaescapestring'})} +\else + \def\pgfutil@directlua#1{} + \def\pgfutil@luaescapestring#1{} +\fi + +\pgfutil@directlua{% + pgfluamathfunctions = require("pgfplotsoldpgfsupp.luamath.functions") + pgfluamathparser = require("pgfplotsoldpgfsupp.luamath.parser")} + + +% Patch some configuration macros such that the modifications are +% available in LUA as well: +\pgfkeys{ + /pgf/trig format/deg/.add code={}{\directlua{pgfluamathfunctions.setTrigFormat("deg")}\aftergroup\pgfmath@settrigformat}, + /pgf/trig format/rad/.add code={}{\directlua{pgfluamathfunctions.setTrigFormat("rad")}\aftergroup\pgfmath@settrigformat}, +} +% ... and reactivate the key: +\pgfmathiftrigonometricusesdeg{% + \pgfkeys{/pgf/trig format/deg}% +}{% + \pgfkeys{/pgf/trig format/rad}% +}% + +% re-activates the current trig format. This is important after a TeX +% group has been closed. +\def\pgfmath@settrigformat{% + \pgfmathiftrigonometricusesdeg{% + \directlua{pgfluamathfunctions.setTrigFormat("deg")}% + }{% + \directlua{pgfluamathfunctions.setTrigFormat("rad")}% + }% +}% + +\let\pgfmathsetseed@pgfbasic = \pgfmathsetseed +\def\pgfmathsetseed#1{% + \pgfmathsetseed@pgfbasic{#1}% + \directlua{pgfluamathfunctions.setRandomSeed(pgfluamathfunctions.tonumber("\pgfmathresult"))}% +}% + +% Patch 'declare function' such that it communicates the function +% directly to LUA. +\let\pgfmathnotifynewdeclarefunction@orig=\pgfmathnotifynewdeclarefunction +\def\pgfmathnotifynewdeclarefunction#1#2#3{% + \pgfmathnotifynewdeclarefunction@orig{#1}{#2}{#3}% + \directlua{pgfluamathparser.pushLocalExpressionFunction(% + "\pgfutil@luaescapestring{#1}",% + #2,% + "\pgfutil@luaescapestring{#3}")}% + % + % ensure that the local function is removed at the end of the + % scope. To this end, we maintain a stack on the LUA side. + \aftergroup\pgfluamathparse@pop@local@function +}% + +\def\pgfluamathparse@pop@local@function{% + \directlua{pgfluamathparser.popLocalExpressionFunction()}% +}% + +% End of luatex stuff +% ******************************************************************* + +% Loading part: based on fpu library + + +% if LUA failed to evaluate the expression, it will be evaluated in +% TeX as fallback. This boolean defines if the error message shall be +% shown or suppressed. The default is to suppress it and show any +% resulting TeX errors. +% +% If LUA fails \pgfmathresult will be empty. +% +% This is actually only for debugging; it will be set implicitly when +% activating/deactivating TeX fallback. +\newif\ifpgfluamathshowerrormessage + +% Defines what happens if LUA failed to evaluate the expression: if +% this is true, the TeX parser will be invoked as fallback. +% +% This happens +% - for \chardef'ed boxes for which LUA lacks evaluation capabilities +% - if the expression includes some function which is unavailable in +% LUA (defined only in TeX) +% - some special cases which simply haven't been added to the LUA +% parser (yet). +% At the time of this writing, this includes +% -- arrays created via '{}' and indexed with '[]' +% -- strings with "<str>" +% -- 'scalar' function +% -- hex/octal/binary input +\newif\ifpgfluamathenableTeXfallback + +\newif\ifpgfluamathcomputationactive +\newif\ifpgfluamathparseractive + +\def\pgfluamath@makecomputationactive{% + \ifpgfluamathcomputationactive + \else + \pgfluamath@checkuninstallcmd% + \pgfluamath@install% + \pgfluamathcomputationactivetrue + \fi} + +\def\pgfluamath@makecomputationinactive{% + \ifpgfluamathcomputationactive + \pgfluamath@uninstall% + \pgfluamathcomputationactivefalse + \fi} + +\let\pgfluamath@pgfmathparse\pgfmathparse +\def\pgfluamath@makeparseractive{% + \ifpgfluamathparseractive + \else + \let\pgfluamath@pgfmathparse\pgfmathparse + \let\pgfmathparse\pgfluamathparse + \pgfluamathparseractivetrue + \fi} + +\def\pgfluamath@makeparserinactive{% + \ifpgfluamathparseractive + \let\pgfmathparse\pgfluamath@pgfmathparse + \pgfluamathparseractivefalse + \fi} + +\pgfqkeys{/pgf}{% + % Enable lua-side computation of \pgfmathresult + % (will be deactivated after the current TeX group) + luamath/.is choice, + luamath/only computation/.code={% + \pgfutil@ifluatex + \pgfluamath@makecomputationactive + \pgfluamath@makeparserinactive + \else + \pgfmath@error{Sorry, you need the luaTeX engine to use the + luamath library}% + \fi}, + luamath/parser and computation/.code={% + \pgfutil@ifluatex + \pgfluamath@makecomputationactive + \pgfluamath@makeparseractive + \else + \pgfmath@error{Sorry, you need the luaTeX engine to use the + luamath library}% + \fi}, + luamath/off/.code={% + \pgfluamath@makecomputationinactive + \pgfluamath@makeparserinactive}, + luamath/.default=only computation, + % + % activates ONLY the parser. This is fast and does not replace the + % \pgfmath* functions. + % @see |parser and computation| which also allows to write + % \pgfmathadd{1}{2} to call LUA + luamath/parser/.code={% + \pgfutil@ifluatex + \pgfluamath@makeparseractive + \else + \pgfmath@error{Sorry, you need the luaTeX engine to use the + luamath library}% + \fi + }, + luamath/output format/.is choice, + luamath/output format/fixed/.code= {\def\pgfluamath@outputformat@choice{0}}, + % returns results for use in the FPU + luamath/output format/float/.code= {\def\pgfluamath@outputformat@choice{1}}, + luamath/output format/fixed, + % this is merely useful for debugging purposes, I guess. + luamath/show error message/.is if=pgfluamathshowerrormessage, + luamath/enable TeX fallback/.is choice, + luamath/enable TeX fallback/true/.code={\pgfluamathenableTeXfallbacktrue\pgfluamathshowerrormessagefalse}, + luamath/enable TeX fallback/false/.code={\pgfluamathenableTeXfallbackfalse\pgfluamathshowerrormessagetrue}, + luamath/enable TeX fallback/.default=true, + luamath/enable TeX fallback=true, +} + +\def\pgfluamath@uninstall@appendcmd#1{% + \expandafter\gdef\expandafter\pgfluamath@uninstall\expandafter{% + \pgfluamath@uninstall #1}} + +% If the uninstall command is already assembled, it will skip the +% uninstall assemblation. +\def\pgfluamath@checkuninstallcmd{% + \pgfutil@ifundefined{pgfluamath@uninstall}{% + \global\let\pgfluamath@uninstall=\pgfutil@empty + }{% + % We already HAVE an uninstall command (prepared globally). + % So: don't waste time assembling one! + \def\pgfluamath@uninstall@appendcmd##1{}% + \def\pgfluamath@prepareuninstallcmd##1{}% + }% +} + +% This assembles an uninstall command globally ON FIRST USAGE. +% See \pgfmathfloat@plots@checkuninstallcmd +\def\pgfluamath@prepareuninstallcmd#1{% + \expandafter\global\expandafter\let + \csname pgfluamath@backup@\string#1\endcsname=#1% + \expandafter\gdef\expandafter\pgfluamath@uninstall\expandafter{% + \pgfluamath@uninstall + \expandafter\let\expandafter#1\csname pgfluamath@backup@\string#1\endcsname}% +} + +\def\pgfluamath@install@function#1=#2{% + \pgfluamath@prepareuninstallcmd{#1}% + \let#1=#2% +} + +\def\pgfluamath@install{% + \pgfluamath@install@function\pgfmathadd@=\pgfluamathadd@% + \pgfluamath@install@function\pgfmathsubtract@=\pgfluamathsubtract@% + \pgfluamath@install@function\pgfmathneg@=\pgfluamathneg@% + \pgfluamath@install@function\pgfmathmultiply@=\pgfluamathmultiply@% + \pgfluamath@install@function\pgfmathdivide@=\pgfluamathdivide@% + % \pgfluamath@install@function\pgfmathdiv@=\pgfluamathdiv@% + \pgfluamath@install@function\pgfmathfactorial@=\pgfluamathfactorial@% + \pgfluamath@install@function\pgfmathsqrt@=\pgfluamathsqrt@% + % \pgfluamath@install@function\pgfmathpow@=\pgfluamathpow@% + \pgfluamath@install@function\pgfmathe@=\pgfluamathe@% + \pgfluamath@install@function\pgfmathexp@=\pgfluamathexp@% + \pgfluamath@install@function\pgfmathln@=\pgfluamathln@% + \pgfluamath@install@function\pgfmathlogten@=\pgfluamathlogten@% + % \pgfluamath@install@function\pgfmathlogtwo@=\pgfluamathlogtwo@% + \pgfluamath@install@function\pgfmathabs@=\pgfluamathabs@% + \pgfluamath@install@function\pgfmathmod@=\pgfluamathmod@% + \pgfluamath@install@function\pgfmathMod@=\pgfluamathMod@% + \pgfluamath@install@function\pgfmathround@=\pgfluamathround@% + \pgfluamath@install@function\pgfmathfloor@=\pgfluamathfloor@% + \pgfluamath@install@function\pgfmathceil@=\pgfluamathceil@% + % \pgfluamath@install@function\pgfmathint@=\pgfluamathint@% + % \pgfluamath@install@function\pgfmathfrac@=\pgfluamathfrac@% + % \pgfluamath@install@function\pgfmathreal@=\pgfluamathreal@% + \pgfluamath@install@function\pgfmathgcd@=\pgfluamathgcd@% + \pgfluamath@install@function\pgfmathisprime@=\pgfluamathisprime@% + \pgfluamath@install@function\pgfmathpi@=\pgfluamathpi@% + \pgfluamath@install@function\pgfmathrad@=\pgfluamathrad@% + \pgfluamath@install@function\pgfmathdeg@=\pgfluamathdeg@% + \pgfluamath@install@function\pgfmathsin@=\pgfluamathsin@% + \pgfluamath@install@function\pgfmathcos@=\pgfluamathcos@% + \pgfluamath@install@function\pgfmathtan@=\pgfluamathtan@% + \pgfluamath@install@function\pgfmathsec@=\pgfluamathsec@% + \pgfluamath@install@function\pgfmathcosec@=\pgfluamathcosec@% + \pgfluamath@install@function\pgfmathcot@=\pgfluamathcot@% + \pgfluamath@install@function\pgfmathasin@=\pgfluamathasin@% + \pgfluamath@install@function\pgfmathacos@=\pgfluamathacos@% + \pgfluamath@install@function\pgfmathatan@=\pgfluamathatan@% + \pgfluamath@install@function\pgfmathatantwo@=\pgfluamathatantwo@% + \pgfluamath@install@function\pgfmathmax@=\pgfluamathmax@% + \pgfluamath@install@function\pgfmathmin@=\pgfluamathmin@% + % \pgfluamath@install@function\pgfmath@pi=\pgfluamathpi@% + % \pgfluamath@install@function\pgfmathpi=\pgfluamathpi@% + % \pgfluamath@install@function\pgfmathe@=\pgfluamathe@% + % \pgfluamath@install@function\pgfmathe=\pgfluamathe@% + % \pgfluamath@install@function\pgfmathlessthan@=\pgfluamathlessthan@% + % \pgfluamath@install@function\pgfmathless@=\pgfluamathlessthan@% + % \pgfluamath@install@function\pgfmathgreaterthan@=\pgfluamathgreaterthan@% + % \pgfluamath@install@function\pgfmathgreater@=\pgfluamathgreaterthan@% + % \pgfluamath@install@function\pgfmathpow@=\pgfluamathpow@ + \pgfluamath@install@function\pgfmathrand@=\pgfluamathrand@ + \pgfluamath@install@function\pgfmathrand=\pgfluamathrand@ + \pgfluamath@install@function\pgfmathrnd@=\pgfluamathrnd@ + \pgfluamath@install@function\pgfmathrnd=\pgfluamathrnd@ + % \pgfluamath@install@function\pgfmathtrue@=\pgfluamathtrue@ + % \pgfluamath@install@function\pgfmathfalse@=\pgfluamathfalse@ + % \pgfluamath@install@function\pgfmathnot@=\pgfluamathnot@ + % \pgfluamath@install@function\pgfmathhex@=\pgfluamathhex@ + % \pgfluamath@install@function\pgfmathHex@=\pgfluamathHex@ + % \pgfluamath@install@function\pgfmathoct@=\pgfluamathoct@ + % \pgfluamath@install@function\pgfmathbin@=\pgfluamathbin@ + % \pgfluamath@install@function\pgfmathand@=\pgfluamathand@ + % \pgfluamath@install@function\pgfmathor@=\pgfluamathor@ + % \pgfluamath@install@function\pgfmathfactorial@=\pgfluamathfactorial@ + % \pgfluamath@install@function\pgfmathveclen@=\pgfluamathveclen@ + % \pgfluamath@install@function\pgfmathcosh@=\pgfluamathcosh@ + % \pgfluamath@install@function\pgfmathsinh@=\pgfluamathsinh@ + % \pgfluamath@install@function\pgfmathtanh@=\pgfluamathtanh@ + % \pgfluamath@install@function@unimplemented{ceil}% + % \pgfluamath@install@function@unimplemented{frac}% + % \pgfluamath@install@function@unimplemented{log2}% + % \pgfluamath@install@function@unimplemented{log10}% + % \pgfluamath@install@function@unimplemented{equalto}% + % \pgfluamath@install@function@unimplemented{random}% + % \pgfluamath@install@function@unimplemented{setseed}% + % \pgfluamath@install@function@unimplemented{Mod}% + % \pgfluamath@install@function@unimplemented{real}% + % \pgfluamath@install@function@unimplemented{notequal}% + \pgfluamath@install@function\pgfmathreciprocal=\pgfluamathreciprocal% + \pgfluamath@install@function\pgfpointnormalised=\pgfluamathpointnormalised +} + +\def\pgfluamathgetresult#1{% + \edef\pgfmathresult{\pgfutil@directlua{tex.print(-1,#1)}}} + +\def\pgfluamathpi@{% + \pgfluamathgetresult{pgfluamathfunctions.pi()}} +\def\pgfluamathe@{% + \pgfluamathgetresult{pgfluamathfunctions.e()}} +\def\pgfluamathadd@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.add(#1,#2)}} +\def\pgfluamathsubtract@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.substract(#1,#2)}} +\def\pgfluamathneg@#1{% + \pgfluamathgetresult{pgfluamathfunctions.neg(#1)}} +\def\pgfluamathmultiply@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.multiply(#1,#2)}} +\def\pgfluamathdivide@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.divide(#1,#2)}} +\def\pgfluamathabs@#1{% + \pgfluamathgetresult{pgfluamathfunctions.abs(#1)}} +\def\pgfluamathround@#1{% + \pgfluamathgetresult{pgfluamathfunctions.round(#1)}} +\def\pgfluamathfloor@#1{% + \pgfluamathgetresult{pgfluamathfunctions.floor(#1)}} +\def\pgfluamathceil@#1{% + \pgfluamathgetresult{pgfluamathfunctions.ceil(#1)}} +\def\pgfluamathgcd@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.gcd(#1,#2)}} +\def\pgfluamathisprime@#1{% + \pgfluamathgetresult{pgfluamathfunctions.isprime(#1)}} +\def\pgfluamathmax@#1{% + \pgfluamathgetresult{% + math.max(pgfluamathfunctions.split_braces_to_explist("#1"))}} +\def\pgfluamathmin@#1{% + \pgfluamathgetresult{% + math.min(pgfluamathfunctions.split_braces_to_explist("#1"))}} +\def\pgfluamathsin@#1{% + \pgfluamathgetresult{pgfluamathfunctions.Sin(#1)}} +\def\pgfluamathcos@#1{% + \pgfluamathgetresult{pgfluamathfunctions.Cos(#1)}} +\def\pgfluamathtan@#1{% + \pgfluamathgetresult{pgfluamathfunctions.Tan(#1)}} +\def\pgfluamathmod@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.mod(#1,#2)}} +\def\pgfluamathMod@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.Mod(#1,#2)}} +\def\pgfluamathrad@#1{% + \pgfluamathgetresult{pgfluamathfunctions.rad(#1)}} +\def\pgfluamathdeg@#1{% + \pgfluamathgetresult{pgfluamathfunctions.deg(#1)}} +\def\pgfluamathatan@#1{% + \pgfluamathgetresult{pgfluamathfunctions.aTan(#1)}} +\def\pgfluamathatantwo@#1#2{% + \pgfluamathgetresult{pgfluamathfunctions.aTan2(#1,#2)}} +\def\pgfluamathasin@#1{% + \pgfluamathgetresult{pgfluamathfunctions.aSin(#1)}} +\def\pgfluamathacos@#1{% + \pgfluamathgetresult{pgfluamathfunctions.aCos(#1)}} +\def\pgfluamathcot@#1{% + \pgfluamathgetresult{1/pgfluamathfunctions.Tan(#1)}} +\def\pgfluamathsec@#1{% + \pgfluamathgetresult{1/pgfluamathfunctions.Cos(#1)}} +\def\pgfluamathcosec@#1{% + \pgfluamathgetresult{1/pgfluamathfunctions.Sin(#1)}} +\def\pgfluamathexp@#1{% + \pgfluamathgetresult{pgfluamathfunctions.exp(#1)}} +\def\pgfluamathln@#1{% + \pgfluamathgetresult{pgfluamathfunctions.log(#1)}} +\def\pgfluamathlogten@#1{% + \pgfluamathgetresult{pgfluamathfunctions.log10(#1)}} +\def\pgfluamathsqrt@#1{% + \pgfluamathgetresult{pgfluamathfunctions.sqrt(#1)}} +\def\pgfluamathrnd@{% + \pgfluamathgetresult{pgfluamathfunctions.rnd()}} +\def\pgfluamathrand@{% + \pgfluamathgetresult{pgfluamathfunctions.rand(-1,1)}} +\def\pgfluamathfactorial@#1{% + \pgfluamathgetresult{pgfluamathfunctions.factorial(#1)}} +\def\pgfluamathreciprocal#1{% + \pgfluamathgetresult{1/#1}} +% \pgfluamath@install@function\pgfmath@pi=\pgfluamathpi@% +% \pgfluamath@install@function\pgfmathpi=\pgfluamathpi@% +% \pgfluamath@install@function\pgfmathe@=\pgfluamathe@% +% \pgfluamath@install@function\pgfmathe=\pgfluamathe@% +% \pgfluamath@install@function\pgfmathlessthan@=\pgfluamathlessthan@% +% \pgfluamath@install@function\pgfmathless@=\pgfluamathlessthan@% +% \pgfluamath@install@function\pgfmathgreaterthan@=\pgfluamathgreaterthan@% +% \pgfluamath@install@function\pgfmathgreater@=\pgfluamathgreaterthan@% +% \pgfluamath@install@function\pgfmathpow@=\pgfluamathpow@ +% \pgfluamath@install@function\pgfmathrand@=\pgfluamathrand@ +% \pgfluamath@install@function\pgfmathrand=\pgfluamathrand@ +% \pgfluamath@install@function\pgfmathrnd@=\pgfluamathrnd@ +% \pgfluamath@install@function\pgfmathrnd=\pgfluamathrnd@ +% \pgfluamath@install@function\pgfmathtrue@=\pgfluamathtrue@ +% \pgfluamath@install@function\pgfmathfalse@=\pgfluamathfalse@ +% \pgfluamath@install@function\pgfmathnot@=\pgfluamathnot@ +% \pgfluamath@install@function\pgfmathhex@=\pgfluamathhex@ +% \pgfluamath@install@function\pgfmathHex@=\pgfluamathHex@ +% \pgfluamath@install@function\pgfmathoct@=\pgfluamathoct@ +% \pgfluamath@install@function\pgfmathbin@=\pgfluamathbin@ +% \pgfluamath@install@function\pgfmathand@=\pgfluamathand@ +% \pgfluamath@install@function\pgfmathor@=\pgfluamathor@ +% \pgfluamath@install@function\pgfmathfactorial@=\pgfluamathfactorial@ +% \pgfluamath@install@function\pgfmathveclen@=\pgfluamathveclen@ +% \pgfluamath@install@function\pgfmathcosh@=\pgfluamathcosh@ +% \pgfluamath@install@function\pgfmathsinh@=\pgfluamathsinh@ +% \pgfluamath@install@function\pgfmathtanh@=\pgfluamathtanh@ + +\def\pgfluamathpointnormalised#1{% + \pgf@process{#1}% + \pgfutil@directlua{% + pgfluamathfunctions.pointnormalised(% + \pgf@sys@tonumber{\pgf@x},\pgf@sys@tonumber{\pgf@y})}% + \ignorespaces} + +% Parser + +\newif\ifpgfluamathunitsdeclared + +% true if and only if LUA failed to evaluate the expression and the +% expression was evaluated by means of the TeX parser as fallback. +% +% This happens +% - for \chardef'ed boxes for which LUA lacks evaluation capabilities +% - if the expression includes some function which is unavailable in +% LUA (defined only in TeX) +% - some special cases which simply haven't been added to the LUA +% parser (yet). +% At the time of this writing, this includes +% -- arrays created via '{}' and indexed with '[]' +% -- strings with "<str>" +% -- 'scalar' function +% -- hex/octal/binary input +\newif\ifpgfluamathusedTeXfallback + +% Parses the math expression and defines \pgfmathresult and +% \ifpgfmathunitsdeclared to contain the result. +% +% If \ifpgfluamathparseractive then the result is also assigned to +% \pgfmathresult. Furthermore, if the expression cannot be evaluated (because LUA does not support +% it), it will be evaluated by mean of TeX as fallback. +% +% @see \ifpgfluamathusedTeXfallback +% @see \ifpgfluamathshowerrormessage +\def\pgfluamathparse#1{% + \pgfluamathusedTeXfallbackfalse + \pgfutil@directlua{pgfluamathparser.texCallParser( + "\pgfutil@luaescapestring{#1}", + \pgfluamath@outputformat@choice, + \ifpgfluamathshowerrormessage true\else false\fi)% + }% + \ifx\pgfmathresult\pgfutil@empty + \ifpgfluamathenableTeXfallback + \pgfluamathusedTeXfallbacktrue + \pgfluamath@pgfmathparse{#1}% + \fi + \fi +} + +\catcode`\"=\pgfliblua@oldcatcodedoublequote +\endinput diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgfmathfloat.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgfmathfloat.code.tex index 58eb9de28f1..241741e53b4 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgfmathfloat.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_pgfmathfloat.code.tex @@ -19,7 +19,7 @@ % with the deployment of this patch or partial content of PGF. Note that the author and/or maintainer of pgfplots has no obligation to fix anything: % This file comes without any warranty as the rest of pgfplots; there is no obligation for help. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% Date of this copy: Di 25. Dez 18:14:20 CET 2012 %%% +%%% Date of this copy: Di 30. Dez 15:31:24 CET 2014 %%% @@ -452,8 +452,29 @@ % Expands a floating point number to scientific format 1.234e5. % % This operation is very fast. -\def\pgfmathfloatvalueof#1{\expandafter\pgfmathfloatvalueof@@#1\relax}% -\def\pgfmathfloatvalueof@@#1Y#2e#3]\relax{% +\def\pgfmathfloatvalueof#1{\expandafter\pgfmathfloatvalueof@@#1@@}% + +% Make it fool proof such that the following arguments work: +% \pgfmathfloatvalueof{1Y1.0e1} -> 1.0e1 +% \pgfmathfloatvalueof{2Y1.0e1} -> -1.0e1 +% and wrong arguments as well: +% \pgfmathfloatvalueof{1} -> 1 +% \pgfmathfloatvalueof{1e2} -> 1e2 +\def\pgfmathfloatvalueof@@#1#2{% + \if#2Y% + % keep in mind that \pgfmathfloatvalueof should be expandable! + % We must not use \let here. Let's hope that #1 and #2 are + % single tokens (not something which was enclosed by curly + % braces...) + \expandafter\pgfmathfloatvalueof@@@\expandafter#1\expandafter#2% + \else + % Oh - no float!? Ok, we cannot report errors in this context. + % So: make it a feature and return the input argument as-is. + % Might be useful, in fact... + \expandafter\pgfmathfloatvalueof@abort\expandafter#1\expandafter#2% + \fi +} +\def\pgfmathfloatvalueof@@@#1Y#2e#3]@@{% \ifcase#1 % 0.0e0% \or @@ -465,6 +486,8 @@ \or -inf% \fi }% +\def\pgfmathfloatvalueof@abort#1@@{#1}% + % Rounds a fixed point number #1 to \pgfmathfloat@round@precision digits precision and returns @@ -932,6 +955,7 @@ \newif\ifpgfmathprintnumber@showpositive \newif\ifpgfmathprintnumber@frac@warn \newif\ifpgfmathprintnumber@frac@whole +\newif\ifpgfmathparsenumber@comma@as@period \long\def\pgfmathfloatfrac@verbatim#1#2{#1/#2}% @@ -1012,6 +1036,8 @@ showpos/.default=true, print sign/.is if=pgfmathprintnumber@showpositive, print sign/.default=true, + read comma as period/.is if=pgfmathparsenumber@comma@as@period, + read comma as period/.default=true, skip 0./.is if=pgfmathprintnumberskipzeroperiod, skip 0./.default=true, skip 0.= false, @@ -1276,7 +1302,7 @@ % The numerator and denominator is always a number (not empty) \def\pgfmathfloatgetfrac#1{% \pgfutil@ifundefined{pgfmathfloatmultiply@}{% - \PackageError{tikz}{Sorry, the number format 'frac' requires '\string\usetikzlibrary{fpu}' (and, optionally, \string\usepackage{fp}) in order to work correctly}{}% + \pgfmath@PackageError{Sorry, the number format 'frac' requires '\string\usetikzlibrary{fpu}' (and, optionally, \string\usepackage{fp}) in order to work correctly}% \edef\pgfmathresult{{#1}{0}{1}}% }{% \pgfmathfloatgetfrac@{#1}% @@ -2270,6 +2296,9 @@ \pgfmathfloatcreate{0}{0.0}{0}% }% },% + /pgf/fpu/handlers/invalid separator/.code 2 args={% + \pgfmath@error{Could not parse input '#1' as a floating point number, sorry. The unreadable part was near the decimal separator '#2'. Do you need the option 'read comma as period'?}{}% + }, /pgf/fpu/handlers/invalid number/.code 2 args={% \pgfmath@error{Could not parse input '#1' as a floating point number, sorry. The unreadable part was near '#2'.}{}% }, @@ -2342,6 +2371,30 @@ \expandafter\def\csname pgffltA@.\endcsname{% read '.9' like '0.9' \pgfmathfloat@a@E=-1 \pgfflt@leadingzero@foundperiod}% +\expandafter\def\csname pgffltA@,\endcsname{% read ',9' like '0,9' + \pgfmathfloat@frenchinput{% + \pgfmathfloat@a@E=-1 + \pgfflt@leadingzero@foundperiod + }% +}% + +\def\pgfmathfloat@frenchinput#1{% + \ifpgfmathparsenumber@comma@as@period + \def\pgf@marshal{#1}% + \expandafter\pgf@marshal + \else + \expandafter\pgfflt@error@separator\expandafter,% + \fi +}% +\def\pgfflt@error@separator#1\pgfflt@EOI{% + \begingroup + \pgfmathfloat@a@Mtok={#1}% + \xdef\pgfmathfloat@glob@TMP{% + \noexpand\pgfmathfloatparsenumber@handleerror + {invalid separator}{\pgfmathresult}{\the\pgfmathfloat@a@Mtok}}% + \endgroup + \pgfmathfloat@glob@TMP +}% \def\pgfflt@finish#1\pgfflt@EOI{} @@ -2399,6 +2452,12 @@ \expandafter\def\csname pgffltB@.\endcsname{% \pgfmathfloat@a@E=-1 \pgfflt@leadingzero@foundperiod}% +\expandafter\def\csname pgffltB@,\endcsname{% + \pgfmathfloat@frenchinput{% + \pgfmathfloat@a@E=-1 + \pgfflt@leadingzero@foundperiod + }% +}% \expandafter\def\csname pgffltB@e\endcsname{% \pgfmathfloat@a@S=0\relax% \pgfmathfloat@a@Mtok={0.0}% @@ -2463,6 +2522,7 @@ \expandafter\def\csname pgffltD@9\endcsname{\pgffltD@nonzerodigit9}% \expandafter\def\csname pgffltD@\pgfmathfloat@POSTFLAGSCHAR\endcsname{\pgfflt@readlowlevelfloat}% \expandafter\def\csname pgffltD@.\endcsname{\pgfflt@finish@number@after@period}% FIXME : inlining? +\expandafter\def\csname pgffltD@,\endcsname{\pgfmathfloat@frenchinput{\pgfflt@finish@number@after@period}}% \expandafter\def\csname pgffltD@e\endcsname{\pgfflt@readexponent}% FIXME : inlining? \let\pgffltD@E=\pgffltD@e \expandafter\def\csname pgffltD@\pgfflt@EOI\endcsname{}% NOP @@ -2522,6 +2582,7 @@ \expandafter\def\csname pgffltE@8\endcsname{\pgffltE@nonzerodigit8}% \expandafter\def\csname pgffltE@9\endcsname{\pgffltE@nonzerodigit9}% \expandafter\def\csname pgffltE@.\endcsname{\pgfflt@finish@number@after@period}% FIXME : inlining? +\expandafter\def\csname pgffltE@,\endcsname{\pgfmathfloat@frenchinput{\pgfflt@finish@number@after@period}}% FIXME : inlining? \def\pgffltE@e{\pgfflt@readexponent}% FIXME : inlining? \let\pgffltE@E=\pgffltE@e \expandafter\def\csname pgffltE@\pgfflt@EOI\endcsname{}% NOP diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_tikzexternalshared.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_tikzexternalshared.code.tex index b1e21bc5222..adf818bef7e 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_tikzexternalshared.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_tikzexternalshared.code.tex @@ -19,7 +19,7 @@ % with the deployment of this patch or partial content of PGF. Note that the author and/or maintainer of pgfplots has no obligation to fix anything: % This file comes without any warranty as the rest of pgfplots; there is no obligation for help. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% Date of this copy: Mi 9. Jul 15:41:39 CEST 2014 %%% +%%% Date of this copy: So 11. Jan 19:35:13 CET 2015 %%% @@ -123,15 +123,22 @@ }% -\pgfutil@ifundefined{pdfshellescape}{% - \def\tikzexternalcheckshellescape{}% +\pgfutil@IfUndefined{pdfshellescape}{% + % let's hope that \usepackage{pdftexcmds} has been used... + \pgfutil@IfUndefined{pdf@shellescape}{% + \def\tikzexternalcheckshellescape{0}% + }{% + \let\tikzexternalcheckshellescape=\pdf@shellescape + }% }{% - \ifnum\pdfshellescape=1 - \def\tikzexternalcheckshellescape{\pgfkeysvalueof{/tikz/external/shell escape}\space}% - \else - \def\tikzexternalcheckshellescape{}% - \fi + \let\tikzexternalcheckshellescape=\pdfshellescape }% +\ifnum\tikzexternalcheckshellescape=1 + \def\tikzexternalcheckshellescape{\pgfkeysvalueof{/tikz/external/shell escape}\space}% +\else + \def\tikzexternalcheckshellescape{}% +\fi + \newif\iftikzexternal@auto@detect@jobname \pgfqkeys{/tikz/external}{ @@ -257,6 +264,7 @@ \fi }, optimize command away=\includegraphics, + optimize command away=\pgfincludeexternalgraphics, % EXPERIMENTAL (UNTESTED): optimize latex env away/.code={% \expandafter\let\expandafter\pgf@tempa\csname #1\endcsname diff --git a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_trig_format.code.tex b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_trig_format.code.tex index 4937d000e0a..4ebb95439e7 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_trig_format.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/oldpgfcompatib/pgfplotsoldpgfsupp_trig_format.code.tex @@ -30,6 +30,43 @@ \fi }% +\pgfutil@ifundefined{pgfmath@multiply@thousand}{% + % Oh - we are working against PGF 2.10 . Apply more patches: + % + \def\pgfmath@multiply@thousand#1.#2#3#4#5\relax{% + \edef\pgfmathresult{#1#2#3#4.#5}% + }% + % Defines \pgfmath@x to be the result of the table lookup for value + % '#1' in table '#2' + % + % #1: a value for which lookup should be performed + % #2: the table's prefix name + % #3: the table's size + \def\pgfmath@table@lookup#1#2#3{% + \pgfmath@x=#1\relax + \expandafter\pgfmath@table@lookup@\the\pgfmath@x\relax{#2}{#3}% + } + \def\pgfmath@table@lookup@#1.#2\relax#3#4{% + \edef\pgf@temp{\Pgf@geT#2}% strip 'pt' suffix. + % + % prepare constant interpolant (i.e. the value at node '#1'): + \pgfmath@x=\csname #3#1\endcsname pt % + % + \c@pgfmath@countc=#1 % + \advance\c@pgfmath@countc by1 % + \ifnum\c@pgfmath@countc<#4 % + % Ah - we have enough elements in the table. + % + % perform linear interpolation: + \pgfmath@ya=\csname #3\the\c@pgfmath@countc\endcsname pt % + \advance\pgfmath@ya by-\pgfmath@x % + \advance\pgfmath@x by0.\pgf@temp\pgfmath@ya + \fi + }% +}{}% + + + \def\pgfmath@scale@rad@to@deg#1{% #1=57.29577#1\relax% 57.29577 = 360/(2*pi) }% diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex index bbf7d10db86..d088694c992 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex @@ -25,7 +25,9 @@ %-------------------------------------------- \edef\pgfplots@oldcatcodesemicolon{\the\catcode`\;}% +\edef\pgfplots@oldcatcodedoublequote{\the\catcode`\"}% \catcode`\;=12 +\catcode`\"=12 \input pgfplotscore.code.tex \input pgfplotslibrary.code.tex @@ -132,6 +134,7 @@ \newif\ifpgfplotsplothandlermesh@hide@refined@edges \newif\ifpgfplots@has@cell@picture \newif\ifpgfplots@substitute@pgfpoint +\newif\ifpgfplots@LUA@backend@supported \newif\ifpgfplots@collect@firstplot@astick \newif\ifpgfplots@units@use @@ -515,6 +518,10 @@ }% } +\newif\ifpgfplots@LUA@fail@on@TeX@fallback +\def\pgfplots@LUA@loglevel@info{4} +\def\pgfplots@LUA@loglevel@debug{5} + \pgfkeys{% /pgfplots/search path for tikz/.search also={/tikz,/pgfplots}, /pgfplots/.is family, @@ -594,6 +601,38 @@ /pgfplots/on layer/.initial=, % mark layer can be 'auto', 'like plot', or a layer name. /pgfplots/mark layer/.initial=, + /pgfplots/lua backend/.is if=pgfplots@LUA@backend@supported, + /pgfplots/lua backend/.default=true, + % + /pgfplots/lua debug/.is choice, + /pgfplots/lua debug/false/.style={/pgfplots/lua debug/off},% + /pgfplots/lua debug/off/.code={% + \def\pgfplots@LUA@backend@debugmode{off}% + \def\pgfplots@LUA@loglevel@debug{5}% + \def\pgfplots@LUA@loglevel@info{4}% + \pgfplots@LUA@fail@on@TeX@fallbackfalse + }, + /pgfplots/lua debug/off and silent/.code={% + \def\pgfplots@LUA@backend@debugmode{off and silent}% + \def\pgfplots@LUA@loglevel@debug{5}% + \def\pgfplots@LUA@loglevel@info{5}% + \pgfplots@LUA@fail@on@TeX@fallbackfalse + }, + % + /pgfplots/lua debug/verbose/.code={% + \def\pgfplots@LUA@backend@debugmode{verbose}% + \def\pgfplots@LUA@loglevel@debug{4}% + \def\pgfplots@LUA@loglevel@info{4}% + \pgfplots@LUA@fail@on@TeX@fallbackfalse + }, + /pgfplots/lua debug/compileerror/.code={% + \def\pgfplots@LUA@backend@debugmode{compileerror}% + \def\pgfplots@LUA@loglevel@debug{4}% + \def\pgfplots@LUA@loglevel@info{4}% + \pgfplots@LUA@fail@on@TeX@fallbacktrue + }, + /pgfplots/lua debug/.default=verbose, + /pgfplots/lua debug=off, /pgfplots/every axis/.style={}, /pgfplots/every axis/.append code={\pgfplotsdeprecatedstylecheck{/tikz/every axis}}, /pgfplots/every axis/.belongs to family=/pgfplots/style commands, @@ -877,6 +916,8 @@ xticklabel=, ytick=, yticklabel=, + zmin=, + zmax=, }, /pgfplots/colorbar right/.style={% /pgfplots/colorbar=true, @@ -1030,8 +1071,9 @@ domain=\pgfkeysvalueof{/pgfplots/point meta min}:\pgfkeysvalueof{/pgfplots/point meta max}, samples y=2, domain y=0:1, + every colorbar, zmin=0,zmax=1, - every colorbar,colorbar shift,colorbar=false] + colorbar shift,colorbar=false] \pgfkeysvalueof{/pgfplots/colorbar addplot}% \endaxis },% @@ -1798,6 +1840,9 @@ /pgfplots/z filter/.code={}, /pgfplots/z filter/.belongs to family=/pgfplots, /pgfplots/filter point/.code=, + /pgfplots/x filter/.expression/.code=\pgfplots@install@filter@expression{x filter}{#1}, + /pgfplots/y filter/.expression/.code=\pgfplots@install@filter@expression{y filter}{#1}, + /pgfplots/z filter/.expression/.code=\pgfplots@install@filter@expression{z filter}{#1}, /pgfplots/restrict x to domain/.style={/pgfplots/@restrict to domain={x}{}{#1}{0}},% /pgfplots/restrict y to domain/.style={/pgfplots/@restrict to domain={y}{}{#1}{0}},% /pgfplots/restrict z to domain/.style={/pgfplots/@restrict to domain={z}{}{#1}{0}},% @@ -3454,7 +3499,7 @@ /pgfplots/point meta/TeX code/.value required, /pgfplots/point meta/TeX code symbolic/.code={\pgfplotssetpointmetainput{TeX code symbolic}{#1}},% /pgfplots/point meta/TeX code symbolic/.value required, - /pgfplots/point meta/symbolic/.style={/pgfplots/point meta/TeX code symbolic={\def\pgfplotspointmeta{#1}}}, + /pgfplots/point meta/symbolic/.style={/pgfplots/point meta/TeX code symbolic={\edef\pgfplotspointmeta{#1}}}, /pgfplots/set point meta if empty/.code={% \ifx\pgfplotspointmetainputhandler\pgfutil@empty \pgfkeysalso{/pgfplots/point meta=#1}% @@ -3693,6 +3738,7 @@ /pgfplots/compat/anchors/1.9/.style= {/pgfplots/compat/anchors/1.3},% /pgfplots/compat/anchors/1.10/.style= {/pgfplots/compat/anchors/1.3},% /pgfplots/compat/anchors/1.11/.style= {/pgfplots/compat/anchors/1.3},% + /pgfplots/compat/anchors/1.12/.style= {/pgfplots/compat/anchors/1.3},% /pgfplots/compat/anchors/newest/.style= {/pgfplots/compat/anchors/1.3},% /pgfplots/compat/anchors/default/.style={/pgfplots/compat/anchors/1.3},% % @@ -3708,6 +3754,7 @@ /pgfplots/compat/empty line/1.9/.style= {/pgfplots/compat/empty line/1.4},% /pgfplots/compat/empty line/1.10/.style= {/pgfplots/compat/empty line/1.4},% /pgfplots/compat/empty line/1.11/.style= {/pgfplots/compat/empty line/1.4},% + /pgfplots/compat/empty line/1.12/.style= {/pgfplots/compat/empty line/1.4},% /pgfplots/compat/empty line/newest/.style= {/pgfplots/compat/empty line/1.4},% /pgfplots/compat/empty line/default/.style= {/pgfplots/compat/empty line/1.4},% % @@ -3723,6 +3770,7 @@ /pgfplots/compat/path replacement/1.9/.style= {/pgfplots/compat/path replacement/1.5.1}, /pgfplots/compat/path replacement/1.10/.style= {/pgfplots/compat/path replacement/1.5.1}, /pgfplots/compat/path replacement/1.11/.style= {/pgfplots/compat/path replacement/1.5.1}, + /pgfplots/compat/path replacement/1.12/.style= {/pgfplots/compat/path replacement/1.5.1}, /pgfplots/compat/path replacement/newest/.style= {/pgfplots/compat/path replacement/1.5.1},% /pgfplots/compat/path replacement/default/.style= {/pgfplots/compat/path replacement/pre 1.3},% % @@ -3738,6 +3786,7 @@ /pgfplots/compat/pgfpoint substitution/1.9/.style= {/pgfplots/compat/pgfpoint substitution/pre 1.3}, /pgfplots/compat/pgfpoint substitution/1.10/.style= {/pgfplots/compat/pgfpoint substitution/pre 1.3}, /pgfplots/compat/pgfpoint substitution/1.11/.code= {\pgfplots@substitute@pgfpointtrue}, + /pgfplots/compat/pgfpoint substitution/1.12/.style= {/pgfplots/compat/pgfpoint substitution/1.11}, /pgfplots/compat/pgfpoint substitution/newest/.style= {/pgfplots/compat/pgfpoint substitution/1.11},% /pgfplots/compat/pgfpoint substitution/default/.style= {/pgfplots/compat/pgfpoint substitution/pre 1.3},% %ellipse/.is if=pgfplots@path@replace@ellipse, @@ -3763,6 +3812,7 @@ /pgfplots/compat/labels/1.9/.style= {/pgfplots/compat/labels/1.8},% /pgfplots/compat/labels/1.10/.style= {/pgfplots/compat/labels/1.8},% /pgfplots/compat/labels/1.11/.style= {/pgfplots/compat/labels/1.8},% + /pgfplots/compat/labels/1.12/.style= {/pgfplots/compat/labels/1.8},% /pgfplots/compat/labels/newest/.style= {/pgfplots/compat/labels/1.8},% /pgfplots/compat/labels/default/.style= {/pgfplots/compat/labels/pre 1.3},% maintain backwards compatibility % @@ -3802,6 +3852,7 @@ },% /pgfplots/compat/bar nodes/1.10/.style= {/pgfplots/compat/bar nodes/1.9},% /pgfplots/compat/bar nodes/1.11/.style= {/pgfplots/compat/bar nodes/1.9},% + /pgfplots/compat/bar nodes/1.12/.style= {/pgfplots/compat/bar nodes/1.9},% /pgfplots/compat/bar nodes/newest/.style= {/pgfplots/compat/bar nodes/1.9},% /pgfplots/compat/bar nodes/default/.style= {/pgfplots/compat/bar nodes/pre 1.3},% maintain backwards compatibility /pgfplots/compat/bar nodes/default, @@ -3832,6 +3883,7 @@ /pgfplots/compat/scaling/1.9/.style={/pgfplots/compat/scaling/1.6}, /pgfplots/compat/scaling/1.10/.style={/pgfplots/compat/scaling/1.6}, /pgfplots/compat/scaling/1.11/.style={/pgfplots/compat/scaling/1.6}, + /pgfplots/compat/scaling/1.12/.style={/pgfplots/compat/scaling/1.6}, /pgfplots/compat/scaling/newest/.style={/pgfplots/compat/scaling/1.6}, /pgfplots/compat/scaling/default/.style={/pgfplots/compat/scaling/1.4}, % @@ -3847,6 +3899,7 @@ /pgfplots/compat/scale mode/1.9/.style={/pgfplots/compat/scale mode/1.6}, /pgfplots/compat/scale mode/1.10/.style={/pgfplots/compat/scale mode/1.6}, /pgfplots/compat/scale mode/1.11/.style={/pgfplots/compat/scale mode/1.6}, + /pgfplots/compat/scale mode/1.12/.style={/pgfplots/compat/scale mode/1.6}, /pgfplots/compat/scale mode/newest/.style={/pgfplots/compat/scale mode/1.6}, /pgfplots/compat/scale mode/default/.style={/pgfplots/compat/scale mode/1.5}, % @@ -3863,6 +3916,7 @@ /pgfplots/compat/plot3graphics/1.9/.style= {/pgfplots/compat/plot3graphics/1.6},% /pgfplots/compat/plot3graphics/1.10/.style= {/pgfplots/compat/plot3graphics/1.6},% /pgfplots/compat/plot3graphics/1.11/.style= {/pgfplots/compat/plot3graphics/1.6},% + /pgfplots/compat/plot3graphics/1.12/.style= {/pgfplots/compat/plot3graphics/1.6},% /pgfplots/compat/plot3graphics/newest/.style= {/pgfplots/compat/plot3graphics/1.6},% /pgfplots/compat/plot3graphics/default/.style= {/pgfplots/compat/plot3graphics/1.5},% % @@ -3905,6 +3959,7 @@ /pgfplots/compat/bar width by units/1.9/.style= {/pgfplots/compat/bar width by units/1.7}, /pgfplots/compat/bar width by units/1.10/.style= {/pgfplots/compat/bar width by units/1.7}, /pgfplots/compat/bar width by units/1.11/.style= {/pgfplots/compat/bar width by units/1.7}, + /pgfplots/compat/bar width by units/1.12/.style= {/pgfplots/compat/bar width by units/1.7}, /pgfplots/compat/bar width by units/newest/.style= {/pgfplots/compat/bar width by units/1.7}, /pgfplots/compat/bar width by units/default/.style={/pgfplots/compat/bar width by units/pre 1.3}, % @@ -3920,22 +3975,40 @@ /pgfplots/compat/BB/1.9/.style= {/pgfplots/compat/BB/1.8},% /pgfplots/compat/BB/1.10/.style= {/pgfplots/compat/BB/1.8},% /pgfplots/compat/BB/1.11/.style= {/pgfplots/compat/BB/1.8},% + /pgfplots/compat/BB/1.12/.style= {/pgfplots/compat/BB/1.8},% /pgfplots/compat/BB/newest/.style= {/pgfplots/compat/BB/1.8}, /pgfplots/compat/BB/default/.style={/pgfplots/compat/BB/pre 1.3}, % /pgfplots/compat/general/.is choice, - /pgfplots/compat/general/pre 1.3/.style={/pgfplots/log origin=infty,/pgfplots/enable tick line clipping=true},% + /pgfplots/compat/general/pre 1.3/.style={ + /pgfplots/log origin=infty, + /pgfplots/enable tick line clipping=true, + /pgfplots/lua backend=false, + /pgfplots/compat/library hook={statistics}{/pgfplots/boxplot/estimator=legacy,/pgfplots/boxplot/ensure mark=false}, + },% /pgfplots/compat/general/1.3/.style= {/pgfplots/compat/general/pre 1.3}, /pgfplots/compat/general/1.4/.style= {/pgfplots/compat/general/pre 1.3},% - /pgfplots/compat/general/1.5/.style= {/pgfplots/log origin=0,/pgfplots/enable tick line clipping=true},% + /pgfplots/compat/general/1.5/.style= { + /pgfplots/compat/general/pre 1.3, + /pgfplots/log origin=0, + /pgfplots/enable tick line clipping=true, + },% /pgfplots/compat/general/1.5.1/.style= {/pgfplots/compat/general/1.5},% /pgfplots/compat/general/1.6/.style= {/pgfplots/compat/general/1.5},% /pgfplots/compat/general/1.7/.style= {/pgfplots/compat/general/1.5},% /pgfplots/compat/general/1.8/.style= {/pgfplots/compat/general/1.5},% /pgfplots/compat/general/1.9/.style= {/pgfplots/compat/general/1.5},% /pgfplots/compat/general/1.10/.style= {/pgfplots/compat/general/1.5},% - /pgfplots/compat/general/1.11/.style= {/pgfplots/compat/general/1.5,/pgfplots/enable tick line clipping=false},% - /pgfplots/compat/general/newest/.style= {/pgfplots/compat/general/1.11}, + /pgfplots/compat/general/1.11/.style= { + /pgfplots/compat/general/1.5, + /pgfplots/enable tick line clipping=false, + },% + /pgfplots/compat/general/1.12/.style= { + /pgfplots/compat/general/1.11, + /pgfplots/lua backend, + /pgfplots/compat/library hook={statistics}{/pgfplots/boxplot/estimator=Excel,/pgfplots/boxplot/ensure mark=true}, + },% + /pgfplots/compat/general/newest/.style= {/pgfplots/compat/general/1.12}, /pgfplots/compat/general/default/.style={/pgfplots/compat/general/1.11}, % /pgfplots/enable tick line clipping/.is if=pgfplots@enable@tick@line@clipping, @@ -3953,7 +4026,7 @@ /pgfplots/compat/show suggested version/.is if=pgfplots@show@suggested@version, /pgfplots/compat/show suggested version=true, /pgfplots/compat/current/.initial=, - /pgfplots/compat/mostrecent/.initial=1.11, + /pgfplots/compat/mostrecent/.initial=1.12, /pgfplots/compat/.style={% % ATTENTION: *every* /pgfplots/compat/ setting needs to accept % the same choices due to this construction: @@ -7871,11 +7944,13 @@ \pgfplots@error{Sorry, 'cell picture=false' is UNSUPPORTED for 'anchor=\pgfplots@anchorname'.}% \fi \if2\pgfplots@cell@picture@mode - \pgfplots@log3{'cell picture=if necessary' resulted in 'cell picture=true'}% + \pgfplots@log5{'cell picture=if necessary' resulted in 'cell picture=true'}% \fi #1\relax }{% - \pgfplots@log3{'cell picture=if necessary' resulted in 'cell picture=false'}% + \if2\pgfplots@cell@picture@mode + \pgfplots@log5{'cell picture=if necessary' resulted in 'cell picture=false'}% + \fi % OK, an a priori anchor is available - we do not really need % a cell picture and this is compatible with the input % options: @@ -9636,6 +9711,9 @@ \pgfkeyssetfamily{/tikz/overlay}{/pgfplots/shared with tikz}% \pgfkeyssetfamily{/tikz/variable}{/pgfplots}% % + \pgfkeysdef{/pgfplots/declare function}{\pgfkeysalso{/pgf/declare function={##1}}}% + \pgfkeyssetfamily{/pgf/declare function}{/pgfplots}% + % % ... we need to set these options during the survey phase % (because it might be interesting for enlarge limits to depend % upon their value): @@ -10314,6 +10392,61 @@ }% }% +% Callback if the LUA backend does not support a sub-operation. The +% reason will be logged. +\def\pgfplots@LUA@backend@failed{% + \ifpgfplots@LUA@fail@on@TeX@fallback + \pgfplots@error{lua backend has been deactivated since some input option is unsupported and 'lua debug=compileerror' is active. Please see the most recent message in your .log file for details}% + \fi +}% + +\def\pgfplots@LUA@visualizationlog@deactivation#1{% + \pgfplots@log{\pgfplots@LUA@loglevel@info}{Using 'lua backend=false' for axis: #1.}% + \pgfplots@LUA@backend@failed +}% +\def\pgfplots@prepare@LUA@api{% + \ifpgfplots@LUA@backend@supported + \ifpgfplots@LUA@supported + \else + \pgfplots@LUA@backend@supportedfalse + \fi + % + \ifpgfplots@stackedmode + \pgfplots@LUA@visualizationlog@deactivation{stacked plots unsupported (yet)}% + \pgfplots@LUA@backend@supportedfalse + \fi + % + \ifpgfplots@xislinear\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@visualizationlog@deactivation{xmode=log unsupported (yet)}\fi + \ifpgfplots@yislinear\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@visualizationlog@deactivation{ymode=log unsupported (yet)}\fi + \ifpgfplots@zislinear\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@visualizationlog@deactivation{zmode=log unsupported (yet)}\fi + % + \pgfkeysgetvalue{/pgfplots/x coord trafo/.@cmd}\pgfplots@loc@TMPc\ifx\pgfplots@loc@TMPc\pgfplots@empty@command@key\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@visualizationlog@deactivation{x coord trafo unsupported}\fi + \pgfkeysgetvalue{/pgfplots/y coord trafo/.@cmd}\pgfplots@loc@TMPc\ifx\pgfplots@loc@TMPc\pgfplots@empty@command@key\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@visualizationlog@deactivation{x coord trafo unsupported}\fi + \pgfkeysgetvalue{/pgfplots/z coord trafo/.@cmd}\pgfplots@loc@TMPc\ifx\pgfplots@loc@TMPc\pgfplots@empty@command@key\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@visualizationlog@deactivation{x coord trafo unsupported}\fi + % + % FIXME: collect all remaining items + % + \ifpgfplots@LUA@backend@supported + \pgfplots@log{\pgfplots@LUA@loglevel@debug}{lua backend=true: Activating LUA backend for axis.}% + \directlua{% + pgfplots.gca = pgfplots.Axis.new(); + pgfplots.gca.is3d = \pgfplots@boolval{pgfplots@threedim}; + pgfplots.gca.clipLimits = \pgfplots@boolval{pgfplots@clip@limits}; + pgfplots.gca.autocomputeAllLimits = \pgfplots@boolval{pgfplots@autocompute@all@limits}; + pgfplots.gca.autocomputeMin = { + \pgfplots@boolval{pgfplots@autocompute@xmin}, + \pgfplots@boolval{pgfplots@autocompute@ymin}, + \pgfplots@boolval{pgfplots@autocompute@zmin} }; + pgfplots.gca.autocomputeMax = { + \pgfplots@boolval{pgfplots@autocompute@xmax}, + \pgfplots@boolval{pgfplots@autocompute@ymax}, + \pgfplots@boolval{pgfplots@autocompute@zmax} }; + % attention: min/max is (also) handed over in \pgfplots@LUA@survey@start + }% + \fi + \fi +}% + \long\def\pgfplotsifissurveyphase#1#2{% \if\pgfplots@phase@name s% #1\relax @@ -10623,6 +10756,7 @@ % % defines \pgfplotsaxisupdatelimitsforcoordinate etc. \pgfplots@prepare@axis@API + \pgfplots@prepare@LUA@api \pgfkeysvalueof{/pgfplots/execute at begin axis}% \pgfkeysvalueof{/pgfplots/execute at begin axis@@}% \def\pgfplots@phase@name{s}% @@ -10683,6 +10817,10 @@ % ensure that (1,2) is automatically converted to (axis cs:1,2) : \pgfplots@change@pgfpoints@to@axiscs % + \ifpgfplots@LUA@backend@supported + \pgfplots@LUA@visualization@update@axis + \fi + % % make it ungrouped: we must not destroy group nesting of tikz % path instructions at this point. \pgfplotslistforeachungrouped\pgfplots@stored@plotlist\as\pgfplots@loc@TMPa{% @@ -10760,6 +10898,8 @@ \pgfplots@finally@correct@child@node@positions \pgfplots@stacked@finalize % + \pgfplots@LUA@cleanup + % \ifpgfplots@colorbar \pgfplots@colorbar@move@outside@scope@with@globalmacro{\pgfplots@glob@TMPa}% \else @@ -10798,6 +10938,58 @@ \aftergroup\pgfplots@cell@picture@remembered } +\def\pgfplots@LUA@visualization@update@axis{% + \ifpgfplots@threedim + \pgfplotsmathvectortocomponents\pgfplots@view@dir@threedim{pgfplots@loc@}{default}% + \fi + % + \let\pgfplots@loc@TMPa\pgfutil@empty% + \pgfplotscoordmath{x}{datascaletrafo get params}% + \edef\pgfplots@loc@TMPa{% + \pgfplots@loc@TMPa + local datascaleTrafoX = pgfplots.DatascaleTrafo.new(\pgfplotsretval,\pgfplotsretvalb);^^J + }% + \pgfplotscoordmath{y}{datascaletrafo get params}% + \edef\pgfplots@loc@TMPa{% + \pgfplots@loc@TMPa + local datascaleTrafoY = pgfplots.DatascaleTrafo.new(\pgfplotsretval,\pgfplotsretvalb);^^J + }% + \pgfplotscoordmath{z}{datascaletrafo get params}% + \edef\pgfplots@loc@TMPa{% + \pgfplots@loc@TMPa + local datascaleTrafoZ = pgfplots.DatascaleTrafo.new(\pgfplotsretval,\pgfplotsretvalb);^^J + }% + % + \edef\pgfplots@loc@TMPa{% + \pgfplots@loc@TMPa + local axis = pgfplots.gca;^^J% + % FIXME : what about datamin/max? + axis.axiswidemetamin = pgfplots.pgftonumber("\pgfplots@axiswide@metamin"); ^^J% + axis.axiswidemetamax = pgfplots.pgftonumber("\pgfplots@axiswide@metamax"); ^^J% + axis.datascaleTrafo = { datascaleTrafoX, datascaleTrafoY, datascaleTrafoZ };^^J% + axis:setunitvectors({ % + { \pgf@sys@tonumber\pgf@xx, \pgf@sys@tonumber\pgf@xy }, + { \pgf@sys@tonumber\pgf@yx, \pgf@sys@tonumber\pgf@yy }, + { \pgf@sys@tonumber\pgf@zx, \pgf@sys@tonumber\pgf@zy } });^^J% + \ifpgfplots@threedim + axis.viewdir = { + pgfplots.pgftonumber("\pgfplots@loc@x"), + pgfplots.pgftonumber("\pgfplots@loc@y"), + pgfplots.pgftonumber("\pgfplots@loc@z") };^^J% + \fi + }% +%\message{Executing \pgfplots@loc@TMPa}% + \directlua{\pgfplots@loc@TMPa} +}% + +\def\pgfplots@LUA@cleanup{% + \ifpgfplots@LUA@backend@supported + \directlua{pgfplots.gca=nil}% + \fi +}% + +% +% This is part of \ifpgfplots@substitute@pgfpoint: \def\pgfplots@environment@opt@@setup@pgfpoint@restores{% % There are places in pgfplots where the default coordinate system % (i.e. the one used whenever one writes (1,2)) needs to be @@ -10818,6 +11010,9 @@ \let\pgfsetyvec@orig=\pgfsetyvec \let\pgfsetzvec@orig=\pgfsetzvec \let\tikz@checkunit@orig=\tikz@checkunit + \let\pgfpatharcaxes@orig=\pgfpatharcaxes + \let\pgfpointpolarxy@orig=\pgfpointpolarxy + \let\tikz@do@arc@orig=\tikz@do@arc % \let\pgfsetxvec=\pgfplots@setxvec@restorepgfpoint \let\pgfsetyvec=\pgfplots@setyvec@restorepgfpoint @@ -10830,6 +11025,9 @@ \let\pgfpointxyz=\pgfpointxyz@orig \let\pgfqpointxyz=\pgfqpointxyz@orig \let\tikz@checkunit=\tikz@checkunit@orig + \let\pgfpointpolarxy=\pgfpointpolarxy@orig + \let\pgfpatharcaxes=\pgfpatharcaxes@orig + \let\tikz@do@arc=\tikz@do@arc@orig }% \def\pgfplots@setxvec@restorepgfpoint#1{% @@ -10889,6 +11087,13 @@ % axis = 2d and plot=3d is forbidden here. \pgfplots@curplot@threedimfalse \fi + % + % + \pgfplots@LUA@visualization@init + % SIDE-effect: \ifpgfplots@LUA@backend@supported might have + % been switched to false here. + % + % \pgfplots@execute@at@begin@plot@visualization@internal % \pgfplots@markers@prepare@layered@graphics@marks @@ -10969,7 +11174,7 @@ \pgfplots@change@pgfpoints@to@axiscs \pgfplots@markers@install@plotmark@handler \let\pgfplots@visphase@name=\pgfplotsaxis@visphase@name@markers - \expandafter\pgfplots@coord@stream@finalize@storedcoords@START\pgfplots@stored@current@data\pgfplots@EOI + \pgfplots@coord@stream@finalize@storedcoords@START \endgroup }% @@ -10984,6 +11189,9 @@ \let\pgfpointxyz=\pgfplotspointaxisxyz \let\pgfqpointxy=\pgfplotsqpointaxisxy \let\pgfqpointxyz=\pgfplotsqpointaxisxyz + \let\pgfpatharcaxes=\pgfplots@patharcaxes + \let\pgfpointpolarxy=\pgfplots@pointpolarxy + \let\tikz@do@arc=\pgfplots@tikz@do@arc % % tikz checks for units before it calls \pgfpointxy . This must % not suffer from TeX's math restrictions, so we have to use the @@ -10992,19 +11200,109 @@ \fi }% +\def\pgfplots@disable@directionmath{% + \def\pgfplotstransformdirectionx##1{\def\pgfmathresult{##1}}% + \let\pgfplotstransformdirectiony=\pgfplotstransformdirectionx + \let\pgfplotstransformdirectionz=\pgfplotstransformdirectionx +}% + +% As of compat=1.11, pgfplots has to accept the following syntax elements: +% +% \draw[green,thick,->] (0,-1) arc[radius=1, start angle= -90, end angle=-180]; +% \draw[green,thick,->] (0,-1) arc[radius=1cm, start angle= -90, end angle=-180]; +% \draw[green,thick,->] (0,-1) arc[radius={transformdirectionx(1)}, start angle= -90, end angle=-180]; +% +% all of them should work. The last one (transformdirectionx) is due +% to legacy compatibility. Since the 1.11 code handles these syntaxes +% automatically, 'transformdirectionx' will be ignored silently. +\def\pgfplots@tikz@do@arc#1#2#3#4{% + \begingroup + % strip 'transformdirectionx' if it occurs in the angles: + \pgfplots@disable@directionmath + \pgfmathparse{#3}% + \t@pgfplots@toka={\tikz@do@arc@orig{#1}{#2}}% + \edef\pgfplots@arc@x{% + \pgfmathresult + \ifpgfmathunitsdeclared pt\fi + }% + \pgfmathparse{#4}% + \xdef\pgfplots@arc@y{% + \pgfmathresult + \ifpgfmathunitsdeclared pt\fi + }% + % ok, invoke the TikZ command with the expanded args: + \xdef\pgfplots@glob@TMPa{\the\t@pgfplots@toka{\pgfplots@arc@x}{\pgfplots@arc@y}}% + \endgroup + \pgfplots@glob@TMPa +}% + +\def\pgfplots@polarxy@#1and #2\@@{% + \edef\pgfplots@polarxy@X{#1}% + \edef\pgfplots@polarxy@Y{#2}% +} +\def\pgfplots@pointpolarxy#1#2{% + \pgfutil@in@{and }{#2}% + \ifpgfutil@in@% + \pgfplots@polarxy@#2\@@% + \else% + \pgfplots@polarxy@#2and #2\@@% + \fi% + \pgfmathparse{#1}% + \let\pgfpoint@angle=\pgfmathresult% + \pgfmathcos@{\pgfpoint@angle}% + \let\pgfpoint@cos=\pgfmathresult + \pgfmathsin@{\pgfpoint@angle}% + \let\pgfpoint@sin=\pgfmathresult + % + \begingroup + \pgfplots@plot@coords@mathparsertrue + \pgf@process{% + \pgfplotspointaxisxyz{\pgfplots@polarxy@X*\pgfpoint@cos}{\pgfplots@polarxy@Y*\pgfpoint@sin}{0}% + }% + \endgroup +}% + +% #1 = angle of first point +% #2 = angle of second point +% #3 = first axis +% #4 = second axis +\def\pgfplots@patharcaxes#1#2#3#4{% + {% + % see docs of \pgfplots@tikz@do@arc for a motivation: + \pgfplots@disable@directionmath + % + % ok, now, evaluate the arcs. Since this implements + % 'substitute pgfpoint', we have to evaluate the angles via + % 'axis direction cs' ... + \let\pgfpointxy=\pgfplotspointaxisdirectionxy + \let\pgfpointxyz=\pgfplotspointaxisdirectionxyz + % + \pgftransformtriangle{\pgfpointorigin}{#3}{#4}% + % + % ... and the coordinates as such using 'axis cs': + \let\pgfpointxy=\pgfplotspointaxisxy + \let\pgfpointxyz=\pgfplotspointaxisxyz + % + \pgfpatharc{#1}{#2}{1pt}% + }% +}% + \def\pgfplots@checkunit@fpu#1{% \ifpgfplots@usefpu - \edef\pgfplots@checkunit@fpu@restore{% - \pgflibraryfpuifactive{% - % ok, leave it active - }{% - \noexpand\pgfkeys{/pgf/fpu=false}% - }% - }% + \begingroup \pgfkeys{/pgf/fpu}% \tikz@checkunit@orig{#1}% \pgfmathfloattofixed{\pgfmathresult}% - \pgfplots@checkunit@fpu@restore + \xdef\pgfplots@glob@TMPd{% + \iftikz@isdimension + \noexpand\tikz@isdimensiontrue + \else + \noexpand\tikz@isdimensionfalse + \fi + \noexpand\def\noexpand\pgfmathresult{\pgfmathresult}% + }% + \endgroup + \pgfplots@glob@TMPd \else \tikz@checkunit@orig{#1}% \fi @@ -11219,3 +11517,4 @@ }% \catcode`\;=\pgfplots@oldcatcodesemicolon +\catcode`\"=\pgfplots@oldcatcodedoublequote diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.code.tex index 42d6c9f4b65..11299b16485 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.errorbars.code.tex @@ -592,7 +592,7 @@ \expandafter\def\csname pgfplots@visphase@\pgfplotsaxis@visphase@name@errorbars\endcsname{% \pgfplots@errorbars@finishwithstyleoptions[]{% \let\tikz@plot@handler=\pgfplots@errorbars@plot@handler - \expandafter\pgfplots@coord@stream@finalize@storedcoords@START\pgfplots@stored@current@data\pgfplots@EOI + \pgfplots@coord@stream@finalize@storedcoords@START }% }% diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code.tex index 902dcecfe14..1e1f8c9a746 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.markers.code.tex @@ -246,8 +246,7 @@ \fi }% - -\def\pgfplots@markers@check@for@default@plot@mark{% +\def\pgfplots@if@has@plot@marks#1#2{% % make sure there is a mark set! \pgfplots@gettikzinternal@keyval{mark}{tikz@plot@mark}{}% \def\pgfplots@loc@TMPa{none}% @@ -256,6 +255,14 @@ \let\tikz@plot@mark\pgfutil@empty \fi \ifx\tikz@plot@mark\pgfutil@empty + #2\relax + \else + #1\relax + \fi +}% + +\def\pgfplots@markers@check@for@default@plot@mark{% + \pgfplots@if@has@plot@marks{}{% \pgfplots@getcurrent@plothandler\pgfplots@basiclevel@plothandler \ifx\pgfplots@basiclevel@plothandler\pgfplothandlerdiscard % oh, the "only marks" plot handler-- and no plot mark!? @@ -268,7 +275,7 @@ \def\tikz@plot@mark{*}% \fi \fi - \fi + }% }% diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex index 126367104a3..2a0e8cac3bd 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex @@ -5,10 +5,10 @@ \catcode`\:=12 \catcode`\+=12 \catcode`\-=12 -\gdef\pgfplotsrevision{1.11-3-g4c99d7a} -\gdef\pgfplotsversion{1.11} -\gdef\pgfplotsversiondatetime{2014-08-04 12:47:48 +0200} -\gdef\pgfplotsrevisiondatetime{2014-08-06 16:56:04 +0200} +\gdef\pgfplotsrevision{1.12} +\gdef\pgfplotsversion{1.12} +\gdef\pgfplotsversiondatetime{2015-01-31 10:35:56 +0100} +\gdef\pgfplotsrevisiondatetime{2015-01-31 10:35:56 +0100} \gdef\pgfplots@glob@TMPa#1-#2-#3 #4\relax{#1/#2/#3} \xdef\pgfplotsversiondate{\expandafter\pgfplots@glob@TMPa\pgfplotsversiondatetime\relax} \xdef\pgfplotsrevisiondate{\expandafter\pgfplots@glob@TMPa\pgfplotsrevisiondatetime\relax} diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex index a1b51498005..d2e76769a3a 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex @@ -3250,59 +3250,66 @@ % - and copy its data scaling to all other axes. If one of the % axes is log, that one overrules it and all data scaling % effects are disabled.. - \begingroup - \let\pgfplots@data@scale@trafo@EXPONENT@common=\pgfutil@empty - \def\pgfplots@data@scale@trafo@EXPONENT@common@arg{-}% this should not match anything in this context. - \pgfplots@if{pgfplots@apply@datatrafo@x}{% - }{% - \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! - }% - \pgfplots@if{pgfplots@apply@datatrafo@y}{% - }{% - \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! - }% - \ifpgfplots@threedim - \pgfplots@if{pgfplots@apply@datatrafo@z}{% + \ifpgfplots@disabledatascaling + \def\pgfplots@loc@TMPd##1{% + \pgfplotscoordmath{##1}{datascaletrafo set params}{0}{0}% + }% + \else + \begingroup + \let\pgfplots@data@scale@trafo@EXPONENT@common=\pgfutil@empty + \ifpgfplots@disabledatascaling + \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! + \fi + \def\pgfplots@data@scale@trafo@EXPONENT@common@arg{-}% this should not match anything in this context. + \pgfplots@if{pgfplots@apply@datatrafo@x}{% }{% \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! }% - \fi - \ifx\pgfplots@data@scale@trafo@EXPONENT@common\pgfutil@empty - % ah - we still need to compute one. ok, search for the - % largest limit. - % - \pgfplots@get@axis@with@largest@limits - \let\pgfplots@data@scale@trafo@EXPONENT@common@arg=\pgfplotsretval + \pgfplots@if{pgfplots@apply@datatrafo@y}{% + }{% + \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! + }% + \ifpgfplots@threedim + \pgfplots@if{pgfplots@apply@datatrafo@z}{% + }{% + \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! + }% + \fi + \ifx\pgfplots@data@scale@trafo@EXPONENT@common\pgfutil@empty + % ah - we still need to compute one. ok, search for the + % largest limit. + % + \pgfplots@get@axis@with@largest@limits + \let\pgfplots@data@scale@trafo@EXPONENT@common@arg=\pgfplotsretval + % + % ok, compute data scaling transformation for the target axis: + \expandafter\pgfplots@set@optimal@datatrafo@for@\pgfplots@data@scale@trafo@EXPONENT@common@arg% + % + \pgfplotscoordmath{\pgfplots@data@scale@trafo@EXPONENT@common@arg}{datascaletrafo get params}% + \let\pgfplots@data@scale@trafo@EXPONENT@common=\pgfmathresult% + \else + % hm. early-out - we already have the scaling trafo. + % return it. + \fi + \global\let\pgfplots@glob@TMPa=\pgfplots@data@scale@trafo@EXPONENT@common + \global\let\pgfplots@glob@TMPb=\pgfplots@data@scale@trafo@EXPONENT@common@arg + \endgroup % - % ok, compute data scaling transformation for the target axis: - \expandafter\pgfplots@set@optimal@datatrafo@for@\pgfplots@data@scale@trafo@EXPONENT@common@arg% + \xdef\pgfplots@glob@TMPc{\expandafter\pgfutil@firstoftwo\pgfplots@glob@TMPa}% % - \pgfplotscoordmath{\pgfplots@data@scale@trafo@EXPONENT@common@arg}{datascaletrafo get params}% - \let\pgfplots@data@scale@trafo@EXPONENT@common=\pgfmathresult% - \else - % hm. early-out - we already have the scaling trafo. - % return it. + \def\pgfplots@loc@TMPd##1{% + \if ##1\pgfplots@glob@TMPb + % we need to set the scaling trafo for the target direction + % (was lost after \endgroup) + \def\pgfplots@loc@TMPa{\pgfplotscoordmath{##1}{datascaletrafo set params}}% + \expandafter\pgfplots@loc@TMPa\pgfplots@glob@TMPa% + \else + \pgfplotscoordmath{##1}{datascaletrafo set params}{\pgfplots@glob@TMPc}{0}% + \pgfplotscoordmath{##1}{datascaletrafo}{\csname pgfplots@##1min\endcsname}% + \pgfplotscoordmath{##1}{datascaletrafo set params}{\pgfplots@glob@TMPc}{\pgfmathresult}% + \fi + }% \fi - \global\let\pgfplots@glob@TMPa=\pgfplots@data@scale@trafo@EXPONENT@common - \global\let\pgfplots@glob@TMPb=\pgfplots@data@scale@trafo@EXPONENT@common@arg - \endgroup - % - \xdef\pgfplots@glob@TMPc{\expandafter\pgfutil@firstoftwo\pgfplots@glob@TMPa}% -%\message{using datascaletrafo of axis '\pgfplots@glob@TMPb' for each axis.^^J}% - % - \def\pgfplots@loc@TMPd##1{% - \if ##1\pgfplots@glob@TMPb - % we need to set the scaling trafo for the target direction - % (was lost after \endgroup) - \def\pgfplots@loc@TMPa{\pgfplotscoordmath{##1}{datascaletrafo set params}}% - \expandafter\pgfplots@loc@TMPa\pgfplots@glob@TMPa% - \else - \pgfplotscoordmath{##1}{datascaletrafo set params}{\pgfplots@glob@TMPc}{0}% - \pgfplotscoordmath{##1}{datascaletrafo}{\csname pgfplots@##1min\endcsname}% -%\message{Initialising the data scale transformation in direction ##1 to 10^\pgfplots@glob@TMPc*##1 - \pgfmathresult...^^J}% - \pgfplotscoordmath{##1}{datascaletrafo set params}{\pgfplots@glob@TMPc}{\pgfmathresult}% - \fi - }% \pgfplots@loc@TMPd x% \pgfplots@loc@TMPd y% \ifpgfplots@threedim diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessing.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessing.code.tex index 6b64807a05c..d370f845a70 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessing.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplotscoordprocessing.code.tex @@ -2539,6 +2539,7 @@ \expandafter\def\csname pgfpmeta@#1@issymbolic\endcsname{0}% \expandafter\def\csname pgfpmeta@#1@explicitinput\endcsname{0}% \expandafter\def\csname pgfpmeta@#1@activate\endcsname{}% + \expandafter\def\csname pgfpmeta@#1@LUA class\endcsname{}% \edef\pgfplotsdeclarepointmetasource@{#1}% \pgfqkeys{/pgfplots/@declare point meta src}{#2}% }% @@ -2605,6 +2606,11 @@ % explicitinput/.code= {\expandafter\def\csname pgfpmeta@\pgfplotsdeclarepointmetasource@ @explicitinput\endcsname{#1}},% + % + % the associated LUA class name (if any). Use an empty string if + % there is none. + LUA class/.code= + {\expandafter\def\csname pgfpmeta@\pgfplotsdeclarepointmetasource@ @LUA class\endcsname{#1}},% }% % An empty one. This is simple to check with @@ -2614,17 +2620,20 @@ \let\pgfplots@current@point@meta=\pgfplots@current@point@x \pgfplotscoordmath{meta}{parsenumber}{\pgfplots@current@point@meta}% \let\pgfplots@current@point@meta=\pgfmathresult - }} + }, + LUA class=pgfplots.XcoordAssignmentPointMetaHandler} \pgfplotsdeclarepointmetasource{y}{assign={% \let\pgfplots@current@point@meta=\pgfplots@current@point@y \pgfplotscoordmath{meta}{parsenumber}{\pgfplots@current@point@meta}% \let\pgfplots@current@point@meta=\pgfmathresult - }} + }, + LUA class=pgfplots.YcoordAssignmentPointMetaHandler} \pgfplotsdeclarepointmetasource{z}{assign={% \let\pgfplots@current@point@meta=\pgfplots@current@point@z \pgfplotscoordmath{meta}{parsenumber}{\pgfplots@current@point@meta}% \let\pgfplots@current@point@meta=\pgfmathresult - }} + }, + LUA class=pgfplots.ZcoordAssignmentPointMetaHandler} \pgfplotsdeclarepointmetasource{explicit}{% assign={% @@ -2634,7 +2643,8 @@ \let\pgfplots@current@point@meta=\pgfmathresult \fi }, - explicitinput=1% + explicitinput=1,% + LUA class=pgfplots.ExplicitPointMetaHandler.new(), }% \pgfplotsdeclarepointmetasource{explicit symbolic}{% assign={},% no math, simply collect. @@ -2664,7 +2674,19 @@ \ifx\pgfpmeta@expr@origchoice\pgfplots@loc@TMPa \let\pgfpmeta@expr@origchoice\pgfutil@empty \fi + % + \pgfplotsutilifcontainsmacro{#1}{% + % oh. The point meta expression contains a backslash - it + % depends on a macro. This means: it depends on \thisrow + % or similar TeX stuff - which must be evaluated by TeX. + % + % LUA cannot be used for this point meta handler. + \let\pgfpmeta@expr@LUA@class\pgfutil@empty + }{% + \def\pgfpmeta@expr@LUA@class{pgfplots.ExpressionPointMetaHandler.new("#1")}% + }% }, + LUA class=\pgfpmeta@expr@LUA@class, }% \pgfkeyssetvalue{/pgfplots/point meta/expr}{}% @@ -3220,6 +3242,7 @@ \let\pgfplots@coord@stream@start@=\pgfplots@PREPARE@COORD@STREAM@start@ \def\pgfplots@coord@stream@coord@{% \def\pgfplots@set@perpointmeta@done{0}% + % NOTE: this might call LUA (if supported): \pgfplotsplothandlersurveypoint }% \def\pgfplots@coord@stream@end@{\pgfplots@PREPARE@COORD@STREAM@end@{#1}}% @@ -3239,6 +3262,7 @@ % \edef\plotnumofactualtype{\numplotsofactualtype}% \csname pgfpmeta@\pgfplotspointmetainputhandler @activate\endcsname + \pgfplots@LUA@survey@start \pgfplotsplothandlersurveystart \pgfplotscoordstream@firstlast@init % @@ -3261,6 +3285,7 @@ % Inside of math expressions, 'x', 'y' and 'z' expand to the % current x,y and z coords respectively. Introduce these (and some % more) shortcuts: + % FIXME : defining the resulting x/y coordinates as 'x' and 'y' constants was a really really bad idea in the first place :-( \pgfplotsmathdeclarepseudoconstant{x}{\let\pgfmathresult=\pgfplots@current@point@x}% \pgfplotsmathdeclarepseudoconstant{y}{\let\pgfmathresult=\pgfplots@current@point@y}% \pgfplotsmathdeclarepseudoconstant{z}{\let\pgfmathresult=\pgfplots@current@point@z}% @@ -3348,6 +3373,9 @@ % #1,#2: see \pgfplots@PREPARE@COORD@STREAM \def\pgfplots@PREPARE@COORD@STREAM@end@#1{% \pgfkeysvalueof{/pgfplots/execute at end survey}% + \ifpgfplots@LUA@backend@supported + \pgfplots@LUA@survey@end + \fi % FIXME : move this the \pgfplotsplothandlersurveyend of mesh plot % handler: \pgfkeyssetvalue{/pgfplots/mesh/num points}{\pgfplots@current@point@coordindex}% @@ -3417,6 +3445,7 @@ \pgfplotssurveyphase@set@visphase@names{#1}% \let\pgfplots@visphase@names=\pgfplotsretval % + \t@pgfplots@tokc={#1}% % % SERIALIZE RESULT: % @@ -3431,6 +3460,13 @@ \noexpand\pgfplots@addplot@enqueue@coords {% precommand(s): \expandafter\noexpand\csname pgfplots@curplot@threedim\ifpgfplots@curplot@threedim true\else false\fi\endcsname + % + % Did we prepare the data within LUA? remember that! + \ifpgfplots@LUA@backend@supported + \noexpand\pgfplots@LUA@backend@supportedtrue + \else + \noexpand\pgfplots@LUA@backend@supportedfalse + \fi \noexpand\def\noexpand\plotnum{\the\pgfplots@numplots}% % % store \plotnumofactualtype @@ -3478,6 +3514,7 @@ \noexpand\def\noexpand\pgfplotsaxisfilteredcoordsaway{\pgfplotsaxisfilteredcoordsaway}% \noexpand\def\noexpand\pgfplotsaxisplothasjumps{\pgfplotsaxisplothasjumps}% \noexpand\pgfkeyssetvalue{/pgfplots/on layer}{\pgfkeysvalueof{/pgfplots/on layer}}% + \noexpand\def\noexpand\pgfplots@serialized@afterpath{\the\t@pgfplots@tokc}% }% {% draw command: \noexpand\path% @@ -3486,14 +3523,14 @@ \pgfplotsapplistXXlet\pgfplots@coord@stream@recorded \pgfplotsapplistXXclear \t@pgfplots@tokc=\expandafter{\pgfplots@coord@stream@recorded}% - \t@pgfplots@tokb={#1;}% \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPa}% \xdef\pgfplots@glob@TMPa{% \the\t@pgfplots@toka {% coordinates which need to be processed in \endaxis. % See % \pgfplots@coord@stream@finalize@storedcoords@START - normalized coordinates {\the\t@pgfplots@tokc}\the\t@pgfplots@tokb + % (will become available as \pgfplots@stored@current@data) + \the\t@pgfplots@tokc }% }% % @@ -3518,6 +3555,202 @@ \fi }% +\def\pgfplots@LUA@survey@log@deactivation#1{% + \pgfplots@log{\pgfplots@LUA@loglevel@info}{Using 'lua backend=false' for plot \the\pgfplots@numplots\space (type '\pgfplotsplothandlername'): #1.}% + \pgfplots@LUA@backend@failed +}% + +\def\pgfplots@LUA@survey@get@filter#1{% + \begingroup + \pgfkeysgetvalue{/pgfplots/#1 filter/.@cmd}\pgfplots@loc@TMPc + \ifx\pgfplots@loc@TMPc\pgfplots@empty@command@key + \let\pgfplotsretval=\pgfutil@empty + \else + \pgfplots@ifisfilterexpression{#1 filter}{% + \pgfkeysgetvalue{/pgfplots/#1 filter/@expressionvalue}\pgfplotsretval + \expandafter\pgfplotsutilifcontainsmacro\expandafter{\pgfplotsretval}{% + \aftergroup\pgfplots@LUA@backend@supportedfalse + \pgfplots@command@to@string\pgfplotsretval\pgfplots@loc@TMPa + \pgfplots@LUA@survey@log@deactivation{#1 filter/.expression='\pgfplots@loc@TMPa' contains a TeX macro}% + \let\pgfplotsretval=\pgfutil@empty + }{% + }% + }{% + \aftergroup\pgfplots@LUA@backend@supportedfalse + \pgfplots@LUA@survey@log@deactivation{LUA does not support #1 filter (yet)}% + \let\pgfplotsretval=\pgfutil@empty + }% + \fi + \pgfmath@smuggleone\pgfplotsretval + \endgroup +}% + +\def\pgfplots@LUA@survey@start{% + \ifpgfplots@LUA@backend@supported + \ifx\pgfplotsplothandlerLUAfactory\pgfutil@empty + \pgfplots@LUA@survey@log@deactivation{plot handler does not support LUA}% + \pgfplots@LUA@backend@supportedfalse + \fi + % + \ifx\pgfplotspointmetainputhandler\pgfutil@empty + \def\pgfplots@loc@TMPa{nil}% + \else + \edef\pgfplots@loc@TMPa{% + \csname pgfpmeta@\pgfplotspointmetainputhandler @LUA class\endcsname}% + \ifx\pgfplots@loc@TMPa\pgfutil@empty + \pgfplots@LUA@survey@log@deactivation{point meta choice does not support LUA}% + \pgfplots@LUA@backend@supportedfalse + \fi + \fi + \ifpgfplots@stackedmode + \pgfplots@LUA@survey@log@deactivation{LUA does not support stacked plots (yet)}% + \pgfplots@LUA@backend@supportedfalse + \fi + \ifpgfplots@errorbars@enabled + \pgfplots@LUA@survey@log@deactivation{LUA does not support error bars (yet)}% + \pgfplots@LUA@backend@supportedfalse + \fi + \ifpgfplots@collect@firstplot@astick + \pgfplots@LUA@survey@log@deactivation{LUA does not support xtick=data (yet)}% + \pgfplots@LUA@backend@supportedfalse + \fi + \pgfkeysgetvalue{/pgfplots/pre filter/.@cmd}\pgfplots@loc@TMPc\ifx\pgfplots@loc@TMPc\pgfplots@empty@command@key\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@survey@log@deactivation{LUA does not support filter (yet)}\fi + \pgfplots@LUA@survey@get@filter x% + \let\pgfplots@loc@filter@x=\pgfplotsretval + \pgfplots@LUA@survey@get@filter y% + \let\pgfplots@loc@filter@y=\pgfplotsretval + \pgfplots@LUA@survey@get@filter z% + \let\pgfplots@loc@filter@z=\pgfplotsretval + \pgfkeysgetvalue{/pgfplots/filter point/.@cmd}\pgfplots@loc@TMPc\ifx\pgfplots@loc@TMPc\pgfplots@empty@command@key\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@survey@log@deactivation{LUA does not support filter (yet)}\fi + % + \pgfkeysgetvalue{/pgfplots/execute for finished point}\pgfplots@loc@TMPc\ifx\pgfplots@loc@TMPc\pgfutil@empty\else \pgfplots@LUA@backend@supportedfalse\fi + % + \pgfkeysgetvalue{/pgfplots/visualization depends on/list}\pgfplots@loc@TMPc \ifx\pgfplots@loc@TMPc\pgfutil@empty\else \pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@survey@log@deactivation{LUA does not support 'visualization depends on' (yet)} \fi + % + % + \edef\pgfplots@loc@TMPc{\pgfkeysvalueof{/pgfplots/data cs}}% + \edef\pgfplots@loc@TMPd{\pgfkeysvalueof{/pgfplots/@expected axis cs}}% + \ifx\pgfplots@loc@TMPc\pgfplots@loc@TMPd\else\pgfplots@LUA@backend@supportedfalse\pgfplots@LUA@survey@log@deactivation{LUA does not support 'data cs' (yet)}\fi + % + % hm. There are various cases which are supported during a + % SURVEY -- but not during a visualization. Check that here: + \if m\pgfplots@colormap@access + \else + \pgfplots@LUA@survey@log@deactivation{color map access=direct not supported (yet)}% + \pgfplots@LUA@backend@supportedfalse + \fi + % + \ifpgfplots@LUA@backend@supported + \begingroup + \pgfkeysgetvalue{/pgfplots/point meta min}\pgfplots@loc@metamin + \pgfkeysgetvalue{/pgfplots/point meta max}\pgfplots@loc@metamax + \pgfplots@log{\pgfplots@LUA@loglevel@debug}{lua backend=true: Activating LUA backend for plot \the\pgfplots@numplots\space (type '\pgfplotsplothandlername').}% + \edef\pgfplots@loc@TMPa{% + local gca = pgfplots.gca;^^J% + gca.min = {^^J% + pgfplots.pgftonumber("\pgfplots@xmin"), ^^J% + pgfplots.pgftonumber("\pgfplots@ymin"), ^^J% + pgfplots.pgftonumber("\pgfplots@zmin")}; ^^J% + gca.max = {^^J% + pgfplots.pgftonumber("\pgfplots@xmax"), ^^J% + pgfplots.pgftonumber("\pgfplots@ymax"), ^^J% + pgfplots.pgftonumber("\pgfplots@zmax")}; ^^J% + % FIXME : what about datamin/datamax!? + local plothandlerFactory = \pgfplotsplothandlerLUAfactory; ^^J% + local plothandler = plothandlerFactory(gca, \pgfplots@loc@TMPa);^^J% second arg: point meta handler + \ifx\pgfplots@loc@metamin\pgfutil@empty + \else + plothandler.autocomputeMetaMin = false;^^J% + plothandler.metamin = pgfplots.pgftonumber("\pgfplots@loc@metamin");^^J% + \fi + \ifx\pgfplots@loc@metamax\pgfutil@empty + \else + plothandler.autocomputeMetaMax = false;^^J% + plothandler.metamax = pgfplots.pgftonumber("\pgfplots@loc@metamax");^^J% + \fi + local config = plothandler.config;^^J% + config.unboundedCoords = "\pgfplots@unbounded@handler";^^J% + config.warnForfilterDiscards = \pgfplots@boolval{pgfplots@warn@for@filter@discards};^^J% + config.pointmetarel = \pgfplots@perpointmeta@rel@choice;^^J% + config.updateLimits = \ifpgfplots@bb@isactive true\else false\fi;^^J% + config.filterExpressionByDir = {^^J% + "\pgfplots@loc@filter@x",^^J% + "\pgfplots@loc@filter@y",^^J% + "\pgfplots@loc@filter@z"};^^J% + gca.plothandlers[\the\pgfplots@numplots+1] = plothandler;^^J% + gca.currentPlotHandler = plothandler;^^J% + plothandler:surveystart();^^J% + }% +%\message{Executing ^^J\pgfplots@loc@TMPa^^J^^J}% + \directlua{\pgfplots@loc@TMPa}% + \endgroup + \fi + \fi +}% + +\def\pgfplots@LUA@survey@point{% + \directlua{pgfplots.texSurveyPoint("\pgfplots@current@point@x","\pgfplots@current@point@y","\pgfplots@current@point@z","\pgfplots@current@point@meta")}% +}% + +\def\pgfplots@LUA@survey@end{% + % LUA defines a couple of TeX macros here... + \directlua{pgfplots.texSurveyEnd()}% + % + \pgfplotsapplistXXpushback{--- acquire from LUA! --}% +}% + +% this appears to be necessary for the mesh legend... +\def\b@pgfplots@LUA@visualization@enabled{0}% + +% PRECONDITION : \pgfplots@LUA@visualization@init has already been +% executed. +\def\pgfplots@LUA@visualization@of@current@plot{% + \def\b@pgfplots@LUA@visualization@enabled{0}% + \ifpgfplots@LUA@backend@supported + \pgfkeysgetvalue{/pgfplots/axis type}\pgfplots@loc@TMPa + \def\pgfplots@loc@TMPb{rectangle}% + \ifx\pgfplots@loc@TMPa\pgfplots@loc@TMPb + \else + % disable visualizer - we cannot do this right now. + \pgfplots@LUA@backend@failed + \let\pgfplotsplothandlerLUAvisualizerfactory=\pgfutil@empty + \fi + % + \ifx\pgfplotsplothandlerLUAvisualizerfactory\pgfutil@empty + % hm. This plot cannot be visualized in LUA - BUT it has a + % LUA survey! Ok, then: acquire the survey results. + % Otherwise we would have nothing here. + % FIXME : what about \pgfplots@LUA@backend@failed in this context!? + \pgfplots@log{\pgfplots@LUA@loglevel@info}{Using 'lua backend=false' for visualization of plot \the\pgfplots@numplots\space (type '\pgfplotsplothandlername'): it has no LUA visualizer.}% + \expandafter\def\expandafter\pgfplots@stored@current@data\expandafter{% + \directlua{pgfplots.texGetSurveyedCoordsToPgfplots()}% + }% + \else + % visualize using LUA! ... and acquire the coordinates. + \expandafter\def\expandafter\pgfplots@stored@current@data\expandafter{% + \directlua{pgfplots.texVisualizePlot(\pgfplotsplothandlerLUAvisualizerfactory)}% + }% +%\message{plot \plotnum: LUA backend returned \pgfplots@stored@current@data^^J}% + % + % ... and ensure that the resulting + % \pgfplots@stored@current@data can be deserialized. It + % contains the fully mapped X/Y coordinates as first item. + \let\pgfplotsaxisdeserializedatapointfrom@private@nonLUA=\pgfplotsaxisdeserializedatapointfrom@private + \def\pgfplotsaxisdeserializedatapointfrom@private##1{% + \pgfplotsaxisdeserializedatapointfrom@private@LUA##1% + }% + \def\pgfplotsaxisdeserializedatapointfrom@private@LUA##1##2##3{% + \global\pgf@x=##1pt % + \global\pgf@y=##2pt % + \pgfplotsaxisdeserializedatapointfrom@private@nonLUA{##3}% + }% + % FIXME : do I need to adopt the serializer as well!? + % + \def\b@pgfplots@LUA@visualization@enabled{1}% + \fi + \fi +}% + % Defines \pgfplotsretval to contain a comma-separated-list of % visualization phase names. May be empty. % @@ -3575,7 +3808,7 @@ % This defines \pgfplots@visphase@default: \expandafter\def\csname pgfplots@visphase@\pgfplotsaxis@visphase@name@default\endcsname{% - \expandafter\pgfplots@coord@stream@finalize@storedcoords@START\pgfplots@stored@current@data\pgfplots@EOI + \pgfplots@coord@stream@finalize@storedcoords@START }% % A routine which transforms the current set of @@ -3825,7 +4058,7 @@ \fi % \pgfkeysgetvalue{/pgfplots/execute for finished point}\pgfplots@loc@TMPa - \ifx\pgfplots@loc@TMPa\pgfplots@empty@command@key + \ifx\pgfplots@loc@TMPa\pgfutil@empty \else \expandafter\def\expandafter\pgfplotsaxisserializedatapoint@private\expandafter{% \pgfplotsaxisserializedatapoint@private @@ -4003,6 +4236,12 @@ \def\pgfplots@perpointmeta@preparetrafo{% \def\pgfplotspointmetarangeexponent{1}% pre-fill \pgfutil@ifundefined{pgfplots@perpointmeta@trafo}{% + \edef\pgfplots@loc@TMPa{\pgfplotscolormaprange}% + \ifnum\pgfplots@loc@TMPa=1000 + \else + \pgfplots@error{LOGIC ERROR: sorry, I have hard-coded the assumption \string\pgfplotscolormaprange = 1000, but now it is \pgfplots@loc@TMPa.}% + \fi + % \let\pgfplots@current@point@meta=\pgfutil@empty \pgfutil@ifundefined{pgfplots@metamax}{\let\pgfplots@metamax=\pgfutil@empty}{} \ifpgfplots@warn@for@filter@discards @@ -4039,11 +4278,6 @@ % phi(m) = ( m- meta_min) * 1000/ (meta_max-meta_min). % % -> precompute the scaling factor! - \edef\pgfplots@loc@TMPa{\pgfplotscolormaprange}% - \ifnum\pgfplots@loc@TMPa=1000 - \else - \pgfplots@error{LOGIC ERROR: sorry, I have hard-coded the assumption \string\pgfplotscolormaprange = 1000, but now it is \pgfplots@loc@TMPa.}% - \fi \if\pgfplots@perpointmeta@rel@choice0% % point meta rel=axis wide: \pgfplots@perpointmeta@preparetrafo@initfrom{pgfplots@axiswide@}% @@ -4077,25 +4311,35 @@ \edef\pgfplotspointmetarange{\csname #1metamin\endcsname:\csname #1metamax\endcsname}% % Now, prepare the trafo as such. % It assigns \pgfmathresult (in fixed point). - \def\pgfplots@perpointmeta@trafo##1{% - \pgfplotscoordmath{meta}{if is}{##1}{u}{% - \def\pgfmathresult{0}% - \pgfplots@perpointmeta@unboundedwarning{##1}% - }{% - \pgfplotscoordmath{meta}{op}{subtract}{{##1}{\csname #1metamin\endcsname}}% - \pgfplotscoordmath{meta}{op}{multiply}{{\pgfmathresult}{\pgfplots@perpointmeta@trafo@factor}}% - \pgfplots@perpointmeta@trafo@clipresult - \pgfplotscoordmath{meta}{tofixed}{\pgfmathresult}% + \ifpgfplots@LUA@backend@supported + \def\pgfplots@perpointmeta@trafo##1{% + \edef\pgfmathresult{% + \directlua{% + pgfplots.texPerpointMetaTrafo("\pgfplots@current@point@meta") + }% + }% }% - }% - \pgfplotscoordmath{meta}{op}{subtract}{{\csname #1metamax\endcsname}{\csname #1metamin\endcsname}}% - \let\pgfplots@loc@TMPa=\pgfmathresult - \pgfplotscoordmath{meta}{zero}% - \let\pgfplots@perpointmeta@lowerrange=\pgfmathresult - \pgfplotscoordmath{meta}{parsenumber}{1000}% - \let\pgfplots@perpointmeta@upperrange=\pgfmathresult - \pgfplotscoordmath{meta}{op}{divide}{{\pgfmathresult}{\pgfplots@loc@TMPa}}% - \let\pgfplots@perpointmeta@trafo@factor=\pgfmathresult + \else + \def\pgfplots@perpointmeta@trafo##1{% + \pgfplotscoordmath{meta}{if is}{##1}{u}{% + \def\pgfmathresult{0}% + \pgfplots@perpointmeta@unboundedwarning{##1}% + }{% + \pgfplotscoordmath{meta}{op}{subtract}{{##1}{\csname #1metamin\endcsname}}% + \pgfplotscoordmath{meta}{op}{multiply}{{\pgfmathresult}{\pgfplots@perpointmeta@trafo@factor}}% + \pgfplots@perpointmeta@trafo@clipresult + \pgfplotscoordmath{meta}{tofixed}{\pgfmathresult}% + }% + }% + \pgfplotscoordmath{meta}{op}{subtract}{{\csname #1metamax\endcsname}{\csname #1metamin\endcsname}}% + \let\pgfplots@loc@TMPa=\pgfmathresult + \pgfplotscoordmath{meta}{zero}% + \let\pgfplots@perpointmeta@lowerrange=\pgfmathresult + \pgfplotscoordmath{meta}{parsenumber}{1000}% + \let\pgfplots@perpointmeta@upperrange=\pgfmathresult + \pgfplotscoordmath{meta}{op}{divide}{{\pgfmathresult}{\pgfplots@loc@TMPa}}% + \let\pgfplots@perpointmeta@trafo@factor=\pgfmathresult + \fi % % Expands to the transformation range as 'a:b': \def\pgfplots@perpointmeta@traforange{0:1000}% @@ -4982,22 +5226,27 @@ % \pgfplots@PREPARE@COORD@STREAM{#3}% % + \def\pgfplots@addplotimpl@expression@xEXPR{#1}% + % % Determine whether the x range is parameterized or uniform and % prepare a macro which assigns \pgfplots@current@point@x: \def\pgfplots@addplotimpl@expression@prepare@x{% \pgfmathparse{#1}% \let\pgfplots@current@point@x=\pgfmathresult }% + \def\pgfplots@addplotimpl@expression@prepare@y{% + \pgfmathparse{\pgfplots@addplotimpl@expression@yEXPR}% + \let\pgfplots@current@point@y=\pgfmathresult + }% \def\pgfplots@addplotimpl@expression@hasuniform@x{0}% - \def\pgfplots@loc@TMPa{#1}% % do we have '\x' as x coordinate? \expandafter\def\expandafter\pgfplots@loc@TMPb\expandafter{\tikz@plot@var}% - \ifx\pgfplots@loc@TMPa\pgfplots@loc@TMPb + \ifx\pgfplots@addplotimpl@expression@xEXPR\pgfplots@loc@TMPb \def\pgfplots@addplotimpl@expression@hasuniform@x{1}% \else - \def\pgfplots@loc@TMPb{x}% + \edef\pgfplots@loc@TMPb{\pgfplots@plot@var@nonmacro}% % do we have 'x' as x coordinate? - \ifx\pgfplots@loc@TMPa\pgfplots@loc@TMPb + \ifx\pgfplots@addplotimpl@expression@xEXPR\pgfplots@loc@TMPb \def\pgfplots@addplotimpl@expression@hasuniform@x{1}% \fi \fi @@ -5009,6 +5258,8 @@ }% \fi % + \def\pgfplots@addplotimpl@expression@hasuniform@y{0}% + % % % Now, prepare the loops. % @@ -5030,6 +5281,25 @@ \expandafter\pgfplots@domain@to@foreach\pgfplots@plot@domain\relax{\pgfplots@plot@samples}% \let\pgfplots@expression@xdomain=\pgfplotsretval % + % do we have '\y' as y coordinate? + \expandafter\def\expandafter\pgfplots@loc@TMPb\expandafter{\pgfplots@plot@var@y}% + \ifx\pgfplots@addplotimpl@expression@yEXPR\pgfplots@loc@TMPb + \def\pgfplots@addplotimpl@expression@hasuniform@y{1}% + \def\pgfplots@addplotimpl@expression@prepare@y{% + \edef\pgfplots@current@point@y{\pgfplots@plot@var@y}% + }% + \else + \edef\pgfplots@loc@TMPb{\pgfplots@plot@var@y@nonmacro}% + % do we have 'y' as y coordinate? + \ifx\addplotimpl@expression@yEXPR\pgfplots@loc@TMPb + \def\pgfplots@addplotimpl@expression@hasuniform@y{1}% + \def\pgfplots@addplotimpl@expression@prepare@y{% + \edef\pgfplots@current@point@y{\pgfplots@plot@var@y}% + }% + \fi + \fi + % + % \if0\b@pgfplots@should@sample@LINE % Samples twodimensionally (a lattice): \expandafter\pgfplots@domain@to@foreach\pgfplots@plot@ydomain\relax{\pgfplots@plot@samples@y}% @@ -5063,11 +5333,12 @@ % % If we have (\x,\y,f(x)), use (\x,0,f(x)) instead and % suppress the error message which would occur for \y. - \expandafter\pgfplotsutilifstringequal\expandafter{\pgfplots@addplotimpl@expression@yEXPR}{\pgfplots@plot@var@y}{% + \if1\pgfplots@addplotimpl@expression@hasuniform@y \def\pgfplots@addplotimpl@expression@yEXPR{0}% - }{% + \def\pgfplots@plot@var@y{0}% + \else \expandafter\edef\pgfplots@plot@var@y{\pgfplots@plot@var@y@nonmacro}% this provides an error message, see above. - }% + \fi \fi \else % Assemble a @@ -5140,14 +5411,130 @@ \fi \expandafter\def\pgfplots@plot@var@y{0}% \def\pgfplots@addplotimpl@expression@yEXPR{#2}% + \def\pgfplots@addplotimpl@expression@zEXPR{}% \def\pgfplots@current@point@z{}% \fi % + % % START: % (NOTE: this does also define 'x', 'y', and 'z' math % expressions!) \pgfplots@coord@stream@start % + \pgfplots@addplotimpl@expression@check@LUA + \if1\pgfplotsretval + \pgfplots@log{\pgfplots@LUA@loglevel@debug}{lua backend=true: Activating LUA version of plot expression for plot \the\pgfplots@numplots\space (type '\pgfplotsplothandlername').}% + \begingroup + \expandafter\def\tikz@plot@var{\pgfplots@plot@var@nonmacro}% + \expandafter\def\pgfplots@plot@var@y{\pgfplots@plot@var@y@nonmacro}% + \expandafter\pgfplots@parse@domain\pgfplots@plot@domain\relax{pgfplots@plot@domain}% + % + \pgfmathparse{\pgfplots@plot@samples}% + \let\pgfplots@plot@samples=\pgfmathresult + % + \if0\b@pgfplots@should@sample@LINE + \expandafter\pgfplots@parse@domain\pgfplots@plot@ydomain\relax{pgfplots@plot@ydomain}% + \pgfmathparse{\pgfplots@plot@samples@y}% + \let\pgfplots@plot@samples@y=\pgfmathresult + \else + \def\pgfplots@plot@ydomain@min{0}% + \def\pgfplots@plot@ydomain@max{0}% + \def\pgfplots@plot@samples@y{1}% + \fi + % + % FIXME : there are some cases in which this here might be a + % bad idea: + % - if someone has redefined math functions on TeX + % - if someone has defined his own math functions (only in + % TeX) + % - if a plot expression contains directlua -- the expansion will play + % funny tricks in this case + \xdef\pgfplotsglobalretval{% + \directlua{% + pgfplots.texAddplotExpressionCoordinateGenerator(^^J% + \ifpgfplots@curplot@threedim true \else false\fi,^^J% + "#1", ^^J% + "\pgfplots@addplotimpl@expression@yEXPR",^^J% + "\pgfplots@addplotimpl@expression@zEXPR",^^J% + \b@pgfplots@should@sample@LINE,^^J% + "\pgfplots@plot@domain@min", "\pgfplots@plot@domain@max",^^J% + "\pgfplots@plot@ydomain@min", "\pgfplots@plot@ydomain@max",^^J% + "\pgfplots@plot@samples",^^J% + "\pgfplots@plot@samples@y",^^J% + "\pgfplots@plot@var@nonmacro",^^J% + "\pgfplots@plot@var@y@nonmacro", + "\pgfplots@plot@samples@at", + "\pgfplots@LUA@backend@debugmode")^^J% + }% + }% + \endgroup + \if0\pgfplotsglobalretval + \pgfplots@log{\pgfplots@LUA@loglevel@info}{lua backend=true: LUA version of plot expression failed. Using TeX version. (plot \the\pgfplots@numplots).}% + \pgfplots@LUA@backend@failed + \pgfplots@addplotimpl@expression@streamall + \else + \fi + \else + \pgfplots@addplotimpl@expression@streamall + \fi + % + \pgfplots@coord@stream@end +}% + +% Defines \pgfplotsretval to be '1' if the pure LUA version of +% \addplot expression is enabled. It defines \pgfplotsretval to be 0 +% if not. +\def\pgfplots@addplotimpl@expression@check@LUA{% + \def\pgfplotsretval{0}% + \ifpgfplots@LUA@backend@supported + \def\pgfplotsretval{1}% + \ifpgfplotsplothandlermesh@patch@type@sampling + \def\pgfplotsretval{0}% + \pgfplots@LUA@plotexpression@log@deactivation{patch type sampling unsupported (yet)}% + \fi + % + \if1\pgfplots@addplotimpl@expression@hasuniform@x + \else + \expandafter\pgfplotsutilifcontainsmacro\expandafter{\pgfplots@addplotimpl@expression@xEXPR}{% + \def\pgfplotsretval{0}% + \pgfplots@command@to@string\pgfplots@addplotimpl@expression@xEXPR\pgfplots@loc@TMPa + \pgfplots@LUA@plotexpression@log@deactivation{x expression '\pgfplots@loc@TMPa' contains a TeX macro}% + }{% + }% + \fi + % + \if1\pgfplots@addplotimpl@expression@hasuniform@y + \else + \expandafter\pgfplotsutilifcontainsmacro\expandafter{\pgfplots@addplotimpl@expression@yEXPR}{% + \def\pgfplotsretval{0}% + \pgfplots@command@to@string\pgfplots@addplotimpl@expression@yEXPR\pgfplots@loc@TMPa + \pgfplots@LUA@plotexpression@log@deactivation{y expression '\pgfplots@loc@TMPa' contains a TeX macro}% + }{% + }% + \fi + % + \ifpgfplots@curplot@threedim + \expandafter\pgfplotsutilifcontainsmacro\expandafter{\pgfplots@addplotimpl@expression@zEXPR}{% + \def\pgfplotsretval{0}% + \pgfplots@command@to@string\pgfplots@addplotimpl@expression@zEXPR\pgfplots@loc@TMPa + \pgfplots@LUA@plotexpression@log@deactivation{z expression '\pgfplots@loc@TMPa' contains a TeX macro}% + }{% + }% + \fi + \fi +}% + +\def\pgfplots@LUA@plotexpression@log@deactivation#1{% + \pgfplots@log{\pgfplots@LUA@loglevel@info}{Deactivating LUA version of plot expression for plot \the\pgfplots@numplots\space (type '\pgfplotsplothandlername'): #1.}% + \pgfplots@LUA@backend@failed +} +\def\pgfplots@parse@domain#1:#2\relax#3{% + \pgfmathparse{#1}% + \expandafter\let\csname #3@min\endcsname=\pgfmathresult% + \pgfmathparse{#2}% + \expandafter\let\csname #3@max\endcsname=\pgfmathresult% +}% +\def\pgfplots@addplotimpl@expression@streamall{% % create a backup of the 'x' and 'y' math expressions which % have been defined in \pgfplots@coord@stream@start: \let\pgfplots@addplotimpl@expression@pseudoconst@old@x=\pgfmathx@ @@ -5188,8 +5575,7 @@ \let\pgfmathy@=\pgfplots@addplotimpl@expression@pseudoconst@y % eval expressions: \pgfplots@addplotimpl@expression@prepare@x% - \pgfmathparse{\pgfplots@addplotimpl@expression@yEXPR}% - \let\pgfplots@current@point@y=\pgfmathresult + \pgfplots@addplotimpl@expression@prepare@y% \ifpgfplots@curplot@threedim \pgfmathparse{\pgfplots@addplotimpl@expression@zEXPR}% \let\pgfplots@current@point@z=\pgfmathresult @@ -5203,8 +5589,7 @@ % process coords as usual: \pgfplots@coord@stream@coord }% - \pgfplots@coord@stream@end -}% +} % Typically, the FPU will generate stuff like '1Y1.0e5'. Since such % internal representations will be available to API users (especially @@ -5241,7 +5626,7 @@ % for that special string. \edef\pgfplots@loc@TMPb{% {\expandafter\noexpand\tikz@plot@var}% - {\noexpand\pgfplots@plot@var@y\the\t@pgfplots@toka}% + {\expandafter\noexpand\pgfplots@plot@var@y\the\t@pgfplots@toka}% }% \expandafter\pgfplots@addplotimpl@expression@@\pgfplots@loc@TMPb{#4}% \else @@ -6630,6 +7015,39 @@ \fi% }% +% #1 the target which will contain the filter +% #2 a math expression. +\def\pgfplots@install@filter@expression#1#2{% + \pgfkeysdef{/pgfplots/#1}{\pgfplots@filter@expression{#1}}% + \pgfkeyssetvalue{/pgfplots/#1/@expressionvalue}{#2}% +}% + +% Executes #2 if the filter key was defined by +% \pgfplots@install@filter@expression. +% +% #1 the target which will contain the filter (like 'x filter') +% #2: true code +% #3: false code +\def\pgfplots@ifisfilterexpression#1#2#3{% + \pgfkeysgetvalue{/pgfplots/#1/.@cmd}\pgfplots@loc@TMPc + \long\def\pgfplots@loc@TMPd##1\pgfeov{\pgfplots@filter@expression{#1}}% + \ifx\pgfplots@loc@TMPc\pgfplots@loc@TMPd + #2\relax + \else + #3\relax + \fi +}% + +% the key name (example: 'x filter') +\def\pgfplots@filter@expression#1{% + \begingroup + \pgfkeys{/pgf/fpu=true}% + \pgfkeysgetvalue{/pgfplots/#1/@expressionvalue}\pgfplots@loc@TMPa + \pgfmathparse{\pgfplots@loc@TMPa}% + \pgfmath@smuggleone\pgfmathresult + \endgroup +}% + % this is a convenience macro to save storage in the long coordinate % lists. \def\pgfplots@stream#1#2{\pgfplotstreampoint{\pgfqpoint{#1}{#2}}} @@ -6658,6 +7076,9 @@ \pgfplots@getcurrent@plothandler\pgfplots@basiclevel@plothandler \pgfplots@gettikzinternal@keyval{mark}{tikz@plot@mark}{}% % + \ifpgfplots@threedim + \pgfplots@apply@zbuffer + \fi % \pgfplots@perpointmeta@preparetrafo % @@ -6678,13 +7099,17 @@ \def\pgfplots@loc@TMPa{1}% \fi % + % OK, initialize the plot handler. + \pgfplotsresetplothandler + \pgfplots@basiclevel@plothandler + \expandafter\pgfplotsplothandlerdeserializestatefrom\expandafter{\pgfplots@serialized@state@plothandler}% + % + \pgfplots@LUA@visualization@of@current@plot + % + \pgfplotstreamstart % % Now, set up coordinate streams. \def\pgfplots@coord@stream@start@{% - \pgfplotsresetplothandler - \pgfplots@basiclevel@plothandler - \expandafter\pgfplotsplothandlerdeserializestatefrom\expandafter{\pgfplots@serialized@state@plothandler}% - \pgfplotstreamstart \let\pgfplots@data@scaletrafo@result=\pgfutil@empty \c@pgfplots@coordindex=0 }% @@ -6695,10 +7120,8 @@ \ifpgfplots@errorbars@enabled \pgfplots@errorbars@visphase@end \fi - \ifpgfplots@apply@datatrafo - \pgfplots@addplot@get@named@startendpoints@command\pgfplots@loc@TMPa - \pgfplots@loc@TMPa - \fi + \pgfplots@addplot@get@named@startendpoints@command\pgfplots@loc@TMPa + \pgfplots@loc@TMPa \pgfplotstreamend }% \begingroup @@ -6729,18 +7152,48 @@ % %\message{Prepared macro \string \pgfplotsaxisvisphasetransformcoordinate {\meaning\pgfplotsaxisvisphasetransformcoordinate}}% %\message{Prepared macro \string \pgfplots@coord@stream@finalize@currentpt {\meaning\pgfplots@coord@stream@finalize@currentpt}}% - \def\pgfplots@coord@stream@coord@{% - \ifpgfplots@stackedmode - \pgfplots@stacked@visphase@stream@coord@ - \fi - \ifx\pgfplots@current@point@x\pgfutil@empty% this implements `unbounded coords=jump', for example - \pgfplotsplothandlervisualizejump + \if1\b@pgfplots@LUA@visualization@enabled + \def\pgfplots@coord@stream@coord@{% + \ifx\pgfplots@current@point@x\pgfutil@empty% this implements `unbounded coords=jump', for example + \pgfplotsplothandlervisualizejump + \else + \pgfplotscoordmath{x}{tofixed}{\pgfplots@current@point@x}\let\pgfplots@current@point@x=\pgfmathresult + \pgfplotscoordmath{y}{tofixed}{\pgfplots@current@point@y}\let\pgfplots@current@point@y=\pgfmathresult + \ifpgfplots@curplot@threedim + \pgfplotscoordmath{z}{tofixed}{\pgfplots@current@point@z}\let\pgfplots@current@point@z=\pgfmathresult + \fi + % no need to call this here -- we got them from LUA: + % \pgfplotsaxis@toPGF@coords + \pgfplots@coord@stream@finalize@currentpt + \fi + }% + \else + \def\pgfplots@coord@stream@coord@{% + \ifpgfplots@stackedmode + \pgfplots@stacked@visphase@stream@coord@ + \fi + \ifx\pgfplots@current@point@x\pgfutil@empty% this implements `unbounded coords=jump', for example + \pgfplotsplothandlervisualizejump + \else + \pgfplotsaxisvisphasegetpoint + \pgfplots@coord@stream@finalize@currentpt + \fi + }% + \fi +} + +\def\pgfplots@LUA@visualization@init{% + \ifpgfplots@LUA@backend@supported + \edef\pgfplots@loc@TMPa{% + \directlua{pgfplots.texVisualizationInit(\plotnum, \ifpgfplots@curplot@threedim true\else false\fi)}% + }% + \if1\pgfplots@loc@TMPa + \pgfplots@log{\pgfplots@LUA@loglevel@debug}{lua backend=true: Activating partial LUA backend for visualization of plot \plotnum.}% \else - \pgfplotsaxisvisphasegetpoint - \pgfplots@coord@stream@finalize@currentpt + \pgfplots@LUA@backend@supportedfalse \fi - }% -} + \fi +}% % Takes the current point (defined by a set of macros) as input and defines \pgf@x and \pgf@y % as the output point. It also defines @@ -6748,14 +7201,13 @@ % transformed canvas coords (those which can be given to % \pgfplotsqpointxyz). % -% Furthermore, it defines keys '/data point/x untransformed' to -% contain the untransformed coords. \def\pgfplotsaxisvisphasegetpoint{% - \pgfkeyslet{/data point/x untransformed}\pgfplots@current@point@x - \pgfkeyslet{/data point/y untransformed}\pgfplots@current@point@y - \pgfkeyslet{/data point/z untransformed}\pgfplots@current@point@z \pgfplotsaxisvisphasetransformcoordinate\pgfplots@current@point@x\pgfplots@current@point@y\pgfplots@current@point@z% \pgfplotsaxisvisphasepreparedatapoint + \pgfplotsaxis@toPGF@coords +}% + +\def\pgfplotsaxis@toPGF@coords{% \ifpgfplots@curplot@threedim \pgfplotsqpointxyz{\pgfplots@current@point@x}{\pgfplots@current@point@y}{\pgfplots@current@point@z}% \else @@ -6773,15 +7225,43 @@ \pgfplotspointgetcoordinatesfromnormalized }% +% PRECONDITION: \pgfplots@current@point@x and its variants is given in +% TRANSFORMED format, i.e. we assume that we are in the visualization +% phase after the coordinates have been prepared. +% POSTCONDITION: the untransformed #1 coordinate is assigned to +% \pgfplotsretval +\def\pgfplotspointgetnormalizedcoordinates@#1{% + % XXX : this is slower than it used to be - in 1.11, I simply + % remembered 'x untransformed'! I switched it to this lazy + % computation due to the LUA backend in which case remembering it + % leads to extensive (=expensive?) communication between lua and + % TeX. Does it hurt here? Scatter plots compute this stuff... + \expandafter\let\expandafter\pgfplotsretval\csname pgfplots@current@point@#1\endcsname + \ifx\pgfplotsretval\pgfutil@empty + \else + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + \pgfplotscoordmath{#1}{datascaletrafo inverse}{\pgfplotsretval}% + \let\pgfplotsretval=\pgfmathresult + }{}% + \fi +}% + % Same as \pgfplotspointgetcoordinates, but the resulting values are % for use in 'normalized axis cs'. \def\pgfplotspointgetnormalizedcoordinates{% - \pgfkeysgetvalue{/data point/x untransformed}\pgfplots@loc@TMPa - \pgfkeyslet{/data point/x}\pgfplots@loc@TMPa - \pgfkeysgetvalue{/data point/y untransformed}\pgfplots@loc@TMPa - \pgfkeyslet{/data point/y}\pgfplots@loc@TMPa - \pgfkeysgetvalue{/data point/z untransformed}\pgfplots@loc@TMPa - \pgfkeyslet{/data point/z}\pgfplots@loc@TMPa + \pgfplotspointgetnormalizedcoordinates@ x% + \pgfkeyslet{/data point/x}\pgfplotsretval + % + \pgfplotspointgetnormalizedcoordinates@ y% + \pgfkeyslet{/data point/y}\pgfplotsretval + % + \ifpgfplots@curplot@threedim + \pgfplotspointgetnormalizedcoordinates@ z% + \pgfkeyslet{/data point/z}\pgfplotsretval + \else + \pgfkeyslet{/data point/z}\pgfutil@empty + \fi + % \pgfkeyslet{/data point/meta}\pgfplots@current@point@meta \edef\pgfplots@loc@TMPa{\pgfplots@current@point@coordindex}% \pgfkeyslet{/data point/index}\pgfplots@loc@TMPa @@ -7047,6 +7527,17 @@ %\message{NO cache hit for \string\pgfplotspointplotattime{#1}^^J}% \begingroup % + \if1\b@pgfplots@LUA@visualization@enabled + \ifx\pgfplots@plot@timer@args\relax + \expandafter\gdef\expandafter\pgfplots@plot@timer@args\expandafter{% + \directlua{pgfplots.texGetSurveyedCoordsToPgfplots()}% + }% + \fi + \let\pgfplotsaxisdeserializedatapointfrom@private=\pgfplotsaxisdeserializedatapointfrom@private@nonLUA + \else + \global\let\pgfplots@plot@timer@args=\pgfplots@stored@current@data + \fi + % % \edef\pgfplots@time{#1}% \pgfplotscoordmathparsemacro{default}{\pgfplots@time}% @@ -7265,19 +7756,12 @@ % either floating point or fixed point coordinates (depending on the % state of the \ifpgfplots@apply@datatrafo boolean) % -\long\def\pgfplots@coord@stream@finalize@storedcoords@START normalized coordinates #1#2;\pgfplots@EOI{% +\long\def\pgfplots@coord@stream@finalize@storedcoords@START{% % de-activate the FPU here! I fear its number % format may cause errors when used in low-level % routines. \pgfkeys{/pgf/fpu=false}% % - \ifpgfplots@threedim - \pgfplots@apply@zbuffer{#1}% - \let\pgfplots@coord@stream@finalize@storedcoords@START@coords=\pgfplotsglobalretval - \global\let\pgfplotsglobalretval=\relax - \else - \def\pgfplots@coord@stream@finalize@storedcoords@START@coords{#1}% - \fi \pgfplots@assert@tikzinternal@exists{tikz@make@last@position}% % \ifpgfplots@clip @@ -7290,8 +7774,10 @@ % \pgfplots@stored@current@cmd%[current plot style] <--- options are already set \pgfextra + % \tikzset{every plot/.try}% \pgfplots@coord@stream@INIT@finalize@storedcoords% + % \iffalse %\ifx\pgfplots@basiclevel@plothandler\pgfplothandlerdiscard % discard!? Well, no need to loop through the elements. @@ -7302,7 +7788,7 @@ \pgfplots@coord@stream@start \pgfplots@coord@stream@end \else - \expandafter\pgfplots@coord@stream@foreach@NORMALIZED\expandafter{\pgfplots@coord@stream@finalize@storedcoords@START@coords}% + \expandafter\pgfplots@coord@stream@foreach@NORMALIZED\expandafter{\pgfplots@stored@current@data}% \fi % % This here ensures that the LAST position of the path is the last plotted point. @@ -7311,16 +7797,18 @@ \xdef\pgfplotlastpoint{\noexpand\pgfpointanchor{current plot end}{center}}% \tikz@make@last@position{\pgfplotlastpoint}% % - \let\pgfplots@plot@timer@args=\pgfplots@coord@stream@finalize@storedcoords@START@coords + % the coordinate stream will be assigned as soon as it is needed: + \global\let\pgfplots@plot@timer@args=\relax \pgfplotspointplotattimeclearcache \let\tikz@timer=\pgfplots@plot@timer% - \pgfplotsaxisvisphase@get@afterpath{#2}% + \pgfplotsaxisvisphase@get@afterpath% \expandafter \endpgfextra \pgfplotsretval - ; + ;% % \pgfplotspointplotattimeclearcache + \global\let\pgfplots@plot@timer@args=\relax % }% @@ -7328,7 +7816,7 @@ % standard tikz instructions which are to be carried out after the % plot path. This depends on the current visualization phase and the % available visualization phases. -\def\pgfplotsaxisvisphase@get@afterpath#1{% +\def\pgfplotsaxisvisphase@get@afterpath{% \ifx\pgfplots@visphase@name\pgfplotsaxis@visphase@name@default % ah - we have the standard visualization phase. Draw them % here. @@ -7336,7 +7824,7 @@ % Note that the existance of (nontrivial) after path % instructions ALWAYS implies the existance of a standard % visualization phase (compare \pgfplotssurveyphase@set@visphase@names) - \def\pgfplotsretval{#1}% + \let\pgfplotsretval=\pgfplots@serialized@afterpath% \else \let\pgfplotsretval=\pgfutil@empty \fi @@ -7499,6 +7987,7 @@ \pgfplots@error{Sorry, plot graphics does not support 'unbounded coords=jump'.}% }% }% + \def\pgfplotsplothandlername{graphics}% }% \def\pgfplots@plot@handler@graphics@collectbb#1{% \pgf@process{#1}% @@ -8254,101 +8743,76 @@ -% #1: a normalized coordinate stream. -% -% Output: a normalized coordinate stream in \pgfplotsglobalretval. -\def\pgfplots@apply@zbuffer#1{% +% Input : \pgfplots@stored@current@data contains the coordinate stream +% Output: \pgfplots@stored@current@data contains the (modified) +% coordinate stream +\def\pgfplots@apply@zbuffer{% \ifcase\pgfplotsplothandlermesh@zbuffer@choice\relax % none. - \gdef\pgfplotsglobalretval{#1}% \or % reverse x seq: only for 'mesh' \if\pgfplots@meshmode n% \pgfplots@error{Sorry, `/pgfplots/z buffer=reverse x seq' can only be used for mesh/surf plots.}% - \gdef\pgfplotsglobalretval{#1}% \else \pgfplotsautocompletemeshkeys \if\pgfplots@plot@mesh@ordering0% % ordering = rowwise -> scanline is cols! \pgfkeysgetvalue{/pgfplots/mesh/cols}\pgfplotsscanlinelength - \pgfplots@apply@zbuffer@reversescanline{#1}% + \pgfplots@apply@zbuffer@reversescanline% \else % ordering = colwise: scanline is rows! \pgfkeysgetvalue{/pgfplots/mesh/rows}\pgfplotsscanlinelength - \pgfplots@apply@zbuffer@reversetransposed{#1}% + \pgfplots@apply@zbuffer@reversetransposed% \fi \fi \or % reverse y seq: only for 'mesh' \if\pgfplots@meshmode n% \pgfplots@error{Sorry, `/pgfplots/z buffer=reverse y seq' can only be used for mesh/surf plots.}% - \gdef\pgfplotsglobalretval{#1}% \else \pgfplotsautocompletemeshkeys \if\pgfplots@plot@mesh@ordering0% % ordering = rowwise -> scanline is cols! \pgfkeysgetvalue{/pgfplots/mesh/cols}\pgfplotsscanlinelength - \pgfplots@apply@zbuffer@reversetransposed{#1}% + \pgfplots@apply@zbuffer@reversetransposed% \else % ordering = colwise: scanline is rows! \pgfkeysgetvalue{/pgfplots/mesh/rows}\pgfplotsscanlinelength - \pgfplots@apply@zbuffer@reversescanline{#1}% + \pgfplots@apply@zbuffer@reversescanline% \fi \fi \or % reverse xy seq: - \begingroup - \def\pgfplots@coord@stream@start{% - \pgfplotsprependlistXnewempty{reversed}% - }% - \def\pgfplots@coord@stream@coord{% - \expandafter\pgfplotsprependlistXpushfront\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded@braced}\to{reversed}% - }% - \def\pgfplots@coord@stream@end{% - \pgfplotsprependlistXlet\pgfplots@loc@TMPa={reversed}% - \pgfplotsprependlistXnewempty{reversed}% clear it - \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa - }% - \pgfplots@coord@stream@foreach@NORMALIZED{#1}% - \endgroup - \or - % sort. - \if\pgfplots@meshmode n% + \ifpgfplots@LUA@backend@supported + \directlua{pgfplots.texApplyZBufferReverseStream()}% + \else \begingroup \def\pgfplots@coord@stream@start{% - \pgfplotsarraynewempty\pgfplots@zbuffer@local - \pgfplotsarrayresize\pgfplots@zbuffer@local{\numcoords}% - \c@pgfplots@scanlineindex=0 - \def\pgfplots@zbuffer@local@SETCUR####1{% - \expandafter\pgfplotsarrayset\c@pgfplots@scanlineindex\of\pgfplots@zbuffer@local\to{####1}% - }% + \pgfplotsprependlistXnewempty{reversed}% }% \def\pgfplots@coord@stream@coord{% - \expandafter\pgfplots@zbuffer@local@SETCUR\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded}% - \advance\c@pgfplots@scanlineindex by1 + \expandafter\pgfplotsprependlistXpushfront\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded@braced}\to{reversed}% }% \def\pgfplots@coord@stream@end{% - \ifnum\c@pgfplots@scanlineindex=\numcoords - \else - \pgfplotsarrayresize\pgfplots@zbuffer@local{\c@pgfplots@scanlineindex}% - \fi - \pgfkeyslet{/pgfplots/iflessthan/.@cmd}\pgfplots@apply@zbuffer@SORT@iflessthan - \pgfkeysdef{/pgfplots/array/unscope pre}{% - \pgfplotsapplistXnewempty{\pgfp@sortedlist}% - \pgfplotsarrayforeachungrouped\pgfplots@zbuffer@local\as\curelem{% - \expandafter\pgfplotsapplistXpushback\expandafter{\expandafter{\curelem}}\to{\pgfp@sortedlist}% - }% - \pgfplotsapplistXlet\pgfplots@loc@TMPa={\pgfp@sortedlist}% - \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa - }% - \pgfkeysdef{/pgfplots/array/unscope post}{}% - \pgfplotsarraysort\pgfplots@zbuffer@local + \pgfplotsprependlistXlet\pgfplots@loc@TMPa={reversed}% + \pgfplotsprependlistXnewempty{reversed}% clear it + \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa }% - \pgfplots@coord@stream@foreach@NORMALIZED{#1}% + \expandafter\pgfplots@coord@stream@foreach@NORMALIZED\expandafter{\pgfplots@stored@current@data}% \endgroup + \let\pgfplots@stored@current@data=\pgfplotsglobalretval + \global\let\pgfplotsglobalretval=\pgfutil@empty + \fi + \or + % sort. + \if\pgfplots@meshmode n% + \ifpgfplots@LUA@backend@supported + \directlua{pgfplots.texApplyZBufferSort()}% + \else + \pgfplots@apply@zbuffer@sort@coordinates + \fi \else % meshmode handles sort separately! - \gdef\pgfplotsglobalretval{#1}% \fi \or % z buffer=auto @@ -8397,10 +8861,10 @@ \fi \fi %\message{z buffer=auto mode chose z buffer= \ifcase\pgfplotsplothandlermesh@zbuffer@choice NONE \or reverse x seq \or reverse y seq \or reverse xy seq \or sort\or default \fi. mesh ordering = \ifcase\pgfplots@plot@mesh@ordering x varies/rowwise\or y varies/colwise\fi}% - % 'z buffer' is no longer 'auto' now: - \pgfplots@apply@zbuffer{#1}% \pgfmath@smuggleone\pgfplotsplothandlermesh@zbuffer@choice \endgroup + % 'z buffer' is no longer 'auto' now: + \pgfplots@apply@zbuffer \else % mesh input=patches \ifpgfplots@threedim @@ -8411,21 +8875,55 @@ \else \pgfkeys{/pgfplots/z buffer=none}% \fi - \gdef\pgfplotsglobalretval{#1}% \fi \or % z buffer=default. \if\pgfplots@meshmode n% % mesh mode deactivated! - \gdef\pgfplotsglobalretval{#1}% \else % mesh=true \pgfkeysalso{/pgfplots/z buffer=auto}% - \pgfplots@apply@zbuffer{#1}% + \pgfplots@apply@zbuffer% \fi \fi }% +\def\pgfplots@apply@zbuffer@sort@coordinates{% + \begingroup + \def\pgfplots@coord@stream@start{% + \pgfplotsarraynewempty\pgfplots@zbuffer@local + \pgfplotsarrayresize\pgfplots@zbuffer@local{\numcoords}% + \c@pgfplots@scanlineindex=0 + \def\pgfplots@zbuffer@local@SETCUR####1{% + \expandafter\pgfplotsarrayset\c@pgfplots@scanlineindex\of\pgfplots@zbuffer@local\to{####1}% + }% + }% + \def\pgfplots@coord@stream@coord{% + \expandafter\pgfplots@zbuffer@local@SETCUR\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded}% + \advance\c@pgfplots@scanlineindex by1 + }% + \def\pgfplots@coord@stream@end{% + \ifnum\c@pgfplots@scanlineindex=\numcoords + \else + \pgfplotsarrayresize\pgfplots@zbuffer@local{\c@pgfplots@scanlineindex}% + \fi + \pgfkeyslet{/pgfplots/iflessthan/.@cmd}\pgfplots@apply@zbuffer@SORT@iflessthan + \pgfkeysdef{/pgfplots/array/unscope pre}{% + \pgfplotsapplistXnewempty{\pgfp@sortedlist}% + \pgfplotsarrayforeachungrouped\pgfplots@zbuffer@local\as\curelem{% + \expandafter\pgfplotsapplistXpushback\expandafter{\expandafter{\curelem}}\to{\pgfp@sortedlist}% + }% + \pgfplotsapplistXlet\pgfplots@loc@TMPa={\pgfp@sortedlist}% + \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa + }% + \pgfkeysdef{/pgfplots/array/unscope post}{}% + \pgfplotsarraysort\pgfplots@zbuffer@local + }% + \expandafter\pgfplots@coord@stream@foreach@NORMALIZED\expandafter{\pgfplots@stored@current@data}% + \endgroup + \let\pgfplots@stored@current@data=\pgfplotsglobalretval + \global\let\pgfplotsglobalretval=\pgfutil@empty +}% % Defines \pgfplotsglobalretval (globally) to be a partial reversion of the % (normalized) 2d coordinate sequence '#1'. % @@ -8440,70 +8938,82 @@ % \pgfplotsscanlinelength contains the scanline length % POSTCONDITION: % \pgfplotsglobalretval contains the partial reversion. -\def\pgfplots@apply@zbuffer@reversescanline#1{% - \begingroup - \def\pgfplots@coord@stream@start{% - \pgfplotsprependlistXnewempty{reversedscanline}% - \c@pgfplots@scanlineindex=0 - \pgfplotsapplistXnewempty{\resultlist}% - }% - \def\pgfplots@coord@stream@coord{% - \expandafter\pgfplotsprependlistXpushfront\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded@braced}\to{reversedscanline}% - \advance\c@pgfplots@scanlineindex by1 - \ifnum\c@pgfplots@scanlineindex=\pgfplotsscanlinelength\relax - \pgfplotsprependlistXlet\pgfplots@loc@TMPa={reversedscanline}% - \expandafter\pgfplotsapplistXpushback\expandafter{\pgfplots@loc@TMPa}\to\resultlist +\def\pgfplots@apply@zbuffer@reversescanline{% + \ifpgfplots@LUA@backend@supported + \directlua{pgfplots.texApplyZBufferReverseScanline(\pgfplotsscanlinelength)}% + \else + \begingroup + \def\pgfplots@coord@stream@start{% \pgfplotsprependlistXnewempty{reversedscanline}% \c@pgfplots@scanlineindex=0 - \fi - }% - \def\pgfplots@coord@stream@end{% - \pgfplotsprependlistXlet\pgfplots@loc@TMPa={reversedscanline}% - \ifx\pgfplots@loc@TMPa\pgfutil@empty - \else - \pgfplots@zbuffer@error - \fi - \pgfplotsapplistXlet\pgfplots@loc@TMPa={\resultlist}% - \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa - }% - \pgfplots@coord@stream@foreach@NORMALIZED{#1}% + \pgfplotsapplistXnewempty{\resultlist}% + }% + \def\pgfplots@coord@stream@coord{% + \expandafter\pgfplotsprependlistXpushfront\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded@braced}\to{reversedscanline}% + \advance\c@pgfplots@scanlineindex by1 + \ifnum\c@pgfplots@scanlineindex=\pgfplotsscanlinelength\relax + \pgfplotsprependlistXlet\pgfplots@loc@TMPa={reversedscanline}% + \expandafter\pgfplotsapplistXpushback\expandafter{\pgfplots@loc@TMPa}\to\resultlist + \pgfplotsprependlistXnewempty{reversedscanline}% + \c@pgfplots@scanlineindex=0 + \fi + }% + \def\pgfplots@coord@stream@end{% + \pgfplotsprependlistXlet\pgfplots@loc@TMPa={reversedscanline}% + \ifx\pgfplots@loc@TMPa\pgfutil@empty + \else + \pgfplots@zbuffer@error + \fi + \pgfplotsapplistXlet\pgfplots@loc@TMPa={\resultlist}% + \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa + }% + \expandafter\pgfplots@coord@stream@foreach@NORMALIZED\expandafter{\pgfplots@stored@current@data}% + \endgroup + \let\pgfplots@stored@current@data=\pgfplotsglobalretval + \global\let\pgfplotsglobalretval=\pgfutil@empty + \fi %\message{I have performed partial reversion of '#1' and got '\pgfplotsglobalretval'!}% - \endgroup }% % A very similar method of \pgfplots@apply@zbuffer@reversescanline, % but this one keeps everything inside of each scanline in the % original ordering, and reverses the ordering in which whole % scanlines occur. -\def\pgfplots@apply@zbuffer@reversetransposed#1{% - \begingroup - \def\pgfplots@coord@stream@start{% - \pgfplotsapplistXnewempty{\scanline}% - \c@pgfplots@scanlineindex=0 - \pgfplotsprependlistXnewempty{resultlist}% - }% - \def\pgfplots@coord@stream@coord{% - \expandafter\pgfplotsapplistXpushback\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded@braced}\to{\scanline}% - \advance\c@pgfplots@scanlineindex by1 - \ifnum\c@pgfplots@scanlineindex=\pgfplotsscanlinelength\relax - \pgfplotsapplistXlet\pgfplots@loc@TMPa={\scanline}% - \expandafter\pgfplotsprependlistXpushfront\expandafter{\pgfplots@loc@TMPa}\to{resultlist} +\def\pgfplots@apply@zbuffer@reversetransposed{% + \ifpgfplots@LUA@backend@supported + \directlua{pgfplots.texApplyZBufferReverseTransposed(\pgfplotsscanlinelength)}% + \else + \begingroup + \def\pgfplots@coord@stream@start{% \pgfplotsapplistXnewempty{\scanline}% \c@pgfplots@scanlineindex=0 - \fi - }% - \def\pgfplots@coord@stream@end{% - \pgfplotsapplistXlet\pgfplots@loc@TMPa={\scanline}% - \ifx\pgfplots@loc@TMPa\pgfutil@empty - \else - \pgfplots@zbuffer@error - \fi - \pgfplotsprependlistXlet\pgfplots@loc@TMPa={resultlist}% - \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa - }% - \pgfplots@coord@stream@foreach@NORMALIZED{#1}% -%\message{I have performed partial reversion of '#1' and got '\pgfplotsglobalretval'!}% - \endgroup + \pgfplotsprependlistXnewempty{resultlist}% + }% + \def\pgfplots@coord@stream@coord{% + \expandafter\pgfplotsapplistXpushback\expandafter{\pgfplots@coord@stream@foreach@NORMALIZED@curencoded@braced}\to{\scanline}% + \advance\c@pgfplots@scanlineindex by1 + \ifnum\c@pgfplots@scanlineindex=\pgfplotsscanlinelength\relax + \pgfplotsapplistXlet\pgfplots@loc@TMPa={\scanline}% + \expandafter\pgfplotsprependlistXpushfront\expandafter{\pgfplots@loc@TMPa}\to{resultlist} + \pgfplotsapplistXnewempty{\scanline}% + \c@pgfplots@scanlineindex=0 + \fi + }% + \def\pgfplots@coord@stream@end{% + \pgfplotsapplistXlet\pgfplots@loc@TMPa={\scanline}% + \ifx\pgfplots@loc@TMPa\pgfutil@empty + \else + \pgfplots@zbuffer@error + \fi + \pgfplotsprependlistXlet\pgfplots@loc@TMPa={resultlist}% + \global\let\pgfplotsglobalretval=\pgfplots@loc@TMPa + }% + \expandafter\pgfplots@coord@stream@foreach@NORMALIZED\expandafter{\pgfplots@stored@current@data}% + \endgroup + \let\pgfplots@stored@current@data=\pgfplotsglobalretval + \global\let\pgfplotsglobalretval=\pgfutil@empty + \fi +%\message{I have performed partial reversion (reverse transposed) of '#1' and got '\pgfplotsglobalretval'!}% }% \def\pgfplots@zbuffer@error{% \pgfplots@error{An internal error occured during z buffer reorderings: the rows/cols where not balanced! I have rows= \pgfkeysvalueof{/pgfplots/mesh/rows}, cols=\pgfkeysvalueof{/pgfplots/mesh/cols}. If this happens to be wrong, you might want to provide rows and cols manually.}% diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex index ac17d5ffb5e..c2ed44a36b7 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplotscore.code.tex @@ -7,7 +7,7 @@ % % It is based on Till Tantau's PGF package. % -% Copyright 2007/2008 by Christian Feuersänger. +% Copyright 2007-2014 by Christian Feuersänger. % % This program is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by @@ -38,8 +38,57 @@ } \pgfplotsutil@IfUndefined{pgfutil@IfUndefined}{\let\pgfutil@IfUndefined=\pgfplotsutil@IfUndefined}{} +\newif\ifpgfplots@LUA@supported +\pgfutil@IfUndefined{directlua}{% + \pgfplots@LUA@supportedfalse +}{% + \pgfplots@LUA@supportedtrue +}% + +% this is an emergency key which allows to switch off LUA support in +% pgfplots early at boot time. +% +% use \def\pgfplotsenablelua{0} to switch it off. '1' switches it on +% (or uncommenting the line). +\pgfutil@IfUndefined{pgfplotsenablelua}{}{% + \def\pgfplots@glob@TMPc{1}% + \ifx\pgfplots@glob@TMPc\pgfplotsenablelua + \else + \pgfplots@LUA@supportedfalse + \fi +}% + +\pgfkeys{ + /pgfplots/lua support/.is choice, + /pgfplots/lua support/true/.code={\pgfplots@LUA@supportedtrue},% + /pgfplots/lua support/false/.code={\pgfplots@LUA@supportedfalse},% + /pgfplots/lua support/auto/.code={% + \pgfutil@IfUndefined{directlua}{% + \pgfplots@LUA@supportedfalse + }{% + \pgfplots@LUA@supportedtrue + }% + },% + %/pgfplots/lua support/auto,% this is the default anyway +} + +\def\pgfplotsloglevel{4}% -\def\pgfplots@log#1#2{\immediate\write-1{Package pgfplots info: #2}}% +\def\pgfplots@log#1#2{% + \ifnum#1>\pgfplotsloglevel\relax + \else + \ifnum\inputlineno=1 + \pgfutil@IfUndefined{@currenvline}{% + \def\pgfplots@log@tmp{}% + }{% + \let\pgfplots@log@tmp=\@currenvline + }% + \else + \def\pgfplots@log@tmp{ on input line \the\inputlineno}% + \fi + \immediate\write-1{Package pgfplots info\pgfplots@log@tmp: #2}% + \fi +}% \def\pgfplots@error#1{\PackageError{pgfplots}{#1}{}}% \def\pgfplotstable@error@pkg#1{\PackageError{pgfplotstable}{#1}{}}% % DO NOT USE THIS METHOD DIRECTLY: use \pgfplotswarning{<warning name>}<args>\pgfeov @@ -241,6 +290,9 @@ /pgfplots/warning/scatter classes no such class/.code={% \pgfplotsthrow@warning{scatter/classes: can't find class for '#1'!? Please make sure you have specified 'scatter src=explicit symbolic'. Ignoring class '#1' (this message will not come again).}% }, + /pgfplots/warning/lua colormap unavailable/.code={% + \pgfplotsthrow@warning{there is no LUA colormap representation for #1. Using TeX arithmetics.}% + }, /pgfplots/warning/interior colormap inefficient/.code={% \pgfplotsthrow@warning{the combination 'shader=interp,interior colormap name' is inefficient (it uses 'shader=faceted interp,faceted color=none') and may slow down the *display* of your document}% }, diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandler.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandler.code.tex index 9d1ee9221e2..fb3ab9b42e2 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandler.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplothandler.code.tex @@ -134,6 +134,7 @@ % -> see also the legend image for mesh plots. % \def\pgfplotsplothandlermesh{% + \def\pgfplotsplothandlername{mesh}% \pgfkeysgetvalue{/pgfplots/patch type}\pgfplotsplothandlermesh@patchclass \ifx\pgfplotsplothandlermesh@patchclass\pgfplotsplothandlermesh@patchclass@defaulttext \let\pgfplotsplothandlermesh@patchclass=\pgfutil@empty @@ -158,6 +159,8 @@ \let\pgfplotsplothandlersurveyend=\pgfplotsplothandlersurveyend@mesh \let\pgfplotsplothandlersurveyaftersetpointmeta=\pgfplotsplothandlersurveyaftersetpointmeta@mesh@cdatanormalize % + \def\pgfplotsplothandlerLUAfactory{pgfplots.MeshPlothandler.new}% + % \pgfkeysgetvalue{/pgfplots/patch table/value}\pgfplotsplothandlermesh@patchtable \ifx\pgfplotsplothandlermesh@patchtable\pgfutil@empty \else @@ -165,6 +168,9 @@ \let\pgfplotsplothandlersurveystart=\pgfplotsplothandlersurveystart@mesh@patchtable \let\pgfplotsplothandlersurveypoint=\pgfplotsplothandlersurveypoint@mesh@patchtable \let\pgfplotsplothandlersurveyend=\pgfplotsplothandlersurveyend@mesh@patchtable + % + % this is currently unsupported in LUA: + \let\pgfplotsplothandlerLUAfactory=\pgfutil@empty \fi \if0\pgfplotsplothandlermesh@colorinput % mesh/color input=colormap @@ -175,99 +181,18 @@ \fi \fi % + % + \pgfplotsifisvisualizationphase{% + \pgfplotsplothandlermesh@init@variables + }{}% + % + % \def\pgf@plotstreamstart{% % \scope % % this shouldn't be necessary, but it doesn't hurt either. \pgfplots@perpointmeta@preparetrafo % - \def\pgfplotsplothandlermesh@ONEDIMMODE{0}% - \pgfplotsplothandlermesh@init@meshkeys - % - % - \let\pgfplotsplothandlermesh@patchclass@input=\pgfplotsplothandlermesh@patchclass - \let\pgfplotsplothandlermesh@patchclass@output=\pgfplotsplothandlermesh@patchclass@input - \if0\pgfplotsplothandlermesh@triangulate - \else - \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@input}{triangulate class}% - \let\pgfplotsplothandlermesh@patchclass@output=\pgfplotsretval - \fi - % - \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@input}{init}% - \ifx\pgfplotsplothandlermesh@patchclass@input\pgfplotsplothandlermesh@patchclass@output - \else - \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{init}% - \fi - % - % assign boolean: - \let\b@pgfplotsplothandlermesh@matrixoutput=\pgfplotsplothandlermesh@matrixinput - \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{allow matrix}% - \if0\pgfplotsretval - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - \ifnum\pgfkeysvalueof{/pgfplots/patch refines}>0 - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - \if1\pgfplotsaxisplothasjumps - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - \if\pgfplotsplothandlermesh@zbuffer@choice4% 'z buffer=sort': - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - % - \if2\pgfplotsplothandlermesh@shader - % shader=interp - % - \pgfkeysgetvalue{/pgfplots/mesh/interior colormap name}\pgfplots@loc@TMPc - \ifx\pgfplots@loc@TMPc\pgfutil@empty - \else - \pgfplotswarning{interior colormap inefficient}\pgfeov% - \pgfplotsset{shader=faceted interp,faceted color=none}% - \fi - \fi - \if2\pgfplotsplothandlermesh@shader - % shader=interp - \if0\pgfplotsplothandlermesh@triangulate - % patch to triangles=false - \else - % no matrix output possible: - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - \else - % 'shader!=interp' - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{get pdf shading type}% - \if5\pgfplotsretval - \else - \def\b@pgfplotsplothandlermesh@matrixoutput{0}% - \fi - % - % special handling: check if Type=5 shadings need to be - % converted to Type=4 - \if0\b@pgfplotsplothandlermesh@matrixoutput - % no matrix output possible - \if5\pgfplotsretval - % pdf shading type=5 (matrix output) - \if2\pgfplotsplothandlermesh@shader - % shader=interp - % - % FIXME : I am unsure if this here is still - % necessary as of 3fc734d7ac3020600c06258b1bc80b22da53edf3 - % -> perhaps the check can be skipped entirely. - % - % oh. shading type=5 is *essentially* the same as - % matrix output, but matrix output is forbidden. - % In that case, triangulate the matrix and shade the - % triangles: - \def\pgfplotsplothandlermesh@triangulate{1}% - \def\pgfplotsplothandlermesh@patchclass@output{triangle}% - % Note shader=faceted interp can be written as - % matrix -- it shades individual elements anyway; - % and one single patch can be written as matrix. - \fi - \fi - \fi % \pgfplotsplothandlermesh@init@DECODE \pgfplotsplothandlermesh@init@REFINE @@ -309,6 +234,133 @@ \let\pgfplotsplothandlerifcurrentpointcanbefirstlast=\pgfplotsplothandlerifcurrentpointcanbefirstlast@mesh }% +\def\pgfplotsplothandlermesh@init@variables{% + % Check if the current shader needs to be reset. + % Do this early as some processing steps depend on it: + \if\pgfplots@meshmode m% mesh + % this is processed by the 'shader=flat' code below. + \def\pgfplotsplothandlermesh@shader{0}% 'flat' + \fi + \ifnum\pgfplotsplothandlermesh@shader>1% 'shader=interp' and 'shader=faceted interp' + \pgflibrarysurfshadingifactive + {}% + {% + \pgfutil@ifundefined{pgfplotsplothandlermesh@shader@warning}{% + \pgfplots@error{Sorry, surface shading (shader=interp) is NOT available for the selected driver `\pgfsysdriver'. I will use 'shader=flat' if you continue now}% + \gdef\pgfplotsplothandlermesh@shader@warning{x}% + }{}% + \def\pgfplotsplothandlermesh@shader{0}% + }% + \fi + % + \def\pgfplotsplothandlermesh@ONEDIMMODE{0}% + \pgfplotsplothandlermesh@init@meshkeys + % + % + \let\pgfplotsplothandlermesh@patchclass@input=\pgfplotsplothandlermesh@patchclass + \let\pgfplotsplothandlermesh@patchclass@output=\pgfplotsplothandlermesh@patchclass@input + \if0\pgfplotsplothandlermesh@triangulate + \else + \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@input}{triangulate class}% + \let\pgfplotsplothandlermesh@patchclass@output=\pgfplotsretval + \fi + % + \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@input}{init}% + \ifx\pgfplotsplothandlermesh@patchclass@input\pgfplotsplothandlermesh@patchclass@output + \else + \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{init}% + \fi + % + % assign boolean: + \let\b@pgfplotsplothandlermesh@matrixoutput=\pgfplotsplothandlermesh@matrixinput + \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{allow matrix}% + \if0\pgfplotsretval + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + \ifnum\pgfkeysvalueof{/pgfplots/patch refines}>0 + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + \if1\pgfplotsaxisplothasjumps + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + \if\pgfplotsplothandlermesh@zbuffer@choice4% 'z buffer=sort': + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + % + \if2\pgfplotsplothandlermesh@shader + % shader=interp + % + \pgfkeysgetvalue{/pgfplots/mesh/interior colormap name}\pgfplots@loc@TMPc + \ifx\pgfplots@loc@TMPc\pgfutil@empty + \else + \pgfplotswarning{interior colormap inefficient}\pgfeov% + \pgfplotsset{shader=faceted interp,faceted color=none}% + \fi + \fi + \if2\pgfplotsplothandlermesh@shader + % shader=interp + \if0\pgfplotsplothandlermesh@triangulate + % patch to triangles=false + \else + % no matrix output possible: + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + \else + % 'shader!=interp' + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{get pdf shading type}% + \if5\pgfplotsretval + \else + \def\b@pgfplotsplothandlermesh@matrixoutput{0}% + \fi + % + % special handling: check if Type=5 shadings need to be + % converted to Type=4 + \if0\b@pgfplotsplothandlermesh@matrixoutput + % no matrix output possible + \if5\pgfplotsretval + % pdf shading type=5 (matrix output) + \if2\pgfplotsplothandlermesh@shader + % shader=interp + % + % FIXME : I am unsure if this here is still + % necessary as of 3fc734d7ac3020600c06258b1bc80b22da53edf3 + % -> perhaps the check can be skipped entirely. + % + % oh. shading type=5 is *essentially* the same as + % matrix output, but matrix output is forbidden. + % In that case, triangulate the matrix and shade the + % triangles: + \def\pgfplotsplothandlermesh@triangulate{1}% + \def\pgfplotsplothandlermesh@patchclass@output{triangle}% + % Note shader=faceted interp can be written as + % matrix -- it shades individual elements anyway; + % and one single patch can be written as matrix. + \fi + \fi + \fi + % + % + \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass}{LUA class}% + \ifx\pgfplotsretval\pgfutil@empty + \let\pgfplotsplothandlerLUAvisualizerfactory=\pgfutil@empty + \else + \edef\pgfplotsplothandlerLUAvisualizerfactory{ + function(plothandler) return pgfplots.MeshVisualizer.new( + plothandler, + \pgfplotsretval(), + pgfplots.pgftonumber("\pgfkeysvalueof{/pgfplots/mesh/rows}"), + pgfplots.pgftonumber("\pgfkeysvalueof{/pgfplots/mesh/cols}"), + \if0\pgfplots@plot@mesh@ordering true\else false\fi, + \if1\pgfplotsplothandlermesh@matrixinput true\else false\fi, + \if1\b@pgfplotsplothandlermesh@matrixoutput true\else false\fi, + \if4\pgfplotsplothandlermesh@zbuffer@choice true\else false\fi)% 'z buffer=sort' + end + }% + \fi +}% + \def\pgfplotsplothandlerifcurrentpointcanbefirstlast@mesh#1#2{% \pgfplotspatchclass{\pgfplotsplothandlermesh@patchclass@output}{if current point can be first last}{#1}{#2}% }% @@ -750,6 +802,7 @@ sample in unit cube={% \pgfplots@error{sample in unit cube: not implemented for \pgfplotspatchclassname}% }, + LUA class=, }% }{}% % @@ -984,6 +1037,14 @@ % point of the patch. Executes ##2 if that is not the case. if current point can be first last/.code= {\expandafter\def\csname pgfpptch\pgfplotsdeclarepatchclass@ if current point can be first last\endcsname##1##2{#1}},% + % + % Defines \pgfplotsretval to contain LUA code which returns a + % factory method (with no arguments) which returns an instance of the + % associated LUA pgfplots.PatchType + % + % If the returned \pgfplotsretval is empty: there is no LUA implementation. + LUA class/.code= + {\expandafter\def\csname pgfpptch\pgfplotsdeclarepatchclass@ LUA class\endcsname{\def\pgfplotsretval{#1}}},% } % This implements 'compute normal' : @@ -1328,6 +1389,7 @@ #1, get pdf shading type=4, get num vertices=\def\pgfplotsretval{3}, + LUA class=pgfplots.TrianglePatchType.new, }% \def\pgfplotspatchclass@tri@recursiverefine@@#1#2M,#3#4M;#5\relax#6{% \expandafter\let\expandafter\pgfplotspatchclass@tri@A@\csname pgfplotspatchclass@tri@#1\endcsname @@ -1459,6 +1521,7 @@ deserialize except vertices=, get pdf shading type=5, get num vertices=\def\pgfplotsretval{4}, + LUA class=pgfplots.RectanglePatchType.new, }% \def\pgfplots@rect@next@A{B} @@ -1786,16 +1849,21 @@ % \if1\pgfplotsplothandlermesh@ONEDIMMODE %\message{initialised DECODE for 1d mode.^^J}% + % FIXME : needs LUA support... \let\pgfplotsplothandlermesh@PIPE@DECODE=\pgfplotsplothandlermesh@PIPE@DECODE@matrix@ONEDIMMODE \else \if0\b@pgfplotsplothandlermesh@matrixoutput - % in fact, this does only remember the maximum capacity; - % it doesn't fill the memory. - \c@pgfplots@scanlineindex=\pgfplotsplothandlermesh@scanlinelength\relax - \advance\c@pgfplots@scanlineindex by1 - \pgfplotsdequenewempty{lastscanline}\capacity{\the\c@pgfplots@scanlineindex}% - \let\pgfplotsplothandlermesh@PIPE@DECODE=\pgfplotsplothandlermesh@PIPE@DECODE@matrix@fillscanline + \if1\b@pgfplots@LUA@visualization@enabled +%\message{initialised DECODE for patch output (from matrix which has already been decoded in LUA).^^J}% + \else + % in fact, this does only remember the maximum capacity; + % it doesn't fill the memory. + \c@pgfplots@scanlineindex=\pgfplotsplothandlermesh@scanlinelength\relax + \advance\c@pgfplots@scanlineindex by1 + \pgfplotsdequenewempty{lastscanline}\capacity{\the\c@pgfplots@scanlineindex}% + \let\pgfplotsplothandlermesh@PIPE@DECODE=\pgfplotsplothandlermesh@PIPE@DECODE@matrix@fillscanline %\message{initialised DECODE for patch output (from matrix).^^J}% + \fi \else % SPECIAL HANDLING! \let\pgfplotsplothandlermesh@PIPE@DECODE=\pgfplotsplothandlermesh@PIPE@DECODE@to@shader @@ -2165,6 +2233,8 @@ % % Prepare: \def\pgfplotsplothandlermesh@definecolor{% + % FIXME : use lua backend to improve this here! it is + % _extremely_ slow! \pgfplotsplothandlermesh@get@flat@color \pgfplotsplothandlermesh@definemappedcolor{\pgfplotsretval}% \pgfplots@drawoptions @@ -2247,24 +2317,6 @@ }% \def\pgfplotsplothandlermesh@init@shader{% - % - % Now, process the 'shader' key here: - \if\pgfplots@meshmode m% mesh - % this is processed by the 'shader=flat' code below. - \def\pgfplotsplothandlermesh@shader{0}% 'flat' - \fi - \ifnum\pgfplotsplothandlermesh@shader>1% 'shader=interp' and 'shader=faceted interp' - \pgflibrarysurfshadingifactive - {}% - {% - \pgfutil@ifundefined{pgfplotsplothandlermesh@shader@warning}{% - \pgfplots@error{Sorry, surface shading (shader=interp) is NOT available for the selected driver `\pgfsysdriver'. I will use 'shader=flat' if you continue now}% - \gdef\pgfplotsplothandlermesh@shader@warning{x}% - }{}% - \def\pgfplotsplothandlermesh@shader{0}% - }% - \fi - % % \ifnum\pgfplotsplothandlermesh@shader>1 % 'shader=2': 'interp': @@ -2568,6 +2620,16 @@ \fi % \if\pgfplotsplothandlermesh@zbuffer@choice4% + \def\pgfplotsplothandlermesh@zbuffer@sort@in@TeX{1}% + \else + \def\pgfplotsplothandlermesh@zbuffer@sort@in@TeX{0}% + \fi + \if1\b@pgfplots@LUA@visualization@enabled + % set it to 'z buffer=none' -- LUA did the job already. + \def\pgfplotsplothandlermesh@zbuffer@sort@in@TeX{0}% + \fi + % + \if\pgfplotsplothandlermesh@zbuffer@sort@in@TeX1% % z buffer=sort: % create a z buffer: % the z buffer contains elements {<view depth>}{{<pt1>}{<pt2>}{<pt3>}{<pt4>}} @@ -2618,6 +2680,8 @@ \expandafter\pgfplotsarraypushback\pgfplots@loc@TMPa\to\pgfplots@zbuffer@local }% \fi + \else + \def\pgfplotsplothandlermesh@zbuffer@sort@in@TeX{0}% \fi }% \def\pgfplotsplothandlermesh@init@mesh@stream{% @@ -2660,12 +2724,14 @@ /pgfplots/mesh/num points=, /pgfplots/mesh input=lattice, /pgfplots/patch type=rectangle, + /pgfplots/z buffer=default, /tikz/x={(0.44237cm,-0.07439cm)}, /tikz/y={(0.30942cm,0.23932cm)}, /tikz/z={(0.0cm,1.5cm)}, scale=0.4, yshift=-0.7cm, /pgfplots/point meta=explicit, + /pgfplots/mesh/color input=colormap, ] \let\pgfplots@metamax=\pgfutil@empty \pgfplots@curplot@threedimtrue @@ -2707,7 +2773,7 @@ }% \def\pgfplotsplothandlermesh@finish{% - \if\pgfplotsplothandlermesh@zbuffer@choice4% + \if\pgfplotsplothandlermesh@zbuffer@sort@in@TeX1% % z buffer=sort: % process the z buffer: \pgfkeyslet{/pgfplots/iflessthan/.@cmd}\pgfplotsplothandlermesh@zbuffer@sort@iflessthen diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex index 450fa25878b..192d6a8abc0 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex @@ -389,6 +389,9 @@ \edef\pgfplotsplothandlername{\string##1}% \pgfmath@smuggleone\pgfplotsplothandlername \endgroup + % + \def\pgfplotsplothandlerLUAfactory{function(axis, pointmetainputhandler) return pgfplots.GenericPlothandler.new("\pgfplotsplothandlername", axis,pointmetainputhandler) end}% + \def\pgfplotsplothandlerLUAvisualizerfactory{pgfplots.defaultPlotVisualizerFactory}% }% }% % Patch all TikZ plot handlers: @@ -483,6 +486,8 @@ % This is necessary before installing a new plot handler! \def\pgfplotsresetplothandler{% \let\pgfplotsplothandlersurveystart=\pgfplotsplothandlersurveystart@default + \let\pgfplotsplothandlerLUAfactory=\pgfplotsplothandlerLUAfactory@default + \let\pgfplotsplothandlerLUAvisualizerfactory=\pgfplotsplothandlerLUAvisualizerfactory@default \let\pgfplotsplothandlername=\pgfplotsplothandlername@default \let\pgfplotsplothandlersurveyend=\pgfplotsplothandlersurveyend@default \let\pgfplotsplothandlersurveypoint=\pgfplotsplothandlersurveypoint@default @@ -513,6 +518,18 @@ [tikz@plot@handler: \meaning\pgf@plotstreamstart]% }% +% This should expand to a LUA function which takes the axis and the point +% meta handler. +% Use empty if there is none. +\def\pgfplotsplothandlerLUAfactory@default{}% + +% This should expand to a LUA function which takes an instance of +% Plothandler and which should return a PlotVisualizer. +% Use empty if there is none. +% +% @see LUA: pgfplots.PlotVisualizer +\def\pgfplotsplothandlerLUAvisualizerfactory@default{}% + % \pgfplotsplothandlerifcurrentpointcanbefirstlast : can be used to % check if the current point of a plot handler can be the global first % or last segment. @@ -539,6 +556,13 @@ % eventually). This DV engine stores data point entries in keys, % namely those in the key path /data point. See the pgf manual. \def\pgfplotsplothandlersurveypoint@default{% + \ifpgfplots@LUA@backend@supported + \pgfplots@LUA@survey@point + \else + \pgfplotsplothandlersurveypoint@default@ + \fi +}% +\def\pgfplotsplothandlersurveypoint@default@{% % reset it. NOTE: this migh be done multiple times. But better one % too much than one too few... \def\pgfplots@set@perpointmeta@done{0}% @@ -1096,12 +1120,12 @@ \E\let\E\pgfplots@current@point@x=\E\pgfmathresult % \E\expandafter\E\pgfplots@prepare@ycoord\E\expandafter{\E\pgfplots@current@point@y}% - \E\expandafter\E\pgfplots@invoke@filter\E\expandafter{\E\pgfmathresult}{y}% + \E\expandafter\E\pgfplots@invoke@filter\E\expandafter{\E\pgfplots@current@point@y}{y}% \E\let\E\pgfplots@current@point@y=\E\pgfmathresult % \ifpgfplots@curplot@threedim \E\expandafter\E\pgfplots@prepare@zcoord\E\expandafter{\E\pgfplots@current@point@z}% - \E\expandafter\E\pgfplots@invoke@filter\E\expandafter{\E\pgfmathresult}{z}% + \E\expandafter\E\pgfplots@invoke@filter\E\expandafter{\E\pgfplots@current@point@z}{z}% \E\let\E\pgfplots@current@point@z=\E\pgfmathresult \fi % @@ -1221,6 +1245,9 @@ quiver/u filter/.code=, quiver/v filter/.code=, quiver/w filter/.code=, + quiver/u filter/.expression/.code=\pgfplots@install@filter@expression{quiver/u filter}{#1}, + quiver/v filter/.expression/.code=\pgfplots@install@filter@expression{quiver/v filter}{#1}, + quiver/w filter/.expression/.code=\pgfplots@install@filter@expression{quiver/w filter}{#1}, quiver/u value/.code =\pgfplots@set@source@for{quiver/u}{#1}{0},% quiver/u/.code =\pgfplots@set@source@for{quiver/u}{#1}{1},% quiver/v value/.code =\pgfplots@set@source@for{quiver/v}{#1}{0},% @@ -1403,6 +1430,7 @@ \let\pgfplotsplothandlerdeserializepointfrom=\pgfplotsplothandlerdeserializepointfrom@quiver \let\pgfplotsplothandlerpointtokeys=\pgfplotsplothandlerpointtokeys@quiver \let\pgfplotsplothandlerquiver@vis@hook=\pgfutil@empty + \def\pgfplotsplothandlername{quiver}% % \ifpgfplots@xislinear \else \pgfplotsplothandlerquivererror \fi \ifpgfplots@yislinear \else \pgfplotsplothandlerquivererror\fi @@ -1523,7 +1551,7 @@ \fi \else % 'every arrow' should provide a high level user interface. - % Use tikz instead of pgf. This is slower, but more powerfull. + % Use tikz instead of pgf. This is slower, but more powerful. \pgfplots@quiver@usetikztrue \pgfplotsaxisifhaspointmeta{% % ASSERT(mapped color is available) @@ -1585,6 +1613,7 @@ hist/data value/.code =\pgfplots@set@source@for{hist/data}{#1}{0},% hist/data/.code =\pgfplots@set@source@for{hist/data}{#1}{1},% hist/data filter/.code=, + hist/data filter/.expression/.code=\pgfplots@install@filter@expression{hist/data filter}{#1}, hist/data value=\pgfkeysvalueof{/data point/y}, % hist/data=y, hist/data min/.initial=\pgfkeysvalueof{/pgfplots/xmin}, @@ -1909,7 +1938,7 @@ contour prepared/.code={% \let\tikz@plot@handler=\pgfplotsplothandlercontourprepared \pgfqkeys{/pgfplots/contour}{% - every contour plot, + every contour plot,% #1,% }% }, @@ -1994,7 +2023,7 @@ contour external/.code={% \edef\tikz@plot@handler{\noexpand\pgfplotsplothandlercontourexternal}% \pgfqkeys{/pgfplots/contour external}{% - every contour plot, + every contour plot,% #1% }% }, @@ -2024,7 +2053,7 @@ set table \"\outfile\"; splot \"\infile\"; }, - cmd={gnuplot \"\script\"}, + cmd={gnuplot \"\script\"},% #1,% }, }, @@ -2057,7 +2086,8 @@ \pgfplotsplothandlersurveyaftersetpointmeta@default % ... and undo the reordering after point meta has been set: \pgfplotsplothandlersurveypoint@contour@axes@reordered@to@std - } + }% + \def\pgfplotsplothandlername{contour prepared}% }% \def\pgfplotsplothandlersurveystart@contour{% diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex index 65562458c82..7f6cda54930 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex @@ -336,9 +336,11 @@ \pgfutil@namelet{pgfplots@stacked@diff@\pgfplots@stacked@dir}{pgfplots@stacked@diff}% \else % Ah - no stacked plot!? Well, than do "something useful": - \pgfplotscoordmath{x}{zero}\let\pgfplots@current@point@x=\pgfmathresult% - \pgfplotscoordmath{y}{zero}\let\pgfplots@current@point@y=\pgfmathresult% - \pgfplotscoordmath{z}{zero}\let\pgfplots@current@point@z=\pgfmathresult% + % ... note that we have to use 'pgfbasic' here as that is the + % "transformed" format. + \pgfplotscoordmath{pgfbasic}{zero}\let\pgfplots@current@point@x=\pgfmathresult% + \pgfplotscoordmath{pgfbasic}{zero}\let\pgfplots@current@point@y=\pgfmathresult% + \pgfplotscoordmath{pgfbasic}{zero}\let\pgfplots@current@point@z=\pgfmathresult% % \pgfplotspointgetnormalizedcoordinates% \pgfplotsutilforeachcommasep{x,y,z}\as\pgfplots@loc@TMPa{% @@ -369,6 +371,11 @@ % - \pgfplots@current@point@[xyz] % - \ifpgfplots@curplot@threedim % are all set properly. +% +% POSTCONDITION: +% - the zero level macro is set (for use in the visualizer) +% - the closed cycle impl is updated +% - the points as such are NOT touched \def\pgfplots@stacked@visphasepreparedatapoint{% \ifx\pgfplots@stacked@zerolevel\pgfutil@empty % this here is the case if we have the first encountered plot, @@ -395,6 +402,9 @@ \pgfplotsaxisvisphasegetpoint \edef\pgfplots@current@point@x{\the\pgf@x}% \edef\pgfplots@current@point@y{\the\pgf@y}% + % this here merely communicates + % \pgfplots@stacked@zerolevelpoint@x and @y outside of the + % group: \pgfplots@stacked@smuggle \endgroup % diff --git a/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap.code.tex b/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap.code.tex index 124406922db..ba639531d5a 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotscolormap.code.tex @@ -85,6 +85,7 @@ \expandafter\let\csname\pgfplots@createcolormap@name @colspace\endcsname=\pgfplotsretval \expandafter\let\csname\pgfplots@createcolormap@name @col@comps\endcsname=\pgfplotsretvalb %\pgfplots@colormap@showdebuginfofor{#1}% + \pgfplots@colormap@LUA@new{#1}% } @@ -345,6 +346,23 @@ \fi }% +\def\pgfplots@colormap@LUA@new#1{% + \ifpgfplots@LUA@supported + \pgfplotscolormapserializecomponentstomacro{#1}\pgfplots@loc@TMPa + \directlua{% + local colorspace =^^J% + pgfplots.\csname pgfpl@cm@#1@colspace\endcsname;^^J% + if colorspace then^^J% + pgfplots.ColorMaps["#1"] = pgfplots.ColorMap.new(^^J% + \csname pgfpl@cm@#1@h\endcsname,^^J% + colorspace,^^J% + { \pgfplots@loc@TMPa });^^J% + else^^J% + io.write("There is no LUA colorspace for '\csname pgfpl@cm@#1@colspace\endcsname' - skipping LUA color map definition of #1\string\n");^^J% + end^^J% + }% + \fi +}% % Shows debug info about colormap #1 into the console. \def\pgfplots@colormap@showdebuginfofor#1{% \message{Debug info for color map '#1':^^J}% @@ -604,6 +622,30 @@ }% }% \def\pgfplotscolormapfind@precomputed[#1:#2][#3]#4#5{% + \ifpgfplots@LUA@supported + \edef\pgfmathresult{% + \directlua{% + pgfplots.texColorMapPrecomputed("#5", #1,#2,#4) + }% + }% + \ifx\pgfmathresult\pgfutil@empty + \pgfplotscolormapfind@precomputed@warn@LUA{#5}% + \pgfplotscolormapfind@precomputed@[#1:#2][#3]{#4}{#5}% + \else + %\message{LUA colormapfind[#1:#2](#4)(#5) = \pgfmathresult^^J}% + \fi + \else + \pgfplotscolormapfind@precomputed@[#1:#2][#3]{#4}{#5}% + \fi +} + +\def\pgfplotscolormapfind@precomputed@warn@LUA#1{% + \expandafter\ifx\csname pgfplotscolormapfind@precomputed@warn@LUA@#1\endcsname\relax + \pgfplotswarning{lua colormap unavailable}{#1}\pgfeov% + \expandafter\gdef\csname pgfplotscolormapfind@precomputed@warn@LUA@#1\endcsname{1}% + \fi +}% +\def\pgfplotscolormapfind@precomputed@[#1:#2][#3]#4#5{% \pgfplotscolormapassertexists{#5}% \begingroup % Step 0: compute #3 if it is missing and write it into diff --git a/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex b/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex index 655c96f2c86..a84276adbc0 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex @@ -164,6 +164,12 @@ }% \def\pgfplotscommandtostring#1#2{\pgfplots@command@to@string{#1}{#2}}% +\begingroup +\catcode`\|=0 +\catcode`\\=12 +|gdef|pgfplots@backslash@as@other{\}% +|endgroup + % As \pgfplots@command@to@string, but it works for commands accepting % arguments. More precisely, #2 will be a string (!) of the form % <argument pattern>{ <body> } @@ -589,7 +595,18 @@ \def\pgfplotsforeachungrouped#1{% \pgfutil@ifnextchar/{\pgfplotsforeachungrouped@{#1}}{\pgfplotsforeachungrouped@{#1}/{}}% }% -\long\def\pgfplotsforeachungrouped@#1/#2in #3#4{% + +% accept both +% \pgfplotsforeachungrouped\x in{1,...,5}{a} +% \pgfplotsforeachungrouped\x in {1,...,5}{a} +\long\def\pgfplotsforeachungrouped@#1/#2in{% + \pgfutil@ifnextchar\bgroup{% + \pgfplotsforeachungrouped@@{#1}{#2}% + }{% + \pgfplots@error{Found unexpected characters: expected 'in '.}% + }% +} +\long\def\pgfplotsforeachungrouped@@#1#2#3#4{% \def\pgfplots@foreach@loc@TMPa{#2}% \ifx\pgfplots@foreach@loc@TMPa\pgfutil@empty \pgfplotsforeachungrouped@isuniform{#3}% @@ -642,10 +659,43 @@ {\noexpand#1}% #4 = the loop macro name {\pgfplots@foreach@loc@meshwidth}% #5 = h {\the\t@pgfplots@toka}% #6 = the code to invoke + {0}% #7 : the loop variable }% \pgfplots@foreach@loc@TMPc }% -\long\def\pgfplotsforeachungroupeduniform@loop@mathengine#1#2#3#4#5#6{% + +% This here is much more accurate and does not suffer from the +% numerical stability issues of the other loop. +% +% TO DO: test it (optimize it?) and enable it for some future compat=<version> +% switch! +\long\def\pgfplotsforeachungroupeduniform@loop@mathengine@PRECISE@CURRENTLY@UNUSED@#1#2#3#4#5#6#7{% + \pgfmathparse{#2+#7*#5}% is this significantly slower than the direct calls? + \let#4=\pgfmathresult + #1{#4}{#3}% substitute this by integer arithmetics + \ifdim\pgfmathresult pt=0pt % + \def\pgfplotsforeach@loc@TMP@{\pgfutil@in@{.0\relax}}% + \expandafter\pgfplotsforeach@loc@TMP@\expandafter{#4\relax}% + \ifpgfutil@in@ + % ah - our current loop variable has .0 as suffix. + % Strip it. + \def\pgfplotsforeach@loc@TMP@##1.0\relax{% + \def#4{##1}% + }% + \expandafter\pgfplotsforeach@loc@TMP@#4\relax + \fi + #6\relax + \def\pgfplotsforeach@loc@TMP@{#7}% + \pgfplotsutil@advancestringcounter\pgfplotsforeach@loc@TMP@ + % + \t@pgfplots@tokc={{#1}{#2}{#3}{#4}{#5}{#6}}% + % loop! + \edef\pgfplots@loc@TMPa{\noexpand\pgfplotsforeachungroupeduniform@loop@mathengine + \the\t@pgfplots@tokc{\pgfplotsforeach@loc@TMP@}}% + \expandafter\pgfplots@loc@TMPa + \fi +}% +\long\def\pgfplotsforeachungroupeduniform@loop@mathengine#1#2#3#4#5#6#7{% #1{#2}{#3}% \ifdim\pgfmathresult pt=0pt \pgfutil@in@{.0\relax}{#2\relax}% @@ -661,7 +711,7 @@ \pgfmathadd@{#2}{#5}% \t@pgfplots@toka={{#1}}% \t@pgfplots@tokb=\expandafter{\pgfmathresult}% - \t@pgfplots@tokc={{#3}{#4}{#5}{#6}}% + \t@pgfplots@tokc={{#3}{#4}{#5}{#6}{--}}% % loop! \edef\pgfplots@loc@TMPa{\noexpand\pgfplotsforeachungroupeduniform@loop@mathengine \the\t@pgfplots@toka @@ -1130,29 +1180,7 @@ \let\pgfplots@y=\pgfmathresult \pgfplotscoordmath{#5}{op}{veclen}{{\pgfplots@x}{\pgfplots@y}}% \let\pgfplots@r=\pgfmathresult - \pgfplotscoordmath{#5}{if is}{\pgfplots@r}{0}{% - \pgfplotscoordmath{#5}{parsenumber}{0}% - }{% - \pgfplotscoordmath{#5}{op}{divide}{{\pgfplots@x}{\pgfplots@r}}% - \let\pgfplots@quot=\pgfmathresult - % - \pgfplotscoordmath{#5}{one}% - \let\pgfplots@loc@TMPc=\pgfmathresult - \pgfplotscoordmath{#5}{min}{\pgfplots@quot}{\pgfplots@loc@TMPc}% - \let\pgfplots@quot=\pgfmathresult - \pgfplotscoordmath{#5}{-one}% - \let\pgfplots@loc@TMPc=\pgfmathresult - \pgfplotscoordmath{#5}{max}{\pgfplots@quot}{\pgfplots@loc@TMPc}% - \let\pgfplots@quot=\pgfmathresult - % - \pgfplotscoordmath{#5}{op}{acos}{{\pgfplots@quot}}% - % - \pgfplotscoordmath{#5}{if is}{\pgfplots@y}{-}{% - \let\pgfplots@acos=\pgfmathresult - \pgfplotscoordmath{#5}{-one}% - \pgfplotscoordmath{#5}{op}{multiply}{{\pgfmathresult}{\pgfplots@acos}}% - }{}% - }% + \pgfplotscoordmath{#5}{op}{atan2}{{\pgfplots@y}{\pgfplots@x}}% \let\pgfplots@deg=\pgfmathresult \xdef\pgfplots@glob@TMPa{\noexpand\def\noexpand#3{\pgfplots@deg}\noexpand\def\noexpand#4{\pgfplots@r}}% \endgroup @@ -1340,6 +1368,21 @@ \ifx\pgfplotsifstringequal@\pgfplotsifstringequal@@ #3\else #4\fi }% +% Checks if the token sequence #1 (unexpanded) contains a macro and +% invokes #2 if so and #3 if not. +\def\pgfplotsutilifcontainsmacro#1#2#3{% + \def\pgfplots@loc@TMPa{#1}% + \pgfplots@command@to@string\pgfplots@loc@TMPa\pgfplots@loc@TMPa + \edef\pgfplots@loc@TMPa{\noexpand\pgfutil@in@{\pgfplots@backslash@as@other}{\pgfplots@loc@TMPa}}% + \pgfplots@loc@TMPa + \ifpgfutil@in@ + \def\pgfplots@loc@TMPa{#2}% + \else + \def\pgfplots@loc@TMPa{#3}% + \fi + \pgfplots@loc@TMPa +}% + % this command is in pgfplotscore.code.tex: % \pgfplotsiffileexists @@ -2015,8 +2058,36 @@ \gdef\pgfplotsHASH{#}% \catcode`\%=12 \gdef\pgfplotsPERCENT{%}} +\def\pgfplots@alloc@catcodetable{% + % it is task of the TeX format to load this. + % context comes with it out-of-the box, and pgfplots.sty loads luatexbase.sty + \pgfutil@IfUndefined{newcatcodetable}{% + % Oh. The TeX format does not have support for + % \newcatcodetable and the associated pgfplots module did not + % load an addon-package!? + % + % We _need_ the catcodes which are active when pgfplots starts. + % And there is no central mechanism to allocate catcodes. I will + % take one for me now and hope that it will not be used (soon). + \def\pgfplotsglobalretval{41}% + }{% + % the macro \pgfplots@luabackend@table is never used by TeX + % code. + % I only need the value inside of the .lua files: whenever + % they print something, they need to use it. + \newcatcodetable\pgfplots@luabackend@table + \let\pgfplotsglobalretval=\pgfplots@luabackend@table + }% +}% \pgfutil@IfUndefined{directlua}{}{% - \directlua{require(\pgfplotsDQ pgfplots\pgfplotsDQ)}% + \directlua{tex.enableprimitives("",tex.extraprimitives())}% + \pgfplots@log3{Initializing with LUA version \directlua{tex.print(_VERSION)}}% + \directlua{require("pgfplots"); pgfplots.pgfplotsversion = "\pgfplotsversion";}% + % + \pgfplots@alloc@catcodetable + \c@pgf@counta=\pgfplotsglobalretval + \savecatcodetable\c@pgf@counta + \directlua{pgfplots.LOAD_TIME_CATCODETABLE = \the\c@pgf@counta}% }% % swaps the content of two macros @@ -2026,6 +2097,10 @@ \let#2=\pgfplotsutil@swap@ }% +\def\pgfplots@boolval#1{% + \pgfplots@if{#1}{true}{false}% +}% + \input pgfplotsliststructure.code.tex \input pgfplotsliststructureext.code.tex \input pgfplotsarray.code.tex diff --git a/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty b/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty index 4517dd035bc..4486315128a 100644 --- a/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty +++ b/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty @@ -48,6 +48,21 @@ \RequirePackage{tikz} +% This is *identical* to \pgfutil@IfUndefined . I copied it here +% because pgf up to and including version 2.10 does not contain it. +\def\pgfplotsutil@IfUndefined#1{% + \begingroup\expandafter\expandafter\expandafter\endgroup + \expandafter\ifx\csname#1\endcsname\relax + \expandafter\pgfutil@firstoftwo + \else + \expandafter\pgfutil@secondoftwo + \fi +} +\pgfplotsutil@IfUndefined{directlua}{}{% + % I need \newcatcodetable + \RequirePackage{luatexbase}% +}% + \def\pgfplots@texdist@protect{\protect}% \input pgfplots.code.tex diff --git a/Master/texmf-dist/tex/plain/pgfplots/pgfplots.tex b/Master/texmf-dist/tex/plain/pgfplots/pgfplots.tex index 22e526ef23e..c4711be164c 100644 --- a/Master/texmf-dist/tex/plain/pgfplots/pgfplots.tex +++ b/Master/texmf-dist/tex/plain/pgfplots/pgfplots.tex @@ -41,6 +41,7 @@ \edef\pgfplotscatcode{\the\catcode`\@}% \catcode`\@=11 % +\input pgfplots.revision.tex \input pgfplots.code.tex% \usetikzlibrary{plotmarks}% % |