# The trestle problem: how to avoid >=< in the output

TeX puts no space between \mathrel characters, so one can type := to make a definition. But careless authors often type stuff like

< a, b > = < c, d >


to indicate that two scalar products are equal, and get the central three characters stuck together with no space around the equality sign. (I do tell them to use \langle and \rangle, fat lot of good it does.) Is there any clever way to override the \mathrel convention, at least in this instance, so that the equality sign is separated from the others, but remains a math relation character?

-
I feel your pain :{ –  David Z Aug 19 '10 at 5:09
What is your relation to these authors? Are you writing a package, or editing a publication? –  Charles Stewart Aug 19 '10 at 6:16
OT: Instead of := one should really use \coloneqq from mathtools because the output of \coloneqq is vertically symmetric. –  Caramdir Aug 19 '10 at 10:09

## 8 Answers

The trick is to store the list of all < and > appearing in the document inside the aux file, and use it in the second run to decide what should be < and >, and what should be \left\langle and \right\rangle.

The solution is a bit long, sorry. See the comments inline.

\makeatletter
% We could probably add some customization here.
%
% < and > as a relation or as a delimiter
\mathchardef\lt@relation=\mathcode\<
\mathchardef\ltgt@bar@relation=\mathcode\|
\mathchardef\gt@relation=\mathcode\>
% Note: \ltgtstep and \ltgtunstep are needed because of the
% \left and \right. Also note that their placement (inside the group)
% is critical.
\def\lt@delimiter{\left\langle\ltgtstep}
\def\ltgt@bar@delimiter{\middle|}
\def\gt@delimiter{\ltgtunstep\right\rangle}
% < and > revert to the relation symbol if the .aux
% disagrees with what we see in the current run.
\let\lt@error@relation\lt@relation
\let\ltgt@bar@error@relation\ltgt@bar@relation
\let\gt@error@relation\gt@relation
\let\lt@error@delimiter\lt@relation
\let\ltgt@bar@error@delimiter\ltgt@bar@relation
\let\gt@error@delimiter\gt@relation

% As in other solutions, we make < and > active in math mode.
% The corresponding control sequences have been defined above.
\begingroup
\catcode\<=\active
\catcode\|=\active
\catcode\>=\active
\gdef<{\lt@active}
\gdef|{\ltgt@bar@active}
\gdef>{\gt@active}
\endgroup
\mathcode\<="8000
\mathcode\|="8000
\mathcode\>="8000

% ===================

% The above commands will be called via
%   \csname lt@\ltgt@error@\ltgt@type\endcsname
% where \ltgt@error@ is {} by default and can be {error@}, and
% where \ltgt@type is {relation} or {delimiter}.
\gdef\ltgt@error@{}
\def\ltgt@type{relation}

% \ltgt@list will hold our list of "<", ">", "|". Each time we append,
% we check that the symbol agrees with the corresponding one from the
% .aux file. If not, we fall back on the error mode.
\gdef\ltgt@list{}
\def\ltgt@append#1{%
\xdef\ltgt@list{\ltgt@list#1}%
\ltgt@prev@pop%
\unless\ifx\ltgt@prev@head#1%
\gdef\ltgt@error@{error@}%
\fi%
}
% We pop the list from the .aux file as we construct the new list.
\def\ltgt@prev@pop{\expandafter\ltgt@prev@pop@aux\ltgtprevlist\relax\relax}
\def\ltgt@prev@pop@aux#1#2\relax{%
\xdef\ltgtprevlist{#2}%
\ifx#1\relax%
\global\let\ltgt@prev@head\relax%
\else%
\global\let\ltgt@prev@head#1%
\fi}

% To take care of grouping
\def\ltgt@append@open{%
\loop
\ifnum\ltgt@depth<\currentgrouplevel
\ltgt@append{(}%
\global\advance \ltgt@depth by 1\relax
\def\ltgt@type{relation}%
\repeat
}
\def\ltgt@append@close{%
\loop
\ifnum\ltgt@depth>\currentgrouplevel
\ltgt@append{)}%
\global\advance \ltgt@depth by -1\relax
\aftergroup\ltgt@append@close
\repeat}

% We will later \let<\lt@active and \let>\gt@active. For now, we just
% define these commands. Each has two pieces: first fill the \ltgt@list,
% putting many "|" to ensure that different groups are really separated
% by at least one "|". Second, typeset the correct symbol depending on
% what can be read from the prevlist (extracted from the .aux file).
\newcount\ltgt@depth
\def\ltgtstep{\global\advance\ltgt@depth by 1\relax}
\def\ltgtunstep{\global\advance\ltgt@depth by -1\relax}
\def\ltgt@openclose{%
\aftergroup\ltgt@append@close%
\unless\ifnum\ltgt@depth=\currentgrouplevel%
%\global\ltgt@depth\currentgrouplevel%
\ltgt@append@open%
\fi%
}
\def\lt@active{%
% fill the list
\ltgt@openclose%
\ltgt@append{<}%
% typeset
\ltgt@ifnextgt@TF{\def\ltgt@type{delimiter}}{\def\ltgt@type{relation}}%
\csname lt@\ltgt@error@\ltgt@type\endcsname%
}
\def\ltgt@bar@active{%
% fill the list
\ltgt@openclose%
\ltgt@append{|}%
% typeset
\csname ltgt@bar@\ltgt@error@\ltgt@type\endcsname%
}
\def\gt@active{%
% fill the list
\ltgt@openclose%
\ltgt@append{>}%
% typeset
\csname gt@\ltgt@error@\ltgt@type\endcsname%
\def\ltgt@type{relation}%
}

% When we see a <, we use \ltgt@ifnextgt@TF{.t.}{.f.} to test if the
% head of the prevlist is a >. If so, we execute {.t.}, otherwise {.f.}.
\newcount\ltgt@ifnextgt@count
\def\ltgt@ifnextgt@TF{%
\global\ltgt@ifnextgt@count0\relax%
\expandafter\ltgt@ifnextgt@readone\ltgtprevlist\relax\relax%
\expandafter\ltgt@ifnextgt@aux\ltgtprevlist\relax%
}
\def\ltgt@ifnextgt@readone#1{%
%\ltgt@ifnextgt@count
%\@ltgt@ifnextgt@false%
\ifx#1\relax
\expandafter\ltgt@ifnextgt@throw@FT
\fi
\ifx#1(%
\global\advance\ltgt@ifnextgt@count by 1\relax
\fi
\ifx#1)%
\global\advance\ltgt@ifnextgt@count by -1\relax
\fi
\ifnum\ltgt@ifnextgt@count<0\relax % no ">" can be found.
\expandafter\ltgt@ifnextgt@throw@FT
\fi
\ifnum\ltgt@ifnextgt@count=0\relax
\ifx#1<\relax % the first relevant character is not ">"
\expandafter\expandafter\expandafter\ltgt@ifnextgt@throw@FT
\else
\ifx#1>\relax % ">" was found!
\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter\ltgt@ifnextgt@throw@TF
\fi
\fi
\fi
\ltgt@ifnextgt@readone
}
\def\ltgt@ifnextgt@throw@FT#1#{\ltgt@use@FT}
\def\ltgt@ifnextgt@throw@TF#1#{\ltgt@use@TF}

