/*<html><pre>*/
#ifndef V_MATRIX_H
#define V_MATRIX_H

typedef struct matrix_s
{
	u32_t		rows,cols;
	mvec_t		**cell;
	mvec_t		*data;
}	matrix_t, *matrix_p;

#ifdef	__cplusplus
extern	"C" {
#endif	/* __cplusplus */
	/* returns malloc()'ed zero-filled block */
	matrix_p	V_GLOBAL	matAlloc(u32_t rows,u32_t cols);
	/* returns malloc()'ed block filled with contents of 'ref' */
	matrix_p	V_GLOBAL	matDuplicate(matrix_t *ref);
	/* matrices must be equal in size; otherwise will be assert() */
	void		V_GLOBAL	matCopy(matrix_t *dest,matrix_t *src);
	/* size of vector must be equal to number of columns of matrix */
	void		V_GLOBAL	matCopyRow(vector_t *dst,matrix_t *m,u32_t row);
	/* size of vector must be equal to number of rows of matrix */
	void		V_GLOBAL	matCopyCol(vector_t *dst,matrix_t *m,u32_t col);
	/* returns malloc()'ed block filled with contents of row */
	vector_p	V_GLOBAL	matDuplicateRow(matrix_t *m,u32_t row);
	/* returns malloc()'ed block filled with contents of col */
	vector_p	V_GLOBAL	matDuplicateCol(matrix_t *m,u32_t col);
	/* sets matrix to unit */
	void		V_GLOBAL	matUnit(matrix_t *m);
	/* matrices must be equal in size; otherwise will be assert() */
	void		V_GLOBAL	matAdd(matrix_t *dest,matrix_t *m1,
								   matrix_t *m2);
	void		V_GLOBAL	matSub(matrix_t *dest,matrix_t *m1,
								   matrix_t *m2);
	void		V_GLOBAL	matNegate(matrix_t *dest,matrix_t *m);
	vboolean	V_GLOBAL	matCompare(matrix_t *m1,matrix_t *m2);
	/* 'row' or 'col' can be NULL */
	void		V_GLOBAL	matMin(matrix_t *m,u32_t *row,u32_t *col);
	/* 'row' or 'col' can be NULL */
	void		V_GLOBAL	matMax(matrix_t *m,u32_t *row,u32_t *col);
	/* matrices must be equal in size; otherwise will be assert() */
	void		V_GLOBAL 	matScale(matrix_t *dest,matrix_t *m,
									 mvec_t x);
	/*	assert()'s if dest->size!=m->rows || m->cols!=v->size */
	void		V_GLOBAL	matVecMul(vector_t *dest,matrix_t *m,
									  vector_t *v);
	/*	assert()'s if ml->cols!=mr->rows || dest->rows!=ml->rows
	 *	|| dest->cols!=mr->cols */
	void		V_GLOBAL	matMul(matrix_t *dest,matrix_t *ml,
									  matrix_t *mr);
	/*	assert()'s if dest->cols!=m->rows || m->cols!=dest->rows */
	void		V_GLOBAL	matTranspose(matrix_t *dest,matrix_t *m);
	/*	assert()'s if m->cols!=m->rows.
		if keepon==0 than 'm' trashed and than DELETED. */
	mvec_t		V_GLOBAL	matDeterm(matrix_t *m,vboolean keepon);
	/*	If keepon!=0, result stored in vector 'b', else 'b' unmodified and
	 *	solution (in new vector) returned as result. */
	vector_p	V_GLOBAL	matSolve(matrix_t *a,vector_t *b,
									vboolean keepon);
	/*	If !keepon, result stored in given matrix, else 'm' unmodified and
	 *	new inversed matrix returned as result. */
	matrix_p	V_GLOBAL	matInverse(matrix_t *m,vboolean keepon);
#ifdef	MATRIX_NO_MACRO
	void		V_GLOBAL	matZero(matrix_t *m);
	u32_t			V_GLOBAL	matColCount(matrix_t *m);
	u32_t			V_GLOBAL	matRowCount(matrix_t *m);
#endif	/* MATRIX_NO_MACRO */
#ifdef  __cplusplus
}
#endif	/* __cplusplus */

#ifndef	MATRIX_NO_MACRO
#define	matZero(m)\
		v_zerodw((m)->data,(m)->rows*(m)->cols*(sizeof(mvec_t)>>2));
#define	matRowCount(m)			((m)->rows)
#define	matColCount(m)			((m)->cols)
#endif	/* MATRIX_NO_MACRO */

#endif /* V_MATRIX_H */
/*</pre></html>*/
/*EOF*/
