diff options
author | Karl Berry <karl@freefriends.org> | 2008-02-24 18:22:07 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2008-02-24 18:22:07 +0000 |
commit | ac768be5ab2e638802806ac364ca4402e8e9935e (patch) | |
tree | bf26e0d972206f02cda2535e35dd8c2a33c04eaa /Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex | |
parent | bc195e7c0fe9d96cd9b6c0230da50da6fc28de26 (diff) |
pgf 2.0, third try
git-svn-id: svn://tug.org/texlive/trunk@6747 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex | 970 |
1 files changed, 970 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex b/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex new file mode 100644 index 00000000000..3d69d34b73c --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex @@ -0,0 +1,970 @@ +% Copyright 2007 Mark Wibrow +% +% 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. + +% This file parses/evaluates a decimal expression. +% +% Version 1.414213 29/9/2007 + +% \pgfmathparse, \pgfmathqparse +% +% Evaluates a decimal expression. +% +% #1 - the expression. +% +% returns +% +% x = the result as a dimension. +% +% E.g. +% \pgfmathparse{3pt*2cm+1.5} +% \pgfmathqparse{3pt*2cm+1.5pt} +% +% Every number in \pgfmathqparse *must* +% specify a unit. +% +\newif\ifpgfmath@quickparse + +\def\pgfmathparse{% + \pgfmath@quickparsefalse% + \pgfmathparse@} + +\def\pgfmathqparse{% + \pgfmath@quickparsetrue% + \pgfmathparse@} + +\def\pgfmath@calcreal#1{#1}% +\def\pgfmath@calcminof#1#2{min(#1,#2)}% +\def\pgfmath@calcmaxof#1#2{max(#1,#2)}% +\def\pgfmath@calcratio#1#2{#1/#2}% + +\def\pgfmathparse@#1{% + \begingroup% + % Reinstall correct font, so that dimensions like 1em are correct + \pgfmath@selectfont% + \let\real\pgfmath@calcreal% + \let\minof\pgfmath@calcminof% + \let\maxof\pgfmath@calcmaxof% + \let\ratio\pgfmath@calcratio% + \edef\pgfmath@temp{#1}% + \pgfmath@resetparsingparameters% + \global\pgfmathunitsdeclaredfalse% + \ifpgfmath@quickparse% + \let\pgfmath@parseoperand\pgfmath@quickparseoperand% + \else% + \let\pgfmath@parseoperand\pgfmath@parseoperand% + \fi% + \let\pgfmath@parsepostgroup\pgfmath@parseoperator% + \expandafter\pgfmath@parse@\pgfmath@temp @@@@@@@@@@@\pgfmath@empty} + + +% \pgfmath@resetparsingparameters +% +% Reset the stack at the begining of the parse/group. +% +\def\pgfmath@resetparsingparameters{% + \pgfmath@stack{\pgfmath@empty\pgfmath@empty\pgfmath@empty\pgfmath@empty}% + \def\pgfmath@stacknextoperator{\pgfmath@empty}% Will not work with \let +} +% \pgfmath@parse@ +% +% Start parsing. Expect one of +% 1) the end of the parse +% 2) the start of a group +% 3) a (possible) operand. +% +\def\pgfmath@parse@#1{% + \def\pgfmath@token{}% + \ifx#1@% + \let\pgfmath@parsenext\pgfmath@endparse% + \else% + \ifx#1(% + \let\pgfmath@parsenext\pgfmath@startparsegroup% + \else% + \edef\pgfmath@token{#1}% + \let\pgfmath@parsenext\pgfmath@parseoperand% + \fi\fi% + \pgfmath@parsenext% +} + +% If no TeX units are declared *at any point* in the parse +% the result is scaled by \pgfmathresultunitscale. +\newif\ifpgfmathunitsdeclared +\def\pgfmathsetresultunitscale#1{\def\pgfmathresultunitscale{#1}} +\def\pgfmathresultunitscale{1} + +% \pgfmath@endparse +% +% Everything stops here. +% +\def\pgfmath@endparse#1\pgfmath@empty{% + \pgfmath@processalloperations% + \pgfmath@stackpop{\pgfmathresult}% + \begingroup% + \ifpgfmathunitsdeclared% + \pgfmath@x1pt\relax% + \else% + \afterassignment\pgfmath@gobbletilpgfmath@% + \pgfmath@x\pgfmathresultunitscale pt\relax\pgfmath@% + \fi% + \expandafter\pgfmath@x\pgfmathresult\pgfmath@x% + \pgfmath@returnone\pgfmath@x% + \endgroup% + \pgfmath@smuggleone{\pgfmathresult}% + \endgroup% + \ignorespaces% +} + +% \pgfmath@startparsegroup +% +% When opening ( is scanned start a new group. +% +\def\pgfmath@startparsegroup{% + \begingroup% + \let\pgfmath@parsepostgroup\pgfmath@parseoperator% + \pgfmath@resetparsingparameters% + \pgfmath@parse@} + +% \pgfmath@endparsegroup +% +% When closing ) is scanned, processes all waiting +% operations (within the group) and close the group. +% +\def\pgfmath@endparsegroup{% + \pgfmath@processalloperations% + \pgfmath@stackpop{\pgfmathresult}% + \expandafter\pgfmath@x\pgfmathresult pt\relax% + \pgfmath@returnone\pgfmath@x% + \endgroup% + \pgfmath@parsepostgroup% +} + +% \pgfmath@parseoperator +% +% An operator is expected here. +% Or the end of the parse or parse group. +% +\def\pgfmath@parseoperator#1{% + \def\pgfmath@token{}% + % Push the operand in \pgfmathresult on to the stack. + \expandafter\pgfmath@stackpushoperand\expandafter{\pgfmathresult}% + \ifx#1@% + \let\pgfmath@parsenext\pgfmath@endparse% + \else% + \ifx#1+% + \let\pgfmath@parsenext\pgfmath@parseadd% + \else% + \ifx#1-% + \let\pgfmath@parsenext\pgfmath@parsesubtract% + \else% + \ifx#1*% + \let\pgfmath@parsenext\pgfmath@parsemultiply% + \else% + \ifx#1/% + \let\pgfmath@parsenext\pgfmath@parsedivide% + \else + \ifx#1)% + \let\pgfmath@parsenext\pgfmath@endparsegroup% + \else% + \ifx#1r% + \let\pgfmath@parsenext\pgfmath@parseradians% + \else% + \ifx#1>% + \let\pgfmath@parsenext\pgfmath@parsegreaterthan% + \else% + \ifx#1<% + \let\pgfmath@parsenext\pgfmath@parselessthan% + \else% + \if#1=% + \let\pgfmath@parsenext\pgfmath@parseequalto% + \else% + \if#1^% + \let\pgfmath@parsenext\pgfmath@parsepower% + \else% + \pgfmath@error{Unknown operator `#1'}% + \let\pgfmath@parsenext\relax% + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi% + \pgfmath@parsenext% +} + +% Use a \toks register as a stack. +\newtoks\pgfmath@stack + +% \pgfmath@stackpushoperator +% +% Push an operator (actually its macro e.g., \pgfmathadd@) +% on to the stack. And keep track of it using the macro +% \pgfmath@stacknextoperator. +% +\def\pgfmath@stackpushoperator#1{% + \edef\pgfmath@temp{\noexpand#1\the\pgfmath@stack}% + \expandafter\pgfmath@stack\expandafter{\pgfmath@temp}% + \def\pgfmath@stacknextoperator{#1}}% <- Must \def. Cannot \let. + +% \pgfmath@stackpushoperand +% +% Push an operand (i.e. a number) on the stack. It is +% put within a TeX group to make popping a lot simpler. +% +\def\pgfmath@stackpushoperand#1{% + \edef\pgfmath@temp{{#1}\the\pgfmath@stack}% + \expandafter\pgfmath@stack\expandafter{\pgfmath@temp}% +} + +% \pgfmath@stackpeek +% +% Peek (i.e. without removal) at the top of the stack. +% +\def\pgfmath@stackpeek{\expandafter\pgfmath@stackpeek@\the\pgfmath@stack\pgfmath@} +\def\pgfmath@stackpeek@#1#2\pgfmath@{#1}% + +% \pgfmath@stackpop +% +% Pop (i.e. remove) the top of the stack into #1. +% +\def\pgfmath@stackpop#1{\expandafter\pgfmath@stackpop@\expandafter#1\the\pgfmath@stack\pgfmath@} +\def\pgfmath@stackpop@#1#2#3\pgfmath@{\edef#1{#2}\pgfmath@stack{#3}}% + +% \pgfmath@stackpopoperation +% +% Remove and perform an operation from the stack. +% +\def\pgfmath@stackpopoperation{% + \expandafter\pgfmath@stackpopoperation@\the\pgfmath@stack\pgfmath@% +} +\def\pgfmath@stackpopoperation@#1#2#3#4#5\pgfmath@{% + \ifx\pgfmath@empty#1\relax% + \pgfmath@stack{\pgfmath@empty\pgfmath@empty\pgfmath@empty\pgfmath@empty}% + \else% + \ifx\pgfmath@empty#2\relax% + \pgfmath@stack{{#1}\pgfmath@empty\pgfmath@empty\pgfmath@empty\pgfmath@empty}% + \else% + #2{#3}{#1}% + \pgfmath@stack{#4#5}% + \expandafter\pgfmath@stackpushoperand\expandafter{\pgfmathresult}% + \fi\fi% + \def\pgfmath@stacknextoperator{#4}} + +% \pgfmath@processalloperations +% +% Process all operation in the stack. The +% overall result is at the top of the stack. +% +\def\pgfmath@processalloperations{% + \expandafter\pgfmath@in@\pgfmath@stacknextoperator{\pgfmath@empty}% + \ifpgfmath@in@% + \let\pgfmath@processnext\relax% + \else% + \pgfmath@stackpopoperation% + \let\pgfmath@processnext\pgfmath@processalloperations% + \fi% + \pgfmath@processnext} + +% \pgfmath@processoperationsuntil +% +% Process operations in the stack, until the specified +% operation/s is/are encountered. The overall result is +% at the top of the stack. +% +\def\pgfmath@processoperationsuntil#1{% + \expandafter\pgfmath@in@\pgfmath@stacknextoperator{#1\pgfmath@empty}% + \ifpgfmath@in@% + \let\pgfmath@processnext\pgfmath@processoperationsuntil@end% + \else% + \pgfmath@stackpopoperation% + \let\pgfmath@processnext\pgfmath@processoperationsuntil% + \fi% + \pgfmath@processnext{#1}} +\def\pgfmath@processoperationsuntil@end#1{} + + +% OK. Now the operators are parsed. +% These correspond to the + - / * ^ < > = operators and r (postfix) function. +% +\def\pgfmath@parseadd{% + % If no operator has been assigned (i.e. + is the first operator scanned), + % do nothing, except add addition to the stack. + \ifx\pgfmath@stacknextoperator\pgfmath@empty% + \else% + % Empty the process stack up to any inequalities. + \pgfmath@processoperationsuntil{\pgfmathequalto@\pgfmathlessthan@\pgfmathgreaterthan@}% + \fi% + \pgfmath@stackpushoperator{\pgfmathadd@}% + \pgfmath@parse@} + +\def\pgfmath@parsesubtract{% + % If no operator has been assigned (i.e. - is the first operator scanned), + % do nothing, except add subtract to the stack. + \ifx\pgfmath@stacknextoperator\pgfmath@empty% + \else% + % Empty the process stack up to any inequalities. + \pgfmath@processoperationsuntil{\pgfmathequalto@\pgfmathlessthan@\pgfmathgreaterthan@}% + \fi% + \pgfmath@stackpushoperator{\pgfmathsubtract@}% + \pgfmath@parse@} + +\def\pgfmath@parsemultiply{% + % If no operator has been assigned (i.e. * is the first operator scanned), + % do nothing, except push multiply onto the stack. + \ifx\pgfmath@stacknextoperator\pgfmath@empty% + \else% + % Process all operations up to inequalites or addition/subtraction + \pgfmath@processoperationsuntil{\pgfmathequalto@\pgfmathlessthan@\pgfmathgreaterthan@% + \pgfmathadd@\pgfmathsubtract@}% + \fi% + \pgfmath@stackpushoperator{\pgfmathmultiply@}% + \pgfmath@parse@} + +\def\pgfmath@parsedivide{% + % If no operator has been assigned (i.e. / is the first operator scanned), + % do nothing, except push divide onto the stack. + \ifx\pgfmath@stacknextoperator\pgfmath@empty% + \else% + % Process all operations up to inequalites or addition/subtraction + \pgfmath@processoperationsuntil{\pgfmathequalto@\pgfmathlessthan@\pgfmathgreaterthan@% + \pgfmathadd@\pgfmathsubtract@}% + \fi% + \pgfmath@stackpushoperator{\pgfmathdivide@}% + \pgfmath@parse@} + +\def\pgfmath@parsegreaterthan{% + % On scanning an equality/inequality operator everything up to + % (but not including) the operator is evaluated... + \pgfmath@processalloperations% + % ...and the operation pushed onto the stack. + \pgfmath@stackpushoperator{\pgfmathgreaterthan@}% + \pgfmath@parse@} + +\def\pgfmath@parselessthan{% + \pgfmath@processalloperations% + \pgfmath@stackpushoperator{\pgfmathlessthan@}% + \pgfmath@parse@} + +\def\pgfmath@parseequalto={% + \pgfmath@processalloperations% + \pgfmath@stackpushoperator{\pgfmathequalto@}% + \pgfmath@parse@} + +\def\pgfmath@parsepower{% + % Easy, just push power onto the stack. + \pgfmath@stackpushoperator{\pgfmathpow@}% + \pgfmath@parse@} + +\def\pgfmath@parseradians{% + % r is a post-fix function... + \ifx\pgfmath@primaryoperation\pgfmath@empty% + \else% + \pgfmath@processoperationsuntil{\pgfmathequalto@\pgfmathlessthan@\pgfmathgreaterthan@% + \pgfmathadd@\pgfmathsubtract@}% + \fi% + \pgfmath@stackpop{\pgfmath@temp}% + \pgfmathdeg@{\pgfmath@temp}% + % ...so processing returns to \pgfmath@parseoperator + \pgfmath@parseoperator} + +\newcount\c@pgfmath@parsecounta +\newcount\c@pgfmath@parsecountb +\newcount\c@pgfmath@parsecountc +\newdimen\pgfmath@parsex + +% \pgfmath@quickparseoperand +% +% An operand can *only* be a dimension. +% +\def\pgfmath@quickparseoperand{% + \afterassignment\pgfmath@quickparseoperand@% + \pgfmath@parsex\pgfmath@token} +\def\pgfmath@quickparseoperand@{% + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \pgfmath@parseoperator% +} + +% \pgfmath@parseoperand +% +% An operand can be an ASCII number (with or without dimensions, with +% or without a decimal point), a TeX register (count, dimen or skip, +% which may have expanded with \the), or a function e.g. sin(X). +% +% It is assumed that after \edef-ing, the only unexpanded tokens are registers. +% +\def\pgfmath@parseoperand{% + \def\pgfmath@sign{}% + \expandafter\pgfmath@parseoperandsign\pgfmath@token} +\def\pgfmath@parseoperandsign#1{% + \pgfmath@in@#1{-+}% + \ifpgfmath@in@ + % Gobble multiple signs. + \edef\pgfmath@sign{\pgfmath@sign#1}% + \expandafter\pgfmath@parseoperandsign% + \else% + \expandafter\pgfmath@parsenumberorfunction\expandafter#1% + \fi% +} + +\newif\ifpgfmath@dimen@ + +\def\pgfmath@ifregisterdimen@#1\pgfmath@{% + \pgfmath@in@{p}{#1}% + \ifpgfmath@in@% + \pgfmath@dimen@true% + \else% + \pgfmath@dimen@false% + \fi} + +\def\pgfmath@parsenumberorfunction#1{% + \let\pgfmath@parsenext\pgfmath@parsenumberorfunction@simple% + \ifx#1\wd\let\pgfmath@parsenext\pgfmath@boxdimen\fi% + \ifx#1\ht\let\pgfmath@parsenext\pgfmath@boxdimen\fi% + \ifx#1\dp\let\pgfmath@parsenext\pgfmath@boxdimen\fi% + \pgfmath@parsenext#1% +} + +\def\pgfmath@boxdimen#1#2{% + \pgfmath@parsex=\pgfmath@sign#1#2% + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \global\pgfmathunitsdeclaredtrue% a dimension has units + \pgfmath@parseoperator% +} + +\def\pgfmath@parsenumberorfunction@simple#1{% + \expandafter\ifcat#1\relax% + % So, a TeX register. + \afterassignment\pgfmath@ifregisterdimen@% + \pgfmath@parsex\pgfmath@sign#1pt\relax\pgfmath@% + \ifpgfmath@dimen@% + % A dimension! So stop scanning operand here. + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \global\pgfmathunitsdeclaredtrue% a dimension has units + \def\pgfmath@temp{}% + \let\pgfmath@parsenext\pgfmath@parseoperator% + \else% + % A count! Expand it, but carry on as usual as it might + % be immediately followed by a dimension. + \ifdim\pgfmath@parsex<0pt\relax% + \edef\pgfmath@sign{\pgfmath@sign-}% + \pgfmath@parsex-\pgfmath@parsex% + \fi% + \edef\pgfmath@temp{\pgfmath@tonumber{\pgfmath@parsex}}% + \let\pgfmath@parsenext\pgfmath@parsenumberorfunction@% + \fi% + \else% + % Could be a number or a function...? + \edef\pgfmath@temp{#1}% + \let\pgfmath@parsenext\pgfmath@parsenumberorfunction@% + \fi% + \expandafter\pgfmath@parsenext\pgfmath@temp% +}% + +\def\pgfmath@parsenumberorfunction@#1{% + \ifx#1(% It might be a group e.g. -(1+2)... + \let\pgfmath@parsenext\pgfmath@parseoperandgroup% + \else% + \pgfmath@in@{#1}{.0123456789}% + \ifpgfmath@in@% ... or a number... + \let\pgfmath@parsenext\pgfmath@parsenumber% + \else% ... or a function. + \let\pgfmath@parsenext\pgfmath@parsefunction% + \fi% + \fi% + \pgfmath@parsenext#1% +}% + +\def\pgfmath@parseoperandgroup({% + \let\pgfmath@postparsegroup\pgfmath@@parseoperandgroup% + \pgfmath@startparsegroup% +} + +\def\pgfmath@@parseoperandgroup{% + \let\pgfmath@postparsegroup\pgfmath@parseoperator% + \edef\pgfmathresult{\pgfmath@sign\pgfmathresult}% + \pgfmath@parseoperator% +} + +\def\pgfmath@parsenumber{% + % Consider the number 3.14159 + % 3 is parsed by assignment to a, then '.' is absorbed and 14159 + % parsed by assignement to b (actually b=114159, see below). + \c@pgfmath@parsecountc0\relax% + \afterassignment\pgfmath@parsedecimalpoint% + \c@pgfmath@parsecounta0} + +\def\pgfmath@parsedecimalpoint#1{% + \ifx#1.% Is there a decimal point? If not, see if there are any units. + \let\pgfmath@parsenext\pgfmath@parsemantissa% + \else% + \c@pgfmath@parsecountb10\relax% The first digit of b is gobbled (see below). + \let\pgfmath@parsenext\pgfmath@parseunits% + \fi% + \pgfmath@parsenext#1} + + + +% We would like to assign the following number (which is the mantisse) +% to a number. However, for a very long mantisse as in 3.141592653589793238462643 +% this will fail since the number becomes too large. +% +% Because of this, we have to do some ``magic'': We scan 9 tokens and +% then do an assignment with a guard after 9 tokens so that the +% assigment cannot fail. +% +\def\pgfmath@parsemantissa.#1#2#3#4#5#6#7#8#9{% + \afterassignment\pgfmath@checkforguard% + % Consider the number: 2.005 + % 2 is assigned to a, but b will be assigned 5, which is *not right*. + % So using 1 here hereresults in b=1005. The first digit is then + % gobbled later, when expanded with \the. + \c@pgfmath@parsecountb1#1#2#3#4#5#6#7#8#9\relax}% + +\def\pgfmath@checkforguard{% + \pgfmath@ifnextchar\relax% + {% + % Ok, this is a looong mantisse. Start gobbling all following + % numbers + \pgfmath@gobblemantisse% + }% + {% + \pgfmath@removeguard% + }% +} + +\def\pgfmath@gobblemantisse\relax#1#2#3#4#5#6#7#8#9{% + \afterassignment\pgfmath@checkforguard% + \c@pgfmath@parsecountc0#1#2#3#4#5#6#7#8#9\relax% these digits are ignored +} + +\def\pgfmath@removeguard#1\relax{\pgfmath@parseunits#1} + + +\def\pgfmath@parseunits#1{% + % Here the extra first digit in b is gobbled. + \edef\pgfmath@resulttemp{% + \pgfmath@sign\the\c@pgfmath@parsecounta.\expandafter\pgfmath@gobbleone\the\c@pgfmath@parsecountb}% + % Check whether #1 is a \dp, \wd, or \ht + \let\pgfmath@parsenext=\pgfmath@parseunits@simple% + \ifx#1\wd\let\pgfmath@parsenext=\pgfmath@parseunits@boxdimen\fi% + \ifx#1\ht\let\pgfmath@parsenext=\pgfmath@parseunits@boxdimen\fi% + \ifx#1\dp\let\pgfmath@parsenext=\pgfmath@parseunits@boxdimen\fi% + \pgfmath@parsenext#1% +} + +\def\pgfmath@parseunits@boxdimen#1#2{% + \pgfmath@parsex=\pgfmath@sign#1#2% + \pgfmath@parsex\pgfmath@resulttemp\pgfmath@parsex% + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \global\pgfmathunitsdeclaredtrue% a dimension has units + \pgfmath@parseoperator% +} + +\def\pgfmath@parseunits@simple#1{% + % Now check if #1 is actually a register. + \ifcat#1\relax% + \afterassignment\pgfmath@ifregisterdimen@% + \pgfmath@parsex#1pt\relax\pgfmath@% + \pgfmath@parsex\pgfmath@resulttemp\pgfmath@parsex% + \ifpgfmath@dimen@% If it's a dimen stop scanning operand here. + \global\pgfmathunitsdeclaredtrue% a dimension has units + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \let\pgfmath@parsenext\pgfmath@parseoperator% + \else + \edef\pgfmath@resulttemp{\pgfmath@tonumber{\pgfmath@parsex}}% + \let\pgfmath@parsenext\pgfmath@parseunits@% + \fi% + \expandafter\pgfmath@parsenext% + \else% + \expandafter\pgfmath@parseunits@\expandafter#1% + \fi} + +\def\pgfmath@parseunits@#1#2{% + % Check if #1 is an operator, or the character `@' indicating the end of the parse. + \pgfmath@in@#1{@+-*/^r<>=()}% + \ifpgfmath@in@% + \edef\pgfmath@tokens{#1#2}% + \edef\pgfmathresult{\pgfmath@resulttemp}% + \let\pgfmath@parsenext\pgfmath@parseoperator% + \else% + \pgfmath@in@#1{Ee}% e+0X + \ifpgfmath@in@% + % Oh no! It might be and em or an ex... + \pgfmath@in@#2{mx}% + \ifpgfmath@in@% + \global\pgfmathunitsdeclaredtrue% + \pgfmath@parsex\pgfmath@resulttemp#1#2\relax% + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \edef\pgfmath@tokens{}% + \let\pgfmath@parsenext\pgfmath@parseoperator% + \else% + \edef\pgfmath@tokens{#2}% + \let\pgfmath@parsenext\pgfmath@parsescientific% + \fi% + \else + % Anything else *should* be a TeX unit. + \global\pgfmathunitsdeclaredtrue% + \pgfmath@parsex\pgfmath@resulttemp#1#2\relax% + \edef\pgfmathresult{\pgfmath@tonumber{\pgfmath@parsex}}% + \edef\pgfmath@tokens{}% + \let\pgfmath@parsenext\pgfmath@parseoperator% + \fi\fi% + \expandafter\pgfmath@parsenext\pgfmath@tokens% +} + +% Parse 'Scientific' notation in the form xEyy +% +\def\pgfmath@parsescientific{% + \afterassignment\pgfmath@parsescientific@% + \c@pgfmath@parsecounta} + +\def\pgfmath@parsescientific@{% + \edef\pgfmath@parsesci@temp{\pgfmath@resulttemp\the\c@pgfmath@parsecountc}% + \expandafter\pgfmathscientific\expandafter{\pgfmath@parsesci@temp}% + {\the\c@pgfmath@parsecounta}% + \edef\pgfmath@resulttemp{\pgfmathresult}% + \pgfmath@parseunits@} + +% Functions parsed (not calculated) here are: +% +% round(X) 'half-up' rounding. +% floor(X) floor function. +% ciel(X) ceiling function. +% abs(X) absolute function. +% +% exp(X) e^X (0 <= X <~= 9.7). +% ln(X) logarithm of X. +% pow(X,Y) X^Y, +% +% sin(X) sine function. +% cos(X) cosine function. +% tan(X) tan function. +% asin(X) arcsine of X (in radians) -1 <= X <= 1 +% acos(X) arccosine of X (in radians) -1 <= X <= 1 +% atan(X) arctangent of X (in radians) -1 <= X <= 1 +% veclen(X,Y) the length Z where Z^2 = X^2 + Y^2 +% mod(X,Y) X modulo Y +% max(X,Y) the maximum of X or Y +% min(X,Y) the minimum of X or Y +% +% NB veclen, mod, max, and min *cannot* be nested. +% +% deg(X) converts X to degrees (X in radians) +% rad(X) converts X to radians (X in degrees) +% +% rnd generate pseudo-random number X (0 <= X <= 1). +% rand generate pseudo-random number X (1 <= X <= -1). +% sqrt(X) square root. +% +% pi the constant PI. + +\def\pgfmath@parsefunction{% + \def\pgfmath@parsedfunctionname{}% + \futurelet\pgfmath@parsetoken\pgfmath@parsefunction@@} +\def\pgfmath@parsefunction@@#1{% + \pgfmath@in@#1{()@+-*/^<>=}% A function name ends with one of these... + \ifpgfmath@in@% + \let\pgfmath@parsefunctionnext\pgfmath@parsefunction@end% + \else% + \ifx\pgfmath@parsetoken\pgfmath@sptoken% ...or a space. + \let\pgfmath@parsefunctionnext\pgfmath@parsefunction@end% + \else% + \let\pgfmath@parsefunctionnext\pgfmath@parsefunction@continue% + \fi\fi% + \pgfmath@parsefunctionnext#1} + +\def\pgfmath@parsefunction@end#1{% + \expandafter\ifx\csname pgfmath@parsefunction@\pgfmath@parsedfunctionname\endcsname\relax% + \pgfmath@reportunknownfunction% + \let\pgfmath@parsefunctionnext\relax% + \else% + \let\pgfmath@parsefunctionnext\pgfmath@executeparsefunction@% + \fi% + \pgfmath@parsefunctionnext#1} + +\def\pgfmath@parsefunction@continue#1{% + \edef\pgfmath@parsedfunctionname{\pgfmath@parsedfunctionname#1}% + \futurelet\pgfmath@parsetoken\pgfmath@parsefunction@@} + +\def\pgfmath@executeparsefunction@{\csname pgfmath@parsefunction@\pgfmath@parsedfunctionname\endcsname} + + +\def\pgfmath@reportunknownfunction{% + \pgfmath@error{Unknown function `\pgfmath@parsedfunctionname'}{}% +} + +% \pgfmath@postfunction +% +% In scanning a function e.g. sin(40), we subvert the normal parsing +% group mechanism by messing around with \pgfmath@parsepostgroup, so +% that after scanning ), the parser doesn't scan for an operator, but +% returns to the macros scanning the function. +% Here the mechanism is restored, and the value of the function is +% stored along with the approprate sign, which was saved earlier. +% +\def\pgfmath@postfunction{% + \let\pgfmath@parsepostgroup\pgfmath@parseoperator% + \edef\pgfmathresult{\pgfmath@sign\pgfmathresult}% + \pgfmath@parseoperator} + + +% \pgfmath@parsefunction@abs +% +\def\pgfmath@parsefunction@abs{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@abs@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@abs@{% + \expandafter\pgfmathabs@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@sqrt +% +\def\pgfmath@parsefunction@sqrt{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@sqrt@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@sqrt@{% + \expandafter\pgfmathsqrt@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@round +% +\def\pgfmath@parsefunction@round{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@round@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@round@{% + \expandafter\pgfmathround@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@floor +% +\def\pgfmath@parsefunction@floor{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@floor@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@floor@{% + \expandafter\pgfmathfloor@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@ceil +% +\def\pgfmath@parsefunction@ceil{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@ceil@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@ceil@{% + \expandafter\pgfmathceil@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@sin +% +\def\pgfmath@parsefunction@sin{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@sin@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@sin@{% + \expandafter\pgfmathsin@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@cos +% +\def\pgfmath@parsefunction@cos{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@cos@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@cos@{% + \expandafter\pgfmathcos@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@asin +% +\def\pgfmath@parsefunction@asin{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@asin@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@asin@{% + \expandafter\pgfmathasin@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@acos +% +\def\pgfmath@parsefunction@acos{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@acos@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@acos@{% + \expandafter\pgfmathacos@\expandafter{\pgfmathresult}% + \pgfmath@postfunction} + +% \pgfmath@parsefunction@atan +% +\def\pgfmath@parsefunction@atan{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@atan@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@atan@{% + \expandafter\pgfmathatan@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@tan +% +\def\pgfmath@parsefunction@tan{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@tan@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@tan@{% + \expandafter\pgfmathtan@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@cot +% +\def\pgfmath@parsefunction@cot{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@cot@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@cot@{% + \expandafter\pgfmathcot@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@sec +% +\def\pgfmath@parsefunction@sec{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@sec@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@sec@{% + \expandafter\pgfmathsec@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@cosec +% +\def\pgfmath@parsefunction@cosec{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@cosec@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@cosec@{% + \expandafter\pgfmathcosec@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@rad +% +\def\pgfmath@parsefunction@rad{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@rad@% + \pgfmath@parse@} +\def\pgfmath@parsefunction@rad@{% + \expandafter\pgfmathrad@\expandafter{\pgfmathresult}% + \pgfmath@postfunction}% + +% \pgfmath@parsefunction@rad +% +\def\pgfmath@parsefunction@deg{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@deg@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@deg@{% + \expandafter\pgfmathdeg@\expandafter{\pgfmathresult}% + \pgfmath@postfunction}% + +% \pgfmath@parsefunction@rnd +% +\def\pgfmath@parsefunction@rnd{% + \expandafter\pgfmathrnd% + \expandafter\pgfmath@postfunction} + +% \pgfmath@parsefunction@rand +% +\def\pgfmath@parsefunction@rand{% + \expandafter\pgfmathrand% + \expandafter\pgfmath@postfunction}% + +% \pgfmath@parsefunction@exp +% +\def\pgfmath@parsefunction@exp{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@exp@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@exp@{% + \expandafter\pgfmathexp@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@ln +% +\def\pgfmath@parsefunction@ln{% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@ln@% + \expandafter\pgfmath@parse@} +\def\pgfmath@parsefunction@ln@{% + \expandafter\pgfmathln@\expandafter{\pgfmathresult}% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@pi +% +\def\pgfmath@parsefunction@pi{% + \pgfmathpi% + \pgfmath@postfunction% +} + +% \pgfmath@parsefunction@veclen +% +\def\pgfmath@parsefunction@veclen{% + \expandafter\pgfmath@parsefunction@veclen@} +\def\pgfmath@parsefunction@veclen@(#1,{% + \pgfmathparse@{#1}\edef\pgfmath@firstoperand{\pgfmathresult}% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@veclen@@ + \pgfmath@startparsegroup} +\def\pgfmath@parsefunction@veclen@@{% + \edef\pgfmath@secondoperand{\pgfmathresult}% + \pgfmathveclen@{\pgfmath@firstoperand}{\pgfmath@secondoperand}% + \pgfmath@postfunction} + +% \pgfmath@parsefunction@mod +% +\def\pgfmath@parsefunction@mod{% + \expandafter\pgfmath@parsefunction@mod@} +\def\pgfmath@parsefunction@mod@(#1,{% + \pgfmathparse@{#1}\edef\pgfmath@firstoperand{\pgfmathresult}% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@mod@@ + \pgfmath@startparsegroup} +\def\pgfmath@parsefunction@mod@@{% + \edef\pgfmath@secondoperand{\pgfmathresult}% + \pgfmathmod@{\pgfmath@firstoperand}{\pgfmath@secondoperand}% + \pgfmath@postfunction} + +% \pgfmath@parsefunction@max +% +\def\pgfmath@parsefunction@max{% + \expandafter\pgfmath@parsefunction@max@} +\def\pgfmath@parsefunction@max@(#1,{% + \pgfmathparse@{#1}\edef\pgfmath@firstoperand{\pgfmathresult}% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@max@@ + \pgfmath@startparsegroup} +\def\pgfmath@parsefunction@max@@{% + \edef\pgfmath@secondoperand{\pgfmathresult}% + \pgfmathmax@{\pgfmath@firstoperand}{\pgfmath@secondoperand}% + \pgfmath@postfunction} + +% \pgfmath@parsefunction@min +% +\def\pgfmath@parsefunction@min{% + \expandafter\pgfmath@parsefunction@min@} +\def\pgfmath@parsefunction@min@(#1,{% + \pgfmathparse@{#1}\edef\pgfmath@firstoperand{\pgfmathresult}% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@min@@ + \pgfmath@startparsegroup} +\def\pgfmath@parsefunction@min@@{% + \edef\pgfmath@secondoperand{\pgfmathresult}% + \pgfmathmin@{\pgfmath@firstoperand}{\pgfmath@secondoperand}% + \pgfmath@postfunction} + +% \pgfmath@parsefunction@pow +% +\def\pgfmath@parsefunction@pow{% + \expandafter\pgfmath@parsefunction@pow@} +\def\pgfmath@parsefunction@pow@(#1,{% + \pgfmathparse@{#1}\edef\pgfmath@firstoperand{\pgfmathresult}% + \let\pgfmath@parsepostgroup\pgfmath@parsefunction@pow@@ + \pgfmath@startparsegroup} +\def\pgfmath@parsefunction@pow@@{% + \edef\pgfmath@secondoperand{\pgfmathresult}% + \pgfmathpow@{\pgfmath@firstoperand}{\pgfmath@secondoperand}% + \pgfmath@postfunction}
\ No newline at end of file |