diff options
Diffstat (limited to 'graphics/pgf/base/doc/pgfmanual-en-math-algorithms.tex')
-rw-r--r-- | graphics/pgf/base/doc/pgfmanual-en-math-algorithms.tex | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/graphics/pgf/base/doc/pgfmanual-en-math-algorithms.tex b/graphics/pgf/base/doc/pgfmanual-en-math-algorithms.tex new file mode 100644 index 0000000000..9a4daeeaff --- /dev/null +++ b/graphics/pgf/base/doc/pgfmanual-en-math-algorithms.tex @@ -0,0 +1,231 @@ +% Copyright 2019 by Mark Wibrow +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Free Documentation License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. + + +\section{Customizing the Mathematical Engine} +\label{pgfmath-reimplement} + +Perhaps you have a desire for some function that \pgfname\ does not provide. +Perhaps you are not happy with the accuracy or efficiency of some of the +algorithms that are implemented in \pgfname. In these cases you will want to +add a function to the parser or replace the current implementations of the +algorithms with your own code. + +The mathematical engine was designed with such customization in mind. It is +possible to add new functions, or modify the code for existing functions. Note, +however, that whilst adding new operators is possible, it can be a rather +tricky business and is only recommended for adventurous users. + +To add a new function to the math engine the following command can be used: + +\begin{command}{\pgfmathdeclarefunction\opt{|*|}\marg{function name}\marg{number of arguments}\marg{code}} + This will set up the parser to recognize a function called \meta{name}. The + name of the function can consist of, uppercase or lowercase letters, + numbers or the underscore |_|. In line with many programming languages, a + function name cannot begin with a number or contain any spaces. The + function may not have been declared earlier, unless the optional star (|*|) + is provided, which forces an ``overwriting'' of the function by the new + function. Note that you \emph{should never change the arity of standard + functions} and you should normally use |\pgfmathredeclarefunction|, + which does not allow you to do anything wrong here. + + The \meta{number of arguments} can be any positive integer, zero, or the + value |...|, which indicates a variable number of arguments. \pgfname{} + treats constants, such as |pi| and |e|, as functions with zero arguments. + Functions with more than nine arguments or with a variable number of + arguments are a ``bit special'' and are discussed below. + + The effect of \meta{code} should be to set the macro |\pgfmathresult| to + the correct value (namely to the result of the computation without units). + Furthermore, the function should have no other side effects, that is, it + should not change any global values. As an example, consider the creation + of a new function |double|, which takes one argument, and returns the value + of that argument times two. + % +\begin{codeexample}[] +\makeatletter +\pgfmathdeclarefunction{double}{1}{ + \begingroup + \pgf@x=#1pt\relax + \multiply\pgf@x by2\relax + \pgfmathreturn\pgf@x + \endgroup +} +\makeatother +\pgfmathparse{double(44.3)}\pgfmathresult +\end{codeexample} + + The macro |\pgfmathreturn|\meta{tokens} must be + directly followed by an |\endgroup| and will save the result of the + computation, by defining |\pgfmathresult| as the expansion of + \meta{tokens} (without units) outside the group, so \meta{tokens} + must be something that can be assigned to a dimension register. + + Alternatively, the |\pgfmathsmuggle|\meta{macro} can be used. This must + also be directly followed by an |\endgroup| and will simply ``smuggle'' the + definition of \meta{macro} outside the \TeX-group. + + By performing computations within a \TeX-group, \pgfname{} registers such + as |\pgf@x|, |\pgf@y| and |\c@pgf@counta|, |\c@pgfcountb|, and so forth, + can be used at will. + + Beyond setting up the parser, this command also defines two macros which + provide access to the function independently of the parser: + % + \begin{itemize} + \item |\pgfmath|\meta{function name} + + This macro will provide a ``public'' interface for the function + \meta{function name} allowing the function to be called + independently of the parser. All arguments passed to this macro are + evaluated using |\pgfmathparse| and then passed on to the following + macro: + \item |\pgfmath|\meta{function name}|@| + + This macro is the ``private'' implementation of the function's + algorithm (but note that, for speed, the parser calls this macro + rather than the ``public'' one). Arguments passed to this macro are + expected to be numbers without units. It is defined using + \meta{code}, but need not be self-contained. + \end{itemize} + + For functions that are declared with less than ten arguments, the public + macro is defined in the same way as normal \TeX{} macros using, for + example, |\def\pgfmathNoArgs{|\meta{code}|}| for a function with no + arguments, or |\def\pgfmathThreeArgs#1#2#3{|\meta{code}|}| for a function + with three arguments. The private macro is defined in the same way, and + each argument can therefore be accessed in \meta{code} using |#1|, |#2| and + so on. + + For functions with more than nine arguments, or functions with a variable + number of arguments, these macros are only defined as taking \emph{one} + argument. The public macro expects its arguments to be comma separated, for + example, |\pgfmathVariableArgs{1.1,3.5,-1.5,2.6}|. Each argument is parsed + and passed on to the private macro as follows: + |\pgfmathVariableArgs@{{1.1}{3.5}{-1.5}{2.6}}|. This means that some + ``extra work'' will be required to access each argument (although it is a + fairly simple task). + + Note that there are two exceptions to this arrangement: the public versions + of the |min| and |max| functions still take two arguments for compatibility + with older versions, but each of these arguments can take several comma + separated values. +\end{command} + +To redefine a function use the following command: + +\begin{command}{\pgfmathredeclarefunction\marg{function name}\marg{code}} + This command redefines the |\pgfmath|\meta{function name}|@| macro with the + new \meta{code}. See the description of the + |\pgfmathdeclarefunction| for details. You cannot change the number of + arguments for an existing function. + % +\begin{codeexample}[] +\makeatletter +\pgfmathdeclarefunction{foo}{1}{ + \begingroup + \pgf@x=#1pt\relax + \multiply\pgf@x by2\relax + \pgfmathreturn\pgf@x + \endgroup +} +\pgfmathparse{foo(42)}\pgfmathresult +\pgfmathredeclarefunction{foo}{ + \begingroup + \pgf@x=#1pt\relax + \multiply\pgf@x by3\relax + \pgfmathreturn\pgf@x + \endgroup +} +\pgfmathparse{foo(42)}\pgfmathresult +\makeatother +\end{codeexample} + % +\end{command} + + \pgfname{} uses the last known definition of a function within the + prevailing scope, so it is possible for a function to be redefined locally. + You should also remember that any |.sty| or |.tex| file containing any + re-implementations should be loaded after |pgfmath|. + + In addition to the above commands, the following key is provided to quickly + create simple ad hoc functions which can greatly improve the readability of + code, and is particularly useful in \tikzname{}: + +\begin{key}{/pgf/declare function=\meta{function definitions}} + This key allows simple functions to be created locally. Its use is perhaps + best illustrated by an example: + % +\begin{codeexample}[] +\begin{tikzpicture} + \draw [help lines] (0,0) grid (3,2); + \draw [blue, thick, x=0.0085cm, y=1cm, + declare function={ + sines(\t,\a,\b)=1 + 0.5*(sin(\t)+sin(\t*\a)+sin(\t*\b)); + }] + plot [domain=0:360, samples=144, smooth] (\x,{sines(\x,3,5)}); +\end{tikzpicture} +\end{codeexample} + + Each definition in \meta{function definitions} takes the form + \meta{name}|(|\meta{arguments}|)=|\meta{definition}|;| (note the semicolon + at the end, this is very important). If multiple functions are being + defined, the semicolon is used to separate them (\emph{not} a comma). The + function \meta{name} can be any name that is not already a function name in + the current scope. The list of \meta{arguments} are commands such as |\x|, + or |\y| (it is not possible to declare functions that take variable numbers + of arguments using this key). If the function takes no arguments, then the + parentheses need not be used. The \meta{definition} should be an expression + that can be parsed by the mathematical engine and should use the commands + specified in \meta{arguments}. + + When specifying multiple functions, functions that appear later on in + \meta{function definitions} can refer to earlier functions: + % +\begin{codeexample}[pre={\pgfmathsetseed{1}}] +\begin{tikzpicture}[ + declare function={ + excitation(\t,\w) = sin(\t*\w); + noise = rnd - 0.5; + source(\t) = excitation(\t,20) + noise; + filter(\t) = 1 - abs(sin(mod(\t, 90))); + speech(\t) = 1 + source(\t)*filter(\t); + } +] + \draw [help lines] (0,0) grid (3,2); + \draw [blue, thick, x=0.0085cm, y=1cm] (0,1) -- + plot [domain=0:360, samples=144, smooth] (\x,{speech(\x)}); +\end{tikzpicture} +\end{codeexample} + % +\end{key} + +\begin{key}{/pgf/declare function/execute at begin function=\meta{tokens}} + These \meta{tokens} are inserted just before |\pgfmathdeclarefunction| + scans the body of the function definition. This is a rather low-level + option, so you should read the implementation to figure out where the + \meta{tokens} are inserted. +\end{key} + +\begin{key}{/pgf/declare function/execute at end function=\meta{tokens}} + These \meta{tokens} are inserted just after |\pgfmathdeclarefunction| has + finished scanning the body of the function definition. This is a rather + low-level option, so you should read the implementation to figure out where + the \meta{tokens} are inserted. +\end{key} + +\begin{key}{/pgf/declare function/ignore spaces=\meta{boolean}} + Uses the two previously described keys |/pgf/declare function/execute at begin function| and + |/pgf/declare function/execute at end function| to install catcodes such + that spaces inside the body of the function definition of + |\pgfmathdeclarefunction| are ignored. The usual \TeX\ tokenization rules + apply, so if the body of the function had already been tokenized by other + means this will become ineffective. If you want to use a space you can use + |~| in the function body which has its catcode set to 10 (space). +\end{key} |