// this matrix_h04.h file has the specialized matrix multiplication subroutines.










//  the bilinear transformation is self-inverse.
//  a skew-symmetric (or skew-Hermitian) matrix transforms to an orthonormal (or unitary) matrix.
//  an orthonormal (or unitary) ... skew-symmetric (or skew-Hermitian).
//  will error-out with a division by zero for a permutation-matrix input.
MATRIX_DLL_API
int matrix_bilinear(MAT *array_in, MAT *array, MAT *scratch_1, MAT *scratch_2,
					MAT *scratch_3, MAT *scratch_4);


/*  better version added at end on Tuesday 06-th January 2004.
//  the array_in should be a given orth-normal matrix.  otherwise, will error out with a return of 128
//  the intentended domain of the angle is the open interval (-pi, pi); however, its modulus of periodicity is 2pi.
//  WARNING:  will error-out for any angle which is an odd multiple of pi.
//  an angle of 0 yields an identity.  an angle of pi/2 yields the original matrix.
MATRIX_DLL_API
int matrix_orthonormal_family(MAT *array_in, double angle, MAT *array, MAT *scratch_1,
							  MAT *scratch_2, MAT *scratch_3, MAT *scratch_4,
							  MAT *scratch_5, MAT *scratch_6);
*/


MATRIX_DLL_API
int matrix_triple_multiply(MAT *array_a, MAT *array_b, MAT *array_c, MAT *array, MAT *scratch_1);


//  multiplies matrix b by matrix a by the transpose of matrix b.
//	if the matrix b is an ortho-normal (unitary) matrix; this is a similarity transformation.
//	as a by-product, it also yields the transpose of the array_b in the array_btr.
MATRIX_DLL_API
int matrix_multiply_babtr(MAT *array_a, MAT *array_b, MAT *array, MAT *array_btr, MAT *scratch_1);


//  multiplies the matrix b by matrix a by the inverse of matrix b.
//  also yields the determinant of the array_b.
MATRIX_DLL_API
int matrix_multiply_babinv(MAT *array_a, MAT *array_b, MAT *array,
						   MAT *scratch_1, MAT *scratch_2, MAT *scratch_3);


//  multiplies the matrix b by the matrix diag by the transpose of matrix b.
//	if the matrix b is an ortho-normal (unitary) matrix; this is a similarity transformation.
//	as a by-product, it also yields the transpose of the array_b in the array_btr.
MATRIX_DLL_API
int matrix_multiply_bdiagbtr(MAT *diag, MAT *array_b, MAT *array,
							 MAT *array_btr, MAT *scratch_1);


//  multiplies the matrix b by the inverse of the matrix diag by the transpose of the matrix b.
//	if the matrix b is an ortho-normal (unitary) matrix; this is a similarity transformation.
//	as a by-product, it also yields the transpose of the array_b in the array_btr
//		and the inverse of the diag in diag_inv.
MATRIX_DLL_API
int matrix_multiply_bdiagibtr(MAT *diag, MAT *array_b, MAT *array,
							 MAT *array_btr, MAT *diag_inv, MAT *scratch_1);

	
//  multiplies the transpose of the matrix b by the matrix diag by the matrix b.
//	if the matrix b is an ortho-normal (unitary) matrix; this is a similarity transformation.
//	as a by-product, it also yields the transpose of the array_b in the array_btr.
MATRIX_DLL_API
int matrix_multiply_btrdiagb(MAT *diag, MAT *array_b, MAT *array,
							 MAT *array_btr, MAT *scratch_1);
	
	
//  multiplies the branspose of the matrix b by the inverse of the matrix diag by the matrix b.
//	if the matrix b is an ortho-normal (unitary) matrix; this is a similarity transformation.
//	as a by-product, it also yields the transpose of the array_b in the array_btr.
MATRIX_DLL_API
int matrix_multiply_btrdiagib(MAT *diag, MAT *array_b, MAT *array,
							 MAT *array_btr, MAT *scratch_1, MAT *scratch_2);


//	multiplies the diag by the array_in.	
MATRIX_DLL_API
int matrix_diag_mat_multiply(MAT *diag, MAT *array_in, MAT *array);


//	multiplies the array_in by the diag.
MATRIX_DLL_API
int matrix_mat_diag_multiply(MAT *array_in, MAT *diag, MAT *array);


//	multiplies the diag_a by the array_in by the diag_b.
MATRIX_DLL_API
int matrix_diag_mat_diag_multiply(MAT *diag_a, MAT *array_in, MAT *diag_b, MAT *array, MAT *scratch);

	
//  multiplies the inverse of the diag_a by the array_in by the inverse of the diag_b.
MATRIX_DLL_API
int matrix_diagi_mat_diagi_multiply(MAT *diag_a, MAT *array_in, MAT *diag_b, MAT *array,
									MAT *scratch_1, MAT *scratch_2, MAT *scratch_3);


