# Typesetting differential equations

Posted on September 18, 2017

This semester I am teaching a course involving linear differential equations, so I have typeset many differential equations that look like this:

Believe me, writing such equations by hand gets tedious very quickly. So, I wanted a macro `\LDE` (for Linear Differential Equation), so that I could just type

``````\LDE{1, -3, 2}{2, 1}
``````

and get the above result. This post describes how to write such a macro using LuaTeX + ConTeXt.

I’ll explain the implementation using a top-down approach. Writing macros in TeX is tough, so let’s delegate all the high lifting to Lua. So, we define a ConTeXt command that simply invokes a Lua function with the appropriate arguments. This can be done using:

``````\startluacode
-- ... lua function LDE to be added ...
interfaces.definecommand {
name      = "LDE",
macro     = LDE,
arguments = {
{"content", "list" },
{"content", "list" },
}
}
\stopluacode
``````

The `name` argument specifies the name of the TeX command (`\LDE` in this case); the `macro` argument specifies the name of the Lua function (`LDE` in this case) which gets called when the TeX macro is invoked; the `arguments` tables specifies the list of arguments of the TeX macros. We specify that the macro has two arguments, both of them are `content` arguemnts (that is, the macro is invoked as `\LDE{...}{...}`) and each arguement should be passed on to the Lua function as a `list` (i.e., a Lua table of strings; other options include `hash` (for key-value list), `number`, and `string`).

Now all we need to do is define the function `LDE`, which takes two comma separated lists as arguments and typesets the resulting differential equation. The basic logic is straight forward. Suppose we have defined a function `derivative` that typesets a derivative (taking care of adding a `+` sign if the coefficient of an intermediate term is positive; not showing the coefficient if the coefficient is `+1` or `-1`; and not showing the term if the coefficient is `0`). Then, the `LDE` function is:

``````\startluacode
-- Lua function derivative to be added

local LDE = function(LHS, RHS)
for i = 1, #LHS do
context(derivative(LHS[i], "y(t)", #LHS - i, i == 1))
end

context("=")
for i = 1, #RHS do
context(derivative(RHS[i], "u(t)", #RHS - i, i == 1))
end
end

interfaces.definecommand { ... }
\stopluacode
``````

The last term in the call to the `derivative` function passes a flag that indicates whether or not the term is the first term.

I’ll not go into the details of the `derivative` function because it is straight forward. So, here is the complete macro with a usage example:

``````\startluacode
local find, format = string.find, string.format

local derivative = function(coefficient, var, order, first)
-- If the coefficient is zero or empty, don't typeset anything
if coefficient == nil or coefficient == "" or coefficient == "0" then
return
end

-- If the coefficient is 1 or -1, we do not want to print the 1.
if coefficient == "1" then
coefficient = ""
elseif coefficient == "-1" then
coefficient = "-"
end

-- If this is not the first coefficient by is a positive coefficient,
-- then add a "+" sign
if not first then
if find(coefficient, "-") ~= 1 then
coefficient = "+" .. coefficient
end
end

-- Format the return value depending on the order of the derivative
local str
if order == 0 then
str = format("%s %s", coefficient, var)
elseif order == 1 then
str = format("%s \\dfrac{ d %s } { dt }", coefficient, var)
else
str = format("%s \\dfrac{ d^{%s} %s } { dt^{%s} }", coefficient, order, var, order)
end
return str
end

local LDE = function(LHS, RHS)
LHS = settings_to_array(LHS)
RHS = settings_to_array(RHS)

for i = 1, #LHS do
context(derivative(LHS[i], "y(t)", #LHS - i, i == 1))
end
context("=")
for i = 1, #RHS do
context(derivative(RHS[i], "u(t)", #RHS - i, i == 1))
end
end

interfaces.definecommand {
name      = "LDE",
macro     = LDE,
arguments = {
{"content", "list" },
{"content", "list" },
}
}

\stopluacode

\starttext
\startformula
\LDE{2,1,-3}{4,0,6}
\stopformula
\startformula
\LDE{a_2, -a_1,a_0}{b_1,b_0}
\stopformula
\stoptext
``````

This entry was posted in Macros and tagged luatex, programming, separating content and presentation.