Numerical Methods With Lual Tex: Juan I. Montijano, Mario Pérez, Luis Rández and Juan Luis Varona
Numerical Methods With Lual Tex: Juan I. Montijano, Mario Pérez, Luis Rández and Juan Luis Varona
1
Article revision 2013/1/27
Abstract An extension of TEX known as LuaTEX has been in development for the
past few years. Its goal is to allow TEX to execute scripts written in the gen-
eral purpose programming language called Lua. There is also LuaLATEX,
which is the corresponding extension for LATEX.
In this paper, we show how LuaLATEX can be used to perform tasks
that require a large amount of mathematical computation. With LuaLATEX
instead of LATEX, we achieve important improvements: since Lua is a gen-
eral purpose language, rendering documents that include evaluation of
mathematical algorithms is much easier, and generating the pdf file be-
comes much faster.
Introduction
TEX (and LATEX) is a document markup language used to typeset beautiful papers
and books. Although it can also do programming commands such as conditional
execution, it is not a general purpose programming language. Thus there are
many tasks that are easily done with other programming languages, but are very
complicated or very slow when done with TEX. Due to this limitation, auxil-
iary programs have been developed to assist TEX with common tasks related to
document preparation. For instance, bibtex or biber to build bibliographies, and
makeindex or xindy to generate indexes. In both cases, sorting a list alphabetically
is a relatively simple task for most programming languages, but it is very com-
plicated to do with TEX, which is why auxiliary applications written in standard
programming languages are used to prepare the bibliography and index.
Another shortcoming of TEX is the computation of mathematical expressions.
One of the most common uses of TEX is to compose mathematical formulas, and
it does this extremely well. However TEX is not good at computing mathematics.
For instance, TEX itself does not have built-in functions to compute a square root,
a sine or a cosine. It is possible to compute mathematical functions with the
help of auxiliary packages written in TEX but, internally, these packages must
compute functions using only addition, subtraction, multiplication and division;
and a large amount of them. This is difficult to program (for package developers)
and slow in the execution.
To address the need to do more complex functions within TEX, an extension
of TEX called LuaTEX was begun a few years ago. (The leaders of the project and
main developers are Taco Hoekwater, Hartmut Henkel and Hans Hagen.) The
idea was to enhance TEX with a previously existing general purpose program-
ming language. After a careful evaluation of possible candidates, the language
chosen was Lua (see http://www.lua.org/), a powerful, fast, lightweight, embed-
dable scripting language that has, of course, a free license suitable to be used with
TEX. Moreover, Lua is easy to learn and use, and anyone with basic programming
skills can use it without difficulty. (Many examples of Lua code can be found
later in this article, and also in http://rosettacode.org/wiki/Category:Lua,
and http://lua-users.org/).
LuaTEX is not TEX, but an extension of TEX, in the same way that pdfTEX or
XETEX are also extensions. In fact, LuaTEX includes pdfTEX (it is an extension of
pdfTEX, and offers backward compatibility), and also has many of the features of
XETEX.
LuaTEX is still in a beta stage, but the current versions are usable (the first
public beta was launched in 2007, and when this paper was written in January
2013, the release used was version 0.74).
It has many new features useful for typographic composition, and examples
can be seen at the project web site http://www.luatex.org, and some papers
using development versions have been published in TUGboat, among them [1, 2,
3, 4, 6, 8]. Most of articles are devoted to the internals and are very technical,
only for true TEX wizards; we do not deal with this in this paper. Instead, our
goal is to show how the mathematical power of the embedded language Lua can
be used in LuaTEX. Of course, when we build LATEX over LuaTEX, we get the
so-called LuaLATEX, which is more familiar for regular LATEX users.
All the examples in this paper are done with LuaLATEX. It is important to note
that the current version of LuaTEX is not meant for production and beta users are
warned of possible future changes in the syntax. For the examples in this article
2
we use only a few general Lua-specific commands, so it is likely these examples
will also work in future versions.
To process a LuaLATEX document we perform the following steps: First, we
must compile with LuaLATEX, not with LATEX; how to do this depends on which ed-
itor we are using. Second, we must load the package luacode with \usepackage{luacode}.
Then, inside LuaLATEX, we jump into Lua mode with the command \directlua;
moreover, we can define Lua routines in a \begin{luacode} – \end{luacode}
environment (also {luacode*} instead of {luacode} can be used); the precise
syntax can be found in the manual “The luacode package” (by Manuel Pégourié-
Gonnard). In the examples, we do not explain all the details of the code; they are
left to the reader’s intuition.
In this paper we present four examples. The first is very simple: the compu-
tation of a trigonometric table. In the other examples we use the LATEX packages
tikz and pgfplots to show Lua’s ability to produce graphical output. Some mathe-
matical skill may be necessary to fully understand the examples, but the reader
can nevertheless see how Lua is able to manage the computation-intensive job. In
any case, we do not explore the more complex possibilities, which involve writ-
ing Lua programs that load existing Lua modules or libraries to perform a wide
range of functions and specialized tasks.
\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
function trigtable ()
for t=0, 45, 3 do
x=math.rad(t)
tex.print(string.format(
’%2d$^{\\circ}$ & %1.9f & %1.9f & %1.9f & %1.9f \\\\’,
3
t, x, math.sin(x), math.cos(x), math.tan(x)))
end
end
\end{luacode*}
\newcommand{\trigtable}{\luadirect{trigtable()}}
\begin{document}
\begin{tabular}{rcccc}
\hline
& $x$ & $\sin(x)$ & $\cos(x)$ & $\tan(x)$ \\
\hline
\trigtable
\hline
\end{tabular}
\end{document}
4
x sin( x ) cos( x ) tan( x )
0◦ 0.000000000 0.000000000 1.000000000 0.000000000
3◦ 0.052359878 0.052335956 0.998629535 0.052407779
6◦ 0.104719755 0.104528463 0.994521895 0.105104235
9◦ 0.157079633 0.156434465 0.987688341 0.158384440
12◦ 0.209439510 0.207911691 0.978147601 0.212556562
15◦ 0.261799388 0.258819045 0.965925826 0.267949192
18◦ 0.314159265 0.309016994 0.951056516 0.324919696
21◦ 0.366519143 0.358367950 0.933580426 0.383864035
24◦ 0.418879020 0.406736643 0.913545458 0.445228685
27◦ 0.471238898 0.453990500 0.891006524 0.509525449
30◦ 0.523598776 0.500000000 0.866025404 0.577350269
33◦ 0.575958653 0.544639035 0.838670568 0.649407593
36◦ 0.628318531 0.587785252 0.809016994 0.726542528
39◦ 0.680678408 0.629320391 0.777145961 0.809784033
42◦ 0.733038286 0.669130606 0.743144825 0.900404044
45◦ 0.785398163 0.707106781 0.707106781 1.000000000
the current version 2.10 has more than 700 pages of complete documentation and
examples); a nice and small paper with a introduction is [7]. Based on pgf/TikZ,
the package pgfplots (by Christian Feuersänger) has additional facilities to plot
mathematical functions like y = f ( x ) (or a parametric function x = f (t), y = g(t))
or visualize data in two or three dimensions. For instance, pgfplots can draw the
axis automatically, as usual in any graphic software.
For completeness, let us start showing the syntax of pgfplots by means of a
data plot; this is an example extracted from its very complete manual (more than
400 pages in the present version 1.7). After loading \usepackage{pgfplots}, the
code
\begin{tikzpicture}
\begin{axis}[xlabel=Cost, ylabel=Error]
\addplot[color=red,mark=x] coordinates {
(2,-2.8559703) (3,-3.5301677) (4,-4.3050655)
(5,-5.1413136) (6,-6.0322865) (7,-6.9675052)
5
−4
Error
−6
−8
2 3 4 5 6 7 8
Cost
(8,-7.9377747)
};
\end{axis}
\end{tikzpicture}
provides the plot in Figure 2. Before going on, note that in future versions the
packages pgf/TikZ and pgfplots could, internally, use LuaLATEX themselves in a
way transparent to the user. This will allow extra power, calculating speed, and
simplicity, but this is not yet available and we will not worry about it in this
paper.
In the next example we consider the Gibbs phenomenon. Using LuaLATEX, the
idea is to compute a data table with Lua (that is easy to program, powerful and
fast in the execution), and plot it with pgfplots.
The Gibbs phenomenon is the peculiar way in which the Fourier series of a
piecewise continuously differentiable periodic function behaves at a jump discon-
tinuity, where the n-th partial sum of the Fourier series has large oscillations near
the jump. It is explained in many harmonic analysis texts, but for the purpose of
this paper the reader can refer to [9].
In our case we consider the function f ( x ) = (π − x )/2 in the interval (0, 2π )
extended by periodicity to the whole real line (it has discontinuity jumps at 2jπ
6
for every integer j). Its Fourier series is
∞
sin(kx )
f (x) = ∑ k
.
k =1
sin(kx )
To show the Gibbs phenomenon, we evaluate the partial sum ∑nk=1 k (for
n = 30) with Lua to generate a table of data, and we plot it with pgfplots.
In the .tex file, we include the following Lua part to compute the partial
sum (function partial_sum) and to export the data with the syntax required by
pgfplots (function print_partial_sum):
\begin{luacode*}
-- Fourier series
function partial_sum(n,x)
partial = 0;
for k = 1, n, 1 do
partial = partial + math.sin(k*x)/k
end;
return partial
end
7
end
\end{luacode*}
\newcommand\addLUADEDplot[5][]{%
\directlua{print_partial_sum(#2,#3,#4,#5,[[#1]])}%
}
which will be used to call the data from pgfplots. Here, the parameters have
the following meaning: #2 indicates the number of terms to be added (n = 30
in our case); the plot will be done in the interval [#3, #4] (from x = 0 to 10π)
sampled in #5 points (to get a very smooth graphic and to show the power of the
method we use 1000 points); finally, the optional argument #1 is used to manage
optional arguments in the \addplot environment (for instance color, width of the
line, . . . ).
Now, the plot is generated by
\pgfplotsset{width=15cm, height=7cm}
\begin{tikzpicture}\small
\begin{axis}[xmin=-0.2, xmax=31.6, ymin=-1.85, ymax=1.85,
xtick={0,5,10,15,20,25,30},
ytick={-1.5,-1.0,-0.5,0.5,1.0,1.5},
minor x tick num=4,
minor y tick num=4,
axis lines=middle,
axis line style={-}
]
% SYNTAX: Partial sum 30, from x = 0 to 10*pi, sampled in 1000 points
\addLUADEDplot[color=blue,smooth]{30}{0}{10*math.pi}{1000};
\end{axis}
\end{tikzpicture}
8
1.5
1
0.5
5 10 15 20 25 30
−0.5
−1
−1.5
sin(kx )
Figure 3: The partial sum ∑30
k =1 k of the Fourier series of f ( x ) = (π − x )/2
illustrating the Gibbs phenomenon.
1
yi+1 = yi + (k1 + 2k2 + 2k3 + k4 ),
6
9
where
k1 = h f ( t i , y i ),
h f (ti + 12 h, yi + 12 k1 ),
k =
2
k3 = h f (ti + 12 h, yi + 12 k2 ),
k =
4 h f (ti + h, yi + k3 ).
See, for instance, [11].
Here, we consider the initial value problem
(
y0 (t) = y(t) cos t + 1 + y(t) ,
p
y(0) = 1.
In the Lua part of our .tex file, we compute the values {(ti , yi )} and export
them with pgfplots syntax by means of
\begin{luacode*}
-- Differential equation y’(t) = f(t,y)
-- with f(t,y) = y * cos(t+sqrt(1+y)).
-- Initial condition: y(0) = 1
function f(t,y)
return y * math.cos(t+math.sqrt(1+y))
end
10
for i=1, npoints do
k1 = h * f(t,y)
k2 = h * f(t+h/2,y+k1/2)
k3 = h * f(t+h/2,y+k2/2)
k4 = h * f(t+h,y+k3)
y = y + (k1+2*k2+2*k3+k4)/6
t = t + h
tex.sprint("("..t..","..y..")")
end
tex.sprint("}")
end
\end{luacode*}
Also, we define the command
\newcommand\addLUADEDplot[3][]{%
\directlua{print_RKfour(#2,#3,[[#1]])}%
}
to call the Lua routine from the LATEX part (the parameter #2 indicates the final
value of t, and #3 is the number of sampled points).
Then, the graphic of Figure 4, which shows the solution of our initial value
problem, is done by means of
\pgfplotsset{width=0.9\textwidth, height=0.6\textwidth}
\begin{tikzpicture}
\begin{axis}[xmin=-0.5, xmax=30.5, ymin=-0.02, ymax=1.03,
xtick={0,5,...,30}, ytick={0,0.2,...,1.0},
enlarge x limits=true,
minor x tick num=4, minor y tick num=4,
axis lines=middle, axis line style={-}
]
% SYNTAX: Solution of the initial value problem
% in the interval [0,30] sampled at 200 points
\addLUADEDplot[color=blue,smooth]{30}{200};
\end{axis}
\end{tikzpicture}
11
1
0.8
0.6
0.4
0.2
5 10 15 20 25 30
12
40
20
0
−10
0
10 −20
Figure 5: The Lorentz attractor (six orbits starting at several initial points).
(0, 1, 0) are plotted in different colors; all of them converge to the 3-dimensional
chaotic attractor known as the Lorenz attractor.
The Lua part of the program uses a discretization of the Lorenz equations
(technically, this is the explicit Euler method yi+1 = yi + h f (ti , yi ), which is less
precise than the Runge-Kutta method of the previous section, but enough to find
the attractor):
\begin{luacode*}
-- Differential equation of the Lorenz attractor
function f(x,y,z)
local sigma = 3
local rho = 26.5
local beta = 1
return {sigma*(y-x), -x*z + rho*x - y, x*y - beta*z}
end
13
local z0 = 0.0
-- we add a random number between -0.25 and 0.25
local x = x0 + (math.random()-0.5)/2
local y = y0 + (math.random()-0.5)/2
local z = z0 + (math.random()-0.5)/2
if option~=[[]] then
tex.sprint("\\addplot3["..option.."] coordinates{")
else
tex.sprint("\\addplot3 coordinates{")
end
-- we dismiss the first 100 points to go into the attractor
for i=1, 100 do
m = f(x,y,z)
x = x + h * m[1]
y = y + h * m[2]
z = z + h * m[3]
end
for i=1, npoints do
m = f(x,y,z)
x = x + h * m[1]
y = y + h * m[2]
z = z + h * m[3]
tex.sprint("("..x..","..y..","..z..")")
end
tex.sprint("}")
end
\end{luacode*}
The function which calls the Lua part from the LATEX part is
\newcommand\addLUADEDplot[3][]{%
\directlua{print_LorAttrWithEulerMethod(#2,#3,[[#1]])}%
}
Here, the parameter #2 gives the step of the discretization, and #3 is the number
of points.
14
The LATEX part is the following. In it, we call the Lua function six times with
different colors:
\begin{tikzpicture}
\begin{axis}
% SYNTAX: Solution of the Lorenz system
% with step h=0.02 sampled at 1000 points.
\addLUADEDplot[color=red,smooth]{0.02}{1000};
\addLUADEDplot[color=green,smooth]{0.02}{1000};
\addLUADEDplot[color=blue,smooth]{0.02}{1000};
\addLUADEDplot[color=cyan,smooth]{0.02}{1000};
\addLUADEDplot[color=magenta,smooth]{0.02}{1000};
\addLUADEDplot[color=yellow,smooth]{0.02}{1000};
\end{axis}
\end{tikzpicture}
References
[1] T. Hoekwater and H. Henkel, LuaTEX 0.60: An overview of changes, TUG-
boat, Volume 31 (2010), No. 2, 174–177. Available from https://www.tug.
org/TUGboat/tb31-2/tb98hoekwater.pdf
[3] P. Isambert, Three things you can do with LuaTEX that would be extremely painful
otherwise, TUGboat, Volume 31 (2010), No. 3, 184–190. Available from https:
//www.tug.org/TUGboat/tb31-3/tb99isambert.pdf
15
[6] A. Mahajan, LuaTEX: A user’s perspective, TUGboat, Volume 30 (2009),
No. 2, 247–251. Available from https://www.tug.org/TUGboat/tb30-2/
tb95mahajan-luatex.pdf
[7] A. Mertz and W. Slough, Graphics with PGF and TikZ, The PracTEX Journal,
2007, No. 1. Available from http://www.tug.org/pracjourn/2007-1/mertz/
[8] A. Reutenauer, LuaTEX for the LATEX user: An introduction, TUGboat, Volume
30 (2009), No. 2, 169. Available from https://www.tug.org/TUGboat/tb30-2/
tb95reutenauer.pdf
16