\def\ltgt@ifnextgt@aux#1#2#{% arg #2 delimited by brace, thrown away.
\ifx#1>%
\expandafter\ltgt@use@FTF%
\else%
\ifx#1|%
\expandafter\expandafter\expandafter\ltgt@use@T%
\else%
% \ifx#1(%)
% \expandafter\expandafter\expandafter\expandafter
% \expandafter\expandafter\expandafter\
\expandafter\expandafter\expandafter\ltgt@use@FFT%
\fi%
\fi%
{\ltgt@ifnextgt@aux#2}%
}

\long\def\ltgt@use@T#1{#1}
\long\def\ltgt@use@TF#1#2{#1}
\long\def\ltgt@use@FT#1#2{#2}
\long\def\ltgt@use@FTF#1#2#3{#2}
\long\def\ltgt@use@FFT#1#2#3{#3}

% We put the definition of the relevant list in the .aux file at the end
% of the run. This file is read at \begin{document}.
\AtEndDocument{\write\@auxout{\gdef\noexpand\ltgtprevlist{\ltgt@list}}}
%
% To ensure that \ltgtprevlist is defined in the first run, we do
\let\ltgtprevlist\relax

% Embedding the test example in the package itself (bad idea, but eh...)
\unless\ifx\documentclass\@twoclasseserror

