%% $Id: kbordermatrix.sty 1335 2026-07-23 09:13:32Z herbert $
%%
%% This file is distributed under the terms of the LaTeX Project Public
%% License from CTAN archives in directory /macros/latex/base/lppl.txt.
%% Either version 1.3 or, at your option, any later version.

\NeedsTeXFormat{LaTeX2e}

\def\fileversion{1.02}
\def\filedate{2026/07/23}

\ProvidesPackage{kbordermatrix}[\filedate~ Bordered matrix with brackets]

%	Original Author:	Kim C Border (+ 2020-11-19)
%	Date:		SuperBowl XXXVII (Go Bucs)
%	Defines \kbordermatrix along the lines of plain tex's
%	\bordermatrix (which is still available in LaTeX).

%	In particular, as with \bordermatrix,
%	1.	The first row is spaced a bit further apart from the rest.
%	2.	The lower (n-1) by (n-1) block is set off by delimiters.
%	3.	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.  As default 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 

\def\set@delims#1#2;{%    hv 20260721
  %\typeout{>>>#1|#2}%
  \def\kbldelim{#1}%
  \def\kbrdelim{#2}%
}

\def\kbordermatrix{\@ifnextchar\bgroup{\kbordermatrix@i[]}{\kbordermatrix@i}}
\def\kbordermatrix@i#1#2#3{%
%  \begingroup
    \set@delims#1#2;
  	%	\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:
			#3\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
}