//  multiplies the transpose of array_a by the array_in by the transpose of array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_matt_mat_matt_multiply(MAT *array_a, MAT *array_in, MAT *array_b, MAT *array,
								  MAT *scratch_1, MAT *scratch_2, MAT *scratch_3);

	
//  multiplies the transpose of array_a by the inverse of the diag_a by the array_in
//		by the inverse of the diag_b by the transpose of array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_matt_diagi_mat_diagi_matt_multiply(MAT *array_a, MAT *diag_a, MAT *array_in,
											  MAT *diag_b, MAT *array_b, MAT *array,
											  MAT *scratch_1, MAT *scratch_2,
											  MAT *scratch_3, MAT *scratch_4);

	
//  multiplies array_a by the diag_a by the array_in by the diag_b by the array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diag_mat_diag_mat_multiply(MAT *array_a, MAT *diag_a, MAT *array_in,
											  MAT *diag_b, MAT *array_b, MAT *array,
											  MAT *scratch_1, MAT *scratch_2);

	
//  multiplies array_a by the diag by the array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diag_mat_multiply(MAT *array_a, MAT *diag, MAT *array_b, MAT *array,
								 MAT *scratch);


//  multiplies array_a by the diag by the transpose of the array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diag_matt_multiply(MAT *array_a, MAT *diag, MAT *array_b, MAT *array,
								 MAT *scratch_1, MAT *scratch_2);

	
//	multiplies the transpose of the array_a by the inverse of diag by the array_b.
//	it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matriix.
MATRIX_DLL_API
int matrix_matt_diagi_mat_multiply(MAT *array_a, MAT *diag, MAT *array_b, MAT *array,
								   MAT *scratch_1, MAT *scratch_2);

	
//  multiplies the array_a by the inverse of diag by the array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diagi_mat_multiply(MAT *array_a, MAT *diag, MAT *array_b, MAT *array,
								  MAT *scratch_1, MAT *scratch_2);


//  multiplies the array_a by the inverse of diag by the transpose of the array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diagi_matt_multiply(MAT *array_a, MAT *diag, MAT *array_b, MAT *array,
								  MAT *scratch_1, MAT *scratch_2);

	
	//  multiplies the transpose of array_a by the inverse of diag by the transpose of array_b.
//  it is intended -- but, not required -- that each of the array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_matt_diagi_matt_multiply(MAT *array_a, MAT *diag, MAT *array_b, MAT *array,
								  MAT *scratch_1, MAT *scratch_2, MAT *scratch_3, MAT *scratch_4);

	
//  multiplies array_a by diag_a by array_b by diag by array_c by diag_c by array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diag_mat_diag_mat_diag_mat_multiply(MAT *array_a, MAT *diag_a, MAT *array_b, MAT *diag,
												   MAT *array_c, MAT *diag_c, MAT *array_d, MAT *array,
												   MAT *scratch_1, MAT *scratch_2, MAT *scratch_3);

	
//	multiplies array_a by the inverse of diag_a by array_b by diag by adday_c by
//	the inverse of diag_c by array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diagi_mat_diag_mat_diagi_mat_multiply(MAT *array_a, MAT *diag_a, MAT *array_b,
													 MAT *diag, MAT *array_c, MAT *diag_c,
													 MAT *array_d, MAT *array, MAT *scratch_1,
													 MAT *scratch_2, MAT *scratch_3, MAT *scratch_4);

	
//	multiplies array_a by the inverse of diag_a by array_b by the inverse of diag by adday_c by
//	the inverse of diag_c by array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diagi_mat_diagi_mat_diagi_mat_multiply(MAT *array_a, MAT *diag_a, MAT *array_b,
													 MAT *diag, MAT *array_c, MAT *diag_c,
													 MAT *array_d, MAT *array, MAT *scratch_1,
													 MAT *scratch_2, MAT *scratch_3, MAT *scratch_4);


//  multiplies the transpose of array_a by the inverse of diag_a by the transpose of array_b
//		by diag by array_c, by diag_c by array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_matt_diagi_matt_diag_mat_diag_mat_multiply(MAT *array_a, MAT *diag_a, MAT *array_b, MAT *diag,
												      MAT *array_c, MAT *diag_c, MAT *array_d, MAT *array,
												      MAT *scratch_1, MAT *scratch_2, MAT *scratch_3,
													  MAT *scratch_4, MAT *scratch_5, MAT *scratch_6);
	
	
