% language=us runpath=texruns:manuals/metafun

\startcomponent metafun-functions

\environment metafun-environment

\startchapter[title={Functions}]

\index{functions}

\startintro

\METAPOST\ provides a wide range of functions, like \type {sind} and \type
{floor}. We will discuss most of them here and define a few more. We will also
introduce a few methods for drawing grids and functions.

\stopintro

\startsection[title={Overview}]

What follows is a short overview of the functions that can be applied to numeric
expressions and strings. Functions that operate on pairs, colors, paths and
pictures are discussed in other chapters.

First of all we have \type {+}, \type {-}, \type {/} and \type {*}. For as far as
is reasonable, you can apply these to numerics, pairs and colors. Strings can be
concatenated by \type {&}.

Pythagorean addition is accomplished by \type {++}, while Pythagorean subtraction
is handled by \type {+-+}. The \type {**} operator gives you exponentiation. The
nature of the \METAPOST\ language is such that you can easily define interesting
functions using such symbols.

The logarithmic functions are based on bytes. This makes them quite accurate but
forces you to think like a computer.

\starttabulate[|lT|l|]
\HL
\NC mexp(x) \NC expential function with base 256 \NC \NR
\NC mlog(x) \NC logarithm with base 256          \NC \NR
\HL
\stoptabulate

The basic goniometric functions operate on degrees, which is why they have a
\quote {d} in their name.

\starttabulate[|lT|l|]
\HL
\NC cosd(x) \NC cosine of $x$ with $x$ in degrees \NC \NR
\NC sind(x) \NC sine of $x$ with $x$ in degrees   \NC \NR
\HL
\stoptabulate

There are three ways to truncate numbers. The \type {round} function can also
handle pairs and colors.

\starttabulate[|lT|l|]
\HL
\NC ceiling(x) \NC the least integer greater than or equal to $x$     \NC \NR
\NC floor(x)   \NC the greatest integer less than or equal to $x$     \NC \NR
\NC round(x)   \NC round each component of $x$ to the nearest integer \NC \NR
\HL
\stoptabulate

Of course we have:

\starttabulate[|lT|l|]
\HL
\NC x mod y     \NC the remainder of $x/y$         \NC \NR
\NC x div y     \NC the integer part of $x/y$      \NC \NR
\NC abs(x)      \NC the absolute value of $x$      \NC \NR
\NC sqrt(x)     \NC the square root of $x$         \NC \NR
\NC x dotprod y \NC the dot product of two vectors \NC \NR
\HL
\stoptabulate

What would life be without a certain randomness and uncertainty:

\starttabulate[|lT|l|]
\HL
\NC normaldeviate     \NC a number with mean 0 and standard deviation 1 \NC \NR
\NC uniformdeviate(x) \NC a number between zero and $x$                 \NC \NR
\HL
\stoptabulate

The following functions are actually macros:

\starttabulate[|lT|l|]
\HL
\NC decr(x,n)   \NC decrement $x$ by $n$                 \NC \NR
\NC incr(x,n)   \NC increment $x$ by $n$                 \NC \NR
\NC max(a,b,..) \NC return the maximum value in the list \NC \NR
\NC min(a,b,..) \NC return the minimum value in the list \NC \NR
\HL
\stoptabulate

The \type {min} and \type {max} funtions can be applied to numerics as well as
strings.

The following functions are related to strings:

\starttabulate[|lT|l|]
\HL
\NC oct s     \NC string representation of an octal number      \NC \NR
\NC hex s     \NC string representation of a hexadecimal number \NC \NR
\NC str s     \NC string representation for a suffix            \NC \NR
\NC ASCII s   \NC \ASCII\ value of the first character          \NC \NR
\NC char x    \NC character of the given \ASCII\ code           \NC \NR
\NC decimal x \NC decimal representation of a numeric           \NC \NR
\HL
\stoptabulate

With \type {substring (i,j) of s} you can filter the substring bounded by the
given indices from the given string.

