% output=pdftex engine=pdftex language=uk
%
% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa
\startcomponent mfun-027
\environment mfun-000
\chapter {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
\section {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|Tl|]
\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
\section {Grids}
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
\setupoutput[pdftex]
\setupcolors[state=start]
\starttext
... definitions ...
\stoptext
\stoptyping
\placefigure
[page]
[fig:gridpage]
{Quick and dirty grid paper.}
{\externalfigure
[mfun-999.pdf]
[page=13,height=.9\textheight]}
\section{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[|c|p|]
\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
\stopcomponent