%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% mrecog.tex %%%%% mrecog.sty %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Mathmode control-sequence recognition for TeX/LaTeX
%
% Version 0.1 (Beta test version)
% Last revised: June 26, 1990
%
% Author: Robert H. Wentworth (rhw@hoh-1.att.com)
%
% (C) Copyright 1990 Robert H. Wentworth
%
% Description:
%	When this file is included in a TeX or LaTeX file,
%	(via \input or as a *.sty file) "command sequence recognition"
%	is activated for all text appearing in math mode.
%	What this means is that any consecutive sequence of two or more
%	letters delimited by nonletters will be checked to see if it is
%	the name of a currently-defined control sequence, and if it is
%	then the sequence of letters will be replaced by the corresponding
%	control sequence.  The intent is to render equations more
%	readable by eliminating the need for explicit escape characters
%	(usually backslashes).
%
% Examples:
%	The following samples expand as if backslashes were inserted
%	in appropriate spots:
%
%		It is obvious that
%		$$ f(x) = (a times b)
%		int_0^{infty} g(x) cos(pi log phi)\,d phi $$
%
%		Note that ``theta'' is not recognized but $theta$ is.
%
%		\def\cis(#1){cos(#1) + i{}sin(#1)}
%		$$e^{i theta} = cis(theta) qquad \hbox{for $theta$ real}$$
%
% Details:
%	Command sequences with explicit escapes (backslashes) will	
%	continue to be recognized in the normal way.
%
%	Single letters are not recognized as command sequences; to type
%	a command sequence whose name is a single letter an explicit
%	escape (backslash) should be used (e.g., $\j$ yields a j without
%	a dot, but $j$ does not).
%
%	Whitespace (spaces, tabs, returns) may delimit letter-sequences.
%	Thus if a sequence of letters which should be interpreted literally
%	is in danger of being recognized as a control sequence, this can
%	be avoided by inserting a space (or {}) into the sequence
%	(e.g., $div$ yields a division sign, but $d i v$ or $di{}v$ does not).
%
%       If the count variable \tracingrecognition is set to a positive number
%	then information regarding what command sequences have been
%	recognized will be printed to the terminal and the log file.
%	This is useful for debugging.
%
%	There should be no effect outside mathmode (unless a symbolic
%	name is used which conflicts with names used in this file;
%	an attempt has been made to minimize the likelihood of this.)
%	Active letters cannot be used without conflicting with the
%	workings of this file, and whitespace must be defined in the
%	usual way within mathmode.
%
%	Recognition can be turned off/on by either of two mechanisms:
%
%		\dorecognition=0 \dorecognition=1
%			This turns recognition off/on very quickly,
%			but some processing overhead continues to
%			be present even when recognition is off;
%			some complicated mathmode macros which object to
%			the use of active letters might be interfered
%			with even when recognition is off.
%			This mechanisim affects only the current
%			group unless a \global assignment is used.
%
%		\deactivatemathletters \activatemathletters
%			These require somewhat more processing to
%			turn recognition off or on, but when
%			recognition is off mathmode is more
%			nearly in its native state, so that even
%			most complicated mathmode macros should
%			function properly.  This mechanism has
%			global effects.
%
%	Recognition is initially on.
%
%	Recognition is recursive.  Thus text generated by macros inside
%	mathmode will itself be scanned for recognizable control sequence
%	names.
%
%	The use of the recognition feature will slow down the processing
%	of equations somewhat, but the additional computations done are
%	linear in the amount of mathmode letter-text scanned, and the
%	memory used is more-or-less constant, so pathological slowdowns
%	or memory overflows are not expected.
%
% Known limitations:
%
%	Command sequences whose names are followed by spaces which
%	precede arguments or syntactically significant tokens will
%	not work properly unless explicitly escaped.  Typically
%	these macros are not part of the natural flow of the
%	equation anyway, so the use of explicit escapes (backslashes)
%	is not particularly objectionable.
%	(This was a design tradeoff.  These could have been made to
%	work, but with the unpleasant side-effect that the sequence
%	\def\cat{dog}\def\dogflea{mouse} $cat flea$ would expand
%	to $mouse$; i.e., the space would only act as a delimiter
%	during the first evaluation.)
%	Examples: use $\hbox to 1in{...}$ rather than $hbox to 1in{...}$;
%	or use $hskip1in etc.$ or $\hskip 1in etc.$ rather than
%	$hskip 1in etc.$.
%
%	The recursive nature of the recognition can cause problems
%	unless one is careful to prevent them.  For example,
%	\def\dog{{\it dog}} $dog$ causes an infinite recursion.
%	Special macros are defined in this file that can be used
%	to prevent such recursion in simple macros:
%
%		\norecogwithin{\dog} will turn off recognition within future
%		expansions of \dog; note that \dog expands in a group, and
%		hence some side-effects will only be local; macro should only
%		be used for macros without arguments.
%
%		\norecogafter{\it} will turn off recognition prior to any
%		subsequent expansion of \it; note that recognition will
%		continue to stay off until local group containing \it
%		ends or \dorecognition=1 occurs.  Recognition is turned
%		off only when \it occurs in mathmode.
%
%	To prevent infinite recursion in common command sequences like
%	\sin, \cos, etc., this file declares \norecogafter{\rm}.
%	This redefines \rm (in a relatively minor way).  The original
%	definition of \rm can be restored using \let\rm=\originalrm.
%
%	In general recursive recognition is awkward to make practical
%	use of.  (Recursive evaluation is a side-effect of the implementation
%	and isn't a priori desirable.)  There are various hazards having to do
%	with differences between the state of letters and spaces under various
%	circumstances.  In a typical problem, the sequence
%		\def\dog#1{sin #1} $dog{theta}$
%	expands to $sintheta$ rather than $\sin\theta$ because the space in
%	the definition of \dog is an ordinary space which does not serve as
%	a recognition-delimiter.  Moving the definition inside mathmode
%	doesn't work either, because the letters of space gets scanned as
%	an ordinary space. (Spaces are modified only when they are first
%	scanned as a token following a letter-sequence which is a
%	candidate for recognition.)  The example works for \dog defined by
%	\def\dog#1{sin{}#1} or \def\dog{\sin#1}.
%
% Improvements/comments:
%	The author would appreciate hearing about any positive or negative
%	experiences people may experience in using this feature, and also
%	about any improvements others may make.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% allow private names using @ in such a way that prior state can be restored.
% this should permit file to be used either as a *.sty file or as a simple
% \input file.
\newif\ifatsignwasaletter
\ifcat @a
    \atsignwasalettertrue
\else
    \atsignwasaletterfalse
    \catcode`\@=11
\fi
 
% change mathcodes to activate letters in mathmode
\def\activatemathletters{%
\begingroup
\def\doallletters{\do{a}\do{b}\do{c}\do{d}\do{e}\do{f}\do{g}\do{h}\do{i}\do{j}
\do{k}\do{l}\do{m}\do{n}\do{o}\do{p}\do{q}\do{r}\do{s}\do{t}\do{u}\do{v}
\do{w}\do{x}\do{y}\do{z}\do{A}\do{B}\do{C}\do{D}\do{E}\do{F}\do{G}\do{H}
\do{I}\do{J}\do{K}\do{L}\do{M}\do{N}\do{O}\do{P}\do{Q}\do{R}\do{S}\do{T}
\do{U}\do{V}\do{W}\do{X}\do{Y}\do{Z}\relax}
\def\do##1{\global\mathcode`##1="8000}
\doallletters
\endgroup}
\activatemathletters
 
% set up command to permit deactivation
\def\deactivatemathletters{%
\global\mathcode`A="7141\global\mathcode`B="7142\global\mathcode`C="7143
\global\mathcode`D="7144\global\mathcode`E="7145\global\mathcode`F="7146
\global\mathcode`G="7147\global\mathcode`H="7148\global\mathcode`I="7149
\global\mathcode`J="714A\global\mathcode`K="714B\global\mathcode`L="714C
\global\mathcode`M="714D\global\mathcode`N="714E\global\mathcode`O="714F
\global\mathcode`P="7150\global\mathcode`Q="7151\global\mathcode`R="7152
\global\mathcode`S="7153\global\mathcode`T="7154\global\mathcode`U="7155
\global\mathcode`V="7156\global\mathcode`W="7157\global\mathcode`X="7158
\global\mathcode`Y="7159\global\mathcode`Z="715A\global\mathcode`a="7161
\global\mathcode`b="7162\global\mathcode`c="7163\global\mathcode`d="7164
\global\mathcode`e="7165\global\mathcode`f="7166\global\mathcode`g="7167
\global\mathcode`h="7168\global\mathcode`i="7169\global\mathcode`j="716A
\global\mathcode`k="716B\global\mathcode`l="716C\global\mathcode`m="716D
\global\mathcode`n="716E\global\mathcode`o="716F\global\mathcode`p="7170
\global\mathcode`q="7171\global\mathcode`r="7172\global\mathcode`s="7173
\global\mathcode`t="7174\global\mathcode`u="7175\global\mathcode`v="7176
\global\mathcode`w="7177\global\mathcode`x="7178\global\mathcode`y="7179
\global\mathcode`z="717A\relax}
 
% set up definitions for active uppercase characters
{\def\\{A}\catcode`A=\active\xdefA{\noexpand\dolett@r{\\}{\mathchar"7141}}}
{\def\\{B}\catcode`B=\active\xdefB{\noexpand\dolett@r{\\}{\mathchar"7142}}}
{\def\\{C}\catcode`C=\active\xdefC{\noexpand\dolett@r{\\}{\mathchar"7143}}}
{\def\\{D}\catcode`D=\active\xdefD{\noexpand\dolett@r{\\}{\mathchar"7144}}}
{\def\\{E}\catcode`E=\active\xdefE{\noexpand\dolett@r{\\}{\mathchar"7145}}}
{\def\\{F}\catcode`F=\active\xdefF{\noexpand\dolett@r{\\}{\mathchar"7146}}}
{\def\\{G}\catcode`G=\active\xdefG{\noexpand\dolett@r{\\}{\mathchar"7147}}}
{\def\\{H}\catcode`H=\active\xdefH{\noexpand\dolett@r{\\}{\mathchar"7148}}}
{\def\\{I}\catcode`I=\active\xdefI{\noexpand\dolett@r{\\}{\mathchar"7149}}}
{\def\\{J}\catcode`J=\active\xdefJ{\noexpand\dolett@r{\\}{\mathchar"714A}}}
{\def\\{K}\catcode`K=\active\xdefK{\noexpand\dolett@r{\\}{\mathchar"714B}}}
{\def\\{L}\catcode`L=\active\xdefL{\noexpand\dolett@r{\\}{\mathchar"714C}}}
{\def\\{M}\catcode`M=\active\xdefM{\noexpand\dolett@r{\\}{\mathchar"714D}}}
{\def\\{N}\catcode`N=\active\xdefN{\noexpand\dolett@r{\\}{\mathchar"714E}}}
{\def\\{O}\catcode`O=\active\xdefO{\noexpand\dolett@r{\\}{\mathchar"714F}}}
{\def\\{P}\catcode`P=\active\xdefP{\noexpand\dolett@r{\\}{\mathchar"7150}}}
{\def\\{Q}\catcode`Q=\active\xdefQ{\noexpand\dolett@r{\\}{\mathchar"7151}}}
{\def\\{R}\catcode`R=\active\xdefR{\noexpand\dolett@r{\\}{\mathchar"7152}}}
{\def\\{S}\catcode`S=\active\xdefS{\noexpand\dolett@r{\\}{\mathchar"7153}}}
{\def\\{T}\catcode`T=\active\xdefT{\noexpand\dolett@r{\\}{\mathchar"7154}}}
{\def\\{U}\catcode`U=\active\xdefU{\noexpand\dolett@r{\\}{\mathchar"7155}}}
{\def\\{V}\catcode`V=\active\xdefV{\noexpand\dolett@r{\\}{\mathchar"7156}}}
{\def\\{W}\catcode`W=\active\xdefW{\noexpand\dolett@r{\\}{\mathchar"7157}}}
{\def\\{X}\catcode`X=\active\xdefX{\noexpand\dolett@r{\\}{\mathchar"7158}}}
{\def\\{Y}\catcode`Y=\active\xdefY{\noexpand\dolett@r{\\}{\mathchar"7159}}}
{\def\\{Z}\catcode`Z=\active\xdefZ{\noexpand\dolett@r{\\}{\mathchar"715A}}}
 
% set up definitions for active uppercase characters
\begingroup
\let\CATCODE=\catcode \let\GDEF=\gdef \def\DOLETT@R{\noexpand\dolett@r}
\def\MATHCHAR{\mathchar} \let\ACTIVE=\active
\let\XDEF=\xdef \let\DEF=\def
{\DEF\\{a}\CATCODE`a=\ACTIVE\XDEFa{\DOLETT@R{\\}{\MATHCHAR"7161}}}
{\DEF\\{b}\CATCODE`b=\ACTIVE\XDEFb{\DOLETT@R{\\}{\MATHCHAR"7162}}}
{\DEF\\{c}\CATCODE`c=\ACTIVE\XDEFc{\DOLETT@R{\\}{\MATHCHAR"7163}}}
{\DEF\\{d}\CATCODE`d=\ACTIVE\XDEFd{\DOLETT@R{\\}{\MATHCHAR"7164}}}
{\DEF\\{e}\CATCODE`e=\ACTIVE\XDEFe{\DOLETT@R{\\}{\MATHCHAR"7165}}}
{\DEF\\{f}\CATCODE`f=\ACTIVE\XDEFf{\DOLETT@R{\\}{\MATHCHAR"7166}}}
{\DEF\\{g}\CATCODE`g=\ACTIVE\XDEFg{\DOLETT@R{\\}{\MATHCHAR"7167}}}
{\DEF\\{h}\CATCODE`h=\ACTIVE\XDEFh{\DOLETT@R{\\}{\MATHCHAR"7168}}}
{\DEF\\{i}\CATCODE`i=\ACTIVE\XDEFi{\DOLETT@R{\\}{\MATHCHAR"7169}}}
{\DEF\\{j}\CATCODE`j=\ACTIVE\XDEFj{\DOLETT@R{\\}{\MATHCHAR"716A}}}
{\DEF\\{k}\CATCODE`k=\ACTIVE\XDEFk{\DOLETT@R{\\}{\MATHCHAR"716B}}}
{\DEF\\{l}\CATCODE`l=\ACTIVE\XDEFl{\DOLETT@R{\\}{\MATHCHAR"716C}}}
{\DEF\\{m}\CATCODE`m=\ACTIVE\XDEFm{\DOLETT@R{\\}{\MATHCHAR"716D}}}
{\DEF\\{n}\CATCODE`n=\ACTIVE\XDEFn{\DOLETT@R{\\}{\MATHCHAR"716E}}}
{\DEF\\{o}\CATCODE`o=\ACTIVE\XDEFo{\DOLETT@R{\\}{\MATHCHAR"716F}}}
{\DEF\\{p}\CATCODE`p=\ACTIVE\XDEFp{\DOLETT@R{\\}{\MATHCHAR"7170}}}
{\DEF\\{q}\CATCODE`q=\ACTIVE\XDEFq{\DOLETT@R{\\}{\MATHCHAR"7171}}}
{\DEF\\{r}\CATCODE`r=\ACTIVE\XDEFr{\DOLETT@R{\\}{\MATHCHAR"7172}}}
{\DEF\\{s}\CATCODE`s=\ACTIVE\XDEFs{\DOLETT@R{\\}{\MATHCHAR"7173}}}
{\DEF\\{t}\CATCODE`t=\ACTIVE\XDEFt{\DOLETT@R{\\}{\MATHCHAR"7174}}}
{\DEF\\{u}\CATCODE`u=\ACTIVE\XDEFu{\DOLETT@R{\\}{\MATHCHAR"7175}}}
{\DEF\\{v}\CATCODE`v=\ACTIVE\XDEFv{\DOLETT@R{\\}{\MATHCHAR"7176}}}
{\DEF\\{w}\CATCODE`w=\ACTIVE\XDEFw{\DOLETT@R{\\}{\MATHCHAR"7177}}}
{\DEF\\{x}\CATCODE`x=\ACTIVE\XDEFx{\DOLETT@R{\\}{\MATHCHAR"7178}}}
{\DEF\\{y}\CATCODE`y=\ACTIVE\XDEFy{\DOLETT@R{\\}{\MATHCHAR"7179}}}
{\DEF\\{z}\CATCODE`z=\ACTIVE\XDEFz{\DOLETT@R{\\}{\MATHCHAR"717A}}}
\endgroup
 
% allocate registers and initialize
\newtoks\cod@toks
\newtoks\lett@rtoks
\newcount\tracingrecognition
\newcount\dorecognition
\newcount\readyneww@rd
\newcount\charsinw@rd
\tracingrecognition=0
\dorecognition=1
\readyneww@rd=1
 
% set up spaces so that if \mak@spacesordin@ry is declared the next whitespace
% character (space, tab, return) will be an ordinary nonletter character.
% effect is undone by \restor@regularspaces
 
\def\mak@spacesordin@ry{%
\catcode`\ =12\catcode`\^^I=12\catcode`\^^M=12\relax}
 
\def\restor@regularspaces{\catcode`\ =10\catcode`\^^I=10\catcode`\^^M=5\relax}
 
% macro to process a letter in mathmode: save forms of letter on
% appropriate token lists, and take appropriate action if letter
% is the first or last in a word
\def\dolett@r#1#2{\ifodd\dorecognition
        \ifodd\readyneww@rd\beginmathw@rd\fi
        \edef\worddef##1{##1={\the\cod@toks#2}}\worddef\cod@toks
        \edef\worddef##1{##1={\the\lett@rtoks\noexpand#1}}\worddef\lett@rtoks
        \advance\charsinw@rd by 1
	\let\enddolett@r=\rec@gnitionenddolett@r
    \else
        \def\enddolett@r{#2}\fi
    \enddolett@r}
\def\rec@gnitionenddolett@r{\futurelet\n@xttok@n\ch@ckn@xttok@n}
 
% macro to decide whether or not next token is special case:
% if open-brace or close-brace follows, simply terminate word;
% otherwise do more extensive processing which involves
% slightly more "destructive" processing on the next token (in that it
% becomes a macro argument).
\def\ch@ckn@xttok@n{\def\trailing@cs{}\ifx\n@xttok@n\bgroup
        \simpl@endw@rd\else
        \ifx\n@xttok@n\egroup
            \simpl@endw@rd\else
            \def\fin@l@cs{\ch@ckn@xtargum@nt}\fi
    \fi
    \fin@l@cs}
 
% macro to terminate word without messing with subsequent tokens
\def\simpl@endw@rd{\def\fin@l@cs{\endmathw@rd\trailing@cs}}
 
% macro to see if next token is a letter; if not, terminates word
\def\ch@ckn@xtargum@nt#1{\ifcat\noexpand#1a\else
        \endmathw@rd\fi
    \trailing@cs#1}
 
% macro to do initialization needed at the beggining of a new word
\def\beginmathw@rd{\readyneww@rd=0
    \charsinw@rd=0
    \cod@toks={}\lett@rtoks={}\mak@spacesordin@ry}
 
% macro to do appropriate processing at the end of a word
\def\endmathw@rd{\restor@regularspaces
    \readyneww@rd=1
    % ready to start new word (new word could be generated by control sequence)
    \ifnum\charsinw@rd=1
        \the\cod@toks % don't recognize single letters as control sequences
    \else
        \expandafter\ifx\csname\the\lett@rtoks\endcsname\relax
            \the\cod@toks
        \else \expandafter\def\expandafter\trailing@cs\expandafter
	    {\csname\the\lett@rtoks\endcsname}\ifnum
	    \tracingrecognition>0
		\immediate\write16{{Recognized math sequence: \expandafter
		\string\csname\the\lett@rtoks\endcsname}}\fi
	\fi
    \fi}
 
% macros to block excessive recognition
 
% redefine macro to turn off recognition, then expand
\def\norecogafter#1{{\let\t@mp@@@=#1%
\xdef#1{\noexpand\ifmmode\dorecognition=0\noexpand\fi\t@mp@@@}}}
 
% redefine argumentless macro to turn off recognition only while it expands
% expansion is done within a group (so side-effects are only local unless
% explicitly global)
\def\norecogwithin#1{{\let\t@mp@@@=#1%
\xdef#1{\begingroup\dorecognition=0\t@mp@@@\endgroup}}}
 
% set up \rm so that it disables subsequent recognition
\let\originalrm=\rm
\norecogafter{\rm}
 
% attempt to restore prior catcode for @
\ifatsignwasaletter
\else
    % hide private names
    \catcode`@=12
\fi
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