In \METAFUN\ we provide a few more functions (you can take a look in \type
{mp-tool.mp} to see how they are defined. You need to be aware of very subtle
rounding errors. Normally these only show up when you reverse an operation. This
is a result from mapping to and from internal quantities.

\starttabulate[|Tl|ml|]
\HL
\NC sqr(x)    \NC x^2       \NC \NR
\NC log(x)    \NC \log(x)   \NC \NR
\NC ln(x)     \NC \ln(x)    \NC \NR
\NC exp(x)    \NC {\rm e}^x \NC \NR
\NC pow(x, p) \NC x^p       \NC \NR
\NC inv(x)    \NC 1/x       \NC \NR
\HL
\stoptabulate

The following sine and cosine functions take radians instead of angles in
degrees.

\starttabulate[|Tl|Tl|Tl|]
\HL
\NC sin(x) \NC asin(x) \NC invsin(x) \NC \NR
\NC cos(x) \NC acos(x) \NC invcos(x) \NC \NR
\HL
\stoptabulate

There are no tangent functions, so we provide both the radian and degrees
versions:

\starttabulate[|Tl|Tl|]
\HL
\NC tan(x) \NC tand(x) \NC \NR
\NC cot(x) \NC cotd(x) \NC \NR
\HL
\stoptabulate

Here are a couple of hyperbolic functions.

\starttabulate[|Tl|Tl|]
\HL
\NC sinh(x) \NC asinh(x) \NC \NR
\NC cosh(x) \NC acosh(x) \NC \NR
\HL
\stoptabulate

We end with a few additional string converters.

\starttabulate[|Tl|l|]
\HL
\NC ddecimal x  \NC decimal representation of a pair   \NC \NR
\NC dddecimal x \NC decimal representation of a color  \NC \NR
\NC condition x \NC string representation of a boolean \NC \NR
\HL
\stoptabulate

\stopsection

\startsection[title={Grids}]

\index{grids}
\index{axis}

Some day you may want to use \METAPOST\ to draw a function like graphic. In the
regular \TEX\ distributions you will find a module \type {graph.mp} that provides
many ways to accomplish this. For the moment, \METAFUN\ does not provide advanced
features with respect to drawing functions, so this section will be relatively
short.

When drawing a functions (for educational purposes) we need to draw a couple of
axis or a grid as well as a shape. Along the axis we can put labels. For this we
can use the \METAPOST\ package \type {format.mp}, but this does not integrate
that well into the way \METAFUN\ deals with text typeset by \TEX.

For those who love dirty tricks and clever macros, close reading of the code in
\type {format.mp} may be worthwhile. The format macros in there use \TEX\ to
typeset the core components of a number, and use the dimensions of those
components to compose combinations of signs, numbers and superscripts.

In \METAFUN\ we have the module \type {mp-form.mp} which contains most of the
code in \type {format.mp} but in a form that is a bit more suited for fine
tuning. This permits us to use either the composition method, or to fall back on
the \type {textext} method that is part of \METAFUN. That way we can also handle
fonts that have digits with different dimensions. Another \quote {change}
concerns the pattern separator. Instead of a \type {%} we use \type {@}; you can
choose to set another separator, but for embedded definitions \type {%} is
definitely a bad choice because \TEX\ sees it as a comment and ignores everything
following it.

\startbuffer[grd]
drawoptions(withpen pencircle scaled 1pt withcolor .625yellow) ;

draw hlingrid(0, 10, 1, 3cm, 3cm) ;
draw vlingrid(0, 10, 1, 3cm, 3cm) ;

draw hlingrid(0, 10, 1, 3cm, 3cm) shifted ( 3.5cm,0) ;
draw vloggrid(0, 10, 1, 3cm, 3cm) shifted ( 3.5cm,0) ;

draw hloggrid(0, 10, 1, 3cm, 3cm) shifted ( 7.0cm,0) ;
draw vlingrid(0, 10, 1, 3cm, 3cm) shifted ( 7.0cm,0) ;

draw hloggrid(0, 10, 1, 3cm, 3cm) shifted (10.5cm,0) ;
draw vloggrid(0, 10, 1, 3cm, 3cm) shifted (10.5cm,0) ;
\stopbuffer

\typebuffer[grd]

\startlinecorrection[blank]
\processMPbuffer[grd]
\stoplinecorrection

\startbuffer[grd]
drawoptions(withpen pencircle scaled 1pt withcolor .625yellow) ;

draw hlingrid(0, 10, 1, 3cm, 3cm) slanted .5 ;
draw vlingrid(0, 10, 1, 3cm, 3cm) slanted .5 ;
\stopbuffer

\typebuffer[grd]

\startlinecorrection[blank]
\processMPbuffer[grd]
\stoplinecorrection

Using macros like these often involves a bit of trial and error. The arguments to
these macros are as follows:

\starttyping
hlingrid (Min, Max, Step, Length, Width)
vlingrid (Min, Max, Step, Length, Height)
hloggrid (Min, Max, Step, Length, Width)
vloggrid (Min, Max, Step, Length, Height)
\stoptyping

The macros take the following text upto the semi||colon into account and return a
picture. We will now apply this knowledge to a more meaningful example. First we
draw a grid.

You can use the grid drawing macros to produce your own paper, for instance using
the following mixed \TEX ||\METAFUN\ code:

\typebuffer[gridpage]

This produces a page (as in \in {figure} [fig:gridpage]) with a metric grid. If
you're hooked to the inch, you can set \type {unit := 1in}. If you want to
process this code, you need to wrap it into the normal document producing
commands:

\starttyping
\setupcolors[state=start]

\starttext
   ... definitions ...
\stoptext
\stoptyping

\placefigure
  [page]
  [fig:gridpage]
  {Quick and dirty grid paper.}
  {\typesetfile
     [mfun-901.tex]
     [page=1,height=.9\textheight]}

\stopsection

\startsection[title={Drawing functions}]

Today there are powerful tools to draw functions on grids, but for simple
functions you can comfortably use \METAPOST. Let's first draw a simple
log||linear grid.

\startbuffer[grd]
drawoptions(withpen pencircle scaled .25pt withcolor .5white) ;

draw hlingrid    (0, 20, .2, 20cm, 10cm) ;
draw vloggrid    (0, 10, .5, 10cm, 20cm) ;

drawoptions(withpen pencircle scaled .50pt) ;

draw hlingrid    (0, 20,  1, 20cm, 10cm) ;
draw vloggrid    (0, 10,  1, 10cm, 20cm) ;
\stopbuffer

\typebuffer[grd]

To this grid we add some labels:

\startbuffer[txt]
fmt_pictures  := false ;    % use TeX as formatting engine
textextoffset := ExHeight ; % a variable set by ConTeXt

draw hlintext.lft(0, 20,  5, 20cm, "@3e") ;
draw vlogtext.bot(0, 10,  9, 10cm, "@3e") ;
\stopbuffer

\typebuffer[txt]

The arguments to the text placement macros are similar to the ones for drawing
the axes. Here we provide a format string.

\starttyping
hlintext (Min, Max, Step, Length, Format)
vlintext (Min, Max, Step, Length, Format)
hlogtext (Min, Max, Step, Length, Format)
vlogtext (Min, Max, Step, Length, Format)
\stoptyping

When drawing a smooth function related curve, you need to provide enough sample
points. The \type {function} macro will generate them for you, but you need to
make sure that for instance the maximum and minimum values are part of the
generated series of points. Also, a smooth curve is not always the right curve.
Therefore we provide three drawing modes:

\starttabulate[|cT|l|]
\HL
\NC \bf method \NC \bf result                     \NC \NR
\HL
\NC 1 \NC a punked curve, drawn using \type {--}  \NC \NR
\NC 2 \NC a smooth curve, drawn using \type {..}  \NC \NR
\NC 3 \NC a tight  curve, drawn using \type {...} \NC \NR
\HL
\stoptabulate

If method~2 or~3 do not give the desired outcome, you can try a smaller step
combined with method~1.

\startbuffer[log]
draw
  function(1,"log(x)","x",1,10,1) xyscaled (10cm,2cm)
  withpen pencircle scaled 5mm withcolor transparent(1,.5,yellow) ;

draw
  function(2,".5log(x)","x",1,10,1) xyscaled (10cm,2cm)
  withpen pencircle scaled 5mm withcolor transparent(1,.5,blue) ;
\stopbuffer

\typebuffer[log]

\placefigure
  [page]
  {An example of a graphic with labels along the axes.}
  {\doifmodeelse{screen}
     {\scale[height=.85\textheight]{\processMPbuffer[grd,txt,log]}}
     {\processMPbuffer[grd,txt,log]}}

The first argument to the \type {function} macro specifies the drawing method.
The last three arguments are the start value, end value and step. The second and
third argument specify the function to be drawn. In this case the pairs \type
{(x,x)} and \type {(.5log(x),x)} are calculated.

\startbuffer[gon]
textextoffset := ExHeight ;

drawoptions(withpen pencircle scaled .50pt) ;

draw hlingrid(-10, 10, 1, 10cm, 10cm) ;
draw vlingrid(  0, 20, 1, 10cm, 20cm) shifted (0,-10cm) ;

drawoptions() ;

draw
  function(2,"x","sind(x)",0,360,10) xyscaled (1cm/36,10cm)
  withpen pencircle scaled 5mm withcolor transparent(1,.5,blue) ;

draw
  function(2,"x","sin(x*pi)",0,epsed(2),.1) xyscaled (10cm/2,5cm)
  withpen pencircle scaled 5mm withcolor transparent(1,.5,yellow) ;

draw
  function(2,"x","cosd(x)",0,360,10) xyscaled (1cm/36,10cm)
  withpen pencircle scaled 5mm withcolor transparent(1,.5,red) ;

draw
  function(2,"x","cos(x*pi)",0,epsed(2),.1) xyscaled (10cm/2,5cm)
  withpen pencircle scaled 5mm withcolor transparent(1,.5,green) ;
\stopbuffer

\typebuffer[gon]

\placefigure
  [page]
  {By using transparent colors, we don't have to calculate
   and mark the common points: they already stand out.}
  {\doifmodeelse{screen}
     {\scale[height=.85\textheight]{\processMPbuffer[gon]}}
     {\processMPbuffer[gon]}}

In this example we draw sinus and cosine functions using degrees and radians. In
the case of radians the end points are not calculated due to rounding errors. In
such case you can use the \type {epsed} value, which gives slightly more
playroom.

\startbuffer[mix]
draw function (1, "x", "sin(2x)"    , 1, 10, .01) scaled 1.5cm
  withpen pencircle scaled 1mm withcolor transparent(1,.5,red) ;
draw function (1, "x", "sin(2x*x)"  , 1, 10, .01) scaled 1.5cm
  withpen pencircle scaled 1mm withcolor transparent(1,.5,green) ;
draw function (1, "x", "sin(2x*x+x)", 1, 10, .01) scaled 1.5cm
  withpen pencircle scaled 1mm withcolor transparent(1,.5,blue) ;
\stopbuffer

\typebuffer[mix]

Of course you can do without a grid. The next example demonstrates a nice
application of transparencies.

\startlinecorrection[blank]
\processMPbuffer[mix]
\stoplinecorrection

If we use the \type {exclusion} method for the transparencies, combined with no
transparency, we get the following alternative.

\startbuffer[mix]
draw function (2, "x", "sin(x)" , 0, 2pi, pi/40) scaled 2cm
  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,red) ;
