%D \module
%D   [       file=t-mathsets,
%D        version=2008-12-06,
%D          title=Math Sets,
%D       subtitle=\CONTEXT\ port of \filename{braket.sty},
%D         author={Aditya Mahajan},
%D          email={adityam [at] umich [dot] edu},
%D           date=\currentdate]
%D
  
%M \usemodule[mathsets] 
%M \setuphead[section]  [page=]
%M \setupbodyfontenvironment[default][em=italic]
%M \loadsetups[t-mathsets.xml]

%D \section Introduction
%D
%D I write a lot of probability expressions which look like this.
%D \startbuffer
%D \startformula
%D \mfunction{E} \left\{ \sum_{y} f(X,y) \,\middle|\, Z \right\}
%D \stopformula
%D \stopbuffer
%D \getbuffer 
%D
%D The usual way to input them is as follows
%D \typebuffer
%D
%D We need to ensure that the delimiters and the {\em conditional} sign \type{|}
%D scale properly, and the spacing around the conditional sign is correct. As a
%D result, the input is markup heavy, and consequently difficult to read.
%D
%D In \LATEX, Donald Arseneau's \filename{braket.sty} can be used to input such
%D expressions in a natural manner, and automatically takes care of the scaling
%D of delimiters and the conditional signs. (The actual package only provides
%D this functionality of bra and ket notation, hence the name, but can be easily
%D extended to probability expressions also. This module is a partial port of
%D \filename{braket.sty} to \CONTEXT.

%D \section Usage
%D
%D To use this module add
%D
%D \starttyping
%D \usemodule[mathsets]
%D \stoptyping
%D 
%D on the top of your file. This module defines one command
%D \type{\definemathset} for defining new math-sets. The syntax of this command
%D is:
%D
%D \setup{definemathset}
%D
%D The first argument is the name of the set to be defined. Thus, after 
%D
%D \starttyping
%D \definemathset[mathset]
%D \stoptyping
%D
%D \type{\mathset} is available as a command. The second argument to
%D \type{\definemathset} are optional assignments \type{text}, \type{left},
%D \type{middle}, \type{right}. For example, if we can use \type{text} to
%D specify what comes at the beginning of the math-set. By default,
%D \type{text=no} which causes no text to appear, but we can change that to any
%D text that we want (Note that \type{\mfunction} tells \CONTEXT\ to use the
%D current math text font)
%D
%D \startbuffer[EXP]
%D \definemathset[EXP] [text=\mfunction{E}]
%D \stopbuffer
%D
%D \typebuffer[EXP] \getbuffer[EXP]
%D
%D We can use \type{\EXP{X}} to get $\EXP{X}$ and \type{\EXP{X|Y}} to get
%D $\EXP{X|Y}$. Scaling of the delimiters and conditional sign are take care
%D automatically. For example
%D
%D \startbuffer
%D \startformula
%D  \EXP{\sum_y f(X,y) | Z }
%D \stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D gives
%D
%D \getbuffer
%D
%D Compare the above input with the one used in the first example.
%D
%D By default, the contents of the set are surrounded by curly brackets (or
%D braces); we can change them by using \type{left} and \type{right} keys. For
%D example.
%D
%D \startbuffer[PR]
%D \definemathset[PR]  [text={\mfunction{Pr}},left=(,right=)]
%D \stopbuffer
%D \startbuffer
%D \startformula
%D    \EXP{ \sum_y f(X,y) | Z = z } = \sum_{x,y} \PR{x,y | Z=z}
%D \stopformula
%D \stopbuffer
%D 
%D \typebuffer[PR] \typebuffer
%D
%D  gives
%D
%D \getbuffer[PR] \getbuffer
%D
%D We also provide a mechanism for changing the conditional bar using the
%D \type{middle} key, although I am not sure if this is needed by anyone. For
%D example, consider the following contrived example
%D
%D \startbuffer
%D \definemathset[VAR][text={\mfunction{Var}}, left=(, right=), middle=\Vert]
%D \startformula
%D    \VAR{f(X,Y) | Y = y }
%D \stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D gives
%D
%D \getbuffer
%D
%D This module also takes care of correct nesting of math-sets, so 
%D \startbuffer
%D \startformula
%D   \EXP{ \sum_{Y} \EXP { \frac{1}{f(X)} | Y } } 
%D \stopformula
%D \stopbuffer
%D \typebuffer gives
%D \getbuffer[EXP] \getbuffer
%D
%D If you do not want some \type{|} to be considered as conditional signs, nest
%D them inside a group \type{{}}. For example, to get 
%D \startbuffer
%D \startformula
%D   \mathset{ x\in {\bf R}^2 | 0<{|x|}<\frac {3}{16} }
%D \stopformula
%D \stopbuffer
%D \getbuffer
%D we typed
%D \typebuffer
%D
%D We can also use limits after the command, for example:
%D
%D \startbuffer
%D \startformula
%D   \EXP_X{F(X, Y) | Y = y } 
%D \stopformula
%D \stopbuffer
%D \typebuffer gives \getbuffer
%D
%D Only one set, \type{\mathset}, is predefined. It is relatively simple
%D to define sets equivalent to those defined in \filename{braket.sty}.
%D
%D \startbuffer
%D \definemathset[BRAKET][left=\langle,right=\rangle]
%D
%D \startformula
%D   \BRAKET{ \phi | \frac{\partial^2}{\partial t^2} | \psi }
%D \stopformula
%D \stopbuffer
%D \typebuffer \getbuffer

%D \section Implementation
%D
%D Most of the ideas are simply a \CONTEXT ified version of the code in
%D \filename{braket.sty}. I mostly used \filename{bracket.sty} to define
%D commands for probability and expectation. So, I have also added the
%D option of declaring such operators using \type{text=no} option for
%D \type|\definemathset|.

\writestatus  {loading}   {ConTeXt Math Sets Module}

\startmodule[mathsets]

\unprotect

%D Since two letter codes are reserved for system modules, and \CONTEXT\
%D seems to be running out of those, I choose a more verbose variable to
%D store options.

\definesystemvariable {mathset}   % Math Set

%D \macros{setupmathset}
%D To specify the default values of text, left, middle, and right delimiters

\def\setupmathset
  {\dosingleargument\getparameters[\??mathset]}

%D \macros
%D    {definemathset}
%D
%D To define a new math set.

\def\definemathset
  {\dodoubleargument\dodefinemathset}


%D Now we define internal macros to take care of the formatting

\let\currentmathset\empty
\let\currentmathsetgrouplevel\empty

\def\mathsetmiddle
  {\ifnum\currentmathsetgrouplevel=\currentgrouplevel
      \expandafter\firstoftwoarguments
    \else
      \expandafter\secondoftwoarguments
    \fi
   {\egroup\,\middle\mathsetparameter\c!middle\,\bgroup}
   {\mathsetparameter\c!middle}}

\def\mathsetparameter#1%
  {\executeifdefined{\??mathset\currentmathset#1}{\executeifdefined{\??mathset#1}\empty}}

\def\dodefinemathset[#1][#2]%
  {\getparameters[\??mathset#1][#2]
   \setvalue{#1}{\dododefinemathset[#1]}}

%D Since \type{|} is already active, we do not have to make it active
%D again.

\def\dododefinemathset[#1]%
  {\begingroup
   \def\currentmathset{#1}
   \edef\currentmathsetgrouplevel{\the\numexpr\currentgrouplevel+2\relax}
   % Not here, else messes subscripts
   % \mathcode`\|32768
   % \let|\mathsetmiddle
   \doifelsenothing{\mathsetparameter\c!text}
      {\dodododefinemathset!notext}
      {\doifelse{\mathsetparameter\c!text}{\v!no}
      {\dodododefinemathset!notext}
      {\docapturemathoplimits\dodododefinemathset!text}}}


\def\setmathmiddle
  {\mathcode`\|32768
   \let|\mathsetmiddle}


%D \type|\docapturemathoplimits| is to capture limits that may follow
%D the text command. This allows the following to work
%D
%D \startbuffer
%D \startformula
%D    \PR^{f,g} {f(X) | g(Y)}
%D \stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D \getbuffer[PR] \getbuffer
%D We need to be a bit careful not to activate \type{|} to soon, as it can also
%D occur in sub- and superscripts. For example
%D \startbuffer
%D \startformula
%D    \EXP_{X|Y}{f(X) | Y = y}
%D \stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D gives
%D
%D \getbuffer[EXP] \getbuffer

\def\dodododefinemathset!notext#1%
  {\setmathmiddle
   \mathopen{}\left\mathsetparameter\c!left
   {#1}%
   \right\mathsetparameter\c!right\mathclose{}%
   \endgroup}
  
%D TODO. Keep the \type|\nolimits| to be configurable.

\def\dodododefinemathset!text#1#2%
    {\mathop{\kern\zeropoint\mathsetparameter\c!text}\nolimits#1%
     \setmathmiddle
     \left\mathsetparameter\c!left
     {#2}%
     \right\mathsetparameter\c!right%
     \endgroup}

%D The extra group in the definition of \type{dodododefinemathset!} is
%D so that such expressions turn out correct
%D \getbuffer[EXP]
%D \startformula
%D \EXP{ \left(\frac {a}{b}\right) | 
%D      \left( \frac{a} {\frac{b}{\sum c}} \right) }
%D \stopformula


%D The \type{\left} and \type{\right} generate a math atom of type inner,
%D while for math sets, we want a math math open atom. To see the difference,
%D consider
%D
%D \startbuffer
%D \startformula
%D  2\left(\frac {3}{4} \right) \qquad \hbox{ vs } \qquad  
%D  2\biggl( \frac {3}{4} \biggr)
%D \stopformula
%D
%D and
%D 
%D \startformula
%D  \Pr\left(\frac {3}{4} \right) \qquad \hbox{ vs } \qquad  
%D  \Pr\biggl( \frac {3}{4} \biggr)
%D \stopformula
%D \stopbuffer
%D \typebuffer 
%D
%D which gives (notice the spacing before the parenthesis)
%D
%D \getbuffer 
%D
%D I will assume that if \type{text} is something, then
%D the default behaviour is desirable, if \type{text} is empty, then I add
%D \type{\mathopen} and \type{\mathclose}.  Using \type{\mathopen} to correct
%D the spacing is due to Frank Mittelbach, see
%D \hyphenatedurl{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/3853}
%D
%D Mathset module ensures that we get the correct spacing in both cases
%D \startbuffer
%D \definemathset[SET][left=(,right=)]
%D \startformula
%D  2\SET{\frac{3}{4}} \qquad \hbox{ and } \qquad 
%D  \PR{ \frac{3}{4} }
%D \stopformula
%D \stopbuffer
%D \getbuffer[PR] \getbuffer which was typed as \typebuffer
%D
%D Also, if its argument is a single character, \type{\mathop} centers it to
%D with respect to the math||axis. Compare the outputs of
%D
%D \startbuffer
%D \ruledhbox{$\mathop{y}\nolimits_x\left\{A\,\middle|\,B\right\}$}
%D \ruledhbox{$\mathop{\kern\zeropoint y}\nolimits_x\left\{A\,\middle|\,B\right\}$}
%D \stopbuffer
%D
%D \typebuffer
%D \getbuffer
%D
%D I have added a \type{\kern\zeropoint} to prevent that.


%D \macros
%D    {docapturemathoplimits}
%D
%D The next macro captures math limits. This should probably go to some
%D general purpose module. There are three different valid inputs
%D \startitemize[n,packed]
%D   \item An operator with neither subscript nor superscript.
%D   \item An operator with one subscript or superscript.
%D   \item An operator with both subscript and superscript.
%D \stopitemize
%D So we scan for four arguments, to capture the following situations
%D \startitemize[packed]
%D   \item \type|_{sub}^{sup}|
%D   \item \type|^{sup}_{sub}|
%D   \item \type|_{sub}|
%D   \item \type|^{sup}|
%D   \item \type|<empty>|
%D \stopitemize

\def\docapturemathoplimits#1%
  {\doifnextcharelse_%
    {\dodocapturemathoplimits{#1}}
    {\doifnextcharelse^%
      {\dodocapturemathoplimits{#1}}
      {#1{}}}}

\def\dodocapturemathoplimits#1#2#3%
  {\doifnextcharelse_%
    {\redocapturemathoplimits{#1}{#2}{#3}}
    {\doifnextcharelse^%
        {\redocapturemathoplimits{#1}{#2}{#3}}
        {#1{#2{#3}}}}}

\def\redocapturemathoplimits#1#2#3#4#5%
  {#1{#2{#3}#4{#5}}}

\setupmathset
  [  \c!left={\{},
    \c!right={\}},
   \c!middle=\vert,
     \c!text=no,]

\definemathset[mathset]

%D \section Change log
%D
%D \startitemize[n, reverse][headstyle=bold]
%D
%D \head \date[d=6,m=12,y=2008]
%D
%D Defined a new macro \type{setmathmiddle}. Now \type{|} is made active after
%D the subscripts, so that things still work when \type{|} is used in the
%D subscripts.
%D
%D \head \date[d=3,m=7,y=2008] 
%D
%D Added \type{text=no} option, included an interface file, and cleaned up the
%D documentation for \TEX live 2008.
%D
%D \head \date[d=17,m=6,y=2007] 
%D       
%D Added \type|\docapturemathoplimits| macro. This prevents a
%D serious bug in the previous version, due to which things like
%D \type{\mathset_{...}} did not work.
%D
%D \head \date[d=11,m=4,y=2007]
%D
%D This version provides some fine tuning of how the sets are displayed
%D by working around two mis|-|features of \TEX\ math: \type|\left|
%D \unknown \type|\right| always create a math inner atom and
%D \type|\mathop| centers its argument if the argument is a single
%D letter. 
%D
%D \head \date[d=25,m=2,y=2007]
%D
%D First version of the module.
%D  
%D \stopitemize

\protect
\stopmodule

