metafun-functions.tex /size: 17 Kb    last modification: 2023-12-21 09:43
1% language=us runpath=texruns:manuals/metafun
2
3\startcomponent metafun-functions
4
5\environment metafun-environment
6
7\startchapter[title={Functions}]
8
9\index{functions}
10
11\startintro
12
13\METAPOST\ provides a wide range of functions, like \type {sind} and \type
14{floor}. We will discuss most of them here and define a few more. We will also
15introduce a few methods for drawing grids and functions.
16
17\stopintro
18
19\startsection[title={Overview}]
20
21What follows is a short overview of the functions that can be applied to numeric
22expressions and strings. Functions that operate on pairs, colors, paths and
23pictures are discussed in other chapters.
24
25First of all we have \type {+}, \type {-}, \type {/} and \type {*}. For as far as
26is reasonable, you can apply these to numerics, pairs and colors. Strings can be
27concatenated by \type {&}.
28
29Pythagorean addition is accomplished by \type {++}, while Pythagorean subtraction
30is handled by \type {+-+}. The \type {**} operator gives you exponentiation. The
31nature of the \METAPOST\ language is such that you can easily define interesting
32functions using such symbols.
33
34The logarithmic functions are based on bytes. This makes them quite accurate but
35forces you to think like a computer.
36
37\starttabulate[|lT|l|]
38\HL
39\NC mexp(x) \NC expential function with base 256 \NC \NR
40\NC mlog(x) \NC logarithm with base 256          \NC \NR
41\HL
42\stoptabulate
43
44The basic goniometric functions operate on degrees, which is why they have a
45\quote {d} in their name.
46
47\starttabulate[|lT|l|]
48\HL
49\NC cosd(x) \NC cosine of $x$ with $x$ in degrees \NC \NR
50\NC sind(x) \NC sine of $x$ with $x$ in degrees   \NC \NR
51\HL
52\stoptabulate
53
54There are three ways to truncate numbers. The \type {round} function can also
55handle pairs and colors.
56
57\starttabulate[|lT|l|]
58\HL
59\NC ceiling(x) \NC the least integer greater than or equal to $x$     \NC \NR
60\NC floor(x)   \NC the greatest integer less than or equal to $x$     \NC \NR
61\NC round(x)   \NC round each component of $x$ to the nearest integer \NC \NR
62\HL
63\stoptabulate
64
65Of course we have:
66
67\starttabulate[|lT|l|]
68\HL
69\NC x mod y     \NC the remainder of $x/y$         \NC \NR
70\NC x div y     \NC the integer part of $x/y$      \NC \NR
71\NC abs(x)      \NC the absolute value of $x$      \NC \NR
72\NC sqrt(x)     \NC the square root of $x$         \NC \NR
73\NC x dotprod y \NC the dot product of two vectors \NC \NR
74\HL
75\stoptabulate
76
77What would life be without a certain randomness and uncertainty:
78
79\starttabulate[|lT|l|]
80\HL
81\NC normaldeviate     \NC a number with mean 0 and standard deviation 1 \NC \NR
82\NC uniformdeviate(x) \NC a number between zero and $x$                 \NC \NR
83\HL
84\stoptabulate
85
86The following functions are actually macros:
87
88\starttabulate[|lT|l|]
89\HL
90\NC decr(x,n)   \NC decrement $x$ by $n$                 \NC \NR
91\NC incr(x,n)   \NC increment $x$ by $n$                 \NC \NR
92\NC max(a,b,..) \NC return the maximum value in the list \NC \NR
93\NC min(a,b,..) \NC return the minimum value in the list \NC \NR
94\HL
95\stoptabulate
96
97The \type {min} and \type {max} funtions can be applied to numerics as well as
98strings.
99
100The following functions are related to strings:
101
102\starttabulate[|lT|l|]
103\HL
104\NC oct s     \NC string representation of an octal number      \NC \NR
105\NC hex s     \NC string representation of a hexadecimal number \NC \NR
106\NC str s     \NC string representation for a suffix            \NC \NR
107\NC ASCII s   \NC \ASCII\ value of the first character          \NC \NR
108\NC char x    \NC character of the given \ASCII\ code           \NC \NR
109\NC decimal x \NC decimal representation of a numeric           \NC \NR
110\HL
111\stoptabulate
112
113With \type {substring (i,j) of s} you can filter the substring bounded by the
114given indices from the given string.
115
116In \METAFUN\ we provide a few more functions (you can take a look in \type
117{mp-tool.mp} to see how they are defined. You need to be aware of very subtle
118rounding errors. Normally these only show up when you reverse an operation. This
119is a result from mapping to and from internal quantities.
120
121\starttabulate[|Tl|ml|]
122\HL
123\NC sqr(x)    \NC x^2       \NC \NR
124\NC log(x)    \NC \log(x)   \NC \NR
125\NC ln(x)     \NC \ln(x)    \NC \NR
126\NC exp(x)    \NC {\rm e}^x \NC \NR
127\NC pow(x, p) \NC x^p       \NC \NR
128\NC inv(x)    \NC 1/x       \NC \NR
129\HL
130\stoptabulate
131
132The following sine and cosine functions take radians instead of angles in
133degrees.
134
135\starttabulate[|Tl|Tl|Tl|]
136\HL
137\NC sin(x) \NC asin(x) \NC invsin(x) \NC \NR
138\NC cos(x) \NC acos(x) \NC invcos(x) \NC \NR
139\HL
140\stoptabulate
141
142There are no tangent functions, so we provide both the radian and degrees
143versions:
144
145\starttabulate[|Tl|Tl|]
146\HL
147\NC tan(x) \NC tand(x) \NC \NR
148\NC cot(x) \NC cotd(x) \NC \NR
149\HL
150\stoptabulate
151
152Here are a couple of hyperbolic functions.
153
154\starttabulate[|Tl|Tl|]
155\HL
156\NC sinh(x) \NC asinh(x) \NC \NR
157\NC cosh(x) \NC acosh(x) \NC \NR
158\HL
159\stoptabulate
160
161We end with a few additional string converters.
162
163\starttabulate[|Tl|l|]
164\HL
165\NC ddecimal x  \NC decimal representation of a pair   \NC \NR
166\NC dddecimal x \NC decimal representation of a color  \NC \NR
167\NC condition x \NC string representation of a boolean \NC \NR
168\HL
169\stoptabulate
170
171\stopsection
172
173\startsection[title={Grids}]
174
175\index{grids}
176\index{axis}
177
178Some day you may want to use \METAPOST\ to draw a function like graphic. In the
179regular \TEX\ distributions you will find a module \type {graph.mp} that provides
180many ways to accomplish this. For the moment, \METAFUN\ does not provide advanced
181features with respect to drawing functions, so this section will be relatively
182short.
183
184When drawing a functions (for educational purposes) we need to draw a couple of
185axis or a grid as well as a shape. Along the axis we can put labels. For this we
186can use the \METAPOST\ package \type {format.mp}, but this does not integrate
187that well into the way \METAFUN\ deals with text typeset by \TEX.
188
189For those who love dirty tricks and clever macros, close reading of the code in
190\type {format.mp} may be worthwhile. The format macros in there use \TEX\ to
191typeset the core components of a number, and use the dimensions of those
192components to compose combinations of signs, numbers and superscripts.
193
194In \METAFUN\ we have the module \type {mp-form.mp} which contains most of the
195code in \type {format.mp} but in a form that is a bit more suited for fine
196tuning. This permits us to use either the composition method, or to fall back on
197the \type {textext} method that is part of \METAFUN. That way we can also handle
198fonts that have digits with different dimensions. Another \quote {change}
199concerns the pattern separator. Instead of a \type {%} we use \type {@}; you can
200choose to set another separator, but for embedded definitions \type {%} is
201definitely a bad choice because \TEX\ sees it as a comment and ignores everything
202following it.
203
204\startbuffer[grd]
205drawoptions(withpen pencircle scaled 1pt withcolor .625yellow) ;
206
207draw hlingrid(0, 10, 1, 3cm, 3cm) ;
208draw vlingrid(0, 10, 1, 3cm, 3cm) ;
209
210draw hlingrid(0, 10, 1, 3cm, 3cm) shifted ( 3.5cm,0) ;
211draw vloggrid(0, 10, 1, 3cm, 3cm) shifted ( 3.5cm,0) ;
212
213draw hloggrid(0, 10, 1, 3cm, 3cm) shifted ( 7.0cm,0) ;
214draw vlingrid(0, 10, 1, 3cm, 3cm) shifted ( 7.0cm,0) ;
215
216draw hloggrid(0, 10, 1, 3cm, 3cm) shifted (10.5cm,0) ;
217draw vloggrid(0, 10, 1, 3cm, 3cm) shifted (10.5cm,0) ;
218\stopbuffer
219
220\typebuffer[grd]
221
222\startlinecorrection[blank]
223\processMPbuffer[grd]
224\stoplinecorrection
225
226\startbuffer[grd]
227drawoptions(withpen pencircle scaled 1pt withcolor .625yellow) ;
228
229draw hlingrid(0, 10, 1, 3cm, 3cm) slanted .5 ;
230draw vlingrid(0, 10, 1, 3cm, 3cm) slanted .5 ;
231\stopbuffer
232
233\typebuffer[grd]
234
235\startlinecorrection[blank]
236\processMPbuffer[grd]
237\stoplinecorrection
238
239Using macros like these often involves a bit of trial and error. The arguments to
240these macros are as follows:
241
242\starttyping
243hlingrid (Min, Max, Step, Length, Width)
244vlingrid (Min, Max, Step, Length, Height)
245hloggrid (Min, Max, Step, Length, Width)
246vloggrid (Min, Max, Step, Length, Height)
247\stoptyping
248
249The macros take the following text upto the semi||colon into account and return a
250picture. We will now apply this knowledge to a more meaningful example. First we
251draw a grid.
252
253You can use the grid drawing macros to produce your own paper, for instance using
254the following mixed \TEX ||\METAFUN\ code:
255
256\typebuffer[gridpage]
257
258This produces a page (as in \in {figure} [fig:gridpage]) with a metric grid. If
259you're hooked to the inch, you can set \type {unit := 1in}. If you want to
260process this code, you need to wrap it into the normal document producing
261commands:
262
263\starttyping
264\setupcolors[state=start]
265
266\starttext
267   ... definitions ...
268\stoptext
269\stoptyping
270
271\placefigure
272  [page]
273  [fig:gridpage]
274  {Quick and dirty grid paper.}
275  {\typesetfile
276     [mfun-901.tex]
277     [page=1,height=.9\textheight]}
278
279\stopsection
280
281\startsection[title={Drawing functions}]
282
283Today there are powerful tools to draw functions on grids, but for simple
284functions you can comfortably use \METAPOST. Let's first draw a simple
285log||linear grid.
286
287\startbuffer[grd]
288drawoptions(withpen pencircle scaled .25pt withcolor .5white) ;
289
290draw hlingrid    (0, 20, .2, 20cm, 10cm) ;
291draw vloggrid    (0, 10, .5, 10cm, 20cm) ;
292
293drawoptions(withpen pencircle scaled .50pt) ;
294
295draw hlingrid    (0, 20,  1, 20cm, 10cm) ;
296draw vloggrid    (0, 10,  1, 10cm, 20cm) ;
297\stopbuffer
298
299\typebuffer[grd]
300
301To this grid we add some labels:
302
303\startbuffer[txt]
304fmt_pictures  := false ;    % use TeX as formatting engine
305textextoffset := ExHeight ; % a variable set by ConTeXt
306
307draw hlintext.lft(0, 20,  5, 20cm, "@3e") ;
308draw vlogtext.bot(0, 10,  9, 10cm, "@3e") ;
309\stopbuffer
310
311\typebuffer[txt]
312
313The arguments to the text placement macros are similar to the ones for drawing
314the axes. Here we provide a format string.
315
316\starttyping
317hlintext (Min, Max, Step, Length, Format)
318vlintext (Min, Max, Step, Length, Format)
319hlogtext (Min, Max, Step, Length, Format)
320vlogtext (Min, Max, Step, Length, Format)
321\stoptyping
322
323When drawing a smooth function related curve, you need to provide enough sample
324points. The \type {function} macro will generate them for you, but you need to
325make sure that for instance the maximum and minimum values are part of the
326generated series of points. Also, a smooth curve is not always the right curve.
327Therefore we provide three drawing modes:
328
329\starttabulate[|cT|l|]
330\HL
331\NC \bf method \NC \bf result                     \NC \NR
332\HL
333\NC 1 \NC a punked curve, drawn using \type {--}  \NC \NR
334\NC 2 \NC a smooth curve, drawn using \type {..}  \NC \NR
335\NC 3 \NC a tight  curve, drawn using \type {...} \NC \NR
336\HL
337\stoptabulate
338
339If method~2 or~3 do not give the desired outcome, you can try a smaller step
340combined with method~1.
341
342\startbuffer[log]
343draw
344  function(1,"log(x)","x",1,10,1) xyscaled (10cm,2cm)
345  withpen pencircle scaled 5mm withcolor transparent(1,.5,yellow) ;
346
347draw
348  function(2,".5log(x)","x",1,10,1) xyscaled (10cm,2cm)
349  withpen pencircle scaled 5mm withcolor transparent(1,.5,blue) ;
350\stopbuffer
351
352\typebuffer[log]
353
354\placefigure
355  [page]
356  {An example of a graphic with labels along the axes.}
357  {\doifmodeelse{screen}
358     {\scale[height=.85\textheight]{\processMPbuffer[grd,txt,log]}}
359     {\processMPbuffer[grd,txt,log]}}
360
361The first argument to the \type {function} macro specifies the drawing method.
362The last three arguments are the start value, end value and step. The second and
363third argument specify the function to be drawn. In this case the pairs \type
364{(x,x)} and \type {(.5log(x),x)} are calculated.
365
366\startbuffer[gon]
367textextoffset := ExHeight ;
368
369drawoptions(withpen pencircle scaled .50pt) ;
370
371draw hlingrid(-10, 10, 1, 10cm, 10cm) ;
372draw vlingrid(  0, 20, 1, 10cm, 20cm) shifted (0,-10cm) ;
373
374drawoptions() ;
375
376draw
377  function(2,"x","sind(x)",0,360,10) xyscaled (1cm/36,10cm)
378  withpen pencircle scaled 5mm withcolor transparent(1,.5,blue) ;
379
380draw
381  function(2,"x","sin(x*pi)",0,epsed(2),.1) xyscaled (10cm/2,5cm)
382  withpen pencircle scaled 5mm withcolor transparent(1,.5,yellow) ;
383
384draw
385  function(2,"x","cosd(x)",0,360,10) xyscaled (1cm/36,10cm)
386  withpen pencircle scaled 5mm withcolor transparent(1,.5,red) ;
387
388draw
389  function(2,"x","cos(x*pi)",0,epsed(2),.1) xyscaled (10cm/2,5cm)
390  withpen pencircle scaled 5mm withcolor transparent(1,.5,green) ;
391\stopbuffer
392
393\typebuffer[gon]
394
395\placefigure
396  [page]
397  {By using transparent colors, we don't have to calculate
398   and mark the common points: they already stand out.}
399  {\doifmodeelse{screen}
400     {\scale[height=.85\textheight]{\processMPbuffer[gon]}}
401     {\processMPbuffer[gon]}}
402
403In this example we draw sinus and cosine functions using degrees and radians. In
404the case of radians the end points are not calculated due to rounding errors. In
405such case you can use the \type {epsed} value, which gives slightly more
406playroom.
407
408\startbuffer[mix]
409draw function (1, "x", "sin(2x)"    , 1, 10, .01) scaled 1.5cm
410  withpen pencircle scaled 1mm withcolor transparent(1,.5,red) ;
411draw function (1, "x", "sin(2x*x)"  , 1, 10, .01) scaled 1.5cm
412  withpen pencircle scaled 1mm withcolor transparent(1,.5,green) ;
413draw function (1, "x", "sin(2x*x+x)", 1, 10, .01) scaled 1.5cm
414  withpen pencircle scaled 1mm withcolor transparent(1,.5,blue) ;
415\stopbuffer
416
417\typebuffer[mix]
418
419Of course you can do without a grid. The next example demonstrates a nice
420application of transparencies.
421
422\startlinecorrection[blank]
423\processMPbuffer[mix]
424\stoplinecorrection
425
426If we use the \type {exclusion} method for the transparencies, combined with no
427transparency, we get the following alternative.
428
429\startbuffer[mix]
430draw function (2, "x", "sin(x)" , 0, 2pi, pi/40) scaled 2cm
431  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,red) ;
432draw function (2, "x", "sin(2x)", 0, 2pi, pi/40) scaled 2cm
433  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,green) ;
434draw function (2, "x", "sin(3x)", 0, 2pi, pi/40) scaled 2cm
435  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,blue) ;
436\stopbuffer
437
438\typebuffer[mix]
439
440\startlinecorrection[blank]
441\processMPbuffer[mix,wipe]
442\stoplinecorrection
443
444The next alternative uses a larger step, and as a result (in drawing mode~2)
445gives worse results. (Without the \type {epsed} it would have looked even worse
446in the end points.
447
448 \startbuffer[mix]
449draw function (2, "x", "sin(x)" , 0, epsed(2pi), pi/10) scaled 2cm
450  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,red) ;
451draw function (2, "x", "sin(2x)", 0, epsed(2pi), pi/10) scaled 2cm
452  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,green) ;
453draw function (2, "x", "sin(3x)", 0, epsed(2pi), pi/10) scaled 2cm
454  withpen pencircle scaled 5mm withcolor transparent("exclusion",1,blue) ;
455\stopbuffer
456
457\typebuffer[mix]
458
459\startlinecorrection[blank]
460\processMPbuffer[mix,wipe]
461\stoplinecorrection
462
463There are enough applications out there to draw nice functions, like gnuplot for
464which Mojca Miklavec made a backend that works well with \CONTEXT. Nevertheless
465it can be illustrative to explore the possibilities of the \CONTEXT, \LUATEX,
466\METAPOST\ combination using functions.
467
468First of all you can use \LUA\ to make paths and this is used in some of the
469debugging and tracing options that come with \CONTEXT. For instance, if you
470process a document with
471
472\starttyping
473context --timing yourdoc.tex
474\stoptyping
475
476then you can afterwards process a file that is generated while processing this
477document:
478
479\starttyping
480context --extras timing yourdoc
481\stoptyping
482
483This will give you a document with graphics that show where \LUATEX\ spent its
484time on. Of course these graphics are generated with \METAPOST.
485
486There are a few helpers built in (and more might follow). For example:
487
488\startbuffer
489draw
490  \ctxlua {
491    metapost.metafun.topath {
492        { x=1, y=1 },
493        { x=1, y=3 },
494        { 4, 1},
495        "cycle"
496    }
497  }
498  xysized(4cm,3cm)
499  withpen pencircle scaled 1mm
500  withcolor .625 red ;
501\stopbuffer
502
503\typebuffer
504
505The \type {topath} function takes a table of points or strings.
506
507\startlinecorrection[blank]
508\processMPbuffer
509\stoplinecorrection
510
511You can pass a connector so
512
513\startbuffer
514draw
515  \ctxlua {
516    metapost.metafun.topath (
517        {
518            { x=1, y=1 },
519            { x=1, y=3 },
520            { 4,   1 },
521            "cycle"
522        },
523        "--"
524    )
525  }
526  xysized(4cm,3cm)
527  withpen pencircle scaled 1mm
528  withcolor .625 red ;
529\stopbuffer
530
531\typebuffer
532
533gives:
534
535\startlinecorrection[blank]
536\processMPbuffer
537\stoplinecorrection
538
539Writing such \LUA\ functions is no big deal. For instance we have available:
540
541\starttyping
542function metapost.metafun.interpolate(f,b,e,s,c)
543    tex.write("(")
544    for i=b,e,(e-b)/s do
545        local d = loadstring (
546            string.formatters["return function(x) return %s end"](f)
547        )
548        if d then
549            d = d()
550            if i > b then
551                tex.write(c or "...")
552            end
553            tex.write(string.formatters["(%F,%F)"](i,d(i)))
554        end
555    end
556    tex.write(")")
557end
558\stoptyping
559
560An example of usage is:
561
562\startbuffer
563draw
564  \ctxlua{metapost.metafun.interpolate(
565    "math.sin(x^2+2*x+math.sqrt(math.abs(x)))",
566    -math.pi/2,math.pi/2,100
567  )}
568  xysized(6cm,3cm)
569  withpen pencircle scaled 1mm
570  withcolor .625 red ;
571\stopbuffer
572
573\typebuffer
574
575And indeed we get some drawing:
576
577\startlinecorrection[blank]
578\processMPbuffer
579\stoplinecorrection
580
581Let's see what happens when we use less accuracy and a different connector:
582
583\startbuffer
584draw
585  \ctxlua{metapost.metafun.interpolate(
586    "math.sin(x^2+2*x+math.sqrt(math.abs(x)))",
587    -math.pi/2,math.pi/2,10,"--"
588  )}
589  xysized(6cm,3cm)
590  withpen pencircle scaled 1mm
591  withcolor .625 red ;
592\stopbuffer
593
594\typebuffer
595
596Now we get:
597
598\startlinecorrection[blank]
599\processMPbuffer
600\stoplinecorrection
601
602Of course we could extend this \LUA\ function with all kind of options and we
603might even do that when we need it.
604
605\stopsection
606
607\stopchapter
608
609\stopcomponent
610