# An even more flexible derivative macro?

I am trying to expand the macro given in Can I have a flexible partial derivative macro? In particular, I would like to add a starred version that does not attempt to sum the exponents of the various derivatives, which is useful if the exponent isn't a number. My attempt is given below, but I didn't make much progress. The way I would like the command to work is shown in the second displayed math environment. Ideally, I would only have one command, and it would behave as shown in the third displayed math environment, but this seems overly ambitious.

\documentclass[12pt]{article}

\makeatletter
\newcommand\derivative[2]
{
\begingroup
\@temptokena{\@gobble}
\@tempcnta\z@
\@for\var:=#2\do
{
\expandafter\@derivative\var\relax
}
\frac
{
d
\ifnum \@tempcnta > \@ne
^{\the\@tempcnta}
\fi
#1
}
{\the\@temptokena}
\endgroup
}
\def\@derivative#1#2\relax
{
\ifx\relax#2\relax
\@temptokena\expandafter{\the\@temptokena \, d #1}
\else
\@temptokena\expandafter{\the\@temptokena \, d #1^{#2}}
\fi
}
\makeatother

\makeatletter
\newcommand\derivativestar[2]
{
\begingroup
\@temptokena{\@gobble}
\@temptokenb{}
\@for\var:=#2\do
{
\expandafter\@derivativestar\var\relax
}
\frac
{
d^{\@temptokenb} #1
}
{\the\@temptokena}
\endgroup
}
\def\@derivativestar#1#2\relax
{
% need to test for first token
\ifx\relax#2\relax
\@temptokena\expandafter{\the\@temptokena \, d #1}
\@temptokenb\expandafter{\the\@temptokenb + 1}
\else
\@temptokena\expandafter{\the\@temptokena \, d #1^{#2}}
\@temptokenb\expandafter{\the\@temptokenb + #2}
\fi
}
\makeatother

\begin{document}

$\derivative{x}{{y}{2},{z}{3}}$

$% \derivative*{x}{{y}{m},{z}{n}} \frac{d x^{m+n}}{d y^{m} \, d z^{n}}$

$% \derivative{x}{{v}{3},{w}{k,2},y,{z}{m}} \frac{d x^{k+m+6}}{d v^{3} \, d w^{k+2} \, d y \, d z^{m}}$

\end{document}

-
Good question. I'm not sure if this is easy since you're implementing algebra with TeX. –  Matthew Leingang Mar 6 '13 at 3:34

From the description, it seems like what you want is auto-detection of non-numerical input. That means you do not need \derivative* but can leave the decision to the code. Robustness could be an issue: in the following I've assume we have a single token for each index (that can be solved). As you've coded in 'traditional' LaTeX, I've stuck as far as possible to the same approach:

\documentclass[12pt]{article}
\makeatletter
\newcommand{\ifintegerTF}[1]{%
\ifnum#1<0 %
\expandafter\@secondoftwo
\else
\ifnum#1>9 %
\expandafter\expandafter\expandafter\@secondoftwo
\else
\expandafter\expandafter\expandafter\@firstoftwo
\fi
\fi
}
\newcommand{\derivative}[2]{%
\begingroup
\toks@{}%
\@temptokena{}%
\@tempcnta\z@
\@tempswatrue
\@for\@tempa:=#2\do{%
\expandafter\derivative@aux@i\@tempa\stop
}%
\frac
{%
d%
\if@tempswa
\ifnum\@tempcnta>\@ne
^{\number\@tempcnta}%
\fi
#1%
\else
#1%
\ifnum\@tempcnta>\z@
\toks@\expandafter\expandafter\expandafter
{\expandafter\the\expandafter\toks@ \expandafter + \the\@tempcnta}%
\fi
^{\expandafter\@gobble\the\toks@}%
\fi
}
{\the\@temptokena}
\endgroup
}
\newcommand{\derivative@aux}{}
\long\def\derivative@aux@i#1#2\stop{%
\@temptokena\expandafter{\the\@temptokena \, d#1}%
\ifx\\#2\\
\else
\def\@tempb{\@gobble}%
\@for\@tempa:=#2\do{%
\expandafter\derivative@aux@ii\@tempa{#1}%
}%
\@temptokena\expandafter\expandafter\expandafter
{\expandafter\the\expandafter\@temptokena\expandafter^\expandafter{\@tempb}}%
\fi
}
\newcommand{\derivative@aux@ii}[2]{%
\ifintegerTF{#1}
{%
\toks@\expandafter{\the\toks@ + #1}%
\@tempswafalse
}%
\protected@edef\@tempb{\@tempb + #1}%
}

\begin{document}

$\derivative{x}{{y}{2},{z}{3}}$

$\derivative{x}{{y}{m},{z}{n}}$

$\derivative{x}{{v}{3},{w}{k,2},y,{z}{m}}$

\end{document}


The key idea is to set a flag to indicate that there are non-numerical index values, and use that flag to then determine how to construct the output.

(If there is interest, I think a LaTeX3 version of this will be somewhat more readable: we don't have an integer test there but the various expansion issues would be easier to solve.)

-
This is nice! But in the second two examples, shouldn't the numerators be d^{m+n}x and d^{m+k+6}x? Also, it would be great to be able to handle, for example, k-2 instead of k+2 in the third example. (Finally, I'd use \partial instead of d, but that's pretty trivial). –  rogerl Mar 6 '13 at 14:35
@rogerl I wondered about both of those points, but according to the 'reference' version in the question it seems that is not what is being asked for. My aim was to produce what the questioner wanted, quite apart from any mathematical interpretation! –  Joseph Wright Mar 6 '13 at 14:38
Very nice! Sticking to traditional LaTeX was a choice born of ignorance, rather than preference, and, if you have the time and inclination, a solution made using more advanced techniques would also be appreciated. Sorry about the typo in placing the superscripts on the variables instead of the "d"s in the numerators of the examples. –  Stirling Mar 7 '13 at 0:24
@Joseph Wright Very helpful!! A request (I couldn't get it to work), could one use the last argument as an optional point of evaluation, like \left|_{#9} \right. kind of thing? –  nate Oct 22 '13 at 20:02

I think that LuaTeX is ideally suited for such tasks. Here is a proof of concept solution in ConTeXt (to translate to LuaLaTeX, you also need to port utilities.parsers.settings_to_array function; see util-prs.lua file in the ConTeXt tree for implementation details of this function)

\startluacode
thirddata = thirddata or {}
-- The pairs() iterator in lua does not guarantee the order in which
-- keys are accessed. So, instead of directly using settings_to_list
-- I use a roundabout iterator.
local settings_to_array = utilities.parsers.settings_to_array

local format = string.format
local split  = string.split

function thirddata.partialD(settings)
local list = settings_to_array(settings)

local sum = 0
local num = {}
local den = {}

for i = 1, #list do
local s = split(list[i], "=")
local key, value = s[1], s[2]

local n = tonumber(value)

if n ~= nil then
sum = sum + n
else
num[#num + 1] = value
end

den[i] = format("\\partial %s^{%s}", key, value)
end

num[#num + 1] = sum
num = table.concat(num, "+")
den = table.concat(den)

num  = format("\\partial^{%s}", num)

context.dfrac( num, den)
end
\stopluacode

\def\partialD%
{\dosingleargument\dopartialD}

\unprotected\def\dopartialD[#1]{\ctxlua{thirddata.partialD(\!!bs#1\!!es)}}

\enablemode[lmmath]

\starttext
\startTEXpage[offset=3mm]
$\partialD[u=m, x=1, y=2, z=n]$
\stopTEXpage
\stoptext


which gives

-