In plain TeX, there is a macro \bordermatrix but I am not very satisfied with it. The problem of that is, the “border” is always at the leftmost and topmost, but not any other combinations. For some unknown reason, I am surprised that no one has any problem with it and no one has every develop a new package to remediate this problem. Thus I do my own.

Dissection of the legacy bordermatrix macro

The code for legacy \bordermatrix, as from the TeXbook, is below

\newdimen\p@renwd \setbox0=\hbox{\tenex B} \p@renwd=\wd0
\def\bordermatrix#1{\begingroup \m@th
  \setbox0=\vbox{\def\cr{\crcr\noalign{\kern2pt\global\let\cr=\endline}}
      \ialign{$##$\hfil\kern2pt\kern\p@renwd&\thinspace\hfil$##$\hfil
        &&\quad\hfil$##$\hfil\crcr
        \omit\strut\hfil\crcr\noalign{\kern-\baselineskip}
        #1\crcr\omit\strut\cr}}
  \setbox2=\vbox{\unvcopy0 \global\setbox1=\lastbox}
  \setbox2=\hbox{\unhbox1 \unskip \global\setbox1=\lastbox}
  \setbox2=\hbox{$\kern\wd1\kern-\p@renwd \left( \kern-\wd1
    \global\setbox1=\vbox{\box1\kern2pt}
    \vcenter{\kern-\ht1 \unvbox0 \kern-\baselineskip} \,\right)$}
\null\;\vbox{\kern\ht1\box2}\endgroup}

The code is explained below:

% Define the width of a bracket as \p@renwd
\newdimen\p@renwd \setbox0=\hbox{\tenex B} \p@renwd=\wd0

% Define the macro \bordermatrix
\def\bordermatrix#1{
\begingroup
  \m@th % Set the mathsurround stuff
  %
  % Put the matrix into box 0, without brackets
  \setbox0=\vbox{
     % Redefine \cr to provide inter-row gap
     \def\cr{\crcr\noalign{\kern2pt\global\let\cr=\endline}}
     % Matrix as an \ialign
     \ialign{
        $##$\hfil\kern2pt\kern\p@renwd& % First column: Big space at right
          \thinspace\hfil$##$\hfil&& % Second column: Small space at left
          \quad\hfil$##$\hfil % All other columns: space at left as inter-column gap
          \crcr % End of \ialign template
        \omit\strut\hfil\crcr % Small space to separate matrix from the line above
        \noalign{\kern-\baselineskip}
        #1\crcr % The matrix as provided by the user
        \omit\strut\cr % One empty cell as the last row
     }
  }
  %
  % Determine the first column's width:
  % Firstly, extract box0 for its last box inside, i.e. the last row
  % Then, unbox the last row to find the last (i.e. leftmost) column, save as box 1
  % Afterwards, the width of box 1 is taken as the width of first column
  \setbox2=\vbox{\unvcopy0 \global\setbox1=\lastbox}
  \setbox2=\hbox{\unhbox1 \unskip \global\setbox1=\lastbox}
  %
  % Put the bracket into the matrix, and save the result as an \hbox
  \setbox2=\hbox{$ % Start math mode
     $\kern\wd1\kern-\p@renwd % Shift right the first column's width minus bracket's width
     \left( % Print the left bracket
     \kern-\wd1 % Shift back the first column's width
     \global\setbox1=\vbox{\box1\kern2pt} % Save box 1's height + 2pt
     \vcenter{ % Make a vbox to print the matrix in correct position
        \kern-\ht1 % Shift upward a box 1's height as the topmost row should not inside bracket
        \unvbox0 % Print the matrix
        \kern-\baselineskip % Subtract a row's height from the calculation of the matrix's height
      } % Now this vbox's height is one row shorter then box 0
      \,\right) % Leave a tiny space and print the right bracket
  $}
  \null\; % Print some small space
  \vbox{\kern\ht1\box2} % Then the bracketed matrix shifted down one row to avoid
                        % the topmost border not overprinting existing text
\endgroup
}

Herbert Voss wrote a manual “Math mode” that describes an enhanced \bordermatrix so that we can provide user-specified bracket type and also it provided \bordermatrix* as an derived version that puts the border at rightmost column and bottommost row.

K. Border wrote a \kbordermatrix that allows the border to be in different font style.

qbordermatrix

My work is a more generic version. It allows any combination of the four sides to be the border.

