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