# Defining arithmetic operators that insert brackets according to usual precedence rules

I have a program that generates bits of Tex code like these:

$\product{a}{\add{b}{c}}\leftrightarrow \add{\product{a}{b}}{\product{a}{c}}$
$\add{a}{\add{b}{c}}\leftrightarrow \add{\add{a}{b}}{c}$
$\product{a}{b}\leftrightarrow \product{b}{a}$
$\product{a}{\product{b}{c}}\leftrightarrow \product{\product{a}{b}}{c}$
$\subtract{\power{x}{\two}}{\power{y}{\two}}\leftrightarrow \product{\add{x}{y}}{\subtract{x}{y}}$


At the moment, I have defined

\newcommand\add[2]{({#1}+{#2})}
\newcommand\subtract[2]{({#1}-{#2})}
\newcommand\product[2]{({#1}{#2})}


But this results in far too many brackets being produced -- for example \sum{\product{a}{b}}{c} is rendered as ((ab)+c).

How can I define \add, \product and other arithmetic operations so that the minimum number of necessary brackets are added? Just to clarify, I want \product{a}{\add{b}{c}} to generate a(b+c), but \sum{\product{a}{b}}{c} to produce ab + c.

NB. If it was straightforward to do this in the code that generated the TeX, I would be doing so!

-
From prefix form to infix form with the usual conventions about precedence? I surely wouldn't undertake the task. ;-) – egreg Feb 19 '14 at 23:26
I've done it in C++ in the past. (Currently using Haskell, where the key problem is that sum, etc. are stored purely as data.) At heart, this is a rendering issue and it would be very nice if it could be solved once and for all in a rendering language. But I have no idea how to start with the tools available in TeX... – Mohan Feb 19 '14 at 23:36
David Carlisle came up with an absolutely brilliant solution, but jfbu's tweak to it is in technical terms a clear improvement. Which should I accept? – Mohan Feb 20 '14 at 17:38

Probably I don't have the precedence rules exactly as you need, but something like

\def\p{0}

\def\power#1#2{%
\ifnum\p>20(\fi
{\def\p{20}#1}^{\def\p{0}#2}%
\ifnum\p>20)\fi}

\def\product#1#2{%
\ifnum\p>20(\fi
{\def\p{20}#1#2}%
\ifnum\p>20)\fi}

\ifnum\p>10(\fi
{\def\p{10}#1+#2}%
\ifnum\p>10)\fi}

\def\subtract#1#2{%
\ifnum\p>8(\fi
{\def\p{9}#1-#2}%
\ifnum\p>8)\fi}

\def\two{2}

$\product{a}{\add{b}{c}}\leftrightarrow \add{\product{a}{b}}{\product{a}{c}}$

$\add{a}{\add{b}{c}}\leftrightarrow \add{\add{a}{b}}{c}$

$\product{a}{b}\leftrightarrow \product{b}{a}$

$\product{a}{\product{b}{c}}\leftrightarrow \product{\product{a}{b}}{c}$

$\subtract{\power{x}{\two}}{\power{y}{\two}}\leftrightarrow \product{\add{x}{y}}{\subtract{x}{y}}$

$\subtract{a}{\subtract{b}{c}}$

$\subtract{\subtract{a}{b}}{c}$

\bye

-
Magnificent!!!! – Steven B. Segletes Feb 20 '14 at 0:26
Absolutely beautiful. Thank you. – Mohan Feb 20 '14 at 0:27
@Mohan I just updated to fix a-b-c – David Carlisle Feb 20 '14 at 0:28
$\subtract{\subtract{\subtract{a}{b}}{c}}{d}$ generates ((a − b) − c) − d but the minimal representation would be a-b-c-d. – jfbu Feb 20 '14 at 14:22
and $\add{a}{\subtract{b}{c}}$ generates a + (b -c) where a + b - c is the minimal representation. – jfbu Feb 20 '14 at 14:29

This answer is initially motivated from David's answer. But to address the issues I raised in the comments a different perspective is needed.

I have not thoroughly tested the code does in all circumstances what is hoped for. The aim is to use as few parentheses as possible.

Update: the sentence about a different perspective is not quite exact. I started with a different perspective but in the end, looking at the result a bit later, I see that the code is only a slight evolution of David's answer. I have thus rewritten it in a style closer to that answer.

\def\p{0}

\def\power #1#2{%
\ifnum\p>3(\fi
{\def\p{4}#1}^{\def\p{0}#2}%
\ifnum\p>3)\fi
}

\def\product #1#2{%
\ifnum\p>2(\fi
{\def\p{2}#1#2}% perhaps #1\cdot #2 would be better
\ifnum\p>2)\fi
}

\ifnum\p>1(\fi
{\def\p{0}#1+#2}%
\ifnum\p>1)\fi
}

\def\subtract #1#2{%
\ifnum\p>0(\fi
{\def\p{0}#1-\def\p{2}#2}%
\ifnum\p>0)\fi
}

\def\two{2}

$\product{a}{\add{b}{c}}\leftrightarrow \add{\product{a}{b}}{\product{a}{c}}$

$\add{a}{\product{b}{c}}$

$\add{a}{\product{b}{\subtract{c}{d}}}$

$\add{a}{\add{b}{c}}\leftrightarrow \add{\add{a}{b}}{c}$

$\product{a}{b}\leftrightarrow \product{b}{a}$

$\product{a}{\product{b}{c}}\leftrightarrow \product{\product{a}{b}}{c}$

$\subtract{\power{x}{\two}}{\power{y}{\two}}\leftrightarrow \product{\add{x}{y}}{\subtract{x}{y}}$

$\subtract{a}{\subtract{b}{c}}$

$\subtract{\subtract{a}{b}}{c}$

$\product{a}{\add{b}{c}}$

$\add{\product{a}{b}}{c}$

$\subtract{a}{\subtract{b}{\subtract{c}{d}}}$

$\subtract{\subtract{\subtract{a}{b}}{c}}{d}$

$\add{a}{\subtract{b}{c}}$

$\subtract{\add{a}{b}}{\add{c}{d}}$

$\add{\subtract{\add{a}{b}}{\add{c}{d}}}{\add{e}{f}}$

$\power{x}{\power{y}{z}}$

$\power{\power{x}{y}}{z}$

$\power{x}{\add{y}{z}}$

$\power{x}{\power{y}{\add{z}{w}}}$

$\subtract{\power{x}{\product{\power{y}{\add{z}{w}}}{\subtract{z}{w}}}}{\subtract{d}{e}}$

\nopagenumbers
\bye


How I wrote it first: (I had something more general in mind for the branch contents, but in the end they differ only in the presence of ( and ))

\catcode@ 11
\long\def\@firstoftwo #1#2{#1}
\long\def\@secondoftwo #1#2{#2}

\def\power #1#2{%
\ifnum\p>3 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{{({\def\p{4}#1}^{\def\p{0}#2})}}{{\def\p{4}#1}^{\def\p{0}#2}}}

\def\product#1#2{%
\ifnum\p>2 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{{(\def\p{2}#1#2)}}{{\def\p{2}#1#2}}}

\ifnum\p>1 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{{(\def\p{0}#1+#2)}}{{\def\p{0}#1+#2}}}

\def\subtract#1#2{%
\ifnum\p>0 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{{(\def\p{0}#1-\def\p{2}#2)}}{{\def\p{0}#1-\def\p{2}#2}}}

\catcode@ 12


-
Am I right in thinking the only change from David Carlisle's answer is that the numerical parameters have been changed? – Mohan Feb 20 '14 at 17:13
it's a bit more for \subtract (\p is changed at two locations and goes up to multiplication in a way) and also \power (the first \p changes in the opposite direction). As a result (((a-b)-c)-d) and a+(b-c) are correctly stripped of parentheses. – jfbu Feb 20 '14 at 17:22
and $\power{\power{\power{x}{y}}{z}}{t}$ is correctly handled to output ((x^y)^z)^t. – jfbu Feb 20 '14 at 17:29