Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to typeset Hilbert-Schmidt-Products as the Liouville-Equivalent of the Hilbert Space Braket, with doubled delimiters, like this: \Lbraket{\rho|\rho} results in <<rho|rho>>.

I was trying to adapt the definition of \Braket from the Braket package to do this, ending up with the following code:

{\catcode`\|=\active                                                             
  \xdef\Lbraket{\protect\expandafter\noexpand\csname Lbraket \endcsname}         
  \expandafter\gdef\csname Lbraket \endcsname#1{\begingroup                      
     \ifx\SavedDoubleVert\relax                                                  
       \let\SavedDoubleVert\|\let\|\BraDoubleVert                                
     \fi                                                                         
     \mathcode`\|32768\let|\BraVert                                              
     \left\langle\kern-0.2em\left\langle{#1}\right\rangle\kern-0.2em\right\rangle\endgroup}
}
\def\BraVert{\@ifnextchar|{\|\@gobble}% turn || into \|                          
     {\egroup\,\mid@vertical\,\bgroup}}                                          
\def\BraDoubleVert{\egroup\,\mid@dblvertical\,\bgroup}                           
\let\SavedDoubleVert\relax
\begingroup                                                                      
 \edef\@tempa{\meaning\middle}                                                   
 \edef\@tempb{\string\middle}                                                    
\expandafter \endgroup \ifx\@tempa\@tempb                                        
 \def\mid@vertical{\middle|}                                                     
 \def\mid@dblvertical{\middle\SavedDoubleVert}                                   
\else                                                                            
 \def\mid@vertical{\mskip1mu\vrule\mskip1mu}                                     
 \def\mid@dblvertical{\mskip1mu\vrule\mskip2.5mu\vrule\mskip1mu}                 
\fi

This works, but for very large formulas the double delimiters are not sufficiently tight, and the negative kerning should be larger.

On the other hand, I've found some code that allows to define double delimiters and doesn't seem to suffer from the same problem. The following is from a newsgroup posting, it defines \lleft and \rright so that e.g. \lleft\langle results in <<.

\catcode`@=11                                                                    
\def\lleft#1#2\rright{\begingroup%                                               
   \def\ts@r{\nulldelimiterspace=0pt \mathsurround=0pt}%                         
   \let\@hat=#1%                                                                 
   \def\sht@im{#2}%                                                              
   \def\@t{{\mathchoice{\def\@fen{\displaystyle}\k@fel}%                         
          {\def\@fen{\textstyle}\k@fel}%                                         
          {\def\@fen{\scriptstyle}\k@fel}%                                       
          {\def\@fen{\scriptscriptstyle}\k@fel}}}%                               
   \def\g@rin{\ts@r\left\@hat\vphantom{\sht@im}\right.}%                         
   \def\k@fel{\setbox0=\hbox{$\@fen\g@rin$}\hbox{%                               
      $\@fen \kern.3875\wd0 \copy0 \kern-.3875\wd0%                              
      \llap{\copy0}\kern.3875\wd0$}}%                                            
      \def\pt@h{\mathopen\@t}\pt@h\sht@im%                                       
      \rright}%                                                                  
\def\rright#1{\let\@hat=#1%                                                      
   \def\st@m{\mathclose\@t}%                                                     
   \st@m\endgroup}                                                               
\catcode`@=12

My question is if there's a way to combine to two code snippets to get a correctly resizing Braket with doubled delimiters. Simply doing the following does not work:

{\catcode`\|=\active                                                             
  \xdef\LBraket{\protect\expandafter\noexpand\csname LBraket \endcsname}         
  \expandafter\gdef\csname LBraket \endcsname#1{\begingroup                      
     \ifx\SavedDoubleVert\relax                                                  
       \let\SavedDoubleVert\|\let\|\BraDoubleVert                                
     \fi                                                                         
     \mathcode`\|32768\let|\BraVert                                              
     \lleft\langle{#1}\rright\rangle\endgroup}
}

This results in an error message:

! Extra \middle.
\mid@vertical ->\middle |

My knowledge of lowlevel TeX is not anywhere near sufficient to understand how the implementation of \lleft and \rright works, but maybe someone sees whether the two snippets can be combined.

share|improve this question

1 Answer 1

up vote 6 down vote accepted

A modification of the very clever \lleft macro can do

\documentclass[a4paper]{article}
\makeatletter
\def\LBlleft#1#2|#3\LBrright{\begingroup
   \def\ts@r{\nulldelimiterspace=0pt \mathsurround=0pt}%
   \let\@hat=#1%
   \def\sht@im{\ts@r\left.#2\nonscript\;\middle|\nonscript\;#3\right.}%
   \def\@t{{\mathchoice{\def\@fen{\displaystyle}\k@fel}%
          {\def\@fen{\textstyle}\k@fel}%
          {\def\@fen{\scriptstyle}\k@fel}%
          {\def\@fen{\scriptscriptstyle}\k@fel}}}%
   \def\g@rin{\ts@r\left\@hat\vphantom{\sht@im}\right.}%
   \def\k@fel{\setbox0=\hbox{$\@fen\g@rin$}\hbox{%
      $\@fen \kern.3875\wd0 \copy0 \kern-.3875\wd0
      \llap{\copy0}\kern.3875\wd0$}}%
      \def\pt@h{\mathopen\@t}\pt@h\sht@im
      \LBrright}%
\def\LBrright#1{\let\@hat=#1%
   \def\st@m{\mathclose\@t}%
   \st@m\endgroup}
\DeclareRobustCommand\LBraket[1]{\LBlleft<#1\LBrright>}
\makeatother
\begin{document}
$\displaystyle\LBraket{\frac{a}{b}|b}$
$\textstyle\LBraket{\frac{a}{b}|b}$
$\scriptstyle\LBraket{\frac{a}{b}|b}$
$\scriptscriptstyle\LBraket{\frac{a}{b}|b}$
\end{document}

ADDED (Support for multiple bars)

\makeatletter

\def\LB@add@@{\aftergroup\LB@add@}
\def\LB@add@{\aftergroup\LB@add}
\def\LB@add{\advance\@tempcnta\@ne}
\def\LB@barsl{\ifcase\@tempcnta\or
  \kern-\nulldelimiterspace\left.\or
  \kern-2\nulldelimiterspace\left.\left.\fi}
\def\LB@barsr{\ifcase\@tempcnta\or
  \right.\kern-\nulldelimiterspace\or
  \right.\right.\kern-2\nulldelimiterspace\fi}

\def\LBlleft#1#2\LBrright{\begingroup
  % count the number of bars
  \mathcode`|="8000
  \begingroup\lccode`~=`| \lowercase{\endgroup\def~}{\aftergroup\LB@add@@}
  \@tempcnta=\z@\setbox\z@=\hbox{$\left<#2\right>$}
  % now \@tempcnta has the number of bars and we redefine |
  \begingroup\lccode`~=`| \lowercase{\endgroup\def~}{\nonscript\;\middle|\nonscript\;}
  \def\ts@r{\nulldelimiterspace=0pt \mathsurround=0pt}%
  \let\@hat=#1%
  \def\sht@im{\LB@barsl#2\LB@barsr}%
  \def\@t{{\mathchoice{\def\@fen{\displaystyle}\k@fel}%
          {\def\@fen{\textstyle}\k@fel}%
          {\def\@fen{\scriptstyle}\k@fel}%
          {\def\@fen{\scriptscriptstyle}\k@fel}}}%
   \def\g@rin{\ts@r\left\@hat\vphantom{\sht@im}\right.}%
   \def\k@fel{\setbox0=\hbox{$\@fen\g@rin$}\hbox{%
      $\@fen \kern.3875\wd0 \copy0 \kern-.3875\wd0
      \llap{\copy0}\kern.3875\wd0$}}%
      \def\pt@h{\mathopen\@t}\pt@h\sht@im
      \LBrright}%
\def\LBrright#1{\let\@hat=#1%
   \def\st@m{\mathclose\@t}%
   \st@m\endgroup}
\DeclareRobustCommand\LBraket[1]{\LBlleft<#1\LBrright>}
\makeatother

It supports at most two bars, but if needed one can extend the macros \LB@barsl and \LB@barsr.

share|improve this answer
    
Works almost, except for the second vertical in e.g. \LBraket{\rho| \hat{\hat{A}} | \rho}, the way \Braket does. Would there be a way to incorporate that as well? –  Michael Goerz Oct 27 '11 at 20:26
    
Well, that indeed does two bars, but unlike the first version, it doesn't seem to scale the negative spacing between the two delimiters. Actually, if someone can pick it apart, I'd love to be able to understand how the original \lleft macro works... what's the trick there? –  Michael Goerz Oct 28 '11 at 11:39
    
@MichaelGoerz See edited answer; I'm still studying the \lleft and \rright magic. :) –  egreg Oct 28 '11 at 12:39
1  
@egreg: Is it possible to modify the code in such a way that the following works: \LBlleft{\{[}#1{]\}}\LBrright. I mean to set two different delimiters. –  Marco Daniel Oct 29 '11 at 8:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.