\documentclass{article}
\begin{document}
The middle delimiter now works: $<a^2|x_{\sum_{i>j_1}i}>$, and nesting as well:
$<\frac{<u|v>+<v_1|v_2>}{<v_1|v>} v_1|v > = <u|v> + <v_1|v_2>, \qquad {i<j}, {k>l}. % Note the use of braces to prevent seeing <j,k>.$
How come the end didn't become $i<j, k>l$? because I enclosed each
inequality in braces. Another case where this can be useful is to get
$<{<a,b>} a,b> = <a,b>^2$.

One more test:
$< {\sum |\lambda_i| v_i}| v > = 0$

\end{document}

\fi

-
Can I just clarify what this does? Is the idea that every time you hit < in the input, if the next < or > in the same math environment is the latter then the <...> form is used, otherwise the regular one? That's an amazing hack :) –  Will Robertson Feb 7 '11 at 23:28
@Will: thanks :), it took me a while to get it straight. Replace "the same math environment" by "the same group", and what you said is right (try \sum_{i<j}^{k>l}). Using \aftergroup and checking for eTeX's \currentgrouplevel, I put (many) | between each group. < and > only match if there is nothing in between. To support nesting, we would need to replace | by { and }, and be careful with the number of braces. I'm too lazy for that tonight. –  Bruno Le Floch Feb 7 '11 at 23:36
Splendid! though it goes well beyond the "clever kludge" I asked for. I worried about the | separator for a moment, but then checked that poor man's Dirac notation like $<\alpha x|\alpha y> = |\alpha|^2 <x|y>$ does not confuse the procedure. –  jvarilly Feb 8 '11 at 6:02
@jvarilly: the | is chosen arbitrarily. I guess it wouldn't be hard to also support Dirac's notation (with eTeX's \middle). I'll try to find some time this week. –  Bruno Le Floch Feb 8 '11 at 6:53
@Bruno: No hurry with Dirac notation. For the middle separator I prefer \mathbin\vert so eTeX is not needed. Thanks again. –  jvarilly Feb 8 '11 at 17:52

If you can get them to use any macros for this, then something like

\newcommand*\sp[2]{\langle#1,#2\rangle}


might be the way to go. (Okay, maybe not \sp since that's \let to ^, but something to indicate the scalar product.)

Since you probably don't want to have less than and greater than in your final output and your coauthors aren't likely to change, then you might have to simply take a final pass through and fix their little mistakes. This is what I do.

-
I've used \ip for inner product. –  ShreevatsaR Aug 19 '10 at 6:23
Maybe try \def\tuple<#1,#2>{\langle#1,#2\rangle}? A nice thing about this macro is that it generalises: it is just as natural to use it with more than two arguments, e.g., \tuple<1,2,3>. –  Charles Stewart Oct 21 '10 at 14:04
This is what I actually use when writing my own documents. If I want Dirac notation, I can change the comma in the definition to \mathbin{|}, too. But what I was looking for was a clever kludge to put in the preamble of other people's source code, without having to rewrite the document. –  jvarilly Dec 5 '10 at 4:00

Some authors really want to distinguish the <...> operator from \langle...\rangle. In this case, you can get the spacing right that way:

\newcommand*\diam [1] {\mathopen< #1 \mathclose>}
\newcommand*\scal [1] {\langle #1 \rangle}
% usage: $$\diam{\phi} = \diam{\psi} \neq \scal{\phi, \psi}$$


I'm surprised nobody mentioned that before.

-

I wonder if

\mathchardef\lt=\mathcode\<
\mathchardef\gt=\mathcode\>
{\catcode\<=\active
\catcode\>=\active
\global\let<=\langle
\global\let>=\rangle}
\mathcode\<="8000
\mathcode\>="8000


is too drastic? Now you can type stuff like <u,v>\gt0. (It probably is too drastic, but I couldn't resist the joke.)

-
I like it :) Alternatively, could you just assign a different mathcode to < and > ? –  Will Robertson Oct 21 '10 at 14:36
No, for mathcodes are 15 bit numbers, while \langle and \rangle are \delimiter commands with 27 bit arguments. –  Harald Hanche-Olsen Oct 21 '10 at 14:48
Ah, I wasn't thinking straight—here's what I sort-of meant: \mathchardef\lt=\mathcode\< \mathchardef\gt=\mathcode\> \DeclareMathDelimiter{<} {\mathopen}{symbols}{"68}{largesymbols}{"0A} \DeclareMathDelimiter{>} {\mathclose}{symbols}{"69}{largesymbols}{"0B} –  Will Robertson Oct 22 '10 at 6:37
Nice joke. Of course, having now to convince your (co)authors to use \lt and \gt instead of < and > doesn't really simplify the problem ... –  Hendrik Vogt Oct 22 '10 at 7:16
Actually, it's not far from what I'd like. With some –  jvarilly Dec 5 '10 at 4:01

Even better, from this answer from Lev Bishop on a relevant question, using mathtools you could define:

\DeclarePairedDelimiter\ip{\langle}{\rangle}


And then use \ip{a,b} for your inner products. The great thing is that you also get for free a starred version \ip*{a,b} which will automagically resize the delimiters as needed.

-

Probably the best thing to do is to offer them a macro (package) that makes typing easier.

Now I am a very lazy typist, so I would do something like this:

\def\<#1>{\langle #1\rangle}
$\<a,b> = \<c,d>$


but probably \< is already used for somethingelse in LaTeX?

In LuaTeX, you can actually change the internal math spacing table, like this:

\Umathrelrelspacing\textstyle=\thickmuskip
\Umathrelrelspacing\displaystyle=\thickmuskip


but as you probably cannot use LuaTeX and it has side-effects for predefined relations like :=, I doubt that will help you.

-
\< is used in the tabbing environment. –  Charles Stewart Aug 19 '10 at 6:00
@Charles Stewart: I don't think that's a problem. Simple testing seems to indicate that \< is only defined inside the tabbing environment. So unless one is trying to use \<a,b> inside a tabbing, I think this would work. I didn't test it though. –  TH. Aug 19 '10 at 6:18
@TH. unless one is trying to use \<a,b> inside a tabbing - which doesn't strike me as all that unlikely. You could use something like \everymath to scope the definition, but that's kind of tricky to make stable. –  Charles Stewart Aug 19 '10 at 7:23
@Charles Stewart: I thought about \everymath, but I couldn't recall the exact semantics. I assume \everymath{foo} \everymath{bar} is the same as just \everymath{bar} in which case you'd need to ensure that \everymath isn't used elsewhere, or else redefine \everymath...but it'd be tricky to get it right in all cases. –  TH. Aug 19 '10 at 7:50
@TH. Unless you are the class author, or you code against a particular class, there is no way to be right with confidence: any assignment to the token list might be undone elsewhere. By no coincidence, I've asked a question about this, tex.stackexchange.com/questions/2016/… –  Charles Stewart Aug 19 '10 at 8:27

What about using a regular expression replace in an editor?

s/<$$[^<]*$$,$$[^>]*$$>/\\langle\1,\2\\rangle/g


This converts < a, b > = < c, d > to \langle a, b \rangle = \langle c, d \rangle.

There are bound to be exceptions, without a better regexp that could detect things like whether the string was in a math/displaymath mode. But used interactively (that is, manually confirming each replacement) this could make the job easier.

-
+1, I think that fixing the source is generally more robust than putting workarounds in the Tex macros. But it's not obvious from the qn that this would work for the qner. It's maybe worth tweaking the regex to make sure the < and > aren't in occurences of \< and \>, say in a tabbing environment. –  Charles Stewart Oct 21 '10 at 13:57
@Charles Good point. But I have reached the limits of the regular expressions I can write in five minutes. :-P Once you get into the lookaheads/lookbehinds I start to get confused. –  Matthew Leingang Oct 21 '10 at 14:09
You don't need anything outside the traditional regular language: I think using [^\]<$$[^<]*$$,$$[^>]*$$[^\>]> as the pattern should work, since it is outside \1 and \2 in the replacement text. Note, in sed, this won't match "<" at the beginning of the line. –  Charles Stewart Oct 21 '10 at 15:52
What does the [^] at the beginning match against? Or is there a missing &lt; or backslash? I had thought about matching for "not a backslash" at the beginning but ran into your caveat: you want to match for "a &lt; not preceded by a backslash" instead of "a &lt; preceded by something not a backslash". But I think we're going off on a tangent... –  Matthew Leingang Oct 22 '10 at 11:20

I'm not sure why no one proposed this, but the first idea that came to my mind is to break the mathrel apart:

< a, b > {=} < c, d >


This seems to just do the trick.

-
Because semantically it's all wrong but (more importantly?) it looks ugly. Compare the output using < and \langle` on a document. –  Juan A. Navarro Oct 21 '10 at 15:20
I know, but the same can be said about the original expression, and the question was neither about semantics nor about making it look better. –  Khaled Hosny Oct 21 '10 at 15:23
But if you're going to fix the source, why choose such an inferior fix? –  Charles Stewart Oct 21 '10 at 15:47