draw function (2, "x", "sin(2x)", 0, 2pi, pi/40) scaled 2cm
  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,green) ;
draw function (2, "x", "sin(3x)", 0, 2pi, pi/40) scaled 2cm
  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,blue) ;
\stopbuffer

\typebuffer[mix]

\startlinecorrection[blank]
\processMPbuffer[mix,wipe]
\stoplinecorrection

The next alternative uses a larger step, and as a result (in drawing mode~2)
gives worse results. (Without the \type {epsed} it would have looked even worse
in the end points.

 \startbuffer[mix]
draw function (2, "x", "sin(x)" , 0, epsed(2pi), pi/10) scaled 2cm
  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,red) ;
draw function (2, "x", "sin(2x)", 0, epsed(2pi), pi/10) scaled 2cm
  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,green) ;
draw function (2, "x", "sin(3x)", 0, epsed(2pi), pi/10) scaled 2cm
  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,blue) ;
\stopbuffer

\typebuffer[mix]

\startlinecorrection[blank]
\processMPbuffer[mix,wipe]
\stoplinecorrection

There are enough applications out there to draw nice functions, like gnuplot for
which Mojca Miklavec made a backend that works well with \CONTEXT. Nevertheless
it can be illustrative to explore the possibilities of the \CONTEXT, \LUATEX,
\METAPOST\ combination using functions.