//  multiplies the transpose of array_a by the inverse of diag_a by the transpose of array_b
//		by the inverse of diag by array_c, by diag_c by array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_matt_diagi_matt_diagi_mat_diag_mat_multiply(MAT *array_a, MAT *diag_a, MAT *array_b, MAT *diag,
												       MAT *array_c, MAT *diag_c, MAT *array_d, MAT *array,
												       MAT *scratch_1, MAT *scratch_2, MAT *scratch_3,
													   MAT *scratch_4, MAT *scratch_5, MAT *scratch_6,
													   MAT *scratch_7);


//  multiplies array_a by diag_a by array_b by diag 
//		by the transpose of array c by the inverse of diag_c by the transnpose of array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diag_mat_diag_matt_diagi_matt_multiply(MAT *array_a, MAT *diag_a, MAT *array_b, MAT *diag,
												      MAT *array_c, MAT *diag_c, MAT *array_d, MAT *array,
												      MAT *scratch_1, MAT *scratch_2, MAT *scratch_3,
													  MAT *scratch_4, MAT *scratch_5, MAT *scratch_6);


//  multiplies array_a by diag_a by array_b by the inverse of diag 
//		by the transpose of array c by the inverse of diag_c by the transnpose of array_d.
//  it is intended -- but, not required -- that each of the array_a, array_b, array_c, and array_d
//		be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_mat_diag_mat_diag_matt_diagi_matt_multiply(MAT *array_a, MAT *diag_a, MAT *array_b, MAT *diag,
												      MAT *array_c, MAT *diag_c, MAT *array_d, MAT *array,
												      MAT *scratch_1, MAT *scratch_2, MAT *scratch_3,
													  MAT *scratch_4, MAT *scratch_5, MAT *scratch_6,
													  MAT *scratch_7);


//	multiplies the inverse of the diag_a by the transpose of array_a by array_in
//		by the transpose of array_b by the inverse of diag_b.
//	it is intended -- but, not required -- that each of array_a and array_b be an ortho-normal matrix.
MATRIX_DLL_API
int matrix_diagi_matt_mat_matt_diagi_multiply(MAT *diag_a, MAT *array_a, MAT *array_in, MAT *array_b,
											  MAT *diag_b, MAT *array, MAT *scratch_1, MAT *scratch_2,
											  MAT *scratch_3, MAT *scratch_4);


MATRIX_DLL_API
int matrix_quintuple_multiply(MAT *array_a, MAT *array_b, MAT *array_c, MAT *array_d, MAT *array_e,
							  MAT *array, MAT *scratch_1, MAT *scratch_2);


MATRIX_DLL_API
int matrix_septuple_multiply(MAT *array_a, MAT *array_b, MAT *array_c, MAT *array_d, MAT *array_e,
							 MAT *array_f, MAT *array_g, MAT *array, MAT *scratch_1, MAT *scratch_2,
							 MAT *scratch_3);


//  complex scalar multiplication:  (a + i b) (array_c + i array_d) = (array_e + i array_f).
//  a, c, and e are the real-parts.  b, d, and f are the imaginary-parts.
//  (a + i b) is the complex-scalar input.  (array_c + i array_d) is the complex-matrix input.
//  (array_e + i array_f) is the complex_matrix output; ie., the product of the foregoing two factors.
MATRIX_DLL_API
int matrix_cmplx_scalar_multiply(double a, double b, MAT *array_c, MAT *array_d, MAT *array_e, MAT *array_f,
								 MAT *scratch_1, MAT *scratch_2);


//  the array_in should be a given orth-normal (unitary) -- but, not a permutation -- matrix.
//	alternatively, it may be a skew-symmetric (skew-Hermitian) -- but, not a zero -- matrix.
//	otherwise, will error out with a return of 128.
//	neither a permutation nor a zero matrix yields meaningful results.  a permutation matrix may error-out with a division by zero.
//  the intentended domain of the angle is the closed interval [-pi, pi]; however, its modulus of periodicity is 2pi.
//  an angle of 0 yields an identity.  an angle of pi/2 yields the original ortho-normal matrix.  an angle of pi yields minus the identity.
//  the resulting ortho-normal (unitary) matrix(-angle) is the transpose -- hence, the inverse -- of matrix(angle).
MATRIX_DLL_API
int matrix_orthonormal_family(MAT *array_in, double angle, MAT *array, MAT *scratch_1,
							  MAT *scratch_2, MAT *scratch_3, MAT *scratch_4,
							  MAT *scratch_5);



// copyright (c) 2003,4 by R.I. 'Scibor-Marchocki.  last modified Monday 17-th May 2004.

// eof