% qbordermatrix.sty - A more flexible \bordermatrix for LaTeX
% Copyright 2010 (c) Adrian S. Tam <adrian.sw.tam@gmail.com>
% 
% This LaTeX package provides three commands, namely,
%   \bordermatrix - similar to the Knuth's version
%   \bordermatrix* - adapted from the manual "Math mode" by Herbert Voss
%                    that provides the border at bottom and right instead
%   \qbordermatrix - Quadri-border matrix, you can select any combination
%                    of the four borders to put outside of the matrix
%
% The \qbordermatrix macro takes the syntax of the following
%    \qbordermatrix[#1]{#2}{
%       a11 & a12 & a13 & a14   
%       a21 & a22 & a23 & a24   
%       a31 & a32 & a33 & a34
%    }
% The optional parameter #1 provides two characters as the matrix's left and
% right delimiters. The parameter #2 provides a subset of "n", "s", "e", "w"
% to tell which border should be outside of the matrix. Then the matrix is
% provided in the last curly bracket.
%
% In this sense, \bordermatrix is same as \qbordermatrix{nw} and
% \bordermatrix* is same as \qbordermatrix{se}. An example is given at
% the bottom of this file.
% 
% Compared to the Knuth's version, the matrices constructed by this package
% has the following properties
%  1. The row height is determined dynamically. Thus if the border row is
%     tall, e.g. a display fraction, the bracket is placed in the correct
%     size.
%  2. The matrix is aligned at the middle of the bracket, regardless the
%     heights of the matrix or the border rows
%  3. Different matrix delimiters are allowed, as long as they can fit into
%     the \left and \right pairs in equations
%  4. The output is in a vbox and the "canva" covers exactly the matrix
% Also the spacing around the matrix is a bit tight.
%
% Please send your comments and enhancement ideas to adrian.sw.tam@gmail.com
% 
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{qbordermatrix}[2010/3/24 qbordermatrix v1.0]
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Support of \bordermatrix and \bordermatrix* as described in "Math mode - v.2.43" by
% Herbert Voss
%
\newdimen\matrixrowsep
\matrixrowsep=2pt
% Determine if an asterisk is following \bordermatrix, and assert \@borderstar
\def\bordermatrix{\@ifnextchar*{\@bordermatrix@se}{\@bordermatrix@nw}}
% If no bracket is provided, use parenthesis
\def\@bordermatrix@se*{\@ifnextchar[{\@bordermatrix@se@i}{\@bordermatrix@se@i[()]}}
\def\@bordermatrix@nw{\@ifnextchar[{\@bordermatrix@nw@i}{\@bordermatrix@nw@i[()]}}
% Construction of the bordermatrix
\def\@bordermatrix@se@i[#1]#2{\@qbordermatrix@i[#1]{se}{#2}}
\def\@bordermatrix@nw@i[#1]#2{\@qbordermatrix@i[#1]{nw}{#2}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% More flexible \qbordermatrix macro
%
\newif\if@north
\newif\if@south
\newif\if@east
\newif\if@west
\def\@swallow#1{}
% If no bracket is provided, use parenthesis
\def\qbordermatrix{\@ifnextchar[{\@qbordermatrix@i}{\@qbordermatrix@i[()]}}
% Construction of the bordermatrix
\def\@qbordermatrix@i[#1]#2#3{%
\begingroup
  % Parse parameters
  \@northfalse\@southfalse\@eastfalse\@westfalse
  \in@{n}{#2}\ifin@\@northtrue\fi
  \in@{s}{#2}\ifin@\@southtrue\fi
  \in@{e}{#2}\ifin@\@easttrue\fi
  \in@{w}{#2}\ifin@\@westtrue\fi
  \m@th % mathsurround stuff
  % compute bracket width
  \setbox\z@\hbox{$\left\@firstoftwo#1\right.$}
  \newdimen\@leftbwd
  \@leftbwd\wd\z@
  \setbox\z@\hbox{$\left.\right\@secondoftwo#1$}
  \newdimen\@rightbwd
  \@rightbwd\wd\z@
  % Define carriage-return for array rows
  \def\cr{\crcr\noalign{\kern\matrixrowsep\global\let\cr\endline}} % for a safer \cr
  \def\\{\cr}
  % Set box0 to contain the matrix without bracket
  \setbox\z@\vbox{%
    \ialign{ % the matrix
      \hfil$##$\hfil\kern 2\p@\kern\@leftbwd & % first column: big space at right for open bracket
      \thinspace\hfil $##$\hfil && % second column: small space at left
      \quad\hfil $##$\hfil % all other columns: big space at left for column separation
      \crcr % end of preamble
      #3\crcr % the matrix itself
    }
  }%
  % Determine the last row height
  % Extract last row from box 0 and measure its height
  \setbox\thr@@\vbox{\unvcopy\z@\global\setbox\tw@\lastbox}
  \setbox\tw@\vbox{\hrule\box\tw@\hrule}
  \newdimen\@lastrowht
  \@lastrowht\ht\tw@
  % Determine the first row height
  % by removing one row at a time from the content of box 0 (copied to box 3).
  % If, after removing a row, the height of the box is less than 4pt, we rollback
  % one step and that is the first row's height
  \loop
    \ifdim\ht\thr@@>0pt
      \setbox\tw@\copy\thr@@
      \setbox\thr@@\vbox{%
        \unvbox\thr@@
        \loop% Remove kern, skip, and penalty until we found a box to remove
          \unkern\unskip\unpenalty
          \global\setbox\@ne\lastbox
          \ifvoid\@ne
        \repeat
      }
  \repeat
  \setbox\tw@\vbox{\hrule\copy\@ne\hrule} % use \copy\tw@ for taller height
  \newdimen\@firstrowht
  \@firstrowht\ht\tw@
  % Determine the last column width
  % After above, the first row is stored in box 1 and we extract the last
  % column and meausre its width
  \setbox\tw@\hbox{%
    \unhcopy\@ne
    \loop
      \unkern\unskip\unpenalty
      \global\setbox\thr@@\lastbox
      \ifvoid\thr@@
    \repeat
  }
  \newdimen\@lastcolwd
  \@lastcolwd\wd\thr@@
  % Determine the first column width
  % The entire first row is stored in box 1 and we do the similar iterations
  % to remove one box at a time from box 1 to find the first column width
  \loop
    \setbox\tw@\copy\@ne
    \setbox\@ne\hbox{%
      \unhbox\@ne
      \loop
        \unkern\unskip\unpenalty
        \setbox\thr@@\lastbox
        \ifvoid\thr@@
      \repeat
    }
    \ifdim\wd\@ne>0pt
  \repeat
  \newdimen\@firstcolwd
  \@firstcolwd\wd\tw@
  % Put the bracket into the matrix:
  % First right shift for first column's width, and put the opening bracket, then
  % left shift to original position to put the matrix, and then shift left to close
  % the bracket and shift back to right.
  % The matrix, however, is also shifted to reflect the desired height of bracket,
  \setbox\tw@\hbox{$
    \if@west\kern\@firstcolwd\kern-\@leftbwd\fi
    \left\@firstoftwo#1
    \if@west\kern-\@firstcolwd\fi
    \vcenter{%
      \if@north\kern-\@firstrowht\fi
      \unvcopy\z@
      \if@south\kern-\@lastrowht\fi
    }
    \if@east\kern-\@lastcolwd\fi
    \right\@secondoftwo#1
    \if@east\kern-\@rightbwd\kern\@lastcolwd\fi
  $}
  % Print the result
  \if@north\setbox\tw@\vbox{\kern\@firstrowht\box\tw@}\fi
  \if@south\setbox\tw@\vtop{\box\tw@\kern\@lastrowht}\fi
  \box\tw@
\endgroup
}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example:
%
% \documentclass{article}
% \usepackage{qbordermatrix}
% \begin{document}
% \hrule y\vrule$\bordermatrix[\{\}]{%
% 0 &   1 &2^{2^2}& 3 & \displaystyle\frac{4}{2} \cr
% a & x_1 & y_2 & z_1 & t_1 \cr
% b & x_3 & y_4 & z_2 & t_2 \cr
% c & x_5 & y_6 & z_3 & t_3 \cr
% d &   1 &2^{2^2}& 3 & \displaystyle\frac{4}{2} \cr
% }$\vrule z\hrule
% 
% \hrule y\vrule$\bordermatrix*[\{\}]{%
% 0 &   1 &2^{2^2}& 3 & \displaystyle\frac{4}{2} \cr
% a & x_1 & y_2 & z_1 & t_1 \cr
% b & x_3 & y_4 & z_2 & t_2 \cr
% c & x_5 & y_6 & z_3 & t_3 \cr
% d &   1 &2^{2^2}& 3 & \displaystyle\frac{4}{2} \cr
% }$\vrule z \hrule
% 
% \hrule y\vrule$\qbordermatrix[\{\}]{nesw}{%
% 0 &   1 &2^{2^2}& 3 & \displaystyle\frac{4}{2} \cr
% a & x_1 & y_2 & z_1 & t_1 \cr
% b & x_3 & y_4 & z_2 & t_2 \cr
% c & x_5 & y_6 & z_3 & t_3 \cr
% d &   1 &2^{2^2}& 3 & \displaystyle\frac{4}{2} \cr
% }$\vrule z
% \hrule
% \end{document}
%