First of all you can use \LUA\ to make paths and this is used in some of the
debugging and tracing options that come with \CONTEXT. For instance, if you
process a document with

\starttyping
context --timing yourdoc.tex
\stoptyping

then you can afterwards process a file that is generated while processing this
document:

\starttyping
context --extras timing yourdoc
\stoptyping

This will give you a document with graphics that show where \LUATEX\ spent its
time on. Of course these graphics are generated with \METAPOST.

There are a few helpers built in (and more might follow). For example:

\startbuffer
draw
  \ctxlua {
    metapost.metafun.topath {
        { x=1, y=1 },
        { x=1, y=3 },
        { 4, 1},
        "cycle"
    }
  }
  xysized(4cm,3cm)
  withpen pencircle scaled 1mm
  withcolor .625 red ;
\stopbuffer

\typebuffer

The \type {topath} function takes a table of points or strings.

\startlinecorrection[blank]
\processMPbuffer
\stoplinecorrection

You can pass a connector so

\startbuffer
draw
  \ctxlua {
    metapost.metafun.topath (
        {
            { x=1, y=1 },
            { x=1, y=3 },
            { 4,   1 },
            "cycle"
        },
        "--"
    )
  }
  xysized(4cm,3cm)
  withpen pencircle scaled 1mm
  withcolor .625 red ;
