#ifndef _NUMclasses_h_
#define _NUMclasses_h_
/* David Weenink, 19991008 */

#include "NUM2.h"
#ifndef _Data_h_
	#include "Data.h"
#endif

#define SVD_members Data_members		\
	long numberOfRows, numberOfColumns;	\
	double tolerance;	\
	double **u, **v, *d;
#define SVD_methods Data_methods
class_create (SVD, Data)

#define GSVD_members Data_members		\
	SVD a, b;
#define GSVD_methods Data_methods
class_create (GSVD, Data)

SVD SVD_create (long numberOfRows, long numberOfColumns);
/*
	my tolerance = eps * MAX (numberOfRows, numberOfColumns) 
	where eps is the floating point precision, approximately 2.2e-16
*/

SVD SVD_create_d (double **m, long numberOfRows, long numberOfColumns);
SVD SVD_create_f (float **m, long numberOfRows, long numberOfColumns);
int SVD_svd_d (SVD me, double **m);
int SVD_svd_f (SVD me, float **m);
/*
	Perform SVD analysis on matrix M, i.e., decompose M as M = UDV'.
	Watch out: dataType contains V, not V' !!
*/
int SVD_compute (SVD me);

int SVD_solve (SVD me, double b[], double x[]);
/* Solve Ax = b */

int SVD_sort (SVD me);
/*
	Sort singular values (and corresponding column vectors of U and V) in decreasing order.
*/

void SVD_setTolerance (SVD me, double tolerance);
double SVD_getTolerance (SVD me);

long SVD_zeroSmallSingularValues (SVD me, double tolerance);
/*
	Zero singular values smaller than maximum_singular_value * tolerance
	If tolerance == 0 then then my tolerance will be used.
	Return the number of s.v.'s zeroed.
*/

GSVD GSVD_create (long numberOfRows1, long numberOfColumns, long numberOfRows2);
GSVD GSVD_create_d (double **m1, long numberOfRows1, long numberOfColumns,
	double **m2, long numberOfRows2);

#endif /* _NUMclasses_h_ */
