Gan_Matrix mA, mB, mC; /* matrices A, B & C */
/* ... create and fill matrices A, B, create matrix C ... */
gan_mat_rmult_q ( &mA, &mB, &mC ); /* C = A*B, OR */
gan_mat_rmultT_q ( &mA, &mB, &mC ); /* C = A*B^T, OR */
gan_matT_rmult_q ( &mA, &mB, &mC ); /* C = A^T*B, OR */
gan_matT_rmultT_q ( &mA, &mB, &mC ); /* C = A^T*B^T, OR */
with similar routines to create the result matrix
Gan_Matrix mA, mB, *pmC; /* matrices A, B & C */
/* ... create and fill matrices A, B ... */
pmC = gan_mat_rmult_s ( &mA, &mB ); /* C = A*B, OR */
pmC = gan_mat_rmultT_s ( &mA, &mB ); /* C = A*B^T, OR */
pmC = gan_matT_rmult_s ( &mA, &mB ); /* C = A^T*B, OR */
pmC = gan_matT_rmultT_s ( &mA, &mB ); /* C = A^T*B^T, OR */
The next set of routines deals with the case where it is known that the
result of multiplying matrices
Gan_Matrix mA, mB; /* matrices A & B */
Gan_SquMatrix smC; /* matrix C */
/* ... create and fill matrices A, B, create matrix C ... */
gan_mat_rmult_sym_q ( &mA, &mB, &mC ); /* C = A*B, OR */
gan_mat_rmultT_sym_q ( &mA, &mB, &mC ); /* C = A*B^T, OR */
gan_matT_rmult_sym_q ( &mA, &mB, &mC ); /* C = A^T*B, OR */
gan_matT_rmultT_sym_q ( &mA, &mB, &mC ); /* C = A^T*B^T */
with the alternatives
Gan_Matrix mA, mB; /* matrices A & B */
Gan_SquMatrix *psmC; /* matrix C */
/* ... create and fill matrices A, B ... */
psmC = gan_mat_rmult_sym_s ( &mA, &mB ); /* C = A*B, OR */
psmC = gan_mat_rmultT_sym_s ( &mA, &mB ); /* C = A*B^T, OR */
psmC = gan_matT_rmult_sym_s ( &mA, &mB ); /* C = A^T*B, OR */
psmC = gan_matT_rmultT_sym_s ( &mA, &mB ); /* C = A^T*B^T */
In the case that
Gan_Matrix mA; /* matrix A */
Gan_SquMatrix smC; /* matrix C */
/* ... create and fill matrix A, create matrix C ... */
gan_mat_srmultT_q ( &mA, &mC ); /* C = A*A^T, OR */
gan_mat_slmultT_q ( &mA, &mC ); /* C = A^T*A */
with the alternatives
Gan_Matrix mA; /* matrix A */
Gan_SquMatrix *psmC; /* matrix C */
/* ... create and fill matrix A ... */
psmC = gan_mat_srmultT_s ( &mA ); /* C = A*A^T, OR */
psmC = gan_mat_slmultT_s ( &mA ); /* C = A^T*A */
If one or both of the input matrices is a special square matrix, there are
many more combinations available. First consider a square matrix
being
multiplied on left or right by a general rectangular matrix
, giving
a result matrix
. Given the possibility of both implicit transpose and
inverse of the square matrix, we need to consider the operations
Gan_SquMatrix smA; /* square matrix A */
Gan_Matrix mB, mC; /* matrices B & C */
/* ... create and fill matrices A, B, create matrix C ... */
/* routines right-multipling A by B */
gan_squmat_rmult_q ( &smA, &mB, &mC ); /* C = A*B, OR */
gan_squmat_rmultT_q ( &smA, &mB, &mC ); /* C = A*B^T, OR */
gan_squmatT_rmult_q ( &smA, &mB, &mC ); /* C = A^T*B, OR */
gan_squmatT_rmultT_q ( &smA, &mB, &mC ); /* C = A^T*B^T, OR */
gan_squmatI_rmult_q ( &smA, &mB, &mC ); /* C = A^-1*B, OR */
gan_squmatI_rmultT_q ( &smA, &mB, &mC ); /* C = A^-1*B^T, OR */
gan_squmatIT_rmult_q ( &smA, &mB, &mC ); /* C = A^-T*B, OR */
gan_squmatIT_rmultT_q ( &smA, &mB, &mC ); /* C = A^-T*B^T */
/* routines left-multipling A by B */
gan_squmat_lmult_q ( &smA, &mB, &mC ); /* C = B*A, OR */
gan_squmat_lmultT_q ( &smA, &mB, &mC ); /* C = B^T*A, OR */
gan_squmatT_lmult_q ( &smA, &mB, &mC ); /* C = B*A^T, OR */
gan_squmatT_lmultT_q ( &smA, &mB, &mC ); /* C = B^T*A^T, OR */
gan_squmatI_lmult_q ( &smA, &mB, &mC ); /* C = B*A^-1, OR */
gan_squmatI_lmultT_q ( &smA, &mB, &mC ); /* C = B^T*A^-1, OR */
gan_squmatIT_lmult_q ( &smA, &mB, &mC ); /* C = B*A^-T, OR */
gan_squmatIT_lmultT_q ( &smA, &mB, &mC ); /* C = B^T*A^-T */
These routines have the alternative form
Gan_SquMatrix smA; /* square matrix A */
Gan_Matrix mB, *pmC; /* matrices B & C */
/* ... create and fill matrices A, B ... */
/* routines right-multipling A by B */
pmC = gan_squmat_rmult_s ( &smA, &mB ); /* C = A*B, OR */
pmC = gan_squmat_rmultT_s ( &smA, &mB ); /* C = A*B^T, OR */
pmC = gan_squmatT_rmult_s ( &smA, &mB ); /* C = A^T*B, OR */
pmC = gan_squmatT_rmultT_s ( &smA, &mB ); /* C = A^T*B^T, OR */
pmC = gan_squmatI_rmult_s ( &smA, &mB ); /* C = A^-1*B, OR */
pmC = gan_squmatI_rmultT_s ( &smA, &mB ); /* C = A^-1*B^T, OR */
pmC = gan_squmatIT_rmult_s ( &smA, &mB ); /* C = A^-T*B, OR */
pmC = gan_squmatIT_rmultT_s ( &smA, &mB ); /* C = A^-T*B^T */
/* routines left-multipling A by B */
pmC = gan_squmat_lmult_s ( &smA, &mB ); /* C = B*A, OR */
pmC = gan_squmat_lmultT_s ( &smA, &mB ); /* C = B^T*A, OR */
pmC = gan_squmatT_lmult_s ( &smA, &mB ); /* C = B*A^T, OR */
pmC = gan_squmatT_lmultT_s ( &smA, &mB ); /* C = B^T*A^T, OR */
pmC = gan_squmatI_lmult_s ( &smA, &mB ); /* C = B*A^-1, OR */
pmC = gan_squmatI_lmultT_s ( &smA, &mB ); /* C = B^T*A^-1, OR */
pmC = gan_squmatIT_lmult_s ( &smA, &mB ); /* C = B*A^-T, OR */
pmC = gan_squmatIT_lmultT_s ( &smA, &mB ); /* C = B^T*A^-T */
The in-place versions will overwrite the contents of matrix
Gan_SquMatrix smA; /* square matrix A */
Gan_Matrix mB; /* matrix B */
/* ... create and fill matrices A, B ... */
/* routines right-multipling A by B */
gan_squmat_rmult_i ( &smA, &mB ); /* replace B = A*B, OR */
gan_squmat_rmultT_i ( &smA, &mB ); /* replace B = A*B^T, OR */
gan_squmatT_rmult_i ( &smA, &mB ); /* replace B = A^T*B, OR */
gan_squmatT_rmultT_i ( &smA, &mB ); /* replace B = A^T*B^T, OR */
gan_squmatI_rmult_i ( &smA, &mB ); /* replace B = A^-1*B, OR */
gan_squmatI_rmultT_i ( &smA, &mB ); /* replace B = A^-1*B^T, OR */
gan_squmatIT_rmult_i ( &smA, &mB ); /* replace B = A^-T*B, OR */
gan_squmatIT_rmultT_i ( &smA, &mB ); /* replace B = A^-T*B^T */
/* routines left-multipling A by B */
gan_squmat_lmult_i ( &smA, &mB ); /* replace B = B*A, OR */
gan_squmat_lmultT_i ( &smA, &mB ); /* replace B = B^T*A, OR */
gan_squmatT_lmult_i ( &smA, &mB ); /* replace B = B*A^T, OR */
gan_squmatT_lmultT_i ( &smA, &mB ); /* replace B = B^T*A^T, OR */
gan_squmatI_lmult_i ( &smA, &mB ); /* replace B = B*A^-1, OR */
gan_squmatI_lmultT_i ( &smA, &mB ); /* replace B = B^T*A^-1, OR */
gan_squmatIT_lmult_i ( &smA, &mB ); /* replace B = B*A^-T, OR */
gan_squmatIT_lmultT_i ( &smA, &mB ); /* replace B = B^T*A^-T */
Now we consider multiplying a square matrix
Gan_SquMatrix smA, smB; /* declare matrices A & B */
/* ... create & fill matrix A, create (& optionally fill) matrix B ... */
gan_squmat_srmultT_squ_q ( &smA, &smB ); /* set B = A*A^T, OR */
gan_squmatT_srmult_squ_q ( &smA, &smB ); /* set B = A^T*A, OR */
gan_squmatI_srmultIT_squ_q ( &smA, &smB ); /* set B = A^-1*A^-T, OR */
gan_squmatIT_srmultI_squ_q ( &smA, &smB ); /* set B = A^-T*A^-1 */
There are also routines to build the result matrix
Gan_SquMatrix smA, *psmB; /* declare matrices A & B */
/* ... create & fill matrix A ... */
psmB = gan_squmat_srmultT_squ_s ( &smA ); /* create B = A*A^T, OR */
psmB = gan_squmatT_srmult_squ_s ( &smA ); /* create B = A^T*A, OR */
psmB = gan_squmatI_srmultIT_squ_s ( &smA ); /* create B = A^-1*A^-T, OR */
psmB = gan_squmatIT_srmultI_squ_s ( &smA ); /* create B = A^-T*A^-1 */
and in-place versions of these operations are also available:
Gan_SquMatrix smA; /* declare matrix A */
/* ... create & fill matrix A ... */
gan_squmat_srmultT_squ_i ( &smA ); /* replace A = A*A^T, OR */
gan_squmatT_srmult_squ_i ( &smA ); /* replace A = A^T*A, OR */
gan_squmatI_srmultIT_squ_i ( &smA ); /* replace A = A^-1*A^-T, OR */
gan_squmatIT_srmultI_squ_i ( &smA ); /* replace A = A^-T*A^-1 */
Finally, there is a set of routines that multiply a symmetric matrix on left
and right by a rectangular matrix and its transpose, producing another
symmetric matrix. The operations implemented are
Gan_SquMatrix smS, smSp; /* declare matrices S & S' */
Gan_Matrix mA, mB; /* declare matrices A & B */
/* ... create & fill matrices S & A, create (& optionally fill) matrices B & Sp ... */
gan_symmat_lrmult_q ( &smS, &mA, &mB, &smSp ); /* set B = S*A^T and Sp = A*S*A^T, OR */
gan_symmat_lrmultT_q ( &smS, &mA, &mB, &smSp ); /* set B = S*A and Sp = A^T*S*A */
with alternative versions that create the result matrix
Gan_SquMatrix smS, *psmSp; /* declare matrices S & S' */
Gan_Matrix mA, mB; /* declare matrices A & B */
/* ... create & fill matrices S & A, create (& optionally fill) matrix B ... */
psmSp = gan_symmat_lrmult_s ( &smS, &mA, &mB ); /* set B = S*A^T and Sp = A*S*A^T, OR */
psmSp = gan_symmat_lrmultT_s ( &smS, &mA, &mB ); /* set B = S*A and Sp = A^T*S*A */
It is allowable to pass NULL for the