\stopbuffer

\typebuffer

gives:

\startlinecorrection[blank]
\processMPbuffer
\stoplinecorrection

Writing such \LUA\ functions is no big deal. For instance we have available:

\starttyping
function metapost.metafun.interpolate(f,b,e,s,c)
    tex.write("(")
    for i=b,e,(e-b)/s do
        local d = loadstring (
            string.formatters["return function(x) return %s end"](f)
        )
        if d then
            d = d()
            if i > b then
                tex.write(c or "...")
            end
            tex.write(string.formatters["(%F,%F)"](i,d(i)))
        end
    end
    tex.write(")")
end
\stoptyping

An example of usage is:

\startbuffer
draw
  \ctxlua{metapost.metafun.interpolate(
    "math.sin(x^2+2*x+math.sqrt(math.abs(x)))",
    -math.pi/2,math.pi/2,100
  )}
  xysized(6cm,3cm)
  withpen pencircle scaled 1mm
  withcolor .625 red ;
\stopbuffer

\typebuffer

And indeed we get some drawing:

\startlinecorrection[blank]
\processMPbuffer
\stoplinecorrection

Let's see what happens when we use less accuracy and a different connector:

\startbuffer
draw
  \ctxlua{metapost.metafun.interpolate(
    "math.sin(x^2+2*x+math.sqrt(math.abs(x)))",
    -math.pi/2,math.pi/2,10,"--"
  )}
  xysized(6cm,3cm)
  withpen pencircle scaled 1mm
  withcolor .625 red ;
\stopbuffer

\typebuffer

Now we get:

\startlinecorrection[blank]
\processMPbuffer
\stoplinecorrection

Of course we could extend this \LUA\ function with all kind of options and we
might even do that when we need it.

\stopsection

\stopchapter

\stopcomponent
