summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/metafun/metafun-functions.tex
blob: 78012740830f9b4da905a1e462516bbde4995931 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
% language=uk
%
% copyright=pragma-ade readme=readme.pdf licence=cc-by-nc-sa

\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