\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{kbordermatrix}[2011/09/21 Bordered matrix with brackets]

%	Author:	Kim C Border <kcborder@caltech.edu>
%	Date:		SuperBowl XXXVII (Go Bucs)

%   Revised 2003/09/20
%		to allow flush right option.
%   Revised 2011/09/21 
%		at urging of Bruno Calfa (CMU) 
%		to coexist with package arydshln
%		by adding \def\@xarraycr ... 

%	Defines \kbordermatrix along the lines of plain tex's
%	\bordermatrix (which is still available in LaTeX).

%	In particular, as with \bordermatrix,
%	1.	It takes the array as an argument.  It does not use \begin{}..\end{}.
%		Is this a feature or a bug?
%	2.	The first row is spaced a bit further apart from the rest.
%	3.	The lower (n-1) by (n-1) block is set off by delimiters.
%	4.	There is an invisible bottom row of the same height as the segregated
%		top row that adds to the height of the equation.

%	Differences from \bordermatrix:
%	1.  Square brackets are used in place of parentheses.
%	2.  You may use \\ instead of \cr.
%	3.  The line heights agree with LaTeX's line heights for the
%		array environment, and \arraystretch is respected.  This means
%		the bottom (n-1) rows align with the rows of an (n-1)-rowed
%		\begin{array}..\end{array} (with or without delimiters).
%	4.	All columns are centered.
%	** Modified 2003-9-20 to allow flush right option.
%	5.	The first column is spaced a bit further apart from the rest.


%	Differences from \left\[\begin{array}...\end{array}\right\]
%	1.	It takes the array as an argument.  It does not use \begin{}..\end{}.
%		Is this a feature or a bug?
%	2.	Consequently, you cannot use a column specifier (e.g., {l|cr}).
%	3.	Consequently the maximum number of columns is not specified.
%	4.	Vertical rules must be put in each row in a separate column.
%	5.  You can use \hline and \cline.

%	At least it works in the cases I have tried, but I offer no guarantees.



%	cf. \bordermatrix p. 361, and \vrulealign p. 392 of The TeXbook



%	Style parameters, they may be redefined according to taste.
	\newcommand{\kbldelim}{[}	%	Left delimiter
	\newcommand{\kbrdelim}{]}%	Right delimiter
			
	\newcommand{\kbrowstyle}{\scriptstyle}%  Style applied to first row
	\newcommand{\kbcolstyle}{\scriptstyle}%   Style applied to first column
	
	\newlength{\kbcolsep}		%	Extra separation after first border column
	\newlength{\kbrowsep}		%	Extra separation after first border row
	
	\setlength{\kbcolsep}{.5\arraycolsep}
	\setlength{\kbrowsep}{.2ex}
	
	\newif\ifkbalignright

%	Scratch lengths (to be computed)
	\newlength{\br@kwd}		%	Width of delimiter
	\newlength{\k@bordht}	%	Height of border column 
	
%	This is it
\newcommand{\kbordermatrix}[1]{%
\begingroup
  	%	\br@kwd depends on font size, so compute it now.
	\setbox0=\hbox{$\left\kbldelim\right.$}
	\setlength{\br@kwd}{\wd0}
		%	Compute the array strut based on current value of \arraystretch.
	\setbox\@arstrutbox\hbox{\vrule 
		\@height\arraystretch\ht\strutbox 	
		\@depth\arraystretch\dp\strutbox
		\@width\z@}
		%	Compute height of first row and extra space.
	\setlength{\k@bordht}{\kbrowsep}
	\addtolength{\k@bordht}{\ht\@arstrutbox}
	\addtolength{\k@bordht}{\dp\@arstrutbox}
		%	turn off mathsurround
	\m@th
		%	Set the first row style
	\def\@kbrowstyle{\kbrowstyle}
		%	Swallow the alignment into box0:
	\setbox0=\vbox{%
			%	Define \cr for first row to include the \kbrowsep
			%	and to reset the row style
		\def\cr{\crcr\noalign{\kern\kbrowsep
			\global\let\cr=\endline
			\global\let\@kbrowstyle=\relax}}
			%	Redefine \\ a la LaTeX:
		\let\\\@arraycr
			%	The following are needed to make a solid \vrule with no gaps
			%	between the lines.
		\lineskip\z@skip	
		\baselineskip\z@skip	
			%	Compute the length of the skip after the first column
		\dimen0\kbcolsep \advance\dimen0\br@kwd
			%	Here begins the alignment:
		\ialign{\tabskip\dimen0		%	This space will show up after the first column
			\kern\arraycolsep\hfil\@arstrut$\kbcolstyle ##$\hfil\kern\arraycolsep&
			\tabskip\z@skip			%	Cancel extra space for other columns
			\kern\arraycolsep\hfil$\@kbrowstyle ##$\ifkbalignright\relax\else\hfil\fi\kern\arraycolsep&&
			\kern\arraycolsep\hfil$\@kbrowstyle ##$\ifkbalignright\relax\else\hfil\fi\kern\arraycolsep\crcr
				%	That ends the template.
				%	Here is the argument:
			#1\crcr}%		End \ialign
	}%	End \setbox0.
		%	\box0 now holds the array.
		%
		%	This next line uses \box2 to hold a throwaway 
		%	copy of \box0, leaving \box0 intact,
		%	while putting the last row in \box5.
	\setbox2=\vbox{\unvcopy0 \global\setbox5=\lastbox}
		%	We want the width of the first column,
		%	so we lop off columns until there is only one left.
		%	It's not elegant or efficient, but at 1 gHz, who cares.
	\loop
		\setbox2=\hbox{\unhbox5 \unskip \global\setbox3=\lastbox}
		\ifhbox3
			\global\setbox5=\box2
			\global\setbox1=\box3
	\repeat
		%	\box1 now holds the first column of last row.
		%
		%	This next line stores the alignment in \box2, 
		%	while calculating the proper
		%	delimiter height and placement.
	\setbox2=\hbox{$\kern\wd1\kern\kbcolsep\kern-\arraycolsep
		\left\kbldelim
		\kern-\wd1\kern-\kbcolsep\kern-\br@kwd
			%
			%	Here is the output.  The \vcenter aligns the array with the "math axis."
			%	The negative vertical \kern only shrinks the delimiter's height.
			%	BTW, I didn't find this in the TeXbook, 
			%	I had to try various \kerns to see what they did in a 
			%	\left[\vcenter{}\right].
	\vcenter{\kern-\k@bordht\vbox{\unvbox0}}
	\right\kbrdelim$}
	\null\vbox{\kern\k@bordht\box2}
		%
	\endgroup
}

