Index: /bdm/itpp_ext.cpp
===================================================================
--- /bdm/itpp_ext.cpp (revision 32)
+++ /bdm/itpp_ext.cpp (revision 35)
@@ -188,5 +188,6 @@
 	    /* (if q not positive go to step 8) */
 	    if (q > 0.0) {
-		w = expm1(q);
+		// TODO: w = expm1(q);
+		w = exp(q)-1;
 		/*  ^^^^^ original code had approximation with rel.err < 2e-7 */
 		/* if t is rejected sample again at step 8 */
Index: /tests/test0.cpp
===================================================================
--- /tests/test0.cpp (revision 32)
+++ /tests/test0.cpp (revision 35)
@@ -49,4 +49,5 @@
 
 	//Exit program:
+	getchar();
 	return 0;
 
Index: /tests/CMakeLists.txt
===================================================================
--- /tests/CMakeLists.txt (revision 33)
+++ /tests/CMakeLists.txt (revision 35)
@@ -10,10 +10,5 @@
 
 IF(WIN32)
-	IF(ITPP_INCLUDE_DIR)
-		include_directories(${ITPP_INCLUDE_DIR})
-	ENDIF(ITPP_INCLUDE_DIR)
-	IF(ITPP_LIB_DIR)
-		link_directories(${ITPP_LIB_DIR})
-	ENDIF(ITPP_LIB_DIR)
+	SET(BdmLibs ${BdmLibs} libacml_dll)
 ENDIF(WIN32)
 
Index: /win32/acml3.6.0/pgi32/include/acml.h
===================================================================
--- /win32/acml3.6.0/pgi32/include/acml.h (revision 35)
+++ /win32/acml3.6.0/pgi32/include/acml.h (revision 35)
@@ -0,0 +1,2410 @@
+/*
+ * ACML version 3.6.0 Copyright AMD,NAG 2003,2004,2005
+ */
+
+/*
+  This is the ACML header file. It contains function prototypes
+  to allow a C programmer to call ACML routines via their C
+  or Fortran interfaces.
+
+  C interfaces to ACML routines differ from FORTRAN interfaces in
+  the following major respects:
+
+    (i) The FORTRAN interface names are appended by an underscore.
+
+   (ii) The C interfaces contain no workspace arguments; all
+        workspace memory is allocated internally.
+
+  (iii) Scalar input arguments are passed by value in C interfaces.
+        FORTRAN interfaces pass all arguments (except for character
+        string "length" arguments that are normally hidden from
+        FORTRAN programmers) by reference.
+
+   (iv) Most arguments that are passed as character string pointers
+        to FORTRAN interfaces are passed by value as single
+        characters to C interfaces. The character string "length"
+        arguments of FORTRAN interfaces are not required in the
+        C interfaces.
+
+  It is important to note that in both the FORTRAN and C interfaces,
+  2-dimensional arrays are assumed to be stored in column-major order.
+  e.g. the matrix A = [ 1.0 2.0 ]
+                      [ 3.0 4.0 ]
+  would be stored in memory as 1.0, 3.0, 2.0, 4.0. This storage order
+  corresponds to a FORTRAN-style 2-D array declaration A(2,2), but not
+  to an array declared as a[2][2] in C which would be stored in
+  row-major order as 1.0, 2.0, 3.0, 4.0.
+
+  As an example, compare the FORTRAN and C interfaces of LAPACK
+  routine dsytrf as implemented in ACML.
+  FORTRAN:
+    void dsytrf_(char *uplo, int *n, double *a, int *lda, int *ipiv,
+                 double *work, int *lwork, int *info, int uplo_len);
+
+  C:
+    void dsytrf(char uplo, int n, double *a, int lda, int *ipiv, int *info);
+
+  C code calling both the above variants might look like this:
+
+    double *a;
+    int *ipiv;
+    double *work;
+    int n, lda, lwork, info;
+
+    //
+    // Assume that all arrays and variables are allocated and initialized
+    // as required by dsytrf.
+    //
+    // Call the FORTRAN version of dsytrf. The first argument is a character
+    // string, and the last argument is the length of that string. The input
+    // scalar arguments n, lda and lwork, as well as the output scalar
+    // argument info, are all passed by reference.
+    dsytrf_("Upper", &n, a, &lda, ipiv, work, &lwork, &info, 5);
+
+    //
+    // Call the C version of dsytrf. The first argument is a character,
+    // workspace is not required, and input scalar arguments n and lda are
+    // passed by value. Output scalar argument info is passed by reference.
+    dsytrf('U', n, a, lda, ipiv, &info);
+
+*/
+
+#ifndef _ACML_H
+#define _ACML_H
+
+/* Under Windows math.h defines "complex" to mean "_complex". */
+#include <math.h>
+#undef complex
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* ------------------------------------------------------------------ */
+
+/* A complex datatype for use by the C interfaces to ACML routines */
+#ifndef _ACML_COMPLEX
+#define _ACML_COMPLEX
+typedef struct
+{
+  float real, imag;
+} complex;
+typedef struct
+{
+  double real, imag;
+} doublecomplex;
+#endif /* !defined(_ACML_COMPLEX) */
+
+/*
+   These typedefs are for routines that are arguments to other routines,
+   e.g. ACML_CGEES_SELECT describes the argument "select" of routine cgees.
+ */
+typedef int (* ACML_CGEES_SELECT)(complex *);
+typedef int (* ACML_CGEESX_SELECT)(complex *);
+typedef int (* ACML_CGGES_SELCTG)(complex *, complex *);
+typedef int (* ACML_CGGESX_SELCTG)(complex *, complex *);
+typedef int (* ACML_DGEES_SELECT)(double *, double *);
+typedef int (* ACML_DGEESX_SELECT)(double *, double *);
+typedef int (* ACML_DGGES_DELCTG)(double *, double *, double *);
+typedef int (* ACML_DGGESX_DELCTG)(double *, double *, double *);
+typedef int (* ACML_SGEES_SELECT)(float *, float *);
+typedef int (* ACML_SGEESX_SELECT)(float *, float *);
+typedef int (* ACML_SGGES_SELCTG)(float *, float *, float *);
+typedef int (* ACML_SGGESX_SELCTG)(float *, float *, float *);
+typedef int (* ACML_ZGEES_SELECT)(doublecomplex *);
+typedef int (* ACML_ZGEESX_SELECT)(doublecomplex *);
+typedef int (* ACML_ZGGES_DELCTG)(doublecomplex *, doublecomplex *);
+typedef int (* ACML_ZGGESX_DELCTG)(doublecomplex *, doublecomplex *);
+typedef void (* ACML_DRANDINITIALIZEUSER_UINI)(int *, int *, int *, int *, int *, int *, int *);
+typedef void (* ACML_DRANDINITIALIZEUSER_UGEN)(int *, int *, double *, int *);
+typedef void (* ACML_SRANDINITIALIZEUSER_UINI)(int *, int *, int *, int *, int *, int *, int *);
+typedef void (* ACML_SRANDINITIALIZEUSER_UGEN)(int *, int *, float *, int *);
+
+/* ------------------------------------------------------------------ */
+/* Below are prototypes for the C interfaces to ACML routines */
+
+/* BLAS C interfaces */
+extern void caxpy(int n, complex *alpha, complex *x, int incx, complex *y, int incy);
+extern void ccopy(int n, complex *x, int incx, complex *y, int incy);
+extern complex cdotc(int n, complex *x, int incx, complex *y, int incy);
+extern complex cdotu(int n, complex *x, int incx, complex *y, int incy);
+extern void cgbmv(char transa, int m, int n, int nsub, int nsuper, complex *alpha, complex *a, int lda, complex *x, int incx, complex *beta, complex *y, int incy);
+extern void cgemm(char transa, char transb, int m, int n, int k, complex *alpha, complex *a, int lda, complex *b, int ldb, complex *beta, complex *c, int ldc);
+extern void cgemv(char transa, int m, int n, complex *alpha, complex *a, int lda, complex *x, int incx, complex *beta, complex *y, int incy);
+extern void cgerc(int m, int n, complex *alpha, complex *x, int incx, complex *y, int incy, complex *a, int lda);
+extern void cgeru(int m, int n, complex *alpha, complex *x, int incx, complex *y, int incy, complex *a, int lda);
+extern void chbmv(char uplo, int n, int ndiag, complex *alpha, complex *a, int lda, complex *x, int incx, complex *beta, complex *y, int incy);
+extern void chemm(char side, char uplo, int m, int n, complex *alpha, complex *a, int lda, complex *b, int ldb, complex *beta, complex *c, int ldc);
+extern void chemv(char uplo, int n, complex *alpha, complex *a, int lda, complex *x, int incx, complex *beta, complex *y, int incy);
+extern void cher(char uplo, int n, float alpha, complex *x, int incx, complex *a, int lda);
+extern void cher2(char uplo, int n, complex *alpha, complex *x, int incx, complex *y, int incy, complex *a, int lda);
+extern void cher2k(char uplo, char transa, int n, int k, complex *alpha, complex *a, int lda, complex *b, int ldb, float beta, complex *c, int ldc);
+extern void cherk(char uplo, char transa, int n, int k, float alpha, complex *a, int lda, float beta, complex *c, int ldc);
+extern void chpmv(char uplo, int n, complex *alpha, complex *a, complex *x, int incx, complex *beta, complex *y, int incy);
+extern void chpr(char uplo, int n, float alpha, complex *x, int incx, complex *a);
+extern void chpr2(char uplo, int n, complex *alpha, complex *x, int incx, complex *y, int incy, complex *a);
+extern void crotg(complex *a, complex *b, float *c, complex *s);
+extern void cscal(int n, complex *alpha, complex *y, int incy);
+extern void csrot(int n, complex *x, int incx, complex *y, int incy, float c, float s);
+extern void csscal(int n, float alpha, complex *y, int incy);
+extern void cswap(int n, complex *x, int incx, complex *y, int incy);
+extern void csymm(char side, char uplo, int m, int n, complex *alpha, complex *a, int lda, complex *b, int ldb, complex *beta, complex *c, int ldc);
+extern void csyr2k(char uplo, char transa, int n, int k, complex *alpha, complex *a, int lda, complex *b, int ldb, complex *beta, complex *c, int ldc);
+extern void csyrk(char uplo, char transa, int n, int k, complex *alpha, complex *a, int lda, complex *beta, complex *c, int ldc);
+extern void ctbmv(char uplo, char transa, char diag, int n, int ndiag, complex *a, int lda, complex *y, int incy);
+extern void ctbsv(char uplo, char transa, char diag, int n, int ndiag, complex *a, int lda, complex *y, int incy);
+extern void ctpmv(char uplo, char transa, char diag, int n, complex *a, complex *y, int incy);
+extern void ctpsv(char uplo, char transa, char diag, int n, complex *a, complex *y, int incy);
+extern void ctrmm(char side, char uplo, char transa, char diag, int m, int n, complex *alpha, complex *a, int lda, complex *b, int ldb);
+extern void ctrmv(char uplo, char transa, char diag, int n, complex *a, int lda, complex *y, int incy);
+extern void ctrsm(char side, char uplo, char transa, char diag, int m, int n, complex *alpha, complex *a, int lda, complex *b, int ldb);
+extern void ctrsv(char uplo, char transa, char diag, int n, complex *a, int lda, complex *y, int incy);
+extern double dasum(int n, double *x, int incx);
+extern void daxpy(int n, double alpha, double *x, int incx, double *y, int incy);
+extern void dcopy(int n, double *x, int incx, double *y, int incy);
+extern double ddot(int n, double *x, int incx, double *y, int incy);
+extern void dgbmv(char transa, int m, int n, int nsub, int nsuper, double alpha, double *a, int lda, double *x, int incx, double beta, double *y, int incy);
+extern void dgemm(char transa, char transb, int m, int n, int k, double alpha, double *a, int lda, double *b, int ldb, double beta, double *c, int ldc);
+extern void dgemv(char transa, int m, int n, double alpha, double *a, int lda, double *x, int incx, double beta, double *y, int incy);
+extern void dger(int m, int n, double alpha, double *x, int incx, double *y, int incy, double *a, int lda);
+extern double dnrm2(int n, double *x, int incx);
+extern void drot(int n, double *x, int incx, double *y, int incy, double c, double s);
+extern void drotg(double *a, double *b, double *c, double *s);
+extern void drotm(int n, double *x, int incx, double *y, int incy, double *param);
+extern void drotmg(double d1, double d2, double b1, double b2, double *param);
+extern void dsbmv(char uplo, int n, int ndiag, double alpha, double *a, int lda, double *x, int incx, double beta, double *y, int incy);
+extern void dscal(int n, double alpha, double *y, int incy);
+extern double dsdot(int n, float *x, int incx, float *y, int incy);
+extern void dspmv(char uplo, int n, double alpha, double *a, double *x, int incx, double beta, double *y, int incy);
+extern void dspr(char uplo, int n, double alpha, double *x, int incx, double *a);
+extern void dspr2(char uplo, int n, double alpha, double *x, int incx, double *y, int incy, double *a);
+extern void dswap(int n, double *x, int incx, double *y, int incy);
+extern void dsymm(char side, char uplo, int m, int n, double alpha, double *a, int lda, double *b, int ldb, double beta, double *c, int ldc);
+extern void dsymv(char uplo, int n, double alpha, double *a, int lda, double *x, int incx, double beta, double *y, int incy);
+extern void dsyr(char uplo, int n, double alpha, double *x, int incx, double *a, int lda);
+extern void dsyr2(char uplo, int n, double alpha, double *x, int incx, double *y, int incy, double *a, int lda);
+extern void dsyr2k(char uplo, char transa, int n, int k, double alpha, double *a, int lda, double *b, int ldb, double beta, double *c, int ldc);
+extern void dsyrk(char uplo, char transa, int n, int k, double alpha, double *a, int lda, double beta, double *c, int ldc);
+extern void dtbmv(char uplo, char transa, char diag, int n, int ndiag, double *a, int lda, double *y, int incy);
+extern void dtbsv(char uplo, char transa, char diag, int n, int ndiag, double *a, int lda, double *y, int incy);
+extern void dtpmv(char uplo, char transa, char diag, int n, double *a, double *y, int incy);
+extern void dtpsv(char uplo, char transa, char diag, int n, double *a, double *y, int incy);
+extern void dtrmm(char side, char uplo, char transa, char diag, int m, int n, double alpha, double *a, int lda, double *b, int ldb);
+extern void dtrmv(char uplo, char transa, char diag, int n, double *a, int lda, double *y, int incy);
+extern void dtrsm(char side, char uplo, char transa, char diag, int m, int n, double alpha, double *a, int lda, double *b, int ldb);
+extern void dtrsv(char uplo, char transa, char diag, int n, double *a, int lda, double *y, int incy);
+extern double dzasum(int n, doublecomplex *x, int incx);
+extern double dznrm2(int n, doublecomplex *x, int incx);
+extern int icamax(int n, complex *x, int incx);
+extern int idamax(int n, double *x, int incx);
+extern int isamax(int n, float *x, int incx);
+extern int izamax(int n, doublecomplex *x, int incx);
+extern int lsame(char ca, char cb);
+extern float sasum(int n, float *x, int incx);
+extern void saxpy(int n, float alpha, float *x, int incx, float *y, int incy);
+extern float scasum(int n, complex *x, int incx);
+extern float scnrm2(int n, complex *x, int incx);
+extern void scopy(int n, float *x, int incx, float *y, int incy);
+extern float sdot(int n, float *x, int incx, float *y, int incy);
+extern float sdsdot(int n, float sb, float *sx, int incx, float *sy, int incy);
+extern void sgbmv(char transa, int m, int n, int nsub, int nsuper, float alpha, float *a, int lda, float *x, int incx, float beta, float *y, int incy);
+extern void sgemm(char transa, char transb, int m, int n, int k, float alpha, float *a, int lda, float *b, int ldb, float beta, float *c, int ldc);
+extern void sgemv(char transa, int m, int n, float alpha, float *a, int lda, float *x, int incx, float beta, float *y, int incy);
+extern void sger(int m, int n, float alpha, float *x, int incx, float *y, int incy, float *a, int lda);
+extern float snrm2(int n, float *x, int incx);
+extern void srot(int n, float *x, int incx, float *y, int incy, float c, float s);
+extern void srotg(float *a, float *b, float *c, float *s);
+extern void srotm(int n, float *x, int incx, float *y, int incy, float *param);
+extern void srotmg(float d1, float d2, float b1, float b2, float *param);
+extern void ssbmv(char uplo, int n, int ndiag, float alpha, float *a, int lda, float *x, int incx, float beta, float *y, int incy);
+extern void sscal(int n, float alpha, float *x, int incx);
+extern void sspmv(char uplo, int n, float alpha, float *a, float *x, int incx, float beta, float *y, int incy);
+extern void sspr(char uplo, int n, float alpha, float *x, int incx, float *a);
+extern void sspr2(char uplo, int n, float alpha, float *x, int incx, float *y, int incy, float *a);
+extern void sswap(int n, float *x, int incx, float *y, int incy);
+extern void ssymm(char side, char uplo, int m, int n, float alpha, float *a, int lda, float *b, int ldb, float beta, float *c, int ldc);
+extern void ssymv(char uplo, int n, float alpha, float *a, int lda, float *x, int incx, float beta, float *y, int incy);
+extern void ssyr(char uplo, int n, float alpha, float *x, int incx, float *a, int lda);
+extern void ssyr2(char uplo, int n, float alpha, float *x, int incx, float *y, int incy, float *a, int lda);
+extern void ssyr2k(char uplo, char transa, int n, int k, float alpha, float *a, int lda, float *b, int ldb, float beta, float *c, int ldc);
+extern void ssyrk(char uplo, char transa, int n, int k, float alpha, float *a, int lda, float beta, float *c, int ldc);
+extern void stbmv(char uplo, char transa, char diag, int n, int ndiag, float *a, int lda, float *y, int incy);
+extern void stbsv(char uplo, char transa, char diag, int n, int ndiag, float *a, int lda, float *y, int incy);
+extern void stpmv(char uplo, char transa, char diag, int n, float *a, float *y, int incy);
+extern void stpsv(char uplo, char transa, char diag, int n, float *a, float *y, int incy);
+extern void strmm(char side, char uplo, char transa, char diag, int m, int n, float alpha, float *a, int lda, float *b, int ldb);
+extern void strmv(char uplo, char transa, char diag, int n, float *a, int lda, float *y, int incy);
+extern void strsm(char side, char uplo, char transa, char diag, int m, int n, float alpha, float *a, int lda, float *b, int ldb);
+extern void strsv(char uplo, char transa, char diag, int n, float *a, int lda, float *y, int incy);
+extern void xerbla(const char *srname, int *info);
+extern void zaxpy(int n, doublecomplex *alpha, doublecomplex *x, int incx, doublecomplex *y, int incy);
+extern void zcopy(int n, doublecomplex *x, int incx, doublecomplex *y, int incy);
+extern doublecomplex zdotc(int n, doublecomplex *x, int incx, doublecomplex *y, int incy);
+extern doublecomplex zdotu(int n, doublecomplex *x, int incx, doublecomplex *y, int incy);
+extern void zdrot(int n, doublecomplex *cx, int incx, doublecomplex *cy, int incy, double c, double s);
+extern void zdscal(int n, double alpha, doublecomplex *y, int incy);
+extern void zgbmv(char transa, int m, int n, int nsub, int nsuper, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *x, int incx, doublecomplex *beta, doublecomplex *y, int incy);
+extern void zgemm(char transa, char transb, int m, int n, int k, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *beta, doublecomplex *c, int ldc);
+extern void zgemv(char transa, int m, int n, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *x, int incx, doublecomplex *beta, doublecomplex *y, int incy);
+extern void zgerc(int m, int n, doublecomplex *alpha, doublecomplex *x, int incx, doublecomplex *y, int incy, doublecomplex *a, int lda);
+extern void zgeru(int m, int n, doublecomplex *alpha, doublecomplex *x, int incx, doublecomplex *y, int incy, doublecomplex *a, int lda);
+extern void zhbmv(char uplo, int n, int ndiag, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *x, int incx, doublecomplex *beta, doublecomplex *y, int incy);
+extern void zhemm(char side, char uplo, int m, int n, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *beta, doublecomplex *c, int ldc);
+extern void zhemv(char uplo, int n, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *x, int incx, doublecomplex *beta, doublecomplex *y, int incy);
+extern void zher(char uplo, int n, double alpha, doublecomplex *x, int incx, doublecomplex *a, int lda);
+extern void zher2(char uplo, int n, doublecomplex *alpha, doublecomplex *x, int incx, doublecomplex *y, int incy, doublecomplex *a, int lda);
+extern void zher2k(char uplo, char transa, int n, int k, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb, double beta, doublecomplex *c, int ldc);
+extern void zherk(char uplo, char transa, int n, int k, double alpha, doublecomplex *a, int lda, double beta, doublecomplex *c, int ldc);
+extern void zhpmv(char uplo, int n, doublecomplex *alpha, doublecomplex *a, doublecomplex *x, int incx, doublecomplex *beta, doublecomplex *y, int incy);
+extern void zhpr(char uplo, int n, double alpha, doublecomplex *x, int incx, doublecomplex *a);
+extern void zhpr2(char uplo, int n, doublecomplex *alpha, doublecomplex *x, int incx, doublecomplex *y, int incy, doublecomplex *a);
+extern void zrotg(doublecomplex *a, doublecomplex *b, double *c, doublecomplex *s);
+extern void zscal(int n, doublecomplex *alpha, doublecomplex *y, int incy);
+extern void zswap(int n, doublecomplex *x, int incx, doublecomplex *y, int incy);
+extern void zsymm(char side, char uplo, int m, int n, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *beta, doublecomplex *c, int ldc);
+extern void zsyr2k(char uplo, char transa, int n, int k, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *beta, doublecomplex *c, int ldc);
+extern void zsyrk(char uplo, char transa, int n, int k, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *beta, doublecomplex *c, int ldc);
+extern void ztbmv(char uplo, char transa, char diag, int n, int ndiag, doublecomplex *a, int lda, doublecomplex *y, int incy);
+extern void ztbsv(char uplo, char transa, char diag, int n, int ndiag, doublecomplex *a, int lda, doublecomplex *y, int incy);
+extern void ztpmv(char uplo, char transa, char diag, int n, doublecomplex *a, doublecomplex *y, int incy);
+extern void ztpsv(char uplo, char transa, char diag, int n, doublecomplex *a, doublecomplex *y, int incy);
+extern void ztrmm(char side, char uplo, char transa, char diag, int m, int n, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb);
+extern void ztrmv(char uplo, char transa, char diag, int n, doublecomplex *a, int lda, doublecomplex *y, int incy);
+extern void ztrsm(char side, char uplo, char transa, char diag, int m, int n, doublecomplex *alpha, doublecomplex *a, int lda, doublecomplex *b, int ldb);
+extern void ztrsv(char uplo, char transa, char diag, int n, doublecomplex *a, int lda, doublecomplex *y, int incy);
+
+/* LAPACK C interfaces */
+extern int ilaenv(int ispec, const char *name, const char *opts, int n1, int n2, int n3, int n4);
+extern void ilaenvset(int ispec, const char *name, const char *opts, int n1, int n2, int n3, int n4, int nvalue, int *info);
+extern void cbdsqr(char uplo, int n, int ncvt, int nru, int ncc, float *d, float *e, complex *vt, int ldvt, complex *u, int ldu, complex *c, int ldc, int *info);
+extern void cgbbrd(char vect, int m, int n, int ncc, int kl, int ku, complex *ab, int ldab, float *d, float *e, complex *q, int ldq, complex *pt, int ldpt, complex *c, int ldc, int *info);
+extern void cgbcon(char norm, int n, int nsub, int nsuper, complex *a, int lda, int *ipiv, float anorm, float *rcond, int *info);
+extern void cgbequ(int m, int n, int nsub, int nsuper, complex *a, int lda, float *rowsc, float *colsc, float *rowcnd, float *colcnd, float *amax, int *info);
+extern void cgbrfs(char transa, int n, int nsub, int nsuper, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cgbsv(int n, int nsub, int nsuper, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+
+/* N.B. In this C interface to cgbsvx, rpvgrw returns what is returned in
+   the first element of RWORK by the FORTRAN interface */
+extern void cgbsvx(char fact, char transa, int n, int nsub, int nsuper, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, char equed, float *rowsc, float *colsc, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, float *rpvgrw, int *info);
+
+extern void cgbtrf(int m, int n, int nsub, int nsuper, complex *a, int lda, int *ipiv, int *info);
+extern void cgbtrs(char transa, int n, int nsub, int nsuper, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void cgebak(char job, char side, int n, int ilo, int ihi, float *scale, int m, complex *v, int ldv, int *info);
+extern void cgebal(char job, int n, complex *a, int lda, int *ilo, int *ihi, float *scale, int *info);
+extern void cgebrd(int m, int n, complex *a, int lda, float *d, float *e, complex *tauq, complex *taup, int *info);
+extern void cgecon(char norm, int n, complex *a, int lda, float anorm, float *rcond, int *info);
+extern void cgeequ(int m, int n, complex *a, int lda, float *rowsc, float *colsc, float *rowcnd, float *colcnd, float *amax, int *info);
+extern void cgees(char jobz, char sortev, ACML_CGEES_SELECT select, int n, complex *a, int lda, int *nout, complex *w, complex *z, int ldz, int *info);
+extern void cgeesx(char jobz, char sortev, ACML_CGEESX_SELECT select, char sense, int n, complex *a, int lda, int *nout, complex *w, complex *z, int ldz, float *rcone, float *rconv, int *info);
+extern void cgeev(char jobvl, char jobvr, int n, complex *a, int lda, complex *w, complex *vl, int ldvl, complex *vr, int ldvr, int *info);
+extern void cgeevx(char balanc, char jobvl, char jobvr, char sense, int n, complex *a, int lda, complex *w, complex *vl, int ldvl, complex *vr, int ldvr, int *ilo, int *ihi, float *scale, float *abnrm, float *rconde, float *rcondv, int *info);
+extern void cgegs(char jobvsl, char jobvsr, int n, complex *a, int lda, complex *b, int ldb, complex *alpha, complex *beta, complex *vsl, int ldvsl, complex *vsr, int ldvsr, int *info);
+extern void cgegv(char jobvl, char jobvr, int n, complex *a, int lda, complex *b, int ldb, complex *alpha, complex *beta, complex *vl, int ldvl, complex *vr, int ldvr, int *info);
+extern void cgehrd(int n, int ilo, int ihi, complex *a, int lda, complex *tau, int *info);
+extern void cgelqf(int m, int n, complex *a, int lda, complex *tau, int *info);
+extern void cgels(char trans, int m, int n, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void cgelsd(int m, int n, int nrhs, complex *a, int lda, complex *b, int ldb, float *s, float rcond, int *rank, int *info);
+extern void cgelss(int m, int n, int nrhs, complex *a, int lda, complex *b, int ldb, float *sing, float rcond, int *irank, int *info);
+extern void cgelsx(int m, int n, int nrhs, complex *a, int lda, complex *b, int ldb, int *jpivot, float rcond, int *irank, int *info);
+extern void cgelsy(int m, int n, int nrhs, complex *a, int lda, complex *b, int ldb, int *jpvt, float rcond, int *rank, int *info);
+extern void cgeqlf(int m, int n, complex *a, int lda, complex *tau, int *info);
+extern void cgeqp3(int m, int n, complex *a, int lda, int *jpvt, complex *tau, int *info);
+extern void cgeqpf(int m, int n, complex *a, int lda, int *jpvt, complex *tau, int *info);
+extern void cgeqrf(int m, int n, complex *a, int lda, complex *tau, int *info);
+extern void cgerfs(char transa, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cgerqf(int m, int n, complex *a, int lda, complex *tau, int *info);
+extern void cgesdd(char jobz, int m, int n, complex *a, int lda, float *s, complex *u, int ldu, complex *vt, int ldvt, int *info);
+extern void cgesv(int n, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void cgesvd(char jobu, char jobvt, int m, int n, complex *a, int lda, float *sing, complex *u, int ldu, complex *vt, int ldvt, int *info);
+
+/* N.B. In this C interface to cgesvx, rpvgrw returns what is returned in
+   the first element of RWORK by the FORTRAN interface */
+extern void cgesvx(char fact, char transa, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, char equed, float *rowsc, float *colsc, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, float *rpvgrw, int *info);
+
+extern void cgetrf(int m, int n, complex *a, int lda, int *ipiv, int *info);
+extern void cgetri(int n, complex *a, int lda, int *ipiv, int *info);
+extern void cgetrs(char transa, int n, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void cggbak(char job, char side, int n, int ilo, int ihi, float *lscale, float *rscale, int m, complex *v, int ldv, int *info);
+extern void cggbal(char job, int n, complex *a, int lda, complex *b, int ldb, int *ilo, int *ihi, float *lscale, float *rscale, int *info);
+extern void cgges(char jobvsl, char jobvsr, char sort, ACML_CGGES_SELCTG selctg, int n, complex *a, int lda, complex *b, int ldb, int *sdim, complex *alpha, complex *beta, complex *vsl, int ldvsl, complex *vsr, int ldvsr, int *info);
+extern void cggesx(char jobvsl, char jobvsr, char sort, ACML_CGGESX_SELCTG selctg, char sense, int n, complex *a, int lda, complex *b, int ldb, int *sdim, complex *alpha, complex *beta, complex *vsl, int ldvsl, complex *vsr, int ldvsr, float *rconde, float *rcondv, int *info);
+extern void cggev(char jobvl, char jobvr, int n, complex *a, int lda, complex *b, int ldb, complex *alpha, complex *beta, complex *vl, int ldvl, complex *vr, int ldvr, int *info);
+extern void cggevx(char balanc, char jobvl, char jobvr, char sense, int n, complex *a, int lda, complex *b, int ldb, complex *alpha, complex *beta, complex *vl, int ldvl, complex *vr, int ldvr, int *ilo, int *ihi, float *lscale, float *rscale, float *abnrm, float *bbnrm, float *rconde, float *rcondv, int *info);
+extern void cggglm(int n, int m, int p, complex *a, int lda, complex *b, int ldb, complex *d, complex *x, complex *y, int *info);
+extern void cgghrd(char compq, char compz, int n, int ilo, int ihi, complex *a, int lda, complex *b, int ldb, complex *q, int ldq, complex *z, int ldz, int *info);
+extern void cgglse(int m, int n, int p, complex *a, int lda, complex *b, int ldb, complex *c, complex *d, complex *x, int *info);
+extern void cggqrf(int n, int m, int p, complex *a, int lda, complex *taua, complex *b, int ldb, complex *taub, int *info);
+extern void cggrqf(int m, int p, int n, complex *a, int lda, complex *taua, complex *b, int ldb, complex *taub, int *info);
+extern void cggsvd(char jobu, char jobv, char jobq, int m, int n, int p, int *k, int *l, complex *a, int lda, complex *b, int ldb, float *alpha, float *beta, complex *u, int ldu, complex *v, int ldv, complex *q, int ldq, int *iwork, int *info);
+extern void cggsvp(char jobu, char jobv, char jobq, int m, int p, int n, complex *a, int lda, complex *b, int ldb, float tola, float tolb, int *k, int *l, complex *u, int ldu, complex *v, int ldv, complex *q, int ldq, int *info);
+extern void cgtcon(char norm, int n, complex *low, complex *diag, complex *up1, complex *up2, int *ipiv, float anorm, float *rcond, int *info);
+extern void cgtrfs(char transa, int n, int nrhs, complex *low, complex *diag, complex *up, complex *lowf, complex *diagf, complex *upf1, complex *upf2, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cgtsv(int n, int nrhs, complex *low, complex *diag, complex *up, complex *b, int ldb, int *info);
+extern void cgtsvx(char fact, char transa, int n, int nrhs, complex *low, complex *diag, complex *up, complex *lowf, complex *diagf, complex *upf1, complex *upf2, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void cgttrf(int n, complex *low, complex *diag, complex *up1, complex *up2, int *ipiv, int *info);
+extern void cgttrs(char transa, int n, int nrhs, complex *low, complex *diag, complex *up1, complex *up2, int *ipiv, complex *b, int ldb, int *info);
+extern void chbev(char jobz, char uplo, int n, int ndiag, complex *a, int lda, float *w, complex *z, int ldz, int *info);
+extern void chbevd(char jobz, char uplo, int n, int kd, complex *ab, int ldab, float *w, complex *z, int ldz, int *info);
+extern void chbevx(char jobz, char range, char uplo, int n, int ndiag, complex *a, int lda, complex *q, int ldq, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, complex *z, int ldz, int *ifail, int *info);
+extern void chbgst(char vect, char uplo, int n, int ka, int kb, complex *ab, int ldab, complex *bb, int ldbb, complex *x, int ldx, int *info);
+extern void chbgv(char jobz, char uplo, int n, int ka, int kb, complex *ab, int ldab, complex *bb, int ldbb, float *w, complex *z, int ldz, int *info);
+extern void chbgvd(char jobz, char uplo, int n, int ka, int kb, complex *ab, int ldab, complex *bb, int ldbb, float *w, complex *z, int ldz, int *info);
+extern void chbgvx(char jobz, char range, char uplo, int n, int ka, int kb, complex *ab, int ldab, complex *bb, int ldbb, complex *q, int ldq, float vl, float vu, int il, int iu, float abstol, int *m, float *w, complex *z, int ldz, int *ifail, int *info);
+extern void chbtrd(char vect, char uplo, int n, int kd, complex *ab, int ldab, float *d, float *e, complex *q, int ldq, int *info);
+extern void checon(char uplo, int n, complex *a, int lda, int *ipiv, float anorm, float *rcond, int *info);
+extern void cheev(char jobz, char uplo, int n, complex *a, int lda, float *w, int *info);
+extern void cheevd(char jobz, char uplo, int n, complex *a, int lda, float *w, int *info);
+extern void cheevr(char jobz, char range, char uplo, int n, complex *a, int lda, float vl, float vu, int il, int iu, float abstol, int *m, float *w, complex *z, int ldz, int *isuppz, int *info);
+extern void cheevx(char jobz, char range, char uplo, int n, complex *a, int lda, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, complex *z, int ldz, int *ifail, int *info);
+extern void chegst(int itype, char uplo, int n, complex *a, int lda, complex *b, int ldb, int *info);
+extern void chegv(int itype, char jobz, char uplo, int n, complex *a, int lda, complex *b, int ldb, float *w, int *info);
+extern void chegvd(int itype, char jobz, char uplo, int n, complex *a, int lda, complex *b, int ldb, float *w, int *info);
+extern void chegvx(int itype, char jobz, char range, char uplo, int n, complex *a, int lda, complex *b, int ldb, float vl, float vu, int il, int iu, float abstol, int *m, float *w, complex *z, int ldz, int *ifail, int *info);
+extern void cherfs(char uplo, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void chesv(char uplo, int n, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void chesvx(char fact, char uplo, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void chetrd(char uplo, int n, complex *a, int lda, float *d, float *e, complex *tau, int *info);
+extern void chetrf(char uplo, int n, complex *a, int lda, int *ipiv, int *info);
+extern void chetri(char uplo, int n, complex *a, int lda, int *ipiv, int *info);
+extern void chetrs(char uplo, int n, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void chgeqz(char job, char compq, char compz, int n, int ilo, int ihi, complex *a, int lda, complex *b, int ldb, complex *alpha, complex *beta, complex *q, int ldq, complex *z, int ldz, int *info);
+extern void chpcon(char uplo, int n, complex *a, int *ipiv, float anorm, float *rcond, int *info);
+extern void chpev(char jobz, char uplo, int n, complex *a, float *w, complex *z, int ldz, int *info);
+extern void chpevd(char jobz, char uplo, int n, complex *ap, float *w, complex *z, int ldz, int *info);
+extern void chpevx(char jobz, char range, char uplo, int n, complex *a, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, complex *z, int ldz, int *ifail, int *info);
+extern void chpgst(int itype, char uplo, int n, complex *ap, complex *bp, int *info);
+extern void chpgv(int itype, char jobz, char uplo, int n, complex *a, complex *b, float *w, complex *z, int ldz, int *info);
+extern void chpgvd(int itype, char jobz, char uplo, int n, complex *ap, complex *bp, float *w, complex *z, int ldz, int *info);
+extern void chpgvx(int itype, char jobz, char range, char uplo, int n, complex *ap, complex *bp, float vl, float vu, int il, int iu, float abstol, int *m, float *w, complex *z, int ldz, int *ifail, int *info);
+extern void chprfs(char uplo, int n, int nrhs, complex *a, complex *af, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void chpsv(char uplo, int n, int nrhs, complex *a, int *ipiv, complex *b, int ldb, int *info);
+extern void chpsvx(char fact, char uplo, int n, int nrhs, complex *a, complex *af, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void chptrd(char uplo, int n, complex *ap, float *d, float *e, complex *tau, int *info);
+extern void chptrf(char uplo, int n, complex *a, int *ipiv, int *info);
+extern void chptri(char uplo, int n, complex *a, int *ipiv, int *info);
+extern void chptrs(char uplo, int n, int nrhs, complex *a, int *ipiv, complex *b, int ldb, int *info);
+extern void chsein(char side, char eigsrc, char initv, int *select, int n, complex *h, int ldh, complex *w, complex *vl, int ldvl, complex *vr, int ldvr, int mm, int *m, int *ifaill, int *ifailr, int *info);
+extern void chseqr(char job, char compz, int n, int ilo, int ihi, complex *h, int ldh, complex *w, complex *z, int ldz, int *info);
+extern void cpbcon(char uplo, int n, int ndiag, complex *a, int lda, float anorm, float *rcond, int *info);
+extern void cpbequ(char uplo, int n, int ndiag, complex *a, int lda, float *scale, float *scond, float *amax, int *info);
+extern void cpbrfs(char uplo, int n, int ndiag, int nrhs, complex *a, int lda, complex *af, int ldaf, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cpbstf(char uplo, int n, int kd, complex *ab, int ldab, int *info);
+extern void cpbsv(char uplo, int n, int ndiag, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void cpbsvx(char fact, char uplo, int n, int ndiag, int nrhs, complex *a, int lda, complex *af, int ldaf, char equed, float *scale, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void cpbtrf(char uplo, int n, int ndiag, complex *a, int lda, int *info);
+extern void cpbtrs(char uplo, int n, int ndiag, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void cpocon(char uplo, int n, complex *a, int lda, float anorm, float *rcond, int *info);
+extern void cpoequ(int n, complex *a, int lda, float *scale, float *scond, float *amax, int *info);
+extern void cporfs(char uplo, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cposv(char uplo, int n, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void cposvx(char fact, char uplo, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, char equed, float *scale, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void cpotrf(char uplo, int n, complex *a, int lda, int *info);
+extern void cpotri(char uplo, int n, complex *a, int lda, int *info);
+extern void cpotrs(char uplo, int n, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void cppcon(char uplo, int n, complex *a, float anorm, float *rcond, int *info);
+extern void cppequ(char uplo, int n, complex *a, float *scale, float *scond, float *amax, int *info);
+extern void cpprfs(char uplo, int n, int nrhs, complex *a, complex *af, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cppsv(char uplo, int n, int nrhs, complex *a, complex *b, int ldb, int *info);
+extern void cppsvx(char fact, char uplo, int n, int nrhs, complex *a, complex *af, char equed, float *scale, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void cpptrf(char uplo, int n, complex *a, int *info);
+extern void cpptri(char uplo, int n, complex *a, int *info);
+extern void cpptrs(char uplo, int n, int nrhs, complex *a, complex *b, int ldb, int *info);
+extern void cptcon(int n, float *diag, complex *offd, float anorm, float *rcond, int *info);
+extern void cpteqr(char compz, int n, float *d, float *e, complex *z, int ldz, int *info);
+extern void cptrfs(char uplo, int n, int nrhs, float *diag, complex *offd, float *diagf, complex *offdf, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cptsv(int n, int nrhs, float *diag, complex *sub, complex *b, int ldb, int *info);
+extern void cptsvx(char fact, int n, int nrhs, float *diag, complex *sub, float *diagf, complex *subf, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void cpttrf(int n, float *diag, complex *offd, int *info);
+extern void cpttrs(char uplo, int n, int nrhs, float *diag, complex *offd, complex *b, int ldb, int *info);
+extern void cspcon(char uplo, int n, complex *a, int *ipiv, float anorm, float *rcond, int *info);
+extern void csprfs(char uplo, int n, int nrhs, complex *a, complex *af, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void cspsv(char uplo, int n, int nrhs, complex *a, int *ipiv, complex *b, int ldb, int *info);
+extern void cspsvx(char fact, char uplo, int n, int nrhs, complex *a, complex *af, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void csptrf(char uplo, int n, complex *a, int *ipiv, int *info);
+extern void csptri(char uplo, int n, complex *a, int *ipiv, int *info);
+extern void csptrs(char uplo, int n, int nrhs, complex *a, int *ipiv, complex *b, int ldb, int *info);
+extern void cstedc(char compz, int n, float *d, float *e, complex *z, int ldz, int *info);
+extern void cstegr(char jobz, char range, int n, float *d, float *e, float vl, float vu, int il, int iu, float abstol, int *m, float *w, complex *z, int ldz, int *isuppz, int *info);
+extern void cstein(int n, float *d, float *e, int m, float *w, int *iblock, int *isplit, complex *z, int ldz, int *ifail, int *info);
+extern void csteqr(char compz, int n, float *d, float *e, complex *z, int ldz, int *info);
+extern void csycon(char uplo, int n, complex *a, int lda, int *ipiv, float anorm, float *rcond, int *info);
+extern void csyrfs(char uplo, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void csysv(char uplo, int n, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void csysvx(char fact, char uplo, int n, int nrhs, complex *a, int lda, complex *af, int ldaf, int *ipiv, complex *b, int ldb, complex *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void csytrf(char uplo, int n, complex *a, int lda, int *ipiv, int *info);
+extern void csytri(char uplo, int n, complex *a, int lda, int *ipiv, int *info);
+extern void csytrs(char uplo, int n, int nrhs, complex *a, int lda, int *ipiv, complex *b, int ldb, int *info);
+extern void ctbcon(char norm, char uplo, char diag, int n, int ndiag, complex *a, int lda, float *rcond, int *info);
+extern void ctbrfs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, complex *a, int lda, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void ctbtrs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void ctgevc(char side, char howmny, int *select, int n, complex *a, int lda, complex *b, int ldb, complex *vl, int ldvl, complex *vr, int ldvr, int mm, int *m, int *info);
+extern void ctgexc(int wantq, int wantz, int n, complex *a, int lda, complex *b, int ldb, complex *q, int ldq, complex *z, int ldz, int *ifst, int *ilst, int *info);
+extern void ctgsen(int ijob, int wantq, int wantz, int *select, int n, complex *a, int lda, complex *b, int ldb, complex *alpha, complex *beta, complex *q, int ldq, complex *z, int ldz, int *m, float *pl, float *pr, float *dif, int *info);
+extern void ctgsja(char jobu, char jobv, char jobq, int m, int p, int n, int k, int l, complex *a, int lda, complex *b, int ldb, float tola, float tolb, float *alpha, float *beta, complex *u, int ldu, complex *v, int ldv, complex *q, int ldq, int *ncycle, int *info);
+extern void ctgsna(char job, char howmnt, int *select, int n, complex *a, int lda, complex *b, int ldb, complex *vl, int ldvl, complex *vr, int ldvr, float *s, float *dif, int mm, int *m, int *info);
+extern void ctgsyl(char trans, int ijob, int m, int n, complex *a, int lda, complex *b, int ldb, complex *c, int ldc, complex *d, int ldd, complex *e, int lde, complex *f, int ldf, float *scale, float *dif, int *info);
+extern void ctpcon(char norm, char uplo, char diag, int n, complex *a, float *rcond, int *info);
+extern void ctprfs(char uplo, char transa, char diag, int n, int nrhs, complex *a, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void ctptri(char uplo, char diag, int n, complex *a, int *info);
+extern void ctptrs(char uplo, char transa, char diag, int n, int nrhs, complex *a, complex *b, int ldb, int *info);
+extern void ctrcon(char norm, char uplo, char diag, int n, complex *a, int lda, float *rcond, int *info);
+extern void ctrevc(char side, char howmny, int *select, int n, complex *t, int ldt, complex *vl, int ldvl, complex *vr, int ldvr, int mm, int *m, int *info);
+extern void ctrexc(char compq, int n, complex *t, int ldt, complex *q, int ldq, int ifst, int ilst, int *info);
+extern void ctrrfs(char uplo, char transa, char diag, int n, int nrhs, complex *a, int lda, complex *b, int ldb, complex *x, int ldx, float *ferr, float *berr, int *info);
+extern void ctrsen(char job, char compq, int *select, int n, complex *t, int ldt, complex *q, int ldq, complex *w, int *m, float *s, float *sep, int *info);
+extern void ctrsna(char job, char howmny, int *select, int n, complex *t, int ldt, complex *vl, int ldvl, complex *vr, int ldvr, float *s, float *sep, int mm, int *m, int *info);
+extern void ctrsyl(char trana, char tranb, int isgn, int m, int n, complex *a, int lda, complex *b, int ldb, complex *c, int ldc, float *scale, int *info);
+extern void ctrtri(char uplo, char diag, int n, complex *a, int lda, int *info);
+extern void ctrtrs(char uplo, char transa, char diag, int n, int nrhs, complex *a, int lda, complex *b, int ldb, int *info);
+extern void ctzrqf(int m, int n, complex *a, int lda, complex *tau, int *info);
+extern void ctzrzf(int m, int n, complex *a, int lda, complex *tau, int *info);
+extern void cungbr(char vect, int m, int n, int k, complex *a, int lda, complex *tau, int *info);
+extern void cunghr(int n, int ilo, int ihi, complex *a, int lda, complex *tau, int *info);
+extern void cunglq(int m, int n, int k, complex *a, int lda, complex *tau, int *info);
+extern void cungql(int m, int n, int k, complex *a, int lda, complex *tau, int *info);
+extern void cungqr(int m, int n, int k, complex *a, int lda, complex *tau, int *info);
+extern void cungrq(int m, int n, int k, complex *a, int lda, complex *tau, int *info);
+extern void cungtr(char uplo, int n, complex *a, int lda, complex *tau, int *info);
+extern void cunmbr(char vect, char side, char trans, int m, int n, int k, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmhr(char side, char trans, int m, int n, int ilo, int ihi, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmlq(char side, char trans, int m, int n, int k, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmql(char side, char trans, int m, int n, int k, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmqr(char side, char trans, int m, int n, int k, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmrq(char side, char trans, int m, int n, int k, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmrz(char side, char trans, int m, int n, int k, int l, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cunmtr(char side, char uplo, char trans, int m, int n, complex *a, int lda, complex *tau, complex *c, int ldc, int *info);
+extern void cupgtr(char uplo, int n, complex *ap, complex *tau, complex *q, int ldq, int *info);
+extern void cupmtr(char side, char uplo, char trans, int m, int n, complex *ap, complex *tau, complex *c, int ldc, int *info);
+extern void dbdsdc(char uplo, char compq, int n, double *d, double *e, double *u, int ldu, double *vt, int ldvt, double *q, int *iq, int *info);
+extern void dbdsqr(char uplo, int n, int ncvt, int nru, int ncc, double *d, double *e, double *vt, int ldvt, double *u, int ldu, double *c, int ldc, int *info);
+extern void ddisna(char job, int m, int n, double *d, double *sep, int *info);
+extern void dgbbrd(char vect, int m, int n, int ncc, int kl, int ku, double *ab, int ldab, double *d, double *e, double *q, int ldq, double *pt, int ldpt, double *c, int ldc, int *info);
+extern void dgbcon(char norm, int n, int nsub, int nsuper, double *a, int lda, int *ipiv, double anorm, double *rcond, int *info);
+extern void dgbequ(int m, int n, int nsub, int nsuper, double *a, int lda, double *rowsc, double *colsc, double *rowcn, double *colcn, double *amax, int *info);
+extern void dgbrfs(char transa, int n, int nsub, int nsuper, int nrhs, double *a, int lda, double *af, int ldaf, int *ipiv, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dgbsv(int n, int nsub, int nsuper, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb, int *info);
+
+/* N.B. In this C interface to dgbsvx, rpvgrw returns what is returned in
+   the first element of WORK by the FORTRAN interface */
+extern void dgbsvx(char fact, char transa, int n, int nsub, int nsuper, int nrhs, double *a, int lda, double *af, int ldaf, int *ipiv, char equed, double *rowsc, double *colsc, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, double *rpvgrw, int *info);
+
+extern void dgbtrf(int m, int n, int nsub, int nsuper, double *a, int lda, int *ipiv, int *info);
+extern void dgbtrs(char transa, int n, int nsub, int nsuper, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb, int *info);
+extern void dgebak(char job, char side, int n, int ilo, int ihi, double *scale, int m, double *v, int ldv, int *info);
+extern void dgebal(char job, int n, double *a, int lda, int *ilo, int *ihi, double *scale, int *info);
+extern void dgebrd(int m, int n, double *a, int lda, double *d, double *e, double *tauq, double *taup, int *info);
+extern void dgecon(char norm, int n, double *a, int lda, double anorm, double *rcond, int *info);
+extern void dgeequ(int m, int n, double *a, int lda, double *rowsc, double *colsc, double *rowcn, double *colcn, double *amax, int *info);
+extern void dgees(char jobz, char sortev, ACML_DGEES_SELECT select, int n, double *a, int lda, int *nout, double *wr, double *wi, double *z, int ldz, int *info);
+extern void dgeesx(char jobz, char sortev, ACML_DGEESX_SELECT select, char sense, int n, double *a, int lda, int *nout, double *wr, double *wi, double *z, int ldz, double *srcone, double *rconv, int *info);
+extern void dgeev(char jobvl, char jobvr, int n, double *a, int lda, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, int *info);
+extern void dgeevx(char balanc, char jobvl, char jobvr, char sense, int n, double *a, int lda, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, int *ilo, int *ihi, double *scale, double *abnrm, double *rcone, double *rconv, int *info);
+extern void dgegs(char jobvsl, char jobvsr, int n, double *a, int lda, double *b, int ldb, double *alphar, double *alphai, double *beta, double *vsl, int ldvsl, double *vsr, int ldvsr, int *info);
+extern void dgegv(char jobvl, char jobvr, int n, double *a, int lda, double *b, int ldb, double *alphar, double *alphai, double *beta, double *vl, int ldvl, double *vr, int ldvr, int *info);
+extern void dgehrd(int n, int ilo, int ihi, double *a, int lda, double *tau, int *info);
+extern void dgelqf(int m, int n, double *a, int lda, double *tau, int *info);
+extern void dgels(char trans, int m, int n, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dgelsd(int m, int n, int nrhs, double *a, int lda, double *b, int ldb, double *s, double rcond, int *rank, int *info);
+extern void dgelss(int m, int n, int nrhs, double *a, int lda, double *b, int ldb, double *sing, double rcond, int *irank, int *info);
+extern void dgelsx(int m, int n, int nrhs, double *a, int lda, double *b, int ldb, int *jpivot, double rcond, int *irank, int *info);
+extern void dgelsy(int m, int n, int nrhs, double *a, int lda, double *b, int ldb, int *jpvt, double rcond, int *rank, int *info);
+extern void dgeqlf(int m, int n, double *a, int lda, double *tau, int *info);
+extern void dgeqp3(int m, int n, double *a, int lda, int *jpvt, double *tau, int *info);
+extern void dgeqpf(int m, int n, double *a, int lda, int *jpivot, double *tau, int *info);
+extern void dgeqrf(int m, int n, double *a, int lda, double *tau, int *info);
+extern void dgerfs(char transa, int n, int nrhs, double *a, int lda, double *af, int ldaf, int *ipiv, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dgerqf(int m, int n, double *a, int lda, double *tau, int *info);
+extern void dgesdd(char jobz, int m, int n, double *a, int lda, double *s, double *u, int ldu, double *vt, int ldvt, int *info);
+extern void dgesv(int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb, int *info);
+extern void dgesvd(char jobu, char jobvt, int m, int n, double *a, int lda, double *sing, double *u, int ldu, double *vt, int ldvt, int *info);
+
+/* N.B. In this C interface to dgesvx, rpvgrw returns what is returned in
+   the first element of WORK by the FORTRAN interface */
+extern void dgesvx(char fact, char transa, int n, int nrhs, double *a, int lda, double *af, int ldaf, int *ipiv, char equed, double *rowsc, double *colsc, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, double *rpvgrw, int *info);
+
+extern void dgetrf(int m, int n, double *a, int lda, int *ipiv, int *info);
+extern void dgetri(int n, double *a, int lda, int *ipiv, int *info);
+extern void dgetrs(char transa, int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb, int *info);
+extern void dggbak(char job, char side, int n, int ilo, int ihi, double *lscale, double *rscale, int m, double *v, int ldv, int *info);
+extern void dggbal(char job, int n, double *a, int lda, double *b, int ldb, int *ilo, int *ihi, double *lscale, double *rscale, int *info);
+extern void dgges(char jobvsl, char jobvsr, char sort, ACML_DGGES_DELCTG delctg, int n, double *a, int lda, double *b, int ldb, int *sdim, double *alphar, double *alphai, double *beta, double *vsl, int ldvsl, double *vsr, int ldvsr, int *info);
+extern void dggesx(char jobvsl, char jobvsr, char sort, ACML_DGGESX_DELCTG delctg, char sense, int n, double *a, int lda, double *b, int ldb, int *sdim, double *alphar, double *alphai, double *beta, double *vsl, int ldvsl, double *vsr, int ldvsr, double *rconde, double *rcondv, int *info);
+extern void dggev(char jobvl, char jobvr, int n, double *a, int lda, double *b, int ldb, double *alphar, double *alphai, double *beta, double *vl, int ldvl, double *vr, int ldvr, int *info);
+extern void dggevx(char balanc, char jobvl, char jobvr, char sense, int n, double *a, int lda, double *b, int ldb, double *alphar, double *alphai, double *beta, double *vl, int ldvl, double *vr, int ldvr, int *ilo, int *ihi, double *lscale, double *rscale, double *abnrm, double *bbnrm, double *rconde, double *rcondv, int *info);
+extern void dggglm(int n, int m, int p, double *a, int lda, double *b, int ldb, double *d, double *x, double *y, int *info);
+extern void dgghrd(char compq, char compz, int n, int ilo, int ihi, double *a, int lda, double *b, int ldb, double *q, int ldq, double *z, int ldz, int *info);
+extern void dgglse(int m, int n, int p, double *a, int lda, double *b, int ldb, double *c, double *d, double *x, int *info);
+extern void dggqrf(int n, int m, int p, double *a, int lda, double *taua, double *b, int ldb, double *taub, int *info);
+extern void dggrqf(int m, int p, int n, double *a, int lda, double *taua, double *b, int ldb, double *taub, int *info);
+extern void dggsvd(char jobu, char jobv, char jobq, int m, int n, int p, int *k, int *l, double *a, int lda, double *b, int ldb, double *alpha, double *beta, double *u, int ldu, double *v, int ldv, double *q, int ldq, int *iwork3, int *info);
+extern void dggsvp(char jobu, char jobv, char jobq, int m, int p, int n, double *a, int lda, double *b, int ldb, double tola, double tolb, int *k, int *l, double *u, int ldu, double *v, int ldv, double *q, int ldq, int *info);
+extern void dgtcon(char norm, int n, double *low, double *diag, double *up1, double *up2, int *ipiv, double anorm, double *rcond, int *info);
+extern void dgtrfs(char transa, int n, int nrhs, double *low, double *diag, double *up, double *lowf, double *diagf, double *upf1, double *upf2, int *ipiv, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dgtsv(int n, int nrhs, double *low, double *diag, double *up, double *b, int ldb, int *info);
+extern void dgtsvx(char fact, char transa, int n, int nrhs, double *low, double *diag, double *up, double *lowf, double *diagf, double *upf1, double *upf2, int *ipiv, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dgttrf(int n, double *low, double *diag, double *up1, double *up2, int *ipiv, int *info);
+extern void dgttrs(char transa, int n, int nrhs, double *low, double *diag, double *up1, double *up2, int *ipiv, double *b, int ldb, int *info);
+extern void dhgeqz(char job, char compq, char compz, int n, int ilo, int ihi, double *a, int lda, double *b, int ldb, double *alphar, double *alphai, double *beta, double *q, int ldq, double *z, int ldz, int *info);
+extern void dhsein(char side, char eigsrc, char initv, int *select, int n, double *h, int ldh, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, int mm, int *m, int *ifaill, int *ifailr, int *info);
+extern void dhseqr(char job, char compz, int n, int ilo, int ihi, double *h, int ldh, double *wr, double *wi, double *z, int ldz, int *info);
+extern double dlamch(char cmach);
+extern void dopgtr(char uplo, int n, double *ap, double *tau, double *q, int ldq, int *info);
+extern void dopmtr(char side, char uplo, char trans, int m, int n, double *ap, double *tau, double *c, int ldc, int *info);
+extern void dorgbr(char vect, int m, int n, int k, double *a, int lda, double *tau, int *info);
+extern void dorghr(int n, int ilo, int ihi, double *a, int lda, double *tau, int *info);
+extern void dorglq(int m, int n, int k, double *a, int lda, double *tau, int *info);
+extern void dorgql(int m, int n, int k, double *a, int lda, double *tau, int *info);
+extern void dorgqr(int m, int n, int k, double *a, int lda, double *tau, int *info);
+extern void dorgrq(int m, int n, int k, double *a, int lda, double *tau, int *info);
+extern void dorgtr(char uplo, int n, double *a, int lda, double *tau, int *info);
+extern void dormbr(char vect, char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormhr(char side, char trans, int m, int n, int ilo, int ihi, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormlq(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormql(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormqr(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormr3(char side, char trans, int m, int n, int k, int l, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormrq(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormrz(char side, char trans, int m, int n, int k, int l, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dormtr(char side, char uplo, char trans, int m, int n, double *a, int lda, double *tau, double *c, int ldc, int *info);
+extern void dpbcon(char uplo, int n, int ndiag, double *a, int lda, double anorm, double *rcond, int *info);
+extern void dpbequ(char uplo, int n, int ndiag, double *a, int lda, double *scale, double *scond, double *amax, int *info);
+extern void dpbrfs(char uplo, int n, int ndiag, int nrhs, double *a, int lda, double *af, int ldaf, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dpbstf(char uplo, int n, int kd, double *ab, int ldab, int *info);
+extern void dpbsv(char uplo, int n, int ndiag, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dpbsvx(char fact, char uplo, int n, int ndiag, int nrhs, double *a, int lda, double *af, int ldaf, char equed, double *scale, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dpbtrf(char uplo, int n, int ndiag, double *a, int lda, int *info);
+extern void dpbtrs(char uplo, int n, int ndiag, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dpocon(char uplo, int n, double *a, int lda, double anorm, double *rcond, int *info);
+extern void dpoequ(int n, double *a, int lda, double *scale, double *scond, double *amax, int *info);
+extern void dporfs(char uplo, int n, int nrhs, double *a, int lda, double *af, int ldaf, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dposv(char uplo, int n, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dposvx(char fact, char uplo, int n, int nrhs, double *a, int lda, double *af, int ldaf, char equed, double *scale, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dpotrf(char uplo, int n, double *a, int lda, int *info);
+extern void dpotri(char uplo, int n, double *a, int lda, int *info);
+extern void dpotrs(char uplo, int n, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dppcon(char uplo, int n, double *a, double anorm, double *rcond, int *info);
+extern void dppequ(char uplo, int n, double *a, double *scale, double *scond, double *amax, int *info);
+extern void dpprfs(char uplo, int n, int nrhs, double *a, double *af, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dppsv(char uplo, int n, int nrhs, double *a, double *b, int ldb, int *info);
+extern void dppsvx(char fact, char uplo, int n, int nrhs, double *a, double *af, char equed, double *scale, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dpptrf(char uplo, int n, double *a, int *info);
+extern void dpptri(char uplo, int n, double *a, int *info);
+extern void dpptrs(char uplo, int n, int nrhs, double *a, double *b, int ldb, int *info);
+extern void dptcon(int n, double *diag, double *offd, double anorm, double *rcond, int *info);
+extern void dpteqr(char compz, int n, double *d, double *e, double *z, int ldz, int *info);
+extern void dptrfs(int n, int nrhs, double *diag, double *offd, double *diagf, double *offdf, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dptsv(int n, int nrhs, double *diag, double *sub, double *b, int ldb, int *info);
+extern void dptsvx(char fact, int n, int nrhs, double *diag, double *sub, double *diagf, double *subf, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dpttrf(int n, double *diag, double *offd, int *info);
+extern void dpttrs(int n, int nrhs, double *diag, double *offd, double *b, int ldb, int *info);
+extern void dsbev(char jobz, char uplo, int n, int ndiag, double *a, int lda, double *w, double *z, int ldz, int *info);
+extern void dsbevd(char jobz, char uplo, int n, int kd, double *ab, int ldab, double *w, double *z, int ldz, int *info);
+extern void dsbevx(char jobz, char range, char uplo, int n, int ndiag, double *a, int lda, double *q, int ldq, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dsbgst(char vect, char uplo, int n, int ka, int kb, double *ab, int ldab, double *bb, int ldbb, double *x, int ldx, int *info);
+extern void dsbgv(char jobz, char uplo, int n, int ka, int kb, double *ab, int ldab, double *bb, int ldbb, double *w, double *z, int ldz, int *info);
+extern void dsbgvd(char jobz, char uplo, int n, int ka, int kb, double *ab, int ldab, double *bb, int ldbb, double *w, double *z, int ldz, int *info);
+extern void dsbgvx(char jobz, char range, char uplo, int n, int ka, int kb, double *ab, int ldab, double *bb, int ldbb, double *q, int ldq, double vl, double vu, int il, int iu, double abstol, int *m, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dsbtrd(char vect, char uplo, int n, int kd, double *ab, int ldab, double *d, double *e, double *q, int ldq, int *info);
+extern double dsecnd(void);
+extern void dspcon(char uplo, int n, double *a, int *ipiv, double anorm, double *rcond, int *info);
+extern void dspev(char jobz, char uplo, int n, double *a, double *w, double *z, int ldz, int *info);
+extern void dspevd(char jobz, char uplo, int n, double *ap, double *w, double *z, int ldz, int *info);
+extern void dspevx(char jobz, char range, char uplo, int n, double *a, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dspgst(int itype, char uplo, int n, double *ap, double *bp, int *info);
+extern void dspgv(int itype, char jobz, char uplo, int n, double *a, double *b, double *w, double *z, int ldz, int *info);
+extern void dspgvd(int itype, char jobz, char uplo, int n, double *ap, double *bp, double *w, double *z, int ldz, int *info);
+extern void dspgvx(int itype, char jobz, char range, char uplo, int n, double *ap, double *bp, double vl, double vu, int il, int iu, double abstol, int *m, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dsprfs(char uplo, int n, int nrhs, double *a, double *af, int *ipiv, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dspsv(char uplo, int n, int nrhs, double *a, int *ipiv, double *b, int ldb, int *info);
+extern void dspsvx(char fact, char uplo, int n, int nrhs, double *a, double *af, int *ipiv, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dsptrd(char uplo, int n, double *ap, double *d, double *e, double *tau, int *info);
+extern void dsptrf(char uplo, int n, double *a, int *ipiv, int *info);
+extern void dsptri(char uplo, int n, double *a, int *ipiv, int *info);
+extern void dsptrs(char uplo, int n, int nrhs, double *a, int *ipiv, double *b, int ldb, int *info);
+extern void dstebz(char range, char order, int n, double vl, double vu, int il, int iu, double abstol, double *d, double *e, int *m, int *nsplit, double *w, int *iblock, int *isplit, int *info);
+extern void dstedc(char compz, int n, double *d, double *e, double *z, int ldz, int *info);
+extern void dstegr(char jobz, char range, int n, double *d, double *e, double vl, double vu, int il, int iu, double abstol, int *m, double *w, double *z, int ldz, int *isuppz, int *info);
+extern void dstein(int n, double *d, double *e, int m, double *w, int *iblock, int *isplit, double *z, int ldz, int *ifail, int *info);
+extern void dsteqr(char compz, int n, double *d, double *e, double *z, int ldz, int *info);
+extern void dsterf(int n, double *d, double *e, int *info);
+extern void dstev(char jobz, int n, double *diag, double *offd, double *z, int ldz, int *info);
+extern void dstevd(char jobz, int n, double *d, double *e, double *z, int ldz, int *info);
+extern void dstevr(char jobz, char range, int n, double *d, double *e, double vl, double vu, int il, int iu, double abstol, int *m, double *w, double *z, int ldz, int *isuppz, int *info);
+extern void dstevx(char jobz, char range, int n, double *diag, double *offd, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dsycon(char uplo, int n, double *a, int lda, int *ipiv, double anorm, double *rcond, int *info);
+extern void dsyev(char jobz, char uplo, int n, double *a, int lda, double *w, int *info);
+extern void dsyevd(char jobz, char uplo, int n, double *a, int lda, double *w, int *info);
+extern void dsyevr(char jobz, char range, char uplo, int n, double *a, int lda, double vl, double vu, int il, int iu, double abstol, int *m, double *w, double *z, int ldz, int *isuppz, int *info);
+extern void dsyevx(char jobz, char range, char uplo, int n, double *a, int lda, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dsygst(int itype, char uplo, int n, double *a, int lda, double *b, int ldb, int *info);
+extern void dsygv(int itype, char jobz, char uplo, int n, double *a, int lda, double *b, int ldb, double *w, int *info);
+extern void dsygvd(int itype, char jobz, char uplo, int n, double *a, int lda, double *b, int ldb, double *w, int *info);
+extern void dsygvx(int itype, char jobz, char range, char uplo, int n, double *a, int lda, double *b, int ldb, double vl, double vu, int il, int iu, double abstol, int *m, double *w, double *z, int ldz, int *ifail, int *info);
+extern void dsyrfs(char uplo, int n, int nrhs, double *a, int lda, double *af, int ldaf, int *ipiv, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dsysv(char uplo, int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb, int *info);
+extern void dsysvx(char fact, char uplo, int n, int nrhs, double *a, int lda, double *af, int ldaf, int *ipiv, double *b, int ldb, double *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void dsytrd(char uplo, int n, double *a, int lda, double *d, double *e, double *tau, int *info);
+extern void dsytrf(char uplo, int n, double *a, int lda, int *ipiv, int *info);
+extern void dsytri(char uplo, int n, double *a, int lda, int *ipiv, int *info);
+extern void dsytrs(char uplo, int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb, int *info);
+extern void dtbcon(char norm, char uplo, char diag, int n, int ndiag, double *a, int lda, double *rcond, int *info);
+extern void dtbrfs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, double *a, int lda, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dtbtrs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dtgevc(char side, char howmny, int *select, int n, double *a, int lda, double *b, int ldb, double *vl, int ldvl, double *vr, int ldvr, int mm, int *m, int *info);
+extern void dtgexc(int wantq, int wantz, int n, double *a, int lda, double *b, int ldb, double *q, int ldq, double *z, int ldz, int *ifst, int *ilst, int *info);
+extern void dtgsen(int ijob, int wantq, int wantz, int *select, int n, double *a, int lda, double *b, int ldb, double *alphar, double *alphai, double *beta, double *q, int ldq, double *z, int ldz, int *m, double *pl, double *pr, double *dif, int *info);
+extern void dtgsja(char jobu, char jobv, char jobq, int m, int p, int n, int k, int l, double *a, int lda, double *b, int ldb, double tola, double tolb, double *alpha, double *beta, double *u, int ldu, double *v, int ldv, double *q, int ldq, int *ncycle, int *info);
+extern void dtgsna(char job, char howmnt, int *select, int n, double *a, int lda, double *b, int ldb, double *vl, int ldvl, double *vr, int ldvr, double *s, double *dif, int mm, int *m, int *info);
+extern void dtgsyl(char trans, int ijob, int m, int n, double *a, int lda, double *b, int ldb, double *c, int ldc, double *d, int ldd, double *e, int lde, double *f, int ldf, double *scale, double *dif, int *info);
+extern void dtpcon(char norm, char uplo, char diag, int n, double *a, double *rcond, int *info);
+extern void dtprfs(char uplo, char transa, char diag, int n, int nrhs, double *a, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dtptri(char uplo, char diag, int n, double *a, int *info);
+extern void dtptrs(char uplo, char transa, char diag, int n, int nrhs, double *a, double *b, int ldb, int *info);
+extern void dtrcon(char norm, char uplo, char diag, int n, double *a, int lda, double *rcond, int *info);
+extern void dtrevc(char side, char howmny, int *select, int n, double *t, int ldt, double *vl, int ldvl, double *vr, int ldvr, int mm, int *m, int *info);
+extern void dtrexc(char compq, int n, double *t, int ldt, double *q, int ldq, int *ifst, int *ilst, int *info);
+extern void dtrrfs(char uplo, char transa, char diag, int n, int nrhs, double *a, int lda, double *b, int ldb, double *x, int ldx, double *ferr, double *berr, int *info);
+extern void dtrsen(char job, char compq, int *select, int n, double *t, int ldt, double *q, int ldq, double *wr, double *wi, int *m, double *s, double *sep, int *info);
+extern void dtrsna(char job, char howmny, int *select, int n, double *t, int ldt, double *vl, int ldvl, double *vr, int ldvr, double *s, double *sep, int mm, int *m, int *info);
+extern void dtrsyl(char trana, char tranb, int isgn, int m, int n, double *a, int lda, double *b, int ldb, double *c, int ldc, double *scale, int *info);
+extern void dtrtri(char uplo, char diag, int n, double *a, int lda, int *info);
+extern void dtrtrs(char uplo, char transa, char diag, int n, int nrhs, double *a, int lda, double *b, int ldb, int *info);
+extern void dtzrqf(int m, int n, double *a, int lda, double *tau, int *info);
+extern void dtzrzf(int m, int n, double *a, int lda, double *tau, int *info);
+extern void sbdsdc(char uplo, char compq, int n, float *d, float *e, float *u, int ldu, float *vt, int ldvt, float *q, int *iq, int *info);
+extern void sbdsqr(char uplo, int n, int ncvt, int nru, int ncc, float *d, float *e, float *vt, int ldvt, float *u, int ldu, float *c, int ldc, int *info);
+extern void sdisna(char job, int m, int n, float *d, float *sep, int *info);
+extern float second(void);
+extern void sgbbrd(char vect, int m, int n, int ncc, int kl, int ku, float *ab, int ldab, float *d, float *e, float *q, int ldq, float *pt, int ldpt, float *c, int ldc, int *info);
+extern void sgbcon(char norm, int n, int nsub, int nsuper, float *a, int lda, int *ipiv, float anorm, float *rcond, int *info);
+extern void sgbequ(int m, int n, int nsub, int nsuper, float *a, int lda, float *rowsc, float *colsc, float *rowcn, float *colcn, float *amax, int *info);
+extern void sgbrfs(char transa, int n, int nsub, int nsuper, int nrhs, float *a, int lda, float *af, int ldaf, int *ipiv, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sgbsv(int n, int nsub, int nsuper, int nrhs, float *a, int lda, int *ipiv, float *b, int ldb, int *info);
+
+/* N.B. In this C interface to sgbsvx, rpvgrw returns what is returned in
+   the first element of WORK by the FORTRAN interface */
+extern void sgbsvx(char fact, char transa, int n, int nsub, int nsuper, int nrhs, float *a, int lda, float *af, int ldaf, int *ipiv, char equed, float *rowsc, float *colsc, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, float *rpvgrw, int *info);
+
+extern void sgbtrf(int m, int n, int nsub, int nsuper, float *a, int lda, int *ipiv, int *info);
+extern void sgbtrs(char transa, int n, int nsub, int nsuper, int nrhs, float *a, int lda, int *ipiv, float *b, int ldb, int *info);
+extern void sgebak(char job, char side, int n, int ilo, int ihi, float *scale, int m, float *v, int ldv, int *info);
+extern void sgebal(char job, int n, float *a, int lda, int *ilo, int *ihi, float *scale, int *info);
+extern void sgebrd(int m, int n, float *a, int lda, float *d, float *e, float *tauq, float *taup, int *info);
+extern void sgecon(char norm, int n, float *a, int lda, float anorm, float *rcond, int *info);
+extern void sgeequ(int m, int n, float *a, int lda, float *rowsc, float *colsc, float *rowcn, float *colcn, float *amax, int *info);
+extern void sgees(char jobz, char sortev, ACML_SGEES_SELECT select, int n, float *a, int lda, int *nout, float *wr, float *wi, float *z, int ldz, int *info);
+extern void sgeesx(char jobz, char sortev, ACML_SGEESX_SELECT select, char sense, int n, float *a, int lda, int *nout, float *wr, float *wi, float *z, int ldz, float *srcone, float *rconv, int *info);
+extern void sgeev(char jobvl, char jobvr, int n, float *a, int lda, float *wr, float *wi, float *vl, int ldvl, float *vr, int ldvr, int *info);
+extern void sgeevx(char balanc, char jobvl, char jobvr, char sense, int n, float *a, int lda, float *wr, float *wi, float *vl, int ldvl, float *vr, int ldvr, int *ilo, int *ihi, float *scale, float *abnrm, float *rcone, float *rconv, int *info);
+extern void sgegs(char jobvsl, char jobvsr, int n, float *a, int lda, float *b, int ldb, float *alphar, float *alphai, float *beta, float *vsl, int ldvsl, float *vsr, int ldvsr, int *info);
+extern void sgegv(char jobvl, char jobvr, int n, float *a, int lda, float *b, int ldb, float *alphar, float *alphai, float *beta, float *vl, int ldvl, float *vr, int ldvr, int *info);
+extern void sgehrd(int n, int ilo, int ihi, float *a, int lda, float *tau, int *info);
+extern void sgelqf(int m, int n, float *a, int lda, float *tau, int *info);
+extern void sgels(char trans, int m, int n, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void sgelsd(int m, int n, int nrhs, float *a, int lda, float *b, int ldb, float *s, float rcond, int *rank, int *info);
+extern void sgelss(int m, int n, int nrhs, float *a, int lda, float *b, int ldb, float *sing, float rcond, int *irank, int *info);
+extern void sgelsx(int m, int n, int nrhs, float *a, int lda, float *b, int ldb, int *jpivot, float rcond, int *irank, int *info);
+extern void sgelsy(int m, int n, int nrhs, float *a, int lda, float *b, int ldb, int *jpvt, float rcond, int *rank, int *info);
+extern void sgeqlf(int m, int n, float *a, int lda, float *tau, int *info);
+extern void sgeqp3(int m, int n, float *a, int lda, int *jpvt, float *tau, int *info);
+extern void sgeqpf(int m, int n, float *a, int lda, int *jpivot, float *tau, int *info);
+extern void sgeqrf(int m, int n, float *a, int lda, float *tau, int *info);
+extern void sgerfs(char transa, int n, int nrhs, float *a, int lda, float *af, int ldaf, int *ipiv, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sgerqf(int m, int n, float *a, int lda, float *tau, int *info);
+extern void sgesdd(char jobz, int m, int n, float *a, int lda, float *s, float *u, int ldu, float *vt, int ldvt, int *info);
+extern void sgesv(int n, int nrhs, float *a, int lda, int *ipiv, float *b, int ldb, int *info);
+extern void sgesvd(char jobu, char jobvt, int m, int n, float *a, int lda, float *sing, float *u, int ldu, float *vt, int ldvt, int *info);
+
+/* N.B. In this C interface to sgesvx, rpvgrw returns what is returned in
+   the first element of WORK by the FORTRAN interface */
+extern void sgesvx(char fact, char transa, int n, int nrhs, float *a, int lda, float *af, int ldaf, int *ipiv, char equed, float *rowsc, float *colsc, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, float *rpvgrw, int *info);
+
+extern void sgetrf(int m, int n, float *a, int lda, int *ipiv, int *info);
+extern void sgetri(int n, float *a, int lda, int *ipiv, int *info);
+extern void sgetrs(char transa, int n, int nrhs, float *a, int lda, int *ipiv, float *b, int ldb, int *info);
+extern void sggbak(char job, char side, int n, int ilo, int ihi, float *lscale, float *rscale, int m, float *v, int ldv, int *info);
+extern void sggbal(char job, int n, float *a, int lda, float *b, int ldb, int *ilo, int *ihi, float *lscale, float *rscale, int *info);
+extern void sgges(char jobvsl, char jobvsr, char sort, ACML_SGGES_SELCTG selctg, int n, float *a, int lda, float *b, int ldb, int *sdim, float *alphar, float *alphai, float *beta, float *vsl, int ldvsl, float *vsr, int ldvsr, int *info);
+extern void sggesx(char jobvsl, char jobvsr, char sort, ACML_SGGESX_SELCTG selctg, char sense, int n, float *a, int lda, float *b, int ldb, int *sdim, float *alphar, float *alphai, float *beta, float *vsl, int ldvsl, float *vsr, int ldvsr, float *rconde, float *rcondv, int *info);
+extern void sggev(char jobvl, char jobvr, int n, float *a, int lda, float *b, int ldb, float *alphar, float *alphai, float *beta, float *vl, int ldvl, float *vr, int ldvr, int *info);
+extern void sggevx(char balanc, char jobvl, char jobvr, char sense, int n, float *a, int lda, float *b, int ldb, float *alphar, float *alphai, float *beta, float *vl, int ldvl, float *vr, int ldvr, int *ilo, int *ihi, float *lscale, float *rscale, float *abnrm, float *bbnrm, float *rconde, float *rcondv, int *info);
+extern void sggglm(int n, int m, int p, float *a, int lda, float *b, int ldb, float *d, float *x, float *y, int *info);
+extern void sgghrd(char compq, char compz, int n, int ilo, int ihi, float *a, int lda, float *b, int ldb, float *q, int ldq, float *z, int ldz, int *info);
+extern void sgglse(int m, int n, int p, float *a, int lda, float *b, int ldb, float *c, float *d, float *x, int *info);
+extern void sggqrf(int n, int m, int p, float *a, int lda, float *taua, float *b, int ldb, float *taub, int *info);
+extern void sggrqf(int m, int p, int n, float *a, int lda, float *taua, float *b, int ldb, float *taub, int *info);
+extern void sggsvd(char jobu, char jobv, char jobq, int m, int n, int p, int *k, int *l, float *a, int lda, float *b, int ldb, float *alpha, float *beta, float *u, int ldu, float *v, int ldv, float *q, int ldq, int *iwork3, int *info);
+extern void sggsvp(char jobu, char jobv, char jobq, int m, int p, int n, float *a, int lda, float *b, int ldb, float tola, float tolb, int *k, int *l, float *u, int ldu, float *v, int ldv, float *q, int ldq, int *info);
+extern void sgtcon(char norm, int n, float *low, float *diag, float *up1, float *up2, int *ipiv, float anorm, float *rcond, int *info);
+extern void sgtrfs(char transa, int n, int nrhs, float *low, float *diag, float *up, float *lowf, float *diagf, float *upf1, float *upf2, int *ipiv, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sgtsv(int n, int nrhs, float *low, float *diag, float *up, float *b, int ldb, int *info);
+extern void sgtsvx(char fact, char transa, int n, int nrhs, float *low, float *diag, float *up, float *lowf, float *diagf, float *upf1, float *upf2, int *ipiv, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void sgttrf(int n, float *low, float *diag, float *up1, float *up2, int *ipiv, int *info);
+extern void sgttrs(char transa, int n, int nrhs, float *low, float *diag, float *up1, float *up2, int *ipiv, float *b, int ldb, int *info);
+extern void shgeqz(char job, char compq, char compz, int n, int ilo, int ihi, float *a, int lda, float *b, int ldb, float *alphar, float *alphai, float *beta, float *q, int ldq, float *z, int ldz, int *info);
+extern void shsein(char side, char eigsrc, char initv, int *select, int n, float *h, int ldh, float *wr, float *wi, float *vl, int ldvl, float *vr, int ldvr, int mm, int *m, int *ifaill, int *ifailr, int *info);
+extern void shseqr(char job, char compz, int n, int ilo, int ihi, float *h, int ldh, float *wr, float *wi, float *z, int ldz, int *info);
+extern float slamch(char cmach);
+extern void sopgtr(char uplo, int n, float *ap, float *tau, float *q, int ldq, int *info);
+extern void sopmtr(char side, char uplo, char trans, int m, int n, float *ap, float *tau, float *c, int ldc, int *info);
+extern void sorgbr(char vect, int m, int n, int k, float *a, int lda, float *tau, int *info);
+extern void sorghr(int n, int ilo, int ihi, float *a, int lda, float *tau, int *info);
+extern void sorglq(int m, int n, int k, float *a, int lda, float *tau, int *info);
+extern void sorgql(int m, int n, int k, float *a, int lda, float *tau, int *info);
+extern void sorgqr(int m, int n, int k, float *a, int lda, float *tau, int *info);
+extern void sorgrq(int m, int n, int k, float *a, int lda, float *tau, int *info);
+extern void sorgtr(char uplo, int n, float *a, int lda, float *tau, int *info);
+extern void sormbr(char vect, char side, char trans, int m, int n, int k, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormhr(char side, char trans, int m, int n, int ilo, int ihi, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormlq(char side, char trans, int m, int n, int k, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormql(char side, char trans, int m, int n, int k, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormqr(char side, char trans, int m, int n, int k, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormr3(char side, char trans, int m, int n, int k, int l, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormrq(char side, char trans, int m, int n, int k, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormrz(char side, char trans, int m, int n, int k, int l, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void sormtr(char side, char uplo, char trans, int m, int n, float *a, int lda, float *tau, float *c, int ldc, int *info);
+extern void spbcon(char uplo, int n, int ndiag, float *a, int lda, float anorm, float *rcond, int *info);
+extern void spbequ(char uplo, int n, int ndiag, float *a, int lda, float *scale, float *scond, float *amax, int *info);
+extern void spbrfs(char uplo, int n, int ndiag, int nrhs, float *a, int lda, float *af, int ldaf, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void spbstf(char uplo, int n, int kd, float *ab, int ldab, int *info);
+extern void spbsv(char uplo, int n, int ndiag, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void spbsvx(char fact, char uplo, int n, int ndiag, int nrhs, float *a, int lda, float *af, int ldaf, char equed, float *scale, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void spbtrf(char uplo, int n, int ndiag, float *a, int lda, int *info);
+extern void spbtrs(char uplo, int n, int ndiag, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void spocon(char uplo, int n, float *a, int lda, float anorm, float *rcond, int *info);
+extern void spoequ(int n, float *a, int lda, float *scale, float *scond, float *amax, int *info);
+extern void sporfs(char uplo, int n, int nrhs, float *a, int lda, float *af, int ldaf, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sposv(char uplo, int n, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void sposvx(char fact, char uplo, int n, int nrhs, float *a, int lda, float *af, int ldaf, char equed, float *scale, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void spotrf(char uplo, int n, float *a, int lda, int *info);
+extern void spotri(char uplo, int n, float *a, int lda, int *info);
+extern void spotrs(char uplo, int n, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void sppcon(char uplo, int n, float *a, float anorm, float *rcond, int *info);
+extern void sppequ(char uplo, int n, float *a, float *scale, float *scond, float *amax, int *info);
+extern void spprfs(char uplo, int n, int nrhs, float *a, float *af, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sppsv(char uplo, int n, int nrhs, float *a, float *b, int ldb, int *info);
+extern void sppsvx(char fact, char uplo, int n, int nrhs, float *a, float *af, char equed, float *scale, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void spptrf(char uplo, int n, float *a, int *info);
+extern void spptri(char uplo, int n, float *a, int *info);
+extern void spptrs(char uplo, int n, int nrhs, float *a, float *b, int ldb, int *info);
+extern void sptcon(int n, float *diag, float *offd, float anorm, float *rcond, int *info);
+extern void spteqr(char compz, int n, float *d, float *e, float *z, int ldz, int *info);
+extern void sptrfs(int n, int nrhs, float *diag, float *offd, float *diagf, float *offdf, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sptsv(int n, int nrhs, float *diag, float *sub, float *b, int ldb, int *info);
+extern void sptsvx(char fact, int n, int nrhs, float *diag, float *sub, float *diagf, float *subf, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void spttrf(int n, float *diag, float *offd, int *info);
+extern void spttrs(int n, int nrhs, float *diag, float *offd, float *b, int ldb, int *info);
+extern void ssbev(char jobz, char uplo, int n, int ndiag, float *a, int lda, float *w, float *z, int ldz, int *info);
+extern void ssbevd(char jobz, char uplo, int n, int kd, float *ab, int ldab, float *w, float *z, int ldz, int *info);
+extern void ssbevx(char jobz, char range, char uplo, int n, int ndiag, float *a, int lda, float *q, int ldq, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, float *z, int ldz, int *ifail, int *info);
+extern void ssbgst(char vect, char uplo, int n, int ka, int kb, float *ab, int ldab, float *bb, int ldbb, float *x, int ldx, int *info);
+extern void ssbgv(char jobz, char uplo, int n, int ka, int kb, float *ab, int ldab, float *bb, int ldbb, float *w, float *z, int ldz, int *info);
+extern void ssbgvd(char jobz, char uplo, int n, int ka, int kb, float *ab, int ldab, float *bb, int ldbb, float *w, float *z, int ldz, int *info);
+extern void ssbgvx(char jobz, char range, char uplo, int n, int ka, int kb, float *ab, int ldab, float *bb, int ldbb, float *q, int ldq, float vl, float vu, int il, int iu, float abstol, int *m, float *w, float *z, int ldz, int *ifail, int *info);
+extern void ssbtrd(char vect, char uplo, int n, int kd, float *ab, int ldab, float *d, float *e, float *q, int ldq, int *info);
+extern void sspcon(char uplo, int n, float *a, int *ipiv, float anorm, float *rcond, int *info);
+extern void sspev(char jobz, char uplo, int n, float *a, float *w, float *z, int ldz, int *info);
+extern void sspevd(char jobz, char uplo, int n, float *ap, float *w, float *z, int ldz, int *info);
+extern void sspevx(char jobz, char range, char uplo, int n, float *a, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, float *z, int ldz, int *ifail, int *info);
+extern void sspgst(int itype, char uplo, int n, float *ap, float *bp, int *info);
+extern void sspgv(int itype, char jobz, char uplo, int n, float *a, float *b, float *w, float *z, int ldz, int *info);
+extern void sspgvd(int itype, char jobz, char uplo, int n, float *ap, float *bp, float *w, float *z, int ldz, int *info);
+extern void sspgvx(int itype, char jobz, char range, char uplo, int n, float *ap, float *bp, float vl, float vu, int il, int iu, float abstol, int *m, float *w, float *z, int ldz, int *ifail, int *info);
+extern void ssprfs(char uplo, int n, int nrhs, float *a, float *af, int *ipiv, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void sspsv(char uplo, int n, int nrhs, float *a, int *ipiv, float *b, int ldb, int *info);
+extern void sspsvx(char fact, char uplo, int n, int nrhs, float *a, float *af, int *ipiv, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void ssptrd(char uplo, int n, float *ap, float *d, float *e, float *tau, int *info);
+extern void ssptrf(char uplo, int n, float *a, int *ipiv, int *info);
+extern void ssptri(char uplo, int n, float *a, int *ipiv, int *info);
+extern void ssptrs(char uplo, int n, int nrhs, float *a, int *ipiv, float *b, int ldb, int *info);
+extern void sstebz(char range, char order, int n, float vl, float vu, int il, int iu, float abstol, float *d, float *e, int *m, int *nsplit, float *w, int *iblock, int *isplit, int *info);
+extern void sstedc(char compz, int n, float *d, float *e, float *z, int ldz, int *info);
+extern void sstegr(char jobz, char range, int n, float *d, float *e, float vl, float vu, int il, int iu, float abstol, int *m, float *w, float *z, int ldz, int *isuppz, int *info);
+extern void sstein(int n, float *d, float *e, int m, float *w, int *iblock, int *isplit, float *z, int ldz, int *ifail, int *info);
+extern void ssteqr(char compz, int n, float *d, float *e, float *z, int ldz, int *info);
+extern void ssterf(int n, float *d, float *e, int *info);
+extern void sstev(char jobz, int n, float *diag, float *offd, float *z, int ldz, int *info);
+extern void sstevd(char jobz, int n, float *d, float *e, float *z, int ldz, int *info);
+extern void sstevr(char jobz, char range, int n, float *d, float *e, float vl, float vu, int il, int iu, float abstol, int *m, float *w, float *z, int ldz, int *isuppz, int *info);
+extern void sstevx(char jobz, char range, int n, float *diag, float *offd, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, float *z, int ldz, int *ifail, int *info);
+extern void ssycon(char uplo, int n, float *a, int lda, int *ipiv, float anorm, float *rcond, int *info);
+extern void ssyev(char jobz, char uplo, int n, float *a, int lda, float *w, int *info);
+extern void ssyevd(char jobz, char uplo, int n, float *a, int lda, float *w, int *info);
+extern void ssyevr(char jobz, char range, char uplo, int n, float *a, int lda, float vl, float vu, int il, int iu, float abstol, int *m, float *w, float *z, int ldz, int *isuppz, int *info);
+extern void ssyevx(char jobz, char range, char uplo, int n, float *a, int lda, float vl, float vu, int il, int iu, float abtol, int *nfound, float *w, float *z, int ldz, int *ifail, int *info);
+extern void ssygst(int itype, char uplo, int n, float *a, int lda, float *b, int ldb, int *info);
+extern void ssygv(int itype, char jobz, char uplo, int n, float *a, int lda, float *b, int ldb, float *w, int *info);
+extern void ssygvd(int itype, char jobz, char uplo, int n, float *a, int lda, float *b, int ldb, float *w, int *info);
+extern void ssygvx(int itype, char jobz, char range, char uplo, int n, float *a, int lda, float *b, int ldb, float vl, float vu, int il, int iu, float abstol, int *m, float *w, float *z, int ldz, int *ifail, int *info);
+extern void ssyrfs(char uplo, int n, int nrhs, float *a, int lda, float *af, int ldaf, int *ipiv, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void ssysv(char uplo, int n, int nrhs, float *a, int lda, int *ipiv, float *b, int ldb, int *info);
+extern void ssysvx(char fact, char uplo, int n, int nrhs, float *a, int lda, float *af, int ldaf, int *ipiv, float *b, int ldb, float *x, int ldx, float *rcond, float *ferr, float *berr, int *info);
+extern void ssytrd(char uplo, int n, float *a, int lda, float *d, float *e, float *tau, int *info);
+extern void ssytrf(char uplo, int n, float *a, int lda, int *ipiv, int *info);
+extern void ssytri(char uplo, int n, float *a, int lda, int *ipiv, int *info);
+extern void ssytrs(char uplo, int n, int nrhs, float *a, int lda, int *ipiv, float *b, int ldb, int *info);
+extern void stbcon(char norm, char uplo, char diag, int n, int ndiag, float *a, int lda, float *rcond, int *info);
+extern void stbrfs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, float *a, int lda, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void stbtrs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void stgevc(char side, char howmny, int *select, int n, float *a, int lda, float *b, int ldb, float *vl, int ldvl, float *vr, int ldvr, int mm, int *m, int *info);
+extern void stgexc(int wantq, int wantz, int n, float *a, int lda, float *b, int ldb, float *q, int ldq, float *z, int ldz, int *ifst, int *ilst, int *info);
+extern void stgsen(int ijob, int wantq, int wantz, int *select, int n, float *a, int lda, float *b, int ldb, float *alphar, float *alphai, float *beta, float *q, int ldq, float *z, int ldz, int *m, float *pl, float *pr, float *dif, int *info);
+extern void stgsja(char jobu, char jobv, char jobq, int m, int p, int n, int k, int l, float *a, int lda, float *b, int ldb, float tola, float tolb, float *alpha, float *beta, float *u, int ldu, float *v, int ldv, float *q, int ldq, int *ncycle, int *info);
+extern void stgsna(char job, char howmnt, int *select, int n, float *a, int lda, float *b, int ldb, float *vl, int ldvl, float *vr, int ldvr, float *s, float *dif, int mm, int *m, int *info);
+extern void stgsyl(char trans, int ijob, int m, int n, float *a, int lda, float *b, int ldb, float *c, int ldc, float *d, int ldd, float *e, int lde, float *f, int ldf, float *scale, float *dif, int *info);
+extern void stpcon(char norm, char uplo, char diag, int n, float *a, float *rcond, int *info);
+extern void stprfs(char uplo, char transa, char diag, int n, int nrhs, float *a, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void stptri(char uplo, char diag, int n, float *a, int *info);
+extern void stptrs(char uplo, char transa, char diag, int n, int nrhs, float *a, float *b, int ldb, int *info);
+extern void strcon(char norm, char uplo, char diag, int n, float *a, int lda, float *rcond, int *info);
+extern void strevc(char side, char howmny, int *select, int n, float *t, int ldt, float *vl, int ldvl, float *vr, int ldvr, int mm, int *m, int *info);
+extern void strexc(char compq, int n, float *t, int ldt, float *q, int ldq, int *ifst, int *ilst, int *info);
+extern void strrfs(char uplo, char transa, char diag, int n, int nrhs, float *a, int lda, float *b, int ldb, float *x, int ldx, float *ferr, float *berr, int *info);
+extern void strsen(char job, char compq, int *select, int n, float *t, int ldt, float *q, int ldq, float *wr, float *wi, int *m, float *s, float *sep, int *info);
+extern void strsna(char job, char howmny, int *select, int n, float *t, int ldt, float *vl, int ldvl, float *vr, int ldvr, float *s, float *sep, int mm, int *m, int *info);
+extern void strsyl(char trana, char tranb, int isgn, int m, int n, float *a, int lda, float *b, int ldb, float *c, int ldc, float *scale, int *info);
+extern void strtri(char uplo, char diag, int n, float *a, int lda, int *info);
+extern void strtrs(char uplo, char transa, char diag, int n, int nrhs, float *a, int lda, float *b, int ldb, int *info);
+extern void stzrqf(int m, int n, float *a, int lda, float *tau, int *info);
+extern void stzrzf(int m, int n, float *a, int lda, float *tau, int *info);
+extern void zbdsqr(char uplo, int n, int ncvt, int nru, int ncc, double *d, double *e, doublecomplex *vt, int ldvt, doublecomplex *u, int ldu, doublecomplex *c, int ldc, int *info);
+extern void zgbbrd(char vect, int m, int n, int ncc, int kl, int ku, doublecomplex *ab, int ldab, double *d, double *e, doublecomplex *q, int ldq, doublecomplex *pt, int ldpt, doublecomplex *c, int ldc, int *info);
+extern void zgbcon(char norm, int n, int nsub, int nsuper, doublecomplex *a, int lda, int *ipiv, double anorm, double *rcond, int *info);
+extern void zgbequ(int m, int n, int nsub, int nsuper, doublecomplex *a, int lda, double *rowsc, double *colsc, double *rowcn, double *colcn, double *amax, int *info);
+extern void zgbrfs(char transa, int n, int nsub, int nsuper, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zgbsv(int n, int nsub, int nsuper, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+
+/* N.B. In this C interface to zgbsvx, rpvgrw returns what is returned in
+   the first element of RWORK by the FORTRAN interface */
+extern void zgbsvx(char fact, char transa, int n, int nsub, int nsuper, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, char equed, double *rowsc, double *colsc, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, double *rpvgrw, int *info);
+
+extern void zgbtrf(int m, int n, int nsub, int nsuper, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zgbtrs(char transa, int n, int nsub, int nsuper, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zgebak(char job, char side, int n, int ilo, int ihi, double *scale, int m, doublecomplex *v, int ldv, int *info);
+extern void zgebal(char job, int n, doublecomplex *a, int lda, int *ilo, int *ihi, double *scale, int *info);
+extern void zgebrd(int m, int n, doublecomplex *a, int lda, double *d, double *e, doublecomplex *tauq, doublecomplex *taup, int *info);
+extern void zgecon(char norm, int n, doublecomplex *a, int lda, double anorm, double *rcond, int *info);
+extern void zgeequ(int m, int n, doublecomplex *a, int lda, double *rowsc, double *colsc, double *rowcn, double *colcn, double *amax, int *info);
+extern void zgees(char jobvs, char sort, ACML_ZGEES_SELECT select, int n, doublecomplex *a, int lda, int *sdim, doublecomplex *w, doublecomplex *vs, int ldvs, int *info);
+extern void zgeesx(char jobvs, char sort, ACML_ZGEESX_SELECT select, char sense, int n, doublecomplex *a, int lda, int *sdim, doublecomplex *w, doublecomplex *vs, int ldvs, double *rconde, double *rcondv, int *info);
+extern void zgeev(char jobvl, char jobvr, int n, doublecomplex *a, int lda, doublecomplex *w, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int *info);
+extern void zgeevx(char balanc, char jobvl, char jobvr, char sense, int n, doublecomplex *a, int lda, doublecomplex *w, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int *ilo, int *ihi, double *scale, double *abnrm, double *rconde, double *rcondv, int *info);
+extern void zgegs(char jobvsl, char jobvsr, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, int ldvsl, doublecomplex *vsr, int ldvsr, int *info);
+extern void zgegv(char jobvl, char jobvr, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int *info);
+extern void zgehrd(int n, int ilo, int ihi, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zgelqf(int m, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zgels(char trans, int m, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void zgelsd(int m, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, double *s, double rcond, int *rank, int *info);
+extern void zgelss(int m, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, double *sing, double rcond, int *irank, int *info);
+extern void zgelsx(int m, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *jpivot, double rcond, int *irank, int *info);
+extern void zgelsy(int m, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *jpvt, double rcond, int *rank, int *info);
+extern void zgeqlf(int m, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zgeqp3(int m, int n, doublecomplex *a, int lda, int *jpvt, doublecomplex *tau, int *info);
+extern void zgeqpf(int m, int n, doublecomplex *a, int lda, int *jpvt, doublecomplex *tau, int *info);
+extern void zgeqrf(int m, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zgerfs(char transa, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zgerqf(int m, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zgesdd(char jobz, int m, int n, doublecomplex *a, int lda, double *s, doublecomplex *u, int ldu, doublecomplex *vt, int ldvt, int *info);
+extern void zgesv(int n, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zgesvd(char jobu, char jobvt, int m, int n, doublecomplex *a, int lda, double *sing, doublecomplex *u, int ldu, doublecomplex *vt, int ldvt, int *info);
+
+/* N.B. In this C interface to zgesvx, rpvgrw returns what is returned in
+   the first element of RWORK by the FORTRAN interface */
+extern void zgesvx(char fact, char transa, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, char equed, double *rowsc, double *colsc, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, double *rpvgrw, int *info);
+
+extern void zgetrf(int m, int n, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zgetri(int n, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zgetrs(char transa, int n, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zggbak(char job, char side, int n, int ilo, int ihi, double *lscale, double *rscale, int m, doublecomplex *v, int ldv, int *info);
+extern void zggbal(char job, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *ilo, int *ihi, double *lscale, double *rscale, int *info);
+extern void zgges(char jobvsl, char jobvsr, char sort, ACML_ZGGES_DELCTG delctg, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *sdim, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, int ldvsl, doublecomplex *vsr, int ldvsr, int *info);
+extern void zggesx(char jobvsl, char jobvsr, char sort, ACML_ZGGESX_DELCTG delctg, char sense, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *sdim, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, int ldvsl, doublecomplex *vsr, int ldvsr, double *rconde, double *rcondv, int *info);
+extern void zggev(char jobvl, char jobvr, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int *info);
+extern void zggevx(char balanc, char jobvl, char jobvr, char sense, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int *ilo, int *ihi, double *lscale, double *rscale, double *abnrm, double *bbnrm, double *rconde, double *rcondv, int *info);
+extern void zggglm(int n, int m, int p, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *d, doublecomplex *x, doublecomplex *y, int *info);
+extern void zgghrd(char compq, char compz, int n, int ilo, int ihi, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *q, int ldq, doublecomplex *z, int ldz, int *info);
+extern void zgglse(int m, int n, int p, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *c, doublecomplex *d, doublecomplex *x, int *info);
+extern void zggqrf(int n, int m, int p, doublecomplex *a, int lda, doublecomplex *taua, doublecomplex *b, int ldb, doublecomplex *taub, int *info);
+extern void zggrqf(int m, int p, int n, doublecomplex *a, int lda, doublecomplex *taua, doublecomplex *b, int ldb, doublecomplex *taub, int *info);
+extern void zggsvd(char jobu, char jobv, char jobq, int m, int n, int p, int *k, int *l, doublecomplex *a, int lda, doublecomplex *b, int ldb, double *alpha, double *beta, doublecomplex *u, int ldu, doublecomplex *v, int ldv, doublecomplex *q, int ldq, int *iwork3, int *info);
+extern void zggsvp(char jobu, char jobv, char jobq, int m, int p, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, double tola, double tolb, int *k, int *l, doublecomplex *u, int ldu, doublecomplex *v, int ldv, doublecomplex *q, int ldq, int *info);
+extern void zgtcon(char norm, int n, doublecomplex *low, doublecomplex *diag, doublecomplex *up1, doublecomplex *up2, int *ipiv, double anorm, double *rcond, int *info);
+extern void zgtrfs(char transa, int n, int nrhs, doublecomplex *low, doublecomplex *diag, doublecomplex *up, doublecomplex *lowf, doublecomplex *diagf, doublecomplex *upf1, doublecomplex *upf2, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zgtsv(int n, int nrhs, doublecomplex *low, doublecomplex *diag, doublecomplex *up, doublecomplex *b, int ldb, int *info);
+extern void zgtsvx(char fact, char transa, int n, int nrhs, doublecomplex *low, doublecomplex *diag, doublecomplex *up, doublecomplex *lowf, doublecomplex *diagf, doublecomplex *upf1, doublecomplex *upf2, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zgttrf(int n, doublecomplex *low, doublecomplex *diag, doublecomplex *up1, doublecomplex *up2, int *ipiv, int *info);
+extern void zgttrs(char transa, int n, int nrhs, doublecomplex *low, doublecomplex *diag, doublecomplex *up1, doublecomplex *up2, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zhbev(char jobz, char uplo, int n, int ndiag, doublecomplex *a, int lda, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhbevd(char jobz, char uplo, int n, int kd, doublecomplex *ab, int ldab, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhbevx(char jobz, char range, char uplo, int n, int ndiag, doublecomplex *a, int lda, doublecomplex *q, int ldq, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zhbgst(char vect, char uplo, int n, int ka, int kb, doublecomplex *ab, int ldab, doublecomplex *bb, int ldbb, doublecomplex *x, int ldx, int *info);
+extern void zhbgv(char jobz, char uplo, int n, int ka, int kb, doublecomplex *ab, int ldab, doublecomplex *bb, int ldbb, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhbgvd(char jobz, char uplo, int n, int ka, int kb, doublecomplex *ab, int ldab, doublecomplex *bb, int ldbb, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhbgvx(char jobz, char range, char uplo, int n, int ka, int kb, doublecomplex *ab, int ldab, doublecomplex *bb, int ldbb, doublecomplex *q, int ldq, double vl, double vu, int il, int iu, double abstol, int *m, double *w, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zhbtrd(char vect, char uplo, int n, int kd, doublecomplex *ab, int ldab, double *d, double *e, doublecomplex *q, int ldq, int *info);
+extern void zhecon(char uplo, int n, doublecomplex *a, int lda, int *ipiv, double anorm, double *rcond, int *info);
+extern void zheev(char jobz, char uplo, int n, doublecomplex *a, int lda, double *w, int *info);
+extern void zheevd(char jobz, char uplo, int n, doublecomplex *a, int lda, double *w, int *info);
+extern void zheevr(char jobz, char range, char uplo, int n, doublecomplex *a, int lda, double vl, double vu, int il, int iu, double abstol, int *m, double *w, doublecomplex *z, int ldz, int *isuppz, int *info);
+extern void zheevx(char jobz, char range, char uplo, int n, doublecomplex *a, int lda, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zhegst(int itype, char uplo, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void zhegv(int itype, char jobz, char uplo, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, double *w, int *info);
+extern void zhegvd(int itype, char jobz, char uplo, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, double *w, int *info);
+extern void zhegvx(int itype, char jobz, char range, char uplo, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, double vl, double vu, int il, int iu, double abstol, int *m, double *w, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zherfs(char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zhesv(char uplo, int n, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zhesvx(char fact, char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zhetrd(char uplo, int n, doublecomplex *a, int lda, double *d, double *e, doublecomplex *tau, int *info);
+extern void zhetrf(char uplo, int n, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zhetri(char uplo, int n, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zhetrs(char uplo, int n, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zhgeqz(char job, char compq, char compz, int n, int ilo, int ihi, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *q, int ldq, doublecomplex *z, int ldz, int *info);
+extern void zhpcon(char uplo, int n, doublecomplex *a, int *ipiv, double anorm, double *rcond, int *info);
+extern void zhpev(char jobz, char uplo, int n, doublecomplex *a, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhpevd(char jobz, char uplo, int n, doublecomplex *ap, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhpevx(char jobz, char range, char uplo, int n, doublecomplex *a, double vl, double vu, int il, int iu, double abtol, int *nfound, double *w, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zhpgst(int itype, char uplo, int n, doublecomplex *ap, doublecomplex *bp, int *info);
+extern void zhpgv(int itype, char jobz, char uplo, int n, doublecomplex *a, doublecomplex *b, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhpgvd(int itype, char jobz, char uplo, int n, doublecomplex *ap, doublecomplex *bp, double *w, doublecomplex *z, int ldz, int *info);
+extern void zhpgvx(int itype, char jobz, char range, char uplo, int n, doublecomplex *ap, doublecomplex *bp, double vl, double vu, int il, int iu, double abstol, int *m, double *w, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zhprfs(char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *af, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zhpsv(char uplo, int n, int nrhs, doublecomplex *a, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zhpsvx(char fact, char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *af, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zhptrd(char uplo, int n, doublecomplex *ap, double *d, double *e, doublecomplex *tau, int *info);
+extern void zhptrf(char uplo, int n, doublecomplex *a, int *ipiv, int *info);
+extern void zhptri(char uplo, int n, doublecomplex *a, int *ipiv, int *info);
+extern void zhptrs(char uplo, int n, int nrhs, doublecomplex *a, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zhsein(char side, char eigsrc, char initv, int *select, int n, doublecomplex *h, int ldh, doublecomplex *w, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int mm, int *m, int *ifaill, int *ifailr, int *info);
+extern void zhseqr(char job, char compz, int n, int ilo, int ihi, doublecomplex *h, int ldh, doublecomplex *w, doublecomplex *z, int ldz, int *info);
+extern void zpbcon(char uplo, int n, int ndiag, doublecomplex *a, int lda, double anorm, double *rcond, int *info);
+extern void zpbequ(char uplo, int n, int ndiag, doublecomplex *a, int lda, double *scale, double *scond, double *amax, int *info);
+extern void zpbrfs(char uplo, int n, int ndiag, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zpbstf(char uplo, int n, int kd, doublecomplex *ab, int ldab, int *info);
+extern void zpbsv(char uplo, int n, int ndiag, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void zpbsvx(char fact, char uplo, int n, int ndiag, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, char equed, double *scale, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zpbtrf(char uplo, int n, int ndiag, doublecomplex *a, int lda, int *info);
+extern void zpbtrs(char uplo, int n, int ndiag, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void zpocon(char uplo, int n, doublecomplex *a, int lda, double anorm, double *rcond, int *info);
+extern void zpoequ(int n, doublecomplex *a, int lda, double *scale, double *scond, double *amax, int *info);
+extern void zporfs(char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zposv(char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void zposvx(char fact, char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, char equed, double *scale, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zpotrf(char uplo, int n, doublecomplex *a, int lda, int *info);
+extern void zpotri(char uplo, int n, doublecomplex *a, int lda, int *info);
+extern void zpotrs(char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void zppcon(char uplo, int n, doublecomplex *a, double anorm, double *rcond, int *info);
+extern void zppequ(char uplo, int n, doublecomplex *a, double *scale, double *scond, double *amax, int *info);
+extern void zpprfs(char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *af, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zppsv(char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *b, int ldb, int *info);
+extern void zppsvx(char fact, char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *af, char equed, double *scale, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zpptrf(char uplo, int n, doublecomplex *a, int *info);
+extern void zpptri(char uplo, int n, doublecomplex *a, int *info);
+extern void zpptrs(char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *b, int ldb, int *info);
+extern void zptcon(int n, double *diag, doublecomplex *offd, double anorm, double *rcond, int *info);
+extern void zpteqr(char compz, int n, double *d, double *e, doublecomplex *z, int ldz, int *info);
+extern void zptrfs(char uplo, int n, int nrhs, double *diag, doublecomplex *offd, double *diagf, doublecomplex *offdf, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zptsv(int n, int nrhs, double *diag, doublecomplex *sub, doublecomplex *b, int ldb, int *info);
+extern void zptsvx(char fact, int n, int nrhs, double *diag, doublecomplex *sub, double *diagf, doublecomplex *subf, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zpttrf(int n, double *diag, doublecomplex *offd, int *info);
+extern void zpttrs(char uplo, int n, int nrhs, double *diag, doublecomplex *offd, doublecomplex *b, int ldb, int *info);
+extern void zspcon(char uplo, int n, doublecomplex *a, int *ipiv, double anorm, double *rcond, int *info);
+extern void zsprfs(char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *af, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zspsv(char uplo, int n, int nrhs, doublecomplex *a, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zspsvx(char fact, char uplo, int n, int nrhs, doublecomplex *a, doublecomplex *af, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zsptrf(char uplo, int n, doublecomplex *a, int *ipiv, int *info);
+extern void zsptri(char uplo, int n, doublecomplex *a, int *ipiv, int *info);
+extern void zsptrs(char uplo, int n, int nrhs, doublecomplex *a, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zstedc(char compz, int n, double *d, double *e, doublecomplex *z, int ldz, int *info);
+extern void zstegr(char jobz, char range, int n, double *d, double *e, double vl, double vu, int il, int iu, double abstol, int *m, double *w, doublecomplex *z, int ldz, int *isuppz, int *info);
+extern void zstein(int n, double *d, double *e, int m, double *w, int *iblock, int *isplit, doublecomplex *z, int ldz, int *ifail, int *info);
+extern void zsteqr(char compz, int n, double *d, double *e, doublecomplex *z, int ldz, int *info);
+extern void zsycon(char uplo, int n, doublecomplex *a, int lda, int *ipiv, double anorm, double *rcond, int *info);
+extern void zsyrfs(char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void zsysv(char uplo, int n, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void zsysvx(char fact, char uplo, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *af, int ldaf, int *ipiv, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *rcond, double *ferr, double *berr, int *info);
+extern void zsytrf(char uplo, int n, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zsytri(char uplo, int n, doublecomplex *a, int lda, int *ipiv, int *info);
+extern void zsytrs(char uplo, int n, int nrhs, doublecomplex *a, int lda, int *ipiv, doublecomplex *b, int ldb, int *info);
+extern void ztbcon(char norm, char uplo, char diag, int n, int ndiag, doublecomplex *a, int lda, double *rcond, int *info);
+extern void ztbrfs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void ztbtrs(char uplo, char transa, char diag, int n, int ndiag, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void ztgevc(char side, char howmny, int *select, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int mm, int *m, int *info);
+extern void ztgexc(int wantq, int wantz, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *q, int ldq, doublecomplex *z, int ldz, int *ifst, int *ilst, int *info);
+extern void ztgsen(int ijob, int wantq, int wantz, int *select, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *q, int ldq, doublecomplex *z, int ldz, int *m, double *pl, double *pr, double *dif, int *info);
+extern void ztgsja(char jobu, char jobv, char jobq, int m, int p, int n, int k, int l, doublecomplex *a, int lda, doublecomplex *b, int ldb, double tola, double tolb, double *alpha, double *beta, doublecomplex *u, int ldu, doublecomplex *v, int ldv, doublecomplex *q, int ldq, int *ncycle, int *info);
+extern void ztgsna(char job, char howmnt, int *select, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, double *s, double *dif, int mm, int *m, int *info);
+extern void ztgsyl(char trans, int ijob, int m, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *c, int ldc, doublecomplex *d, int ldd, doublecomplex *e, int lde, doublecomplex *f, int ldf, double *scale, double *dif, int *info);
+extern void ztpcon(char norm, char uplo, char diag, int n, doublecomplex *a, double *rcond, int *info);
+extern void ztprfs(char uplo, char transa, char diag, int n, int nrhs, doublecomplex *a, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void ztptri(char uplo, char diag, int n, doublecomplex *a, int *info);
+extern void ztptrs(char uplo, char transa, char diag, int n, int nrhs, doublecomplex *a, doublecomplex *b, int ldb, int *info);
+extern void ztrcon(char norm, char uplo, char diag, int n, doublecomplex *a, int lda, double *rcond, int *info);
+extern void ztrevc(char side, char howmny, int *select, int n, doublecomplex *t, int ldt, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, int mm, int *m, int *info);
+extern void ztrexc(char compq, int n, doublecomplex *t, int ldt, doublecomplex *q, int ldq, int ifst, int ilst, int *info);
+extern void ztrrfs(char uplo, char transa, char diag, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *x, int ldx, double *ferr, double *berr, int *info);
+extern void ztrsen(char job, char compq, int *select, int n, doublecomplex *t, int ldt, doublecomplex *q, int ldq, doublecomplex *w, int *m, double *s, double *sep, int *info);
+extern void ztrsna(char job, char howmny, int *select, int n, doublecomplex *t, int ldt, doublecomplex *vl, int ldvl, doublecomplex *vr, int ldvr, double *s, double *sep, int mm, int *m, int *info);
+extern void ztrsyl(char trana, char tranb, int isgn, int m, int n, doublecomplex *a, int lda, doublecomplex *b, int ldb, doublecomplex *c, int ldc, double *scale, int *info);
+extern void ztrtri(char uplo, char diag, int n, doublecomplex *a, int lda, int *info);
+extern void ztrtrs(char uplo, char transa, char diag, int n, int nrhs, doublecomplex *a, int lda, doublecomplex *b, int ldb, int *info);
+extern void ztzrqf(int m, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void ztzrzf(int m, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zungbr(char vect, int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zunghr(int n, int ilo, int ihi, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zunglq(int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zungql(int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zungqr(int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zungrq(int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zungtr(char uplo, int n, doublecomplex *a, int lda, doublecomplex *tau, int *info);
+extern void zunmbr(char vect, char side, char trans, int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmhr(char side, char trans, int m, int n, int ilo, int ihi, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmlq(char side, char trans, int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmql(char side, char trans, int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmqr(char side, char trans, int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmrq(char side, char trans, int m, int n, int k, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmrz(char side, char trans, int m, int n, int k, int l, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zunmtr(char side, char uplo, char trans, int m, int n, doublecomplex *a, int lda, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+extern void zupgtr(char uplo, int n, doublecomplex *ap, doublecomplex *tau, doublecomplex *q, int ldq, int *info);
+extern void zupmtr(char side, char uplo, char trans, int m, int n, doublecomplex *ap, doublecomplex *tau, doublecomplex *c, int ldc, int *info);
+
+/* FFT C interfaces */
+extern void cfft1d(int mode, int n, complex *x, complex *comm, int *info);
+extern void cfft1dx(int mode, float scale, int inpl, int n, complex *x, int incx, complex *y, int incy, complex *comm, int *info);
+extern void cfft1m(int mode, int nseq, int n, complex *x, complex *comm, int *info);
+extern void cfft1mx(int mode, float scale, int inpl, int nseq, int n, complex *x, int incx1, int incx2, complex *y, int incy1, int incy2, complex *comm, int *info);
+extern void cfft2d(int mode, int m, int n, complex *x, complex *comm, int *info);
+extern void cfft2dx(int mode, float scale, int ltrans, int inpl, int m, int n, complex *x, int incx1, int incx2, complex *y, int incy1, int incy2, complex *comm, int *info);
+extern void cfft3d(int mode, int l, int m, int n, complex *x, complex *comm, int *info);
+extern void cfft3dx(int mode, float scale, int ltrans, int inpl, int l, int m, int n, complex *x, complex *y, complex *comm, int *info);
+extern void cfft3dy(int mode, float scale, int inpl, int l, int m, int n, complex *x, int incx1, int incx2, int incx3, complex *y, int incy1, int incy2, int incy3, complex *comm, int lcomm, int *info);
+extern void csfft(int mode, int n, float *x, float *comm, int *info);
+extern void csfftm(int nseq, int n, float *x, float *comm, int *info);
+extern void dzfft(int mode, int n, double *x, double *comm, int *info);
+extern void dzfftm(int nseq, int n, double *x, double *comm, int *info);
+extern void scfft(int mode, int n, float *x, float *comm, int *info);
+extern void scfftm(int nseq, int n, float *x, float *comm, int *info);
+extern void zdfft(int mode, int n, double *x, double *comm, int *info);
+extern void zdfftm(int nseq, int n, double *x, double *comm, int *info);
+extern void zfft1d(int mode, int n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft1dx(int mode, double scale, int inpl, int n, doublecomplex *x, int incx, doublecomplex *y, int incy, doublecomplex *comm, int *info);
+extern void zfft1m(int mode, int nseq, int n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft1mx(int mode, double scale, int inpl, int nseq, int n, doublecomplex *x, int incx1, int incx2, doublecomplex *y, int incy1, int incy2, doublecomplex *comm, int *info);
+extern void zfft2d(int mode, int m, int n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft2dx(int mode, double scale, int ltrans, int inpl, int m, int n, doublecomplex *x, int incx1, int incx2, doublecomplex *y, int incy1, int incy2, doublecomplex *comm, int *info);
+extern void zfft3d(int mode, int l, int m, int n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft3dx(int mode, double scale, int ltrans, int inpl, int l, int m, int n, doublecomplex *x, doublecomplex *y, doublecomplex *comm, int *info);
+extern void zfft3dy(int mode, double scale, int inpl, int l, int m, int n, doublecomplex *x, int incx1, int incx2, int incx3, doublecomplex *y, int incy1, int incy2, int incy3, doublecomplex *comm, int lcomm, int *info);
+
+/* Sparse BLAS interfaces */
+extern void caxpyi(int nz, complex a, complex *x, int *indx, complex *y);
+extern complex cdotci(int nz, complex *x, int *indx, complex *y);
+extern complex cdotui(int nz, complex *x, int *indx, complex *y);
+extern void cgthr(int nz, complex *y, complex *x, int *indx);
+extern void cgthrz(int nz, complex *y, complex *x, int *indx);
+extern void csctr(int nz, complex *x, int *indx, complex *y);
+extern void daxpyi(int nz, double a, double *x, int *indx, double *y);
+extern double ddoti(int nz, double *x, int *indx, double *y);
+extern void dgthr(int nz, double *y, double *x, int *indx);
+extern void dgthrz(int nz, double *y, double *x, int *indx);
+extern void droti(int nz, double *x, int *indx, double *y, double c, double s);
+extern void dsctr(int nz, double *x, int *indx, double *y);
+extern void saxpyi(int nz, float a, float *x, int *indx, float *y);
+extern float sdoti(int nz, float *x, int *indx, float *y);
+extern void sgthr(int nz, float *y, float *x, int *indx);
+extern void sgthrz(int nz, float *y, float *x, int *indx);
+extern void sroti(int nz, float *x, int *indx, float *y, float c, float s);
+extern void ssctr(int nz, float *x, int *indx, float *y);
+extern void zaxpyi(int nz, doublecomplex a, doublecomplex *x, int *indx, doublecomplex *y);
+extern doublecomplex zdotci(int nz, doublecomplex *x, int *indx, doublecomplex *y);
+extern doublecomplex zdotui(int nz, doublecomplex *x, int *indx, doublecomplex *y);
+extern void zgthr(int nz, doublecomplex *y, doublecomplex *x, int *indx);
+extern void zgthrz(int nz, doublecomplex *y, doublecomplex *x, int *indx);
+extern void zsctr(int nz, doublecomplex *x, int *indx, doublecomplex *y);
+
+/* Random number generators */
+extern void drandbeta(int n, double a, double b, int *state, double *x, int *info);
+extern void drandbinomial(int n, int m, double p, int *state, int *x, int *info);
+extern void drandbinomialreference(int m, double p, double *ref, int *lref, int *info);
+extern void drandblumblumshub(int n, int *state, double *x, int *info);
+extern void drandcauchy(int n, double a, double b, int *state, double *x, int *info);
+extern void drandchisquared(int n, int df, int *state, double *x, int *info);
+extern void dranddiscreteuniform(int n, int a, int b, int *state, int *x, int *info);
+extern void drandexponential(int n, double a, int *state, double *x, int *info);
+extern void drandf(int n, int df1, int df2, int *state, double *x, int *info);
+extern void drandgamma(int n, double a, double b, int *state, double *x, int *info);
+extern void drandgaussian(int n, double xmu, double var, int *state, double *x, int *info);
+extern void drandgeneraldiscrete(int n, double *ref, int *state, int *x, int *info);
+extern void drandgeometric(int n, double p, int *state, int *x, int *info);
+extern void drandgeometricreference(double p, double *ref, int *lref, int *info);
+extern void drandhypergeometric(int n, int np, int ns, int m, int *state, int *x, int *info);
+extern void drandhypergeometricreference(int np, int ns, int m, double *ref, int *lref, int *info);
+extern void drandinitialize(int genid, int subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void drandinitializebbs(int nbits, int lp, int *p, int lq, int *q, int ls, int *s, int *state, int *lstate, int *info);
+extern void drandinitializeuser(ACML_DRANDINITIALIZEUSER_UINI uini, ACML_DRANDINITIALIZEUSER_UGEN ugen, int genid, int subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void drandleapfrog(int n, int k, int *state, int *info);
+extern void drandlogistic(int n, double a, double b, int *state, double *x, int *info);
+extern void drandlognormal(int n, double xmu, double var, int *state, double *x, int *info);
+extern void drandmultinomial(int n, int m, double *p, int k, int *state, int *x, int ldx, int *info);
+extern void drandmultinormalreference(int m, double *xmu, double *c, int ldc, double *ref, int *lref, int *info);
+extern void drandmultinormalr(int n, double *ref, int *state, double *x, int ldx, int *info);
+extern void drandmultistudentstreference(int m, int df, double *xmu, double *c, int ldc, double *ref, int *lref, int *info);
+extern void drandmultistudentstr(int n, double *ref, int *state, double *x, int ldx, int *info);
+extern void drandnegativebinomial(int n, int m, double p, int *state, int *x, int *info);
+extern void drandnegativebinomialreference(int m, double p, double *ref, int *lref, int *info);
+extern void drandpoisson(int n, double lambda, int *state, int *x, int *info);
+extern void drandpoissonreference(double lambda, double *ref, int *lref, int *info);
+extern void drandskipahead(int n, int *state, int *info);
+extern void drandstudentst(int n, int df, int *state, double *x, int *info);
+extern void drandtriangular(int n, double xmin, double xmed, double xmax, int *state, double *x, int *info);
+extern void dranduniform(int n, double a, double b, int *state, double *x, int *info);
+extern void drandvonmises(int n, double vk, int *state, double *x, int *info);
+extern void drandweibull(int n, double a, double b, int *state, double *x, int *info);
+extern void drandmultinormal(int n, int m, double *xmu, double *c, int ldc, int *state, double *x, int ldx, int *info);
+extern void drandmultistudentst(int n, int m, int df, double *xmu, double *c, int ldc, int *state, double *x, int ldx, int *info);
+extern void srandbeta(int n, float a, float b, int *state, float *x, int *info);
+extern void srandblumblumshub(int n, int *state, float *x, int *info);
+extern void srandbinomial(int n, int m, float p, int *state, int *x, int *info);
+extern void srandbinomialreference(int m, float p, float *ref, int *lref, int *info);
+extern void srandcauchy(int n, float a, float b, int *state, float *x, int *info);
+extern void srandchisquared(int n, int df, int *state, float *x, int *info);
+extern void sranddiscreteuniform(int n, int a, int b, int *state, int *x, int *info);
+extern void srandexponential(int n, float a, int *state, float *x, int *info);
+extern void srandf(int n, int df1, int df2, int *state, float *x, int *info);
+extern void srandgamma(int n, float a, float b, int *state, float *x, int *info);
+extern void srandgaussian(int n, float xmu, float var, int *state, float *x, int *info);
+extern void srandgeneraldiscrete(int n, float *ref, int *state, int *x, int *info);
+extern void srandgeometric(int n, float p, int *state, int *x, int *info);
+extern void srandgeometricreference(float p, float *ref, int *lref, int *info);
+extern void srandhypergeometric(int n, int np, int ns, int m, int *state, int *x, int *info);
+extern void srandhypergeometricreference(int np, int ns, int m, float *ref, int *lref, int *info);
+extern void srandinitialize(int genid, int subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void srandinitializebbs(int nbits, int lp, int *p, int lq, int *q, int ls, int *s, int *state, int *lstate, int *info);
+extern void srandinitializeuser(ACML_SRANDINITIALIZEUSER_UINI uini, ACML_SRANDINITIALIZEUSER_UGEN ugen, int genid, int subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void srandleapfrog(int n, int k, int *state, int *info);
+extern void srandlogistic(int n, float a, float b, int *state, float *x, int *info);
+extern void srandlognormal(int n, float xmu, float var, int *state, float *x, int *info);
+extern void srandmultinomial(int n, int m, float *p, int k, int *state, int *x, int ldx, int *info);
+extern void srandmultinormalreference(int m, float *xmu, float *c, int ldc, float *ref, int *lref, int *info);
+extern void srandmultinormalr(int n, float *ref, int *state, float *x, int ldx, int *info);
+extern void srandmultistudentstreference(int m, int df, float *xmu, float *c, int ldc, float *ref, int *lref, int *info);
+extern void srandmultistudentstr(int n, float *ref, int *state, float *x, int ldx, int *info);
+extern void srandnegativebinomial(int n, int m, float p, int *state, int *x, int *info);
+extern void srandnegativebinomialreference(int m, float p, float *ref, int *lref, int *info);
+extern void srandpoisson(int n, float lambda, int *state, int *x, int *info);
+extern void srandpoissonreference(float lambda, float *ref, int *lref, int *info);
+extern void srandskipahead(int n, int *state, int *info);
+extern void srandstudentst(int n, int df, int *state, float *x, int *info);
+extern void srandtriangular(int n, float xmin, float xmed, float xmax, int *state, float *x, int *info);
+extern void sranduniform(int n, float a, float b, int *state, float *x, int *info);
+extern void srandvonmises(int n, float vk, int *state, float *x, int *info);
+extern void srandweibull(int n, float a, float b, int *state, float *x, int *info);
+extern void srandmultinormal(int n, int m, float *xmu, float *c, int ldc, int *state, float *x, int ldx, int *info);
+extern void srandmultistudentst(int n, int m, int df, float *xmu, float *c, int ldc, int *state, float *x, int ldx, int *info);
+
+/* ACML version information */
+extern void acmlversion(int *major, int *minor, int *patch);
+extern void acmlinfo(void);
+
+/* OMP interfaces */
+extern int acmlgetmaxthreads(void);
+extern int acmlgetnumthreads(void);
+extern void acmlsetnumthreads(int numthreads);
+extern int acmlgetnumprocs(void);
+
+/* Basic complex arithmetic routines for C */
+extern complex compose_complex(float x, float y);
+extern float complex_real(complex z);
+extern float complex_imag(complex z);
+extern complex complex_negate(complex z);
+extern complex complex_conjugate(complex z);
+extern complex complex_add(complex z1, complex z2);
+extern complex complex_subtract(complex z1, complex z2);
+extern complex complex_multiply(complex z1, complex z2);
+extern complex complex_divide(complex z1, complex z2);
+extern int complex_equal(complex z1, complex z2);
+extern int complex_notequal(complex z1, complex z2);
+extern float complex_abs(complex z);
+
+extern doublecomplex compose_doublecomplex(double x, double y);
+extern double doublecomplex_real(doublecomplex z);
+extern double doublecomplex_imag(doublecomplex z);
+extern doublecomplex doublecomplex_negate(doublecomplex z);
+extern doublecomplex doublecomplex_conjugate(doublecomplex z);
+extern doublecomplex doublecomplex_add(doublecomplex z1, doublecomplex z2);
+extern doublecomplex doublecomplex_subtract(doublecomplex z1, doublecomplex z2);
+extern doublecomplex doublecomplex_multiply(doublecomplex z1, doublecomplex z2);
+extern doublecomplex doublecomplex_divide(doublecomplex z1, doublecomplex z2);
+extern int doublecomplex_equal(doublecomplex z1, doublecomplex z2);
+extern int doublecomplex_notequal(doublecomplex z1, doublecomplex z2);
+extern double doublecomplex_abs(doublecomplex z);
+
+/* minmax utilities */
+extern int acml_imax2(int a, int b);
+extern int acml_imin2(int a, int b);
+extern int acml_imax3(int a, int b, int c);
+extern int acml_imin3(int a, int b, int c);
+extern float acml_fmax2(float a, float b);
+extern float acml_fmin2(float a, float b);
+extern float acml_fmax3(float a, float b, float c);
+extern float acml_fmin3(float a, float b, float c);
+extern double acml_dmax2(double a, double b);
+extern double acml_dmin2(double a, double b);
+extern double acml_dmax3(double a, double b, double c);
+extern double acml_dmin3(double a, double b, double c);
+
+/* ------------------------------------------------------------------ */
+/* Below are prototypes for the FORTRAN interfaces to ACML routines */
+
+/*
+   g77 promotes the return value of FORTRAN REAL functions to DOUBLE.
+   Other compilers do not. If linking against a g77-compiled version
+   of ACML, and calling such functions via their FORTRAN interface,
+   (e.g. sasum_) the C programmer needs to be aware of this. Calling
+   the C interface should always be safe. Functions affected in this
+   way are the ACML BLAS functions:
+
+          sasum_
+          scasum_
+          scnrm2_
+          sdot_
+          sdoti_
+          sdsdot_
+          snrm2_
+
+   and the ACML LAPACK functions
+
+          second_
+          slamch_
+
+   In order to get the expected behaviour, the macro
+   FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE should be defined at the time
+   of compilation of your C program which includes acml.h if you intend
+   to call such a function from your C program and link to a g77-compiled
+   version of ACML.
+
+   N.B. the GNU gfortran compiler does NOT promote REAL to DOUBLE
+   by default. Using the -ff2c flag with gfortran forces compatibility
+   with g77 in this respect.
+ */
+/* BLAS routines */
+extern void caxpy_(int *n, complex *alpha, complex *x, int *incx, complex *y, int *incy);
+extern void ccopy_(int *n, complex *x, int *incx, complex *y, int *incy);
+extern complex cdotc_(complex *ret_val, int *n, complex *x, int *incx, complex *y, int *incy);
+extern void cdotcsub_(complex *ret_val, int *n, complex *x, int *incx, complex *y, int *incy);
+extern complex cdotu_(complex *ret_val, int *n, complex *x, int *incx, complex *y, int *incy);
+extern void cdotusub_(complex *ret_val, int *n, complex *x, int *incx, complex *y, int *incy);
+extern void cgbmv_(char *trans, int *m, int *n, int *kl, int *ku, complex *alpha, complex *a, int *lda, complex *x, int *incx, complex *beta, complex *y, int *incy, int trans_len);
+extern void cgemm_(char *transa, char *transb, int *m, int *n, int *k, complex *alpha, complex *a, int *lda, complex *b, int *ldb, complex *beta, complex *c, int *ldc, int transa_len, int transb_len);
+extern void cgemv_(char *trans, int *m, int *n, complex *alpha, complex *a, int *lda, complex *x, int *incx, complex *beta, complex *y, int *incy, int trans_len);
+extern void cgerc_(int *m, int *n, complex *alpha, complex *x, int *incx, complex *y, int *incy, complex *a, int *lda);
+extern void cgeru_(int *m, int *n, complex *alpha, complex *x, int *incx, complex *y, int *incy, complex *a, int *lda);
+extern void chbmv_(char *uplo, int *n, int *k, complex *alpha, complex *a, int *lda, complex *x, int *incx, complex *beta, complex *y, int *incy, int uplo_len);
+extern void chemm_(char *side, char *uplo, int *m, int *n, complex *alpha, complex *a, int *lda, complex *b, int *ldb, complex *beta, complex *c, int *ldc, int side_len, int uplo_len);
+extern void chemv_(char *uplo, int *n, complex *alpha, complex *a, int *lda, complex *x, int *incx, complex *beta, complex *y, int *incy, int uplo_len);
+extern void cher_(char *uplo, int *n, float *alpha, complex *x, int *incx, complex *a, int *lda, int uplo_len);
+extern void cher2_(char *uplo, int *n, complex *alpha, complex *x, int *incx, complex *y, int *incy, complex *a, int *lda, int uplo_len);
+extern void cher2k_(char *uplo, char *trans, int *n, int *k, complex *alpha, complex *a, int *lda, complex *b, int *ldb, float *beta, complex *c, int *ldc, int uplo_len, int trans_len);
+extern void cherk_(char *uplo, char *trans, int *n, int *k, float *alpha, complex *a, int *lda, float *beta, complex *c, int *ldc, int uplo_len, int trans_len);
+extern void chpmv_(char *uplo, int *n, complex *alpha, complex *a, complex *x, int *incx, complex *beta, complex *y, int *incy, int uplo_len);
+extern void chpr_(char *uplo, int *n, float *alpha, complex *x, int *incx, complex *a, int uplo_len);
+extern void chpr2_(char *uplo, int *n, complex *alpha, complex *x, int *incx, complex *y, int *incy, complex *a, int uplo_len);
+extern void crotg_(complex *a, complex *b, float *c, complex *s);
+extern void cscal_(int *n, complex *alpha, complex *x, int *incx);
+extern void csrot_(int *n, complex *x, int *incx, complex *y, int *incy, float *c, float *s);
+extern void csscal_(int *n, float *alpha, complex *x, int *incx);
+extern void cswap_(int *n, complex *x, int *incx, complex *y, int *incy);
+extern void csymm_(char *side, char *uplo, int *m, int *n, complex *alpha, complex *a, int *lda, complex *b, int *ldb, complex *beta, complex *c, int *ldc, int side_len, int uplo_len);
+extern void csyr2k_(char *uplo, char *trans, int *n, int *k, complex *alpha, complex *a, int *lda, complex *b, int *ldb, complex *beta, complex *c, int *ldc, int uplo_len, int trans_len);
+extern void csyrk_(char *uplo, char *trans, int *n, int *k, complex *alpha, complex *a, int *lda, complex *beta, complex *c, int *ldc, int uplo_len, int trans_len);
+extern void ctbmv_(char *uplo, char *trans, char *diag, int *n, int *k, complex *a, int *lda, complex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ctbsv_(char *uplo, char *trans, char *diag, int *n, int *k, complex *a, int *lda, complex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ctpmv_(char *uplo, char *trans, char *diag, int *n, complex *ap, complex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ctpsv_(char *uplo, char *trans, char *diag, int *n, complex *ap, complex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ctrmm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, complex *alpha, complex *a, int *lda, complex *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void ctrmv_(char *uplo, char *trans, char *diag, int *n, complex *a, int *lda, complex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ctrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, complex *alpha, complex *a, int *lda, complex *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void ctrsv_(char *uplo, char *trans, char *diag, int *n, complex *a, int *lda, complex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern double dasum_(int *n, double *x, int *incx);
+extern void daxpy_(int *n, double *alpha, double *x, int *incx, double *y, int *incy);
+extern double dcabs1_(doublecomplex *z);
+extern void dcopy_(int *n, double *x, int *incx, double *y, int *incy);
+extern double ddot_(int *n, double *x, int *incx, double *y, int *incy);
+extern void dgbmv_(char *trans, int *m, int *n, int *kl, int *ku, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy, int trans_len);
+extern void dgemm_(char *transa, char *transb, int *m, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc, int transa_len, int transb_len);
+extern void dgemv_(char *trans, int *m, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy, int trans_len);
+extern void dger_(int *m, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *a, int *lda);
+extern double dnrm2_(int *n, double *x, int *incx);
+extern void drot_(int *n, double *x, int *incx, double *y, int *incy, double *c, double *s);
+extern void drotg_(double *a, double *b, double *c, double *s);
+extern void drotm_(int *n, double *x, int *incx, double *y, int *incy, double *param);
+extern void drotmg_(double *d1, double *d2, double *b1, double *b2, double *param);
+extern void dsbmv_(char *uplo, int *n, int *k, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy, int uplo_len);
+extern void dscal_(int *n, double *alpha, double *x, int *incx);
+extern double dsdot_(int *n, float *sx, int *incx, float *sy, int *incy);
+extern void dspmv_(char *uplo, int *n, double *alpha, double *ap, double *x, int *incx, double *beta, double *y, int *incy, int uplo_len);
+extern void dspr_(char *uplo, int *n, double *alpha, double *x, int *incx, double *ap, int uplo_len);
+extern void dspr2_(char *uplo, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *ap, int uplo_len);
+extern void dswap_(int *n, double *x, int *incx, double *y, int *incy);
+extern void dsymm_(char *side, char *uplo, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc, int side_len, int uplo_len);
+extern void dsymv_(char *uplo, int *n, double *alpha, double *a, int *lda, double *x, int *incx, double *beta, double *y, int *incy, int uplo_len);
+extern void dsyr_(char *uplo, int *n, double *alpha, double *x, int *incx, double *a, int *lda, int uplo_len);
+extern void dsyr2_(char *uplo, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *a, int *lda, int uplo_len);
+extern void dsyr2k_(char *uplo, char *trans, int *n, int *k, double *alpha, double *a, int *lda, double *b, int *ldb, double *beta, double *c, int *ldc, int uplo_len, int trans_len);
+extern void dsyrk_(char *uplo, char *trans, int *n, int *k, double *alpha, double *a, int *lda, double *beta, double *c, int *ldc, int uplo_len, int trans_len);
+extern void dtbmv_(char *uplo, char *trans, char *diag, int *n, int *k, double *a, int *lda, double *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void dtbsv_(char *uplo, char *trans, char *diag, int *n, int *k, double *a, int *lda, double *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void dtpmv_(char *uplo, char *trans, char *diag, int *n, double *ap, double *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void dtpsv_(char *uplo, char *trans, char *diag, int *n, double *ap, double *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void dtrmm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void dtrmv_(char *uplo, char *trans, char *diag, int *n, double *a, int *lda, double *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *a, int *lda, double *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void dtrsv_(char *uplo, char *trans, char *diag, int *n, double *a, int *lda, double *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern double dzasum_(int *n, doublecomplex *x, int *incx);
+extern double dznrm2_(int *n, doublecomplex *x, int *incx);
+extern int icamax_(int *n, complex *x, int *incx);
+extern int idamax_(int *n, double *x, int *incx);
+extern int isamax_(int *n, float *x, int *incx);
+extern int izamax_(int *n, doublecomplex *x, int *incx);
+extern int lsame_(char *ca, char *cb, int ca_len, int cb_len);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double sasum_(int *n, float *x, int *incx);
+#else
+extern float sasum_(int *n, float *x, int *incx);
+#endif
+
+extern void saxpy_(int *n, float *alpha, float *x, int *incx, float *y, int *incy);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double scasum_(int *n, complex *x, int *incx);
+extern double scnrm2_(int *n, complex *x, int *incx);
+#else
+extern float scasum_(int *n, complex *x, int *incx);
+extern float scnrm2_(int *n, complex *x, int *incx);
+#endif
+
+extern void scopy_(int *n, float *x, int *incx, float *y, int *incy);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double sdot_(int *n, float *x, int *incx, float *y, int *incy);
+extern double sdsdot_(int *n, float *b, float *x, int *incx, float *y, int *incy);
+#else
+extern float sdot_(int *n, float *x, int *incx, float *y, int *incy);
+extern float sdsdot_(int *n, float *b, float *x, int *incx, float *y, int *incy);
+#endif
+
+extern void sgbmv_(char *trans, int *m, int *n, int *kl, int *ku, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy, int trans_len);
+extern void sgemm_(char *transa, char *transb, int *m, int *n, int *k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc, int transa_len, int transb_len);
+extern void sgemv_(char *trans, int *m, int *n, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy, int trans_len);
+extern void sger_(int *m, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *a, int *lda);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double snrm2_(int *n, float *x, int *incx);
+#else
+extern float snrm2_(int *n, float *x, int *incx);
+#endif
+
+extern void srot_(int *n, float *x, int *incx, float *y, int *incy, float *c, float *s);
+extern void srotg_(float *a, float *b, float *c, float *s);
+extern void srotm_(int *n, float *x, int *incx, float *y, int *incy, float *param);
+extern void srotmg_(float *d1, float *d2, float *b1, float *b2, float *param);
+extern void ssbmv_(char *uplo, int *n, int *k, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy, int uplo_len);
+extern void sscal_(int *n, float *alpha, float *x, int *incx);
+extern void sspmv_(char *uplo, int *n, float *alpha, float *ap, float *x, int *incx, float *beta, float *y, int *incy, int uplo_len);
+extern void sspr_(char *uplo, int *n, float *alpha, float *x, int *incx, float *ap, int uplo_len);
+extern void sspr2_(char *uplo, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *ap, int uplo_len);
+extern void sswap_(int *n, float *x, int *incx, float *y, int *incy);
+extern void ssymm_(char *side, char *uplo, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc, int side_len, int uplo_len);
+extern void ssymv_(char *uplo, int *n, float *alpha, float *a, int *lda, float *x, int *incx, float *beta, float *y, int *incy, int uplo_len);
+extern void ssyr_(char *uplo, int *n, float *alpha, float *x, int *incx, float *a, int *lda, int uplo_len);
+extern void ssyr2_(char *uplo, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *a, int *lda, int uplo_len);
+extern void ssyr2k_(char *uplo, char *trans, int *n, int *k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta, float *c, int *ldc, int uplo_len, int trans_len);
+extern void ssyrk_(char *uplo, char *trans, int *n, int *k, float *alpha, float *a, int *lda, float *beta, float *c, int *ldc, int uplo_len, int trans_len);
+extern void stbmv_(char *uplo, char *trans, char *diag, int *n, int *k, float *a, int *lda, float *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void stbsv_(char *uplo, char *trans, char *diag, int *n, int *k, float *a, int *lda, float *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void stpmv_(char *uplo, char *trans, char *diag, int *n, float *ap, float *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void stpsv_(char *uplo, char *trans, char *diag, int *n, float *ap, float *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void strmm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void strmv_(char *uplo, char *trans, char *diag, int *n, float *a, int *lda, float *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void strsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *a, int *lda, float *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void strsv_(char *uplo, char *trans, char *diag, int *n, float *a, int *lda, float *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void xerbla_(const char *srname, int *info, int srname_len);
+extern void zaxpy_(int *n, doublecomplex *alpha, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern void zcopy_(int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern doublecomplex zdotc_(doublecomplex *ret_val, int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern void zdotcsub_(doublecomplex *ret_val, int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern doublecomplex zdotu_(doublecomplex *ret_val, int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern void zdotusub_(doublecomplex *ret_val, int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern void zdrot_(int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy, double *c, double *s);
+extern void zdscal_(int *n, double *alpha, doublecomplex *x, int *incx);
+extern void zgbmv_(char *trans, int *m, int *n, int *kl, int *ku, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *x, int *incx, doublecomplex *beta, doublecomplex *y, int *incy, int trans_len);
+extern void zgemm_(char *transa, char *transb, int *m, int *n, int *k, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *beta, doublecomplex *c, int *ldc, int transa_len, int transb_len);
+extern void zgemv_(char *trans, int *m, int *n, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *x, int *incx, doublecomplex *beta, doublecomplex *y, int *incy, int trans_len);
+extern void zgerc_(int *m, int *n, doublecomplex *alpha, doublecomplex *x, int *incx, doublecomplex *y, int *incy, doublecomplex *a, int *lda);
+extern void zgeru_(int *m, int *n, doublecomplex *alpha, doublecomplex *x, int *incx, doublecomplex *y, int *incy, doublecomplex *a, int *lda);
+extern void zhbmv_(char *uplo, int *n, int *k, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *x, int *incx, doublecomplex *beta, doublecomplex *y, int *incy, int uplo_len);
+extern void zhemm_(char *side, char *uplo, int *m, int *n, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *beta, doublecomplex *c, int *ldc, int side_len, int uplo_len);
+extern void zhemv_(char *uplo, int *n, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *x, int *incx, doublecomplex *beta, doublecomplex *y, int *incy, int uplo_len);
+extern void zher_(char *uplo, int *n, double *alpha, doublecomplex *x, int *incx, doublecomplex *a, int *lda, int uplo_len);
+extern void zher2_(char *uplo, int *n, doublecomplex *alpha, doublecomplex *x, int *incx, doublecomplex *y, int *incy, doublecomplex *a, int *lda, int uplo_len);
+extern void zher2k_(char *uplo, char *trans, int *n, int *k, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *beta, doublecomplex *c, int *ldc, int uplo_len, int trans_len);
+extern void zherk_(char *uplo, char *trans, int *n, int *k, double *alpha, doublecomplex *a, int *lda, double *beta, doublecomplex *c, int *ldc, int uplo_len, int trans_len);
+extern void zhpmv_(char *uplo, int *n, doublecomplex *alpha, doublecomplex *a, doublecomplex *x, int *incx, doublecomplex *beta, doublecomplex *y, int *incy, int uplo_len);
+extern void zhpr_(char *uplo, int *n, double *alpha, doublecomplex *x, int *incx, doublecomplex *a, int uplo_len);
+extern void zhpr2_(char *uplo, int *n, doublecomplex *alpha, doublecomplex *x, int *incx, doublecomplex *y, int *incy, doublecomplex *a, int uplo_len);
+extern void zrotg_(doublecomplex *a, doublecomplex *b, double *c, doublecomplex *s);
+extern void zscal_(int *n, doublecomplex *alpha, doublecomplex *x, int *incx);
+extern void zswap_(int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy);
+extern void zsymm_(char *side, char *uplo, int *m, int *n, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *beta, doublecomplex *c, int *ldc, int side_len, int uplo_len);
+extern void zsyr2k_(char *uplo, char *trans, int *n, int *k, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *beta, doublecomplex *c, int *ldc, int uplo_len, int trans_len);
+extern void zsyrk_(char *uplo, char *trans, int *n, int *k, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *beta, doublecomplex *c, int *ldc, int uplo_len, int trans_len);
+extern void ztbmv_(char *uplo, char *trans, char *diag, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ztbsv_(char *uplo, char *trans, char *diag, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ztpmv_(char *uplo, char *trans, char *diag, int *n, doublecomplex *ap, doublecomplex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ztpsv_(char *uplo, char *trans, char *diag, int *n, doublecomplex *ap, doublecomplex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ztrmm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void ztrmv_(char *uplo, char *trans, char *diag, int *n, doublecomplex *a, int *lda, doublecomplex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+extern void ztrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int side_len, int uplo_len, int transa_len, int diag_len);
+extern void ztrsv_(char *uplo, char *trans, char *diag, int *n, doublecomplex *a, int *lda, doublecomplex *x, int *incx, int uplo_len, int trans_len, int diag_len);
+
+/* LAPACK routines */
+extern int ilaenv_(int *ispec, const char *name, const char *opts, int *n1, int *n2, int *n3, int *n4, int name_len, int opts_len);
+extern void ilaenvset_(int *ispec, const char *name, const char *opts, int *n1, int *n2, int *n3, int *n4, int *nvalue, int *info, int name_len, int opts_len);
+extern void cbdsqr_(char *uplo, int *n, int *ncvt, int *nru, int *ncc, float *d, float *e, complex *vt, int *ldvt, complex *u, int *ldu, complex *c, int *ldc, float *rwork, int *info, int uplo_len);
+extern void cgbbrd_(char *vect, int *m, int *n, int *ncc, int *kl, int *ku, complex *ab, int *ldab, float *d, float *e, complex *q, int *ldq, complex *pt, int *ldpt, complex *c, int *ldc, complex *work, float *rwork, int *info, int vect_len);
+extern void cgbcon_(char *norm, int *n, int *kl, int *ku, complex *ab, int *ldab, int *ipiv, float *anorm, float *rcond, complex *work, float *rwork, int *info, int norm_len);
+extern void cgbequ_(int *m, int *n, int *kl, int *ku, complex *ab, int *ldab, float *r, float *c, float *rowcnd, float *colcnd, float *amax, int *info);
+extern void cgbrfs_(char *trans, int *n, int *kl, int *ku, int *nrhs, complex *ab, int *ldab, complex *afb, int *ldafb, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int trans_len);
+extern void cgbsv_(int *n, int *kl, int *ku, int *nrhs, complex *ab, int *ldab, int *ipiv, complex *b, int *ldb, int *info);
+extern void cgbsvx_(char *fact, char *trans, int *n, int *kl, int *ku, int *nrhs, complex *ab, int *ldab, complex *afb, int *ldafb, int *ipiv, char *equed, float *r, float *c, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void cgbtrf_(int *m, int *n, int *kl, int *ku, complex *ab, int *ldab, int *ipiv, int *info);
+extern void cgbtrs_(char *trans, int *n, int *kl, int *ku, int *nrhs, complex *ab, int *ldab, int *ipiv, complex *b, int *ldb, int *info, int trans_len);
+extern void cgebak_(char *job, char *side, int *n, int *ilo, int *ihi, float *scale, int *m, complex *v, int *ldv, int *info, int job_len, int side_len);
+extern void cgebal_(char *job, int *n, complex *a, int *lda, int *ilo, int *ihi, float *scale, int *info, int job_len);
+extern void cgebrd_(int *m, int *n, complex *a, int *lda, float *d, float *e, complex *tauq, complex *taup, complex *work, int *lwork, int *info);
+extern void cgecon_(char *norm, int *n, complex *a, int *lda, float *anorm, float *rcond, complex *work, float *rwork, int *info, int norm_len);
+extern void cgeequ_(int *m, int *n, complex *a, int *lda, float *r, float *c, float *rowcnd, float *colcnd, float *amax, int *info);
+extern void cgees_(char *jobvs, char *sort, ACML_CGEES_SELECT select, int *n, complex *a, int *lda, int *sdim, complex *w, complex *vs, int *ldvs, complex *work, int *lwork, float *rwork, int *bwork, int *info, int jobvs_len, int sort_len);
+extern void cgeesx_(char *jobvs, char *sort, ACML_CGEESX_SELECT select, char *sense, int *n, complex *a, int *lda, int *sdim, complex *w, complex *vs, int *ldvs, float *rconde, float *rcondv, complex *work, int *lwork, float *rwork, int *bwork, int *info, int jobvs_len, int sort_len, int sense_len);
+extern void cgeev_(char *jobvl, char *jobvr, int *n, complex *a, int *lda, complex *w, complex *vl, int *ldvl, complex *vr, int *ldvr, complex *work, int *lwork, float *rwork, int *info, int jobvl_len, int jobvr_len);
+extern void cgeevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, complex *a, int *lda, complex *w, complex *vl, int *ldvl, complex *vr, int *ldvr, int *ilo, int *ihi, float *scale, float *abnrm, float *rconde, float *rcondv, complex *work, int *lwork, float *rwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void cgegs_(char *jobvsl, char *jobvsr, int *n, complex *a, int *lda, complex *b, int *ldb, complex *alpha, complex *beta, complex *vsl, int *ldvsl, complex *vsr, int *ldvsr, complex *work, int *lwork, float *rwork, int *info, int jobvsl_len, int jobvsr_len);
+extern void cgegv_(char *jobvl, char *jobvr, int *n, complex *a, int *lda, complex *b, int *ldb, complex *alpha, complex *beta, complex *vl, int *ldvl, complex *vr, int *ldvr, complex *work, int *lwork, float *rwork, int *info, int jobvl_len, int jobvr_len);
+extern void cgehrd_(int *n, int *ilo, int *ihi, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cgelqf_(int *m, int *n, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cgels_(char *trans, int *m, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, complex *work, int *lwork, int *info, int trans_len);
+extern void cgelsd_(int *m, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, float *s, float *rcond, int *rank, complex *work, int *lwork, float *rwork, int *iwork, int *info);
+extern void cgelss_(int *m, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, float *s, float *rcond, int *rank, complex *work, int *lwork, float *rwork, int *info);
+extern void cgelsx_(int *m, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, int *jpvt, float *rcond, int *rank, complex *work, float *rwork, int *info);
+extern void cgelsy_(int *m, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, int *jpvt, float *rcond, int *rank, complex *work, int *lwork, float *rwork, int *info);
+extern void cgeqlf_(int *m, int *n, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cgeqp3_(int *m, int *n, complex *a, int *lda, int *jpvt, complex *tau, complex *work, int *lwork, float *rwork, int *info);
+extern void cgeqpf_(int *m, int *n, complex *a, int *lda, int *jpvt, complex *tau, complex *work, float *rwork, int *info);
+extern void cgeqrf_(int *m, int *n, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cgerfs_(char *trans, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int trans_len);
+extern void cgerqf_(int *m, int *n, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cgesdd_(char *jobz, int *m, int *n, complex *a, int *lda, float *s, complex *u, int *ldu, complex *vt, int *ldvt, complex *work, int *lwork, float *rwork, int *iwork, int *info, int jobz_len);
+extern void cgesv_(int *n, int *nrhs, complex *a, int *lda, int *ipiv, complex *b, int *ldb, int *info);
+extern void cgesvd_(char *jobu, char *jobvt, int *m, int *n, complex *a, int *lda, float *s, complex *u, int *ldu, complex *vt, int *ldvt, complex *work, int *lwork, float *rwork, int *info, int jobu_len, int jobvt_len);
+extern void cgesvx_(char *fact, char *trans, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv, char *equed, float *r, float *c, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void cgetrf_(int *m, int *n, complex *a, int *lda, int *ipiv, int *info);
+extern void cgetri_(int *n, complex *a, int *lda, int *ipiv, complex *work, int *lwork, int *info);
+extern void cgetrs_(char *trans, int *n, int *nrhs, complex *a, int *lda, int *ipiv, complex *b, int *ldb, int *info, int trans_len);
+extern void cggbak_(char *job, char *side, int *n, int *ilo, int *ihi, float *lscale, float *rscale, int *m, complex *v, int *ldv, int *info, int job_len, int side_len);
+extern void cggbal_(char *job, int *n, complex *a, int *lda, complex *b, int *ldb, int *ilo, int *ihi, float *lscale, float *rscale, float *work, int *info, int job_len);
+extern void cgges_(char *jobvsl, char *jobvsr, char *sort, ACML_CGGES_SELCTG selctg, int *n, complex *a, int *lda, complex *b, int *ldb, int *sdim, complex *alpha, complex *beta, complex *vsl, int *ldvsl, complex *vsr, int *ldvsr, complex *work, int *lwork, float *rwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len);
+extern void cggesx_(char *jobvsl, char *jobvsr, char *sort, ACML_CGGESX_SELCTG selctg, char *sense, int *n, complex *a, int *lda, complex *b, int *ldb, int *sdim, complex *alpha, complex *beta, complex *vsl, int *ldvsl, complex *vsr, int *ldvsr, float *rconde, float *rcondv, complex *work, int *lwork, float *rwork, int *iwork, int *liwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len, int sense_len);
+extern void cggev_(char *jobvl, char *jobvr, int *n, complex *a, int *lda, complex *b, int *ldb, complex *alpha, complex *beta, complex *vl, int *ldvl, complex *vr, int *ldvr, complex *work, int *lwork, float *rwork, int *info, int jobvl_len, int jobvr_len);
+extern void cggevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, complex *a, int *lda, complex *b, int *ldb, complex *alpha, complex *beta, complex *vl, int *ldvl, complex *vr, int *ldvr, int *ilo, int *ihi, float *lscale, float *rscale, float *abnrm, float *bbnrm, float *rconde, float *rcondv, complex *work, int *lwork, float *rwork, int *iwork, int *bwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void cggglm_(int *n, int *m, int *p, complex *a, int *lda, complex *b, int *ldb, complex *d, complex *x, complex *y, complex *work, int *lwork, int *info);
+extern void cgghrd_(char *compq, char *compz, int *n, int *ilo, int *ihi, complex *a, int *lda, complex *b, int *ldb, complex *q, int *ldq, complex *z, int *ldz, int *info, int compq_len, int compz_len);
+extern void cgglse_(int *m, int *n, int *p, complex *a, int *lda, complex *b, int *ldb, complex *c, complex *d, complex *x, complex *work, int *lwork, int *info);
+extern void cggqrf_(int *n, int *m, int *p, complex *a, int *lda, complex *taua, complex *b, int *ldb, complex *taub, complex *work, int *lwork, int *info);
+extern void cggrqf_(int *m, int *p, int *n, complex *a, int *lda, complex *taua, complex *b, int *ldb, complex *taub, complex *work, int *lwork, int *info);
+extern void cggsvd_(char *jobu, char *jobv, char *jobq, int *m, int *n, int *p, int *k, int *l, complex *a, int *lda, complex *b, int *ldb, float *alpha, float *beta, complex *u, int *ldu, complex *v, int *ldv, complex *q, int *ldq, complex *work, float *rwork, int *iwork, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void cggsvp_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, complex *a, int *lda, complex *b, int *ldb, float *tola, float *tolb, int *k, int *l, complex *u, int *ldu, complex *v, int *ldv, complex *q, int *ldq, int *iwork, float *rwork, complex *tau, complex *work, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void cgtcon_(char *norm, int *n, complex *dl, complex *d, complex *du, complex *du2, int *ipiv, float *anorm, float *rcond, complex *work, int *info, int norm_len);
+extern void cgtrfs_(char *trans, int *n, int *nrhs, complex *dl, complex *d, complex *du, complex *dlf, complex *df, complex *duf, complex *du2, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int trans_len);
+extern void cgtsv_(int *n, int *nrhs, complex *dl, complex *d, complex *du, complex *b, int *ldb, int *info);
+extern void cgtsvx_(char *fact, char *trans, int *n, int *nrhs, complex *dl, complex *d, complex *du, complex *dlf, complex *df, complex *duf, complex *du2, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int trans_len);
+extern void cgttrf_(int *n, complex *dl, complex *d, complex *du, complex *du2, int *ipiv, int *info);
+extern void cgttrs_(char *trans, int *n, int *nrhs, complex *dl, complex *d, complex *du, complex *du2, int *ipiv, complex *b, int *ldb, int *info, int trans_len);
+extern void chbev_(char *jobz, char *uplo, int *n, int *kd, complex *ab, int *ldab, float *w, complex *z, int *ldz, complex *work, float *rwork, int *info, int jobz_len, int uplo_len);
+extern void chbevd_(char *jobz, char *uplo, int *n, int *kd, complex *ab, int *ldab, float *w, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void chbevx_(char *jobz, char *range, char *uplo, int *n, int *kd, complex *ab, int *ldab, complex *q, int *ldq, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, complex *work, float *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void chbgst_(char *vect, char *uplo, int *n, int *ka, int *kb, complex *ab, int *ldab, complex *bb, int *ldbb, complex *x, int *ldx, complex *work, float *rwork, int *info, int vect_len, int uplo_len);
+extern void chbgv_(char *jobz, char *uplo, int *n, int *ka, int *kb, complex *ab, int *ldab, complex *bb, int *ldbb, float *w, complex *z, int *ldz, complex *work, float *rwork, int *info, int jobz_len, int uplo_len);
+extern void chbgvd_(char *jobz, char *uplo, int *n, int *ka, int *kb, complex *ab, int *ldab, complex *bb, int *ldbb, float *w, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void chbgvx_(char *jobz, char *range, char *uplo, int *n, int *ka, int *kb, complex *ab, int *ldab, complex *bb, int *ldbb, complex *q, int *ldq, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, complex *work, float *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void chbtrd_(char *vect, char *uplo, int *n, int *kd, complex *ab, int *ldab, float *d, float *e, complex *q, int *ldq, complex *work, int *info, int vect_len, int uplo_len);
+extern void checon_(char *uplo, int *n, complex *a, int *lda, int *ipiv, float *anorm, float *rcond, complex *work, int *info, int uplo_len);
+extern void cheev_(char *jobz, char *uplo, int *n, complex *a, int *lda, float *w, complex *work, int *lwork, float *rwork, int *info, int jobz_len, int uplo_len);
+extern void cheevd_(char *jobz, char *uplo, int *n, complex *a, int *lda, float *w, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void cheevr_(char *jobz, char *range, char *uplo, int *n, complex *a, int *lda, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, int *isuppz, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len, int uplo_len);
+extern void cheevx_(char *jobz, char *range, char *uplo, int *n, complex *a, int *lda, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void chegst_(int *itype, char *uplo, int *n, complex *a, int *lda, complex *b, int *ldb, int *info, int uplo_len);
+extern void chegv_(int *itype, char *jobz, char *uplo, int *n, complex *a, int *lda, complex *b, int *ldb, float *w, complex *work, int *lwork, float *rwork, int *info, int jobz_len, int uplo_len);
+extern void chegvd_(int *itype, char *jobz, char *uplo, int *n, complex *a, int *lda, complex *b, int *ldb, float *w, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void chegvx_(int *itype, char *jobz, char *range, char *uplo, int *n, complex *a, int *lda, complex *b, int *ldb, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void cherfs_(char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void chesv_(char *uplo, int *n, int *nrhs, complex *a, int *lda, int *ipiv, complex *b, int *ldb, complex *work, int *lwork, int *info, int uplo_len);
+extern void chesvx_(char *fact, char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, int *lwork, float *rwork, int *info, int fact_len, int uplo_len);
+extern void chetrd_(char *uplo, int *n, complex *a, int *lda, float *d, float *e, complex *tau, complex *work, int *lwork, int *info, int uplo_len);
+extern void chetrf_(char *uplo, int *n, complex *a, int *lda, int *ipiv, complex *work, int *lwork, int *info, int uplo_len);
+extern void chetri_(char *uplo, int *n, complex *a, int *lda, int *ipiv, complex *work, int *info, int uplo_len);
+extern void chetrs_(char *uplo, int *n, int *nrhs, complex *a, int *lda, int *ipiv, complex *b, int *ldb, int *info, int uplo_len);
+extern void chgeqz_(char *job, char *compq, char *compz, int *n, int *ilo, int *ihi, complex *a, int *lda, complex *b, int *ldb, complex *alpha, complex *beta, complex *q, int *ldq, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *info, int job_len, int compq_len, int compz_len);
+extern void chpcon_(char *uplo, int *n, complex *ap, int *ipiv, float *anorm, float *rcond, complex *work, int *info, int uplo_len);
+extern void chpev_(char *jobz, char *uplo, int *n, complex *ap, float *w, complex *z, int *ldz, complex *work, float *rwork, int *info, int jobz_len, int uplo_len);
+extern void chpevd_(char *jobz, char *uplo, int *n, complex *ap, float *w, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void chpevx_(char *jobz, char *range, char *uplo, int *n, complex *ap, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, complex *work, float *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void chpgst_(int *itype, char *uplo, int *n, complex *ap, complex *bp, int *info, int uplo_len);
+extern void chpgv_(int *itype, char *jobz, char *uplo, int *n, complex *ap, complex *bp, float *w, complex *z, int *ldz, complex *work, float *rwork, int *info, int jobz_len, int uplo_len);
+extern void chpgvd_(int *itype, char *jobz, char *uplo, int *n, complex *ap, complex *bp, float *w, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void chpgvx_(int *itype, char *jobz, char *range, char *uplo, int *n, complex *ap, complex *bp, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, complex *work, float *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void chprfs_(char *uplo, int *n, int *nrhs, complex *ap, complex *afp, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void chpsv_(char *uplo, int *n, int *nrhs, complex *ap, int *ipiv, complex *b, int *ldb, int *info, int uplo_len);
+extern void chpsvx_(char *fact, char *uplo, int *n, int *nrhs, complex *ap, complex *afp, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int uplo_len);
+extern void chptrd_(char *uplo, int *n, complex *ap, float *d, float *e, complex *tau, int *info, int uplo_len);
+extern void chptrf_(char *uplo, int *n, complex *ap, int *ipiv, int *info, int uplo_len);
+extern void chptri_(char *uplo, int *n, complex *ap, int *ipiv, complex *work, int *info, int uplo_len);
+extern void chptrs_(char *uplo, int *n, int *nrhs, complex *ap, int *ipiv, complex *b, int *ldb, int *info, int uplo_len);
+extern void chsein_(char *side, char *eigsrc, char *initv, int *select, int *n, complex *h, int *ldh, complex *w, complex *vl, int *ldvl, complex *vr, int *ldvr, int *mm, int *m, complex *work, float *rwork, int *ifaill, int *ifailr, int *info, int side_len, int eigsrc_len, int initv_len);
+extern void chseqr_(char *job, char *compz, int *n, int *ilo, int *ihi, complex *h, int *ldh, complex *w, complex *z, int *ldz, complex *work, int *lwork, int *info, int job_len, int compz_len);
+extern void cpbcon_(char *uplo, int *n, int *kd, complex *ab, int *ldab, float *anorm, float *rcond, complex *work, float *rwork, int *info, int uplo_len);
+extern void cpbequ_(char *uplo, int *n, int *kd, complex *ab, int *ldab, float *s, float *scond, float *amax, int *info, int uplo_len);
+extern void cpbrfs_(char *uplo, int *n, int *kd, int *nrhs, complex *ab, int *ldab, complex *afb, int *ldafb, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void cpbstf_(char *uplo, int *n, int *kd, complex *ab, int *ldab, int *info, int uplo_len);
+extern void cpbsv_(char *uplo, int *n, int *kd, int *nrhs, complex *ab, int *ldab, complex *b, int *ldb, int *info, int uplo_len);
+extern void cpbsvx_(char *fact, char *uplo, int *n, int *kd, int *nrhs, complex *ab, int *ldab, complex *afb, int *ldafb, char *equed, float *s, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void cpbtrf_(char *uplo, int *n, int *kd, complex *ab, int *ldab, int *info, int uplo_len);
+extern void cpbtrs_(char *uplo, int *n, int *kd, int *nrhs, complex *ab, int *ldab, complex *b, int *ldb, int *info, int uplo_len);
+extern void cpocon_(char *uplo, int *n, complex *a, int *lda, float *anorm, float *rcond, complex *work, float *rwork, int *info, int uplo_len);
+extern void cpoequ_(int *n, complex *a, int *lda, float *s, float *scond, float *amax, int *info);
+extern void cporfs_(char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void cposv_(char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, int *info, int uplo_len);
+extern void cposvx_(char *fact, char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, char *equed, float *s, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void cpotrf_(char *uplo, int *n, complex *a, int *lda, int *info, int uplo_len);
+extern void cpotri_(char *uplo, int *n, complex *a, int *lda, int *info, int uplo_len);
+extern void cpotrs_(char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, int *info, int uplo_len);
+extern void cppcon_(char *uplo, int *n, complex *ap, float *anorm, float *rcond, complex *work, float *rwork, int *info, int uplo_len);
+extern void cppequ_(char *uplo, int *n, complex *ap, float *s, float *scond, float *amax, int *info, int uplo_len);
+extern void cpprfs_(char *uplo, int *n, int *nrhs, complex *ap, complex *afp, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void cppsv_(char *uplo, int *n, int *nrhs, complex *ap, complex *b, int *ldb, int *info, int uplo_len);
+extern void cppsvx_(char *fact, char *uplo, int *n, int *nrhs, complex *ap, complex *afp, char *equed, float *s, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void cpptrf_(char *uplo, int *n, complex *ap, int *info, int uplo_len);
+extern void cpptri_(char *uplo, int *n, complex *ap, int *info, int uplo_len);
+extern void cpptrs_(char *uplo, int *n, int *nrhs, complex *ap, complex *b, int *ldb, int *info, int uplo_len);
+extern void cptcon_(int *n, float *d, complex *e, float *anorm, float *rcond, float *rwork, int *info);
+extern void cpteqr_(char *compz, int *n, float *d, float *e, complex *z, int *ldz, float *work, int *info, int compz_len);
+extern void cptrfs_(char *uplo, int *n, int *nrhs, float *d, complex *e, float *df, complex *ef, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void cptsv_(int *n, int *nrhs, float *d, complex *e, complex *b, int *ldb, int *info);
+extern void cptsvx_(char *fact, int *n, int *nrhs, float *d, complex *e, float *df, complex *ef, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len);
+extern void cpttrf_(int *n, float *d, complex *e, int *info);
+extern void cpttrs_(char *uplo, int *n, int *nrhs, float *d, complex *e, complex *b, int *ldb, int *info, int uplo_len);
+extern void cspcon_(char *uplo, int *n, complex *ap, int *ipiv, float *anorm, float *rcond, complex *work, int *info, int uplo_len);
+extern void csprfs_(char *uplo, int *n, int *nrhs, complex *ap, complex *afp, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void cspsv_(char *uplo, int *n, int *nrhs, complex *ap, int *ipiv, complex *b, int *ldb, int *info, int uplo_len);
+extern void cspsvx_(char *fact, char *uplo, int *n, int *nrhs, complex *ap, complex *afp, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, float *rwork, int *info, int fact_len, int uplo_len);
+extern void csptrf_(char *uplo, int *n, complex *ap, int *ipiv, int *info, int uplo_len);
+extern void csptri_(char *uplo, int *n, complex *ap, int *ipiv, complex *work, int *info, int uplo_len);
+extern void csptrs_(char *uplo, int *n, int *nrhs, complex *ap, int *ipiv, complex *b, int *ldb, int *info, int uplo_len);
+extern void cstedc_(char *compz, int *n, float *d, float *e, complex *z, int *ldz, complex *work, int *lwork, float *rwork, int *lrwork, int *iwork, int *liwork, int *info, int compz_len);
+extern void cstegr_(char *jobz, char *range, int *n, float *d, float *e, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, complex *z, int *ldz, int *isuppz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len);
+extern void cstein_(int *n, float *d, float *e, int *m, float *w, int *iblock, int *isplit, complex *z, int *ldz, float *work, int *iwork, int *ifail, int *info);
+extern void csteqr_(char *compz, int *n, float *d, float *e, complex *z, int *ldz, float *work, int *info, int compz_len);
+extern void csycon_(char *uplo, int *n, complex *a, int *lda, int *ipiv, float *anorm, float *rcond, complex *work, int *info, int uplo_len);
+extern void csyrfs_(char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len);
+extern void csysv_(char *uplo, int *n, int *nrhs, complex *a, int *lda, int *ipiv, complex *b, int *ldb, complex *work, int *lwork, int *info, int uplo_len);
+extern void csysvx_(char *fact, char *uplo, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv, complex *b, int *ldb, complex *x, int *ldx, float *rcond, float *ferr, float *berr, complex *work, int *lwork, float *rwork, int *info, int fact_len, int uplo_len);
+extern void csytrf_(char *uplo, int *n, complex *a, int *lda, int *ipiv, complex *work, int *lwork, int *info, int uplo_len);
+extern void csytri_(char *uplo, int *n, complex *a, int *lda, int *ipiv, complex *work, int *info, int uplo_len);
+extern void csytrs_(char *uplo, int *n, int *nrhs, complex *a, int *lda, int *ipiv, complex *b, int *ldb, int *info, int uplo_len);
+extern void ctbcon_(char *norm, char *uplo, char *diag, int *n, int *kd, complex *ab, int *ldab, float *rcond, complex *work, float *rwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void ctbrfs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, complex *ab, int *ldab, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ctbtrs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, complex *ab, int *ldab, complex *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ctgevc_(char *side, char *howmny, int *select, int *n, complex *a, int *lda, complex *b, int *ldb, complex *vl, int *ldvl, complex *vr, int *ldvr, int *mm, int *m, complex *work, float *rwork, int *info, int side_len, int howmny_len);
+extern void ctgexc_(int *wantq, int *wantz, int *n, complex *a, int *lda, complex *b, int *ldb, complex *q, int *ldq, complex *z, int *ldz, int *ifst, int *ilst, int *info);
+extern void ctgsen_(int *ijob, int *wantq, int *wantz, int *select, int *n, complex *a, int *lda, complex *b, int *ldb, complex *alpha, complex *beta, complex *q, int *ldq, complex *z, int *ldz, int *m, float *pl, float *pr, float *dif, complex *work, int *lwork, int *iwork, int *liwork, int *info);
+extern void ctgsja_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, int *k, int *l, complex *a, int *lda, complex *b, int *ldb, float *tola, float *tolb, float *alpha, float *beta, complex *u, int *ldu, complex *v, int *ldv, complex *q, int *ldq, complex *work, int *ncycle, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void ctgsna_(char *job, char *howmny, int *select, int *n, complex *a, int *lda, complex *b, int *ldb, complex *vl, int *ldvl, complex *vr, int *ldvr, float *s, float *dif, int *mm, int *m, complex *work, int *lwork, int *iwork, int *info, int job_len, int howmny_len);
+extern void ctgsyl_(char *trans, int *ijob, int *m, int *n, complex *a, int *lda, complex *b, int *ldb, complex *c, int *ldc, complex *d, int *ldd, complex *e, int *lde, complex *f, int *ldf, float *scale, float *dif, complex *work, int *lwork, int *iwork, int *info, int trans_len);
+extern void ctpcon_(char *norm, char *uplo, char *diag, int *n, complex *ap, float *rcond, complex *work, float *rwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void ctprfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, complex *ap, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ctptri_(char *uplo, char *diag, int *n, complex *ap, int *info, int uplo_len, int diag_len);
+extern void ctptrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, complex *ap, complex *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ctrcon_(char *norm, char *uplo, char *diag, int *n, complex *a, int *lda, float *rcond, complex *work, float *rwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void ctrevc_(char *side, char *howmny, int *select, int *n, complex *t, int *ldt, complex *vl, int *ldvl, complex *vr, int *ldvr, int *mm, int *m, complex *work, float *rwork, int *info, int side_len, int howmny_len);
+extern void ctrexc_(char *compq, int *n, complex *t, int *ldt, complex *q, int *ldq, int *ifst, int *ilst, int *info, int compq_len);
+extern void ctrrfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, complex *x, int *ldx, float *ferr, float *berr, complex *work, float *rwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ctrsen_(char *job, char *compq, int *select, int *n, complex *t, int *ldt, complex *q, int *ldq, complex *w, int *m, float *s, float *sep, complex *work, int *lwork, int *info, int job_len, int compq_len);
+extern void ctrsna_(char *job, char *howmny, int *select, int *n, complex *t, int *ldt, complex *vl, int *ldvl, complex *vr, int *ldvr, float *s, float *sep, int *mm, int *m, complex *work, int *ldwork, float *rwork, int *info, int job_len, int howmny_len);
+extern void ctrsyl_(char *trana, char *tranb, int *isgn, int *m, int *n, complex *a, int *lda, complex *b, int *ldb, complex *c, int *ldc, float *scale, int *info, int trana_len, int tranb_len);
+extern void ctrtri_(char *uplo, char *diag, int *n, complex *a, int *lda, int *info, int uplo_len, int diag_len);
+extern void ctrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ctzrqf_(int *m, int *n, complex *a, int *lda, complex *tau, int *info);
+extern void ctzrzf_(int *m, int *n, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cungbr_(char *vect, int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info, int vect_len);
+extern void cunghr_(int *n, int *ilo, int *ihi, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cunglq_(int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cungql_(int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cungqr_(int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cungrq_(int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info);
+extern void cungtr_(char *uplo, int *n, complex *a, int *lda, complex *tau, complex *work, int *lwork, int *info, int uplo_len);
+extern void cunmbr_(char *vect, char *side, char *trans, int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int vect_len, int side_len, int trans_len);
+extern void cunmhr_(char *side, char *trans, int *m, int *n, int *ilo, int *ihi, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void cunmlq_(char *side, char *trans, int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void cunmql_(char *side, char *trans, int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void cunmqr_(char *side, char *trans, int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void cunmr3_(char *side, char *trans, int *m, int *n, int *k, int *l, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *info, int side_len, int trans_len);
+extern void cunmrq_(char *side, char *trans, int *m, int *n, int *k, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void cunmrz_(char *side, char *trans, int *m, int *n, int *k, int *l, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void cunmtr_(char *side, char *uplo, char *trans, int *m, int *n, complex *a, int *lda, complex *tau, complex *c, int *ldc, complex *work, int *lwork, int *info, int side_len, int uplo_len, int trans_len);
+extern void cupgtr_(char *uplo, int *n, complex *ap, complex *tau, complex *q, int *ldq, complex *work, int *info, int uplo_len);
+extern void cupmtr_(char *side, char *uplo, char *trans, int *m, int *n, complex *ap, complex *tau, complex *c, int *ldc, complex *work, int *info, int side_len, int uplo_len, int trans_len);
+extern void dbdsdc_(char *uplo, char *compq, int *n, double *d, double *e, double *u, int *ldu, double *vt, int *ldvt, double *q, int *iq, double *work, int *iwork, int *info, int uplo_len, int compq_len);
+extern void dbdsqr_(char *uplo, int *n, int *ncvt, int *nru, int *ncc, double *d, double *e, double *vt, int *ldvt, double *u, int *ldu, double *c, int *ldc, double *work, int *info, int uplo_len);
+extern void ddisna_(char *job, int *m, int *n, double *d, double *sep, int *info, int job_len);
+extern void dgbbrd_(char *vect, int *m, int *n, int *ncc, int *kl, int *ku, double *ab, int *ldab, double *d, double *e, double *q, int *ldq, double *pt, int *ldpt, double *c, int *ldc, double *work, int *info, int vect_len);
+extern void dgbcon_(char *norm, int *n, int *kl, int *ku, double *ab, int *ldab, int *ipiv, double *anorm, double *rcond, double *work, int *iwork, int *info, int norm_len);
+extern void dgbequ_(int *m, int *n, int *kl, int *ku, double *ab, int *ldab, double *r, double *c, double *rowcnd, double *colcnd, double *amax, int *info);
+extern void dgbrfs_(char *trans, int *n, int *kl, int *ku, int *nrhs, double *ab, int *ldab, double *afb, int *ldafb, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int trans_len);
+extern void dgbsv_(int *n, int *kl, int *ku, int *nrhs, double *ab, int *ldab, int *ipiv, double *b, int *ldb, int *info);
+extern void dgbsvx_(char *fact, char *trans, int *n, int *kl, int *ku, int *nrhs, double *ab, int *ldab, double *afb, int *ldafb, int *ipiv, char *equed, double *r, double *c, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void dgbtrf_(int *m, int *n, int *kl, int *ku, double *ab, int *ldab, int *ipiv, int *info);
+extern void dgbtrs_(char *trans, int *n, int *kl, int *ku, int *nrhs, double *ab, int *ldab, int *ipiv, double *b, int *ldb, int *info, int trans_len);
+extern void dgebak_(char *job, char *side, int *n, int *ilo, int *ihi, double *scale, int *m, double *v, int *ldv, int *info, int job_len, int side_len);
+extern void dgebal_(char *job, int *n, double *a, int *lda, int *ilo, int *ihi, double *scale, int *info, int job_len);
+extern void dgebrd_(int *m, int *n, double *a, int *lda, double *d, double *e, double *tauq, double *taup, double *work, int *lwork, int *info);
+extern void dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info, int norm_len);
+extern void dgeequ_(int *m, int *n, double *a, int *lda, double *r, double *c, double *rowcnd, double *colcnd, double *amax, int *info);
+extern void dgees_(char *jobvs, char *sort, ACML_DGEES_SELECT select, int *n, double *a, int *lda, int *sdim, double *wr, double *wi, double *vs, int *ldvs, double *work, int *lwork, int *bwork, int *info, int jobvs_len, int sort_len);
+extern void dgeesx_(char *jobvs, char *sort, ACML_DGEESX_SELECT select, char *sense, int *n, double *a, int *lda, int *sdim, double *wr, double *wi, double *vs, int *ldvs, double *rconde, double *rcondv, double *work, int *lwork, int *iwork, int *liwork, int *bwork, int *info, int jobvs_len, int sort_len, int sense_len);
+extern void dgeev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info, int jobvl_len, int jobvr_len);
+extern void dgeevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, int *ilo, int *ihi, double *scale, double *abnrm, double *rconde, double *rcondv, double *work, int *lwork, int *iwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void dgegs_(char *jobvsl, char *jobvsr, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai, double *beta, double *vsl, int *ldvsl, double *vsr, int *ldvsr, double *work, int *lwork, int *info, int jobvsl_len, int jobvsr_len);
+extern void dgegv_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai, double *beta, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info, int jobvl_len, int jobvr_len);
+extern void dgehrd_(int *n, int *ilo, int *ihi, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dgelqf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dgels_(char *trans, int *m, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *work, int *lwork, int *info, int trans_len);
+extern void dgelsd_(int *m, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *s, double *rcond, int *rank, double *work, int *lwork, int *iwork, int *info);
+extern void dgelss_(int *m, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *s, double *rcond, int *rank, double *work, int *lwork, int *info);
+extern void dgelsx_(int *m, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *jpvt, double *rcond, int *rank, double *work, int *info);
+extern void dgelsy_(int *m, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *jpvt, double *rcond, int *rank, double *work, int *lwork, int *info);
+extern void dgeqlf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info);
+extern void dgeqpf_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *info);
+extern void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dgerfs_(char *trans, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int trans_len);
+extern void dgerqf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dgesdd_(char *jobz, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork, int *iwork, int *info, int jobz_len);
+extern void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
+extern void dgesvd_(char *jobu, char *jobvt, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt, double *work, int *lwork, int *info, int jobu_len, int jobvt_len);
+extern void dgesvx_(char *fact, char *trans, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, char *equed, double *r, double *c, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
+extern void dgetri_(int *n, double *a, int *lda, int *ipiv, double *work, int *lwork, int *info);
+extern void dgetrs_(char *trans, int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info, int trans_len);
+extern void dggbak_(char *job, char *side, int *n, int *ilo, int *ihi, double *lscale, double *rscale, int *m, double *v, int *ldv, int *info, int job_len, int side_len);
+extern void dggbal_(char *job, int *n, double *a, int *lda, double *b, int *ldb, int *ilo, int *ihi, double *lscale, double *rscale, double *work, int *info, int job_len);
+extern void dgges_(char *jobvsl, char *jobvsr, char *sort, ACML_DGGES_DELCTG delctg, int *n, double *a, int *lda, double *b, int *ldb, int *sdim, double *alphar, double *alphai, double *beta, double *vsl, int *ldvsl, double *vsr, int *ldvsr, double *work, int *lwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len);
+extern void dggesx_(char *jobvsl, char *jobvsr, char *sort, ACML_DGGESX_DELCTG delctg, char *sense, int *n, double *a, int *lda, double *b, int *ldb, int *sdim, double *alphar, double *alphai, double *beta, double *vsl, int *ldvsl, double *vsr, int *ldvsr, double *rconde, double *rcondv, double *work, int *lwork, int *iwork, int *liwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len, int sense_len);
+extern void dggev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai, double *beta, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info, int jobvl_len, int jobvr_len);
+extern void dggevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai, double *beta, double *vl, int *ldvl, double *vr, int *ldvr, int *ilo, int *ihi, double *lscale, double *rscale, double *abnrm, double *bbnrm, double *rconde, double *rcondv, double *work, int *lwork, int *iwork, int *bwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void dggglm_(int *n, int *m, int *p, double *a, int *lda, double *b, int *ldb, double *d, double *x, double *y, double *work, int *lwork, int *info);
+extern void dgghrd_(char *compq, char *compz, int *n, int *ilo, int *ihi, double *a, int *lda, double *b, int *ldb, double *q, int *ldq, double *z, int *ldz, int *info, int compq_len, int compz_len);
+extern void dgglse_(int *m, int *n, int *p, double *a, int *lda, double *b, int *ldb, double *c, double *d, double *x, double *work, int *lwork, int *info);
+extern void dggqrf_(int *n, int *m, int *p, double *a, int *lda, double *taua, double *b, int *ldb, double *taub, double *work, int *lwork, int *info);
+extern void dggrqf_(int *m, int *p, int *n, double *a, int *lda, double *taua, double *b, int *ldb, double *taub, double *work, int *lwork, int *info);
+extern void dggsvd_(char *jobu, char *jobv, char *jobq, int *m, int *n, int *p, int *k, int *l, double *a, int *lda, double *b, int *ldb, double *alpha, double *beta, double *u, int *ldu, double *v, int *ldv, double *q, int *ldq, double *work, int *iwork, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void dggsvp_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, double *a, int *lda, double *b, int *ldb, double *tola, double *tolb, int *k, int *l, double *u, int *ldu, double *v, int *ldv, double *q, int *ldq, int *iwork, double *tau, double *work, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void dgtcon_(char *norm, int *n, double *dl, double *d, double *du, double *du2, int *ipiv, double *anorm, double *rcond, double *work, int *iwork, int *info, int norm_len);
+extern void dgtrfs_(char *trans, int *n, int *nrhs, double *dl, double *d, double *du, double *dlf, double *df, double *duf, double *du2, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int trans_len);
+extern void dgtsv_(int *n, int *nrhs, double *dl, double *d, double *du, double *b, int *ldb, int *info);
+extern void dgtsvx_(char *fact, char *trans, int *n, int *nrhs, double *dl, double *d, double *du, double *dlf, double *df, double *duf, double *du2, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int trans_len);
+extern void dgttrf_(int *n, double *dl, double *d, double *du, double *du2, int *ipiv, int *info);
+extern void dgttrs_(char *trans, int *n, int *nrhs, double *dl, double *d, double *du, double *du2, int *ipiv, double *b, int *ldb, int *info, int trans_len);
+extern void dhgeqz_(char *job, char *compq, char *compz, int *n, int *ilo, int *ihi, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai, double *beta, double *q, int *ldq, double *z, int *ldz, double *work, int *lwork, int *info, int job_len, int compq_len, int compz_len);
+extern void dhsein_(char *side, char *eigsrc, char *initv, int *select, int *n, double *h, int *ldh, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, int *mm, int *m, double *work, int *ifaill, int *ifailr, int *info, int side_len, int eigsrc_len, int initv_len);
+extern void dhseqr_(char *job, char *compz, int *n, int *ilo, int *ihi, double *h, int *ldh, double *wr, double *wi, double *z, int *ldz, double *work, int *lwork, int *info, int job_len, int compz_len);
+extern double dlamch_(char *cmach, int cmach_len);
+extern void dopgtr_(char *uplo, int *n, double *ap, double *tau, double *q, int *ldq, double *work, int *info, int uplo_len);
+extern void dopmtr_(char *side, char *uplo, char *trans, int *m, int *n, double *ap, double *tau, double *c, int *ldc, double *work, int *info, int side_len, int uplo_len, int trans_len);
+extern void dorgbr_(char *vect, int *m, int *n, int *k, double *a, int *lda, double *tau, double *work, int *lwork, int *info, int vect_len);
+extern void dorghr_(int *n, int *ilo, int *ihi, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dorglq_(int *m, int *n, int *k, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dorgql_(int *m, int *n, int *k, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dorgqr_(int *m, int *n, int *k, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dorgrq_(int *m, int *n, int *k, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void dorgtr_(char *uplo, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info, int uplo_len);
+extern void dormbr_(char *vect, char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int vect_len, int side_len, int trans_len);
+extern void dormhr_(char *side, char *trans, int *m, int *n, int *ilo, int *ihi, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int trans_len);
+extern void dormlq_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int trans_len);
+extern void dormql_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int trans_len);
+extern void dormqr_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int trans_len);
+extern void dormr3_(char *side, char *trans, int *m, int *n, int *k, int *l, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *info, int side_len, int trans_len);
+extern void dormrq_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int trans_len);
+extern void dormrz_(char *side, char *trans, int *m, int *n, int *k, int *l, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int trans_len);
+extern void dormtr_(char *side, char *uplo, char *trans, int *m, int *n, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info, int side_len, int uplo_len, int trans_len);
+extern void dpbcon_(char *uplo, int *n, int *kd, double *ab, int *ldab, double *anorm, double *rcond, double *work, int *iwork, int *info, int uplo_len);
+extern void dpbequ_(char *uplo, int *n, int *kd, double *ab, int *ldab, double *s, double *scond, double *amax, int *info, int uplo_len);
+extern void dpbrfs_(char *uplo, int *n, int *kd, int *nrhs, double *ab, int *ldab, double *afb, int *ldafb, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len);
+extern void dpbstf_(char *uplo, int *n, int *kd, double *ab, int *ldab, int *info, int uplo_len);
+extern void dpbsv_(char *uplo, int *n, int *kd, int *nrhs, double *ab, int *ldab, double *b, int *ldb, int *info, int uplo_len);
+extern void dpbsvx_(char *fact, char *uplo, int *n, int *kd, int *nrhs, double *ab, int *ldab, double *afb, int *ldafb, char *equed, double *s, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void dpbtrf_(char *uplo, int *n, int *kd, double *ab, int *ldab, int *info, int uplo_len);
+extern void dpbtrs_(char *uplo, int *n, int *kd, int *nrhs, double *ab, int *ldab, double *b, int *ldb, int *info, int uplo_len);
+extern void dpocon_(char *uplo, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info, int uplo_len);
+extern void dpoequ_(int *n, double *a, int *lda, double *s, double *scond, double *amax, int *info);
+extern void dporfs_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len);
+extern void dposv_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info, int uplo_len);
+extern void dposvx_(char *fact, char *uplo, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, char *equed, double *s, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void dpotrf_(char *uplo, int *n, double *a, int *lda, int *info, int uplo_len);
+extern void dpotri_(char *uplo, int *n, double *a, int *lda, int *info, int uplo_len);
+extern void dpotrs_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info, int uplo_len);
+extern void dppcon_(char *uplo, int *n, double *ap, double *anorm, double *rcond, double *work, int *iwork, int *info, int uplo_len);
+extern void dppequ_(char *uplo, int *n, double *ap, double *s, double *scond, double *amax, int *info, int uplo_len);
+extern void dpprfs_(char *uplo, int *n, int *nrhs, double *ap, double *afp, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len);
+extern void dppsv_(char *uplo, int *n, int *nrhs, double *ap, double *b, int *ldb, int *info, int uplo_len);
+extern void dppsvx_(char *fact, char *uplo, int *n, int *nrhs, double *ap, double *afp, char *equed, double *s, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void dpptrf_(char *uplo, int *n, double *ap, int *info, int uplo_len);
+extern void dpptri_(char *uplo, int *n, double *ap, int *info, int uplo_len);
+extern void dpptrs_(char *uplo, int *n, int *nrhs, double *ap, double *b, int *ldb, int *info, int uplo_len);
+extern void dptcon_(int *n, double *d, double *e, double *anorm, double *rcond, double *work, int *info);
+extern void dpteqr_(char *compz, int *n, double *d, double *e, double *z, int *ldz, double *work, int *info, int compz_len);
+extern void dptrfs_(int *n, int *nrhs, double *d, double *e, double *df, double *ef, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *info);
+extern void dptsv_(int *n, int *nrhs, double *d, double *e, double *b, int *ldb, int *info);
+extern void dptsvx_(char *fact, int *n, int *nrhs, double *d, double *e, double *df, double *ef, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *info, int fact_len);
+extern void dpttrf_(int *n, double *d, double *e, int *info);
+extern void dpttrs_(int *n, int *nrhs, double *d, double *e, double *b, int *ldb, int *info);
+extern void dsbev_(char *jobz, char *uplo, int *n, int *kd, double *ab, int *ldab, double *w, double *z, int *ldz, double *work, int *info, int jobz_len, int uplo_len);
+extern void dsbevd_(char *jobz, char *uplo, int *n, int *kd, double *ab, int *ldab, double *w, double *z, int *ldz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void dsbevx_(char *jobz, char *range, char *uplo, int *n, int *kd, double *ab, int *ldab, double *q, int *ldq, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dsbgst_(char *vect, char *uplo, int *n, int *ka, int *kb, double *ab, int *ldab, double *bb, int *ldbb, double *x, int *ldx, double *work, int *info, int vect_len, int uplo_len);
+extern void dsbgv_(char *jobz, char *uplo, int *n, int *ka, int *kb, double *ab, int *ldab, double *bb, int *ldbb, double *w, double *z, int *ldz, double *work, int *info, int jobz_len, int uplo_len);
+extern void dsbgvd_(char *jobz, char *uplo, int *n, int *ka, int *kb, double *ab, int *ldab, double *bb, int *ldbb, double *w, double *z, int *ldz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void dsbgvx_(char *jobz, char *range, char *uplo, int *n, int *ka, int *kb, double *ab, int *ldab, double *bb, int *ldbb, double *q, int *ldq, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dsbtrd_(char *vect, char *uplo, int *n, int *kd, double *ab, int *ldab, double *d, double *e, double *q, int *ldq, double *work, int *info, int vect_len, int uplo_len);
+extern double dsecnd_(void);
+extern void dspcon_(char *uplo, int *n, double *ap, int *ipiv, double *anorm, double *rcond, double *work, int *iwork, int *info, int uplo_len);
+extern void dspev_(char *jobz, char *uplo, int *n, double *ap, double *w, double *z, int *ldz, double *work, int *info, int jobz_len, int uplo_len);
+extern void dspevd_(char *jobz, char *uplo, int *n, double *ap, double *w, double *z, int *ldz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void dspevx_(char *jobz, char *range, char *uplo, int *n, double *ap, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dspgst_(int *itype, char *uplo, int *n, double *ap, double *bp, int *info, int uplo_len);
+extern void dspgv_(int *itype, char *jobz, char *uplo, int *n, double *ap, double *bp, double *w, double *z, int *ldz, double *work, int *info, int jobz_len, int uplo_len);
+extern void dspgvd_(int *itype, char *jobz, char *uplo, int *n, double *ap, double *bp, double *w, double *z, int *ldz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void dspgvx_(int *itype, char *jobz, char *range, char *uplo, int *n, double *ap, double *bp, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dsprfs_(char *uplo, int *n, int *nrhs, double *ap, double *afp, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len);
+extern void dspsv_(char *uplo, int *n, int *nrhs, double *ap, int *ipiv, double *b, int *ldb, int *info, int uplo_len);
+extern void dspsvx_(char *fact, char *uplo, int *n, int *nrhs, double *ap, double *afp, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *iwork, int *info, int fact_len, int uplo_len);
+extern void dsptrd_(char *uplo, int *n, double *ap, double *d, double *e, double *tau, int *info, int uplo_len);
+extern void dsptrf_(char *uplo, int *n, double *ap, int *ipiv, int *info, int uplo_len);
+extern void dsptri_(char *uplo, int *n, double *ap, int *ipiv, double *work, int *info, int uplo_len);
+extern void dsptrs_(char *uplo, int *n, int *nrhs, double *ap, int *ipiv, double *b, int *ldb, int *info, int uplo_len);
+extern void dstebz_(char *range, char *order, int *n, double *vl, double *vu, int *il, int *iu, double *abstol, double *d, double *e, int *m, int *nsplit, double *w, int *iblock, int *isplit, double *work, int *iwork, int *info, int range_len, int order_len);
+extern void dstedc_(char *compz, int *n, double *d, double *e, double *z, int *ldz, double *work, int *lwork, int *iwork, int *liwork, int *info, int compz_len);
+extern void dstegr_(char *jobz, char *range, int *n, double *d, double *e, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, int *isuppz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len);
+extern void dstein_(int *n, double *d, double *e, int *m, double *w, int *iblock, int *isplit, double *z, int *ldz, double *work, int *iwork, int *ifail, int *info);
+extern void dsteqr_(char *compz, int *n, double *d, double *e, double *z, int *ldz, double *work, int *info, int compz_len);
+extern void dsterf_(int *n, double *d, double *e, int *info);
+extern void dstev_(char *jobz, int *n, double *d, double *e, double *z, int *ldz, double *work, int *info, int jobz_len);
+extern void dstevd_(char *jobz, int *n, double *d, double *e, double *z, int *ldz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len);
+extern void dstevr_(char *jobz, char *range, int *n, double *d, double *e, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, int *isuppz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len);
+extern void dstevx_(char *jobz, char *range, int *n, double *d, double *e, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len);
+extern void dsycon_(char *uplo, int *n, double *a, int *lda, int *ipiv, double *anorm, double *rcond, double *work, int *iwork, int *info, int uplo_len);
+extern void dsyev_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w, double *work, int *lwork, int *info, int jobz_len, int uplo_len);
+extern void dsyevd_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void dsyevr_(char *jobz, char *range, char *uplo, int *n, double *a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, int *isuppz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dsyevx_(char *jobz, char *range, char *uplo, int *n, double *a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *lwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dsygst_(int *itype, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, int *info, int uplo_len);
+extern void dsygv_(int *itype, char *jobz, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *w, double *work, int *lwork, int *info, int jobz_len, int uplo_len);
+extern void dsygvd_(int *itype, char *jobz, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *w, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void dsygvx_(int *itype, char *jobz, char *range, char *uplo, int *n, double *a, int *lda, double *b, int *ldb, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, double *z, int *ldz, double *work, int *lwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void dsyrfs_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len);
+extern void dsysv_(char *uplo, int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, double *work, int *lwork, int *info, int uplo_len);
+extern void dsysvx_(char *fact, char *uplo, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr, double *work, int *lwork, int *iwork, int *info, int fact_len, int uplo_len);
+extern void dsytrd_(char *uplo, int *n, double *a, int *lda, double *d, double *e, double *tau, double *work, int *lwork, int *info, int uplo_len);
+extern void dsytrf_(char *uplo, int *n, double *a, int *lda, int *ipiv, double *work, int *lwork, int *info, int uplo_len);
+extern void dsytri_(char *uplo, int *n, double *a, int *lda, int *ipiv, double *work, int *info, int uplo_len);
+extern void dsytrs_(char *uplo, int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info, int uplo_len);
+extern void dtbcon_(char *norm, char *uplo, char *diag, int *n, int *kd, double *ab, int *ldab, double *rcond, double *work, int *iwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void dtbrfs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, double *ab, int *ldab, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void dtbtrs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, double *ab, int *ldab, double *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void dtgevc_(char *side, char *howmny, int *select, int *n, double *a, int *lda, double *b, int *ldb, double *vl, int *ldvl, double *vr, int *ldvr, int *mm, int *m, double *work, int *info, int side_len, int howmny_len);
+extern void dtgexc_(int *wantq, int *wantz, int *n, double *a, int *lda, double *b, int *ldb, double *q, int *ldq, double *z, int *ldz, int *ifst, int *ilst, double *work, int *lwork, int *info);
+extern void dtgsen_(int *ijob, int *wantq, int *wantz, int *select, int *n, double *a, int *lda, double *b, int *ldb, double *alphar, double *alphai, double *beta, double *q, int *ldq, double *z, int *ldz, int *m, double *pl, double *pr, double *dif, double *work, int *lwork, int *iwork, int *liwork, int *info);
+extern void dtgsja_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, int *k, int *l, double *a, int *lda, double *b, int *ldb, double *tola, double *tolb, double *alpha, double *beta, double *u, int *ldu, double *v, int *ldv, double *q, int *ldq, double *work, int *ncycle, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void dtgsna_(char *job, char *howmny, int *select, int *n, double *a, int *lda, double *b, int *ldb, double *vl, int *ldvl, double *vr, int *ldvr, double *s, double *dif, int *mm, int *m, double *work, int *lwork, int *iwork, int *info, int job_len, int howmny_len);
+extern void dtgsyl_(char *trans, int *ijob, int *m, int *n, double *a, int *lda, double *b, int *ldb, double *c, int *ldc, double *d, int *ldd, double *e, int *lde, double *f, int *ldf, double *scale, double *dif, double *work, int *lwork, int *iwork, int *info, int trans_len);
+extern void dtpcon_(char *norm, char *uplo, char *diag, int *n, double *ap, double *rcond, double *work, int *iwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void dtprfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *ap, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void dtptri_(char *uplo, char *diag, int *n, double *ap, int *info, int uplo_len, int diag_len);
+extern void dtptrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *ap, double *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void dtrcon_(char *norm, char *uplo, char *diag, int *n, double *a, int *lda, double *rcond, double *work, int *iwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void dtrevc_(char *side, char *howmny, int *select, int *n, double *t, int *ldt, double *vl, int *ldvl, double *vr, int *ldvr, int *mm, int *m, double *work, int *info, int side_len, int howmny_len);
+extern void dtrexc_(char *compq, int *n, double *t, int *ldt, double *q, int *ldq, int *ifst, int *ilst, double *work, int *info, int compq_len);
+extern void dtrrfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *x, int *ldx, double *ferr, double *berr, double *work, int *iwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void dtrsen_(char *job, char *compq, int *select, int *n, double *t, int *ldt, double *q, int *ldq, double *wr, double *wi, int *m, double *s, double *sep, double *work, int *lwork, int *iwork, int *liwork, int *info, int job_len, int compq_len);
+extern void dtrsna_(char *job, char *howmny, int *select, int *n, double *t, int *ldt, double *vl, int *ldvl, double *vr, int *ldvr, double *s, double *sep, int *mm, int *m, double *work, int *ldwork, int *iwork, int *info, int job_len, int howmny_len);
+extern void dtrsyl_(char *trana, char *tranb, int *isgn, int *m, int *n, double *a, int *lda, double *b, int *ldb, double *c, int *ldc, double *scale, int *info, int trana_len, int tranb_len);
+extern void dtrtri_(char *uplo, char *diag, int *n, double *a, int *lda, int *info, int uplo_len, int diag_len);
+extern void dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void dtzrqf_(int *m, int *n, double *a, int *lda, double *tau, int *info);
+extern void dtzrzf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info);
+extern void sbdsdc_(char *uplo, char *compq, int *n, float *d, float *e, float *u, int *ldu, float *vt, int *ldvt, float *q, int *iq, float *work, int *iwork, int *info, int uplo_len, int compq_len);
+extern void sbdsqr_(char *uplo, int *n, int *ncvt, int *nru, int *ncc, float *d, float *e, float *vt, int *ldvt, float *u, int *ldu, float *c, int *ldc, float *work, int *info, int uplo_len);
+extern void sdisna_(char *job, int *m, int *n, float *d, float *sep, int *info, int job_len);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double second_(void);
+#else
+extern float second_(void);
+#endif
+
+extern void sgbbrd_(char *vect, int *m, int *n, int *ncc, int *kl, int *ku, float *ab, int *ldab, float *d, float *e, float *q, int *ldq, float *pt, int *ldpt, float *c, int *ldc, float *work, int *info, int vect_len);
+extern void sgbcon_(char *norm, int *n, int *kl, int *ku, float *ab, int *ldab, int *ipiv, float *anorm, float *rcond, float *work, int *iwork, int *info, int norm_len);
+extern void sgbequ_(int *m, int *n, int *kl, int *ku, float *ab, int *ldab, float *r, float *c, float *rowcnd, float *colcnd, float *amax, int *info);
+extern void sgbrfs_(char *trans, int *n, int *kl, int *ku, int *nrhs, float *ab, int *ldab, float *afb, int *ldafb, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int trans_len);
+extern void sgbsv_(int *n, int *kl, int *ku, int *nrhs, float *ab, int *ldab, int *ipiv, float *b, int *ldb, int *info);
+extern void sgbsvx_(char *fact, char *trans, int *n, int *kl, int *ku, int *nrhs, float *ab, int *ldab, float *afb, int *ldafb, int *ipiv, char *equed, float *r, float *c, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void sgbtrf_(int *m, int *n, int *kl, int *ku, float *ab, int *ldab, int *ipiv, int *info);
+extern void sgbtrs_(char *trans, int *n, int *kl, int *ku, int *nrhs, float *ab, int *ldab, int *ipiv, float *b, int *ldb, int *info, int trans_len);
+extern void sgebak_(char *job, char *side, int *n, int *ilo, int *ihi, float *scale, int *m, float *v, int *ldv, int *info, int job_len, int side_len);
+extern void sgebal_(char *job, int *n, float *a, int *lda, int *ilo, int *ihi, float *scale, int *info, int job_len);
+extern void sgebrd_(int *m, int *n, float *a, int *lda, float *d, float *e, float *tauq, float *taup, float *work, int *lwork, int *info);
+extern void sgecon_(char *norm, int *n, float *a, int *lda, float *anorm, float *rcond, float *work, int *iwork, int *info, int norm_len);
+extern void sgeequ_(int *m, int *n, float *a, int *lda, float *r, float *c, float *rowcnd, float *colcnd, float *amax, int *info);
+extern void sgees_(char *jobvs, char *sort, ACML_SGEES_SELECT select, int *n, float *a, int *lda, int *sdim, float *wr, float *wi, float *vs, int *ldvs, float *work, int *lwork, int *bwork, int *info, int jobvs_len, int sort_len);
+extern void sgeesx_(char *jobvs, char *sort, ACML_SGEESX_SELECT select, char *sense, int *n, float *a, int *lda, int *sdim, float *wr, float *wi, float *vs, int *ldvs, float *rconde, float *rcondv, float *work, int *lwork, int *iwork, int *liwork, int *bwork, int *info, int jobvs_len, int sort_len, int sense_len);
+extern void sgeev_(char *jobvl, char *jobvr, int *n, float *a, int *lda, float *wr, float *wi, float *vl, int *ldvl, float *vr, int *ldvr, float *work, int *lwork, int *info, int jobvl_len, int jobvr_len);
+extern void sgeevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, float *a, int *lda, float *wr, float *wi, float *vl, int *ldvl, float *vr, int *ldvr, int *ilo, int *ihi, float *scale, float *abnrm, float *rconde, float *rcondv, float *work, int *lwork, int *iwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void sgegs_(char *jobvsl, char *jobvsr, int *n, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *vsl, int *ldvsl, float *vsr, int *ldvsr, float *work, int *lwork, int *info, int jobvsl_len, int jobvsr_len);
+extern void sgegv_(char *jobvl, char *jobvr, int *n, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *vl, int *ldvl, float *vr, int *ldvr, float *work, int *lwork, int *info, int jobvl_len, int jobvr_len);
+extern void sgehrd_(int *n, int *ilo, int *ihi, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sgelqf_(int *m, int *n, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sgels_(char *trans, int *m, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, float *work, int *lwork, int *info, int trans_len);
+extern void sgelsd_(int *m, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, float *s, float *rcond, int *rank, float *work, int *lwork, int *iwork, int *info);
+extern void sgelss_(int *m, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, float *s, float *rcond, int *rank, float *work, int *lwork, int *info);
+extern void sgelsx_(int *m, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, int *jpvt, float *rcond, int *rank, float *work, int *info);
+extern void sgelsy_(int *m, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, int *jpvt, float *rcond, int *rank, float *work, int *lwork, int *info);
+extern void sgeqlf_(int *m, int *n, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sgeqp3_(int *m, int *n, float *a, int *lda, int *jpvt, float *tau, float *work, int *lwork, int *info);
+extern void sgeqpf_(int *m, int *n, float *a, int *lda, int *jpvt, float *tau, float *work, int *info);
+extern void sgeqrf_(int *m, int *n, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sgerfs_(char *trans, int *n, int *nrhs, float *a, int *lda, float *af, int *ldaf, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int trans_len);
+extern void sgerqf_(int *m, int *n, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sgesdd_(char *jobz, int *m, int *n, float *a, int *lda, float *s, float *u, int *ldu, float *vt, int *ldvt, float *work, int *lwork, int *iwork, int *info, int jobz_len);
+extern void sgesv_(int *n, int *nrhs, float *a, int *lda, int *ipiv, float *b, int *ldb, int *info);
+extern void sgesvd_(char *jobu, char *jobvt, int *m, int *n, float *a, int *lda, float *s, float *u, int *ldu, float *vt, int *ldvt, float *work, int *lwork, int *info, int jobu_len, int jobvt_len);
+extern void sgesvx_(char *fact, char *trans, int *n, int *nrhs, float *a, int *lda, float *af, int *ldaf, int *ipiv, char *equed, float *r, float *c, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void sgetrf_(int *m, int *n, float *a, int *lda, int *ipiv, int *info);
+extern void sgetri_(int *n, float *a, int *lda, int *ipiv, float *work, int *lwork, int *info);
+extern void sgetrs_(char *trans, int *n, int *nrhs, float *a, int *lda, int *ipiv, float *b, int *ldb, int *info, int trans_len);
+extern void sggbak_(char *job, char *side, int *n, int *ilo, int *ihi, float *lscale, float *rscale, int *m, float *v, int *ldv, int *info, int job_len, int side_len);
+extern void sggbal_(char *job, int *n, float *a, int *lda, float *b, int *ldb, int *ilo, int *ihi, float *lscale, float *rscale, float *work, int *info, int job_len);
+extern void sgges_(char *jobvsl, char *jobvsr, char *sort, ACML_SGGES_SELCTG selctg, int *n, float *a, int *lda, float *b, int *ldb, int *sdim, float *alphar, float *alphai, float *beta, float *vsl, int *ldvsl, float *vsr, int *ldvsr, float *work, int *lwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len);
+extern void sggesx_(char *jobvsl, char *jobvsr, char *sort, ACML_SGGESX_SELCTG selctg, char *sense, int *n, float *a, int *lda, float *b, int *ldb, int *sdim, float *alphar, float *alphai, float *beta, float *vsl, int *ldvsl, float *vsr, int *ldvsr, float *rconde, float *rcondv, float *work, int *lwork, int *iwork, int *liwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len, int sense_len);
+extern void sggev_(char *jobvl, char *jobvr, int *n, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *vl, int *ldvl, float *vr, int *ldvr, float *work, int *lwork, int *info, int jobvl_len, int jobvr_len);
+extern void sggevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *vl, int *ldvl, float *vr, int *ldvr, int *ilo, int *ihi, float *lscale, float *rscale, float *abnrm, float *bbnrm, float *rconde, float *rcondv, float *work, int *lwork, int *iwork, int *bwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void sggglm_(int *n, int *m, int *p, float *a, int *lda, float *b, int *ldb, float *d, float *x, float *y, float *work, int *lwork, int *info);
+extern void sgghrd_(char *compq, char *compz, int *n, int *ilo, int *ihi, float *a, int *lda, float *b, int *ldb, float *q, int *ldq, float *z, int *ldz, int *info, int compq_len, int compz_len);
+extern void sgglse_(int *m, int *n, int *p, float *a, int *lda, float *b, int *ldb, float *c, float *d, float *x, float *work, int *lwork, int *info);
+extern void sggqrf_(int *n, int *m, int *p, float *a, int *lda, float *taua, float *b, int *ldb, float *taub, float *work, int *lwork, int *info);
+extern void sggrqf_(int *m, int *p, int *n, float *a, int *lda, float *taua, float *b, int *ldb, float *taub, float *work, int *lwork, int *info);
+extern void sggsvd_(char *jobu, char *jobv, char *jobq, int *m, int *n, int *p, int *k, int *l, float *a, int *lda, float *b, int *ldb, float *alpha, float *beta, float *u, int *ldu, float *v, int *ldv, float *q, int *ldq, float *work, int *iwork, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void sggsvp_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, float *a, int *lda, float *b, int *ldb, float *tola, float *tolb, int *k, int *l, float *u, int *ldu, float *v, int *ldv, float *q, int *ldq, int *iwork, float *tau, float *work, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void sgtcon_(char *norm, int *n, float *dl, float *d, float *du, float *du2, int *ipiv, float *anorm, float *rcond, float *work, int *iwork, int *info, int norm_len);
+extern void sgtrfs_(char *trans, int *n, int *nrhs, float *dl, float *d, float *du, float *dlf, float *df, float *duf, float *du2, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int trans_len);
+extern void sgtsv_(int *n, int *nrhs, float *dl, float *d, float *du, float *b, int *ldb, int *info);
+extern void sgtsvx_(char *fact, char *trans, int *n, int *nrhs, float *dl, float *d, float *du, float *dlf, float *df, float *duf, float *du2, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int trans_len);
+extern void sgttrf_(int *n, float *dl, float *d, float *du, float *du2, int *ipiv, int *info);
+extern void sgttrs_(char *trans, int *n, int *nrhs, float *dl, float *d, float *du, float *du2, int *ipiv, float *b, int *ldb, int *info, int trans_len);
+extern void shgeqz_(char *job, char *compq, char *compz, int *n, int *ilo, int *ihi, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *q, int *ldq, float *z, int *ldz, float *work, int *lwork, int *info, int job_len, int compq_len, int compz_len);
+extern void shsein_(char *side, char *eigsrc, char *initv, int *select, int *n, float *h, int *ldh, float *wr, float *wi, float *vl, int *ldvl, float *vr, int *ldvr, int *mm, int *m, float *work, int *ifaill, int *ifailr, int *info, int side_len, int eigsrc_len, int initv_len);
+extern void shseqr_(char *job, char *compz, int *n, int *ilo, int *ihi, float *h, int *ldh, float *wr, float *wi, float *z, int *ldz, float *work, int *lwork, int *info, int job_len, int compz_len);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double slamch_(char *cmach, int cmach_len);
+#else
+extern float slamch_(char *cmach, int cmach_len);
+#endif
+
+extern void sopgtr_(char *uplo, int *n, float *ap, float *tau, float *q, int *ldq, float *work, int *info, int uplo_len);
+extern void sopmtr_(char *side, char *uplo, char *trans, int *m, int *n, float *ap, float *tau, float *c, int *ldc, float *work, int *info, int side_len, int uplo_len, int trans_len);
+extern void sorgbr_(char *vect, int *m, int *n, int *k, float *a, int *lda, float *tau, float *work, int *lwork, int *info, int vect_len);
+extern void sorghr_(int *n, int *ilo, int *ihi, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sorglq_(int *m, int *n, int *k, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sorgql_(int *m, int *n, int *k, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sorgqr_(int *m, int *n, int *k, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sorgrq_(int *m, int *n, int *k, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void sorgtr_(char *uplo, int *n, float *a, int *lda, float *tau, float *work, int *lwork, int *info, int uplo_len);
+extern void sormbr_(char *vect, char *side, char *trans, int *m, int *n, int *k, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int vect_len, int side_len, int trans_len);
+extern void sormhr_(char *side, char *trans, int *m, int *n, int *ilo, int *ihi, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int trans_len);
+extern void sormlq_(char *side, char *trans, int *m, int *n, int *k, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int trans_len);
+extern void sormql_(char *side, char *trans, int *m, int *n, int *k, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int trans_len);
+extern void sormqr_(char *side, char *trans, int *m, int *n, int *k, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int trans_len);
+extern void sormr3_(char *side, char *trans, int *m, int *n, int *k, int *l, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *info, int side_len, int trans_len);
+extern void sormrq_(char *side, char *trans, int *m, int *n, int *k, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int trans_len);
+extern void sormrz_(char *side, char *trans, int *m, int *n, int *k, int *l, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int trans_len);
+extern void sormtr_(char *side, char *uplo, char *trans, int *m, int *n, float *a, int *lda, float *tau, float *c, int *ldc, float *work, int *lwork, int *info, int side_len, int uplo_len, int trans_len);
+extern void spbcon_(char *uplo, int *n, int *kd, float *ab, int *ldab, float *anorm, float *rcond, float *work, int *iwork, int *info, int uplo_len);
+extern void spbequ_(char *uplo, int *n, int *kd, float *ab, int *ldab, float *s, float *scond, float *amax, int *info, int uplo_len);
+extern void spbrfs_(char *uplo, int *n, int *kd, int *nrhs, float *ab, int *ldab, float *afb, int *ldafb, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len);
+extern void spbstf_(char *uplo, int *n, int *kd, float *ab, int *ldab, int *info, int uplo_len);
+extern void spbsv_(char *uplo, int *n, int *kd, int *nrhs, float *ab, int *ldab, float *b, int *ldb, int *info, int uplo_len);
+extern void spbsvx_(char *fact, char *uplo, int *n, int *kd, int *nrhs, float *ab, int *ldab, float *afb, int *ldafb, char *equed, float *s, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void spbtrf_(char *uplo, int *n, int *kd, float *ab, int *ldab, int *info, int uplo_len);
+extern void spbtrs_(char *uplo, int *n, int *kd, int *nrhs, float *ab, int *ldab, float *b, int *ldb, int *info, int uplo_len);
+extern void spocon_(char *uplo, int *n, float *a, int *lda, float *anorm, float *rcond, float *work, int *iwork, int *info, int uplo_len);
+extern void spoequ_(int *n, float *a, int *lda, float *s, float *scond, float *amax, int *info);
+extern void sporfs_(char *uplo, int *n, int *nrhs, float *a, int *lda, float *af, int *ldaf, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len);
+extern void sposv_(char *uplo, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, int *info, int uplo_len);
+extern void sposvx_(char *fact, char *uplo, int *n, int *nrhs, float *a, int *lda, float *af, int *ldaf, char *equed, float *s, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void spotrf_(char *uplo, int *n, float *a, int *lda, int *info, int uplo_len);
+extern void spotri_(char *uplo, int *n, float *a, int *lda, int *info, int uplo_len);
+extern void spotrs_(char *uplo, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, int *info, int uplo_len);
+extern void sppcon_(char *uplo, int *n, float *ap, float *anorm, float *rcond, float *work, int *iwork, int *info, int uplo_len);
+extern void sppequ_(char *uplo, int *n, float *ap, float *s, float *scond, float *amax, int *info, int uplo_len);
+extern void spprfs_(char *uplo, int *n, int *nrhs, float *ap, float *afp, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len);
+extern void sppsv_(char *uplo, int *n, int *nrhs, float *ap, float *b, int *ldb, int *info, int uplo_len);
+extern void sppsvx_(char *fact, char *uplo, int *n, int *nrhs, float *ap, float *afp, char *equed, float *s, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void spptrf_(char *uplo, int *n, float *ap, int *info, int uplo_len);
+extern void spptri_(char *uplo, int *n, float *ap, int *info, int uplo_len);
+extern void spptrs_(char *uplo, int *n, int *nrhs, float *ap, float *b, int *ldb, int *info, int uplo_len);
+extern void sptcon_(int *n, float *d, float *e, float *anorm, float *rcond, float *work, int *info);
+extern void spteqr_(char *compz, int *n, float *d, float *e, float *z, int *ldz, float *work, int *info, int compz_len);
+extern void sptrfs_(int *n, int *nrhs, float *d, float *e, float *df, float *ef, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *info);
+extern void sptsv_(int *n, int *nrhs, float *d, float *e, float *b, int *ldb, int *info);
+extern void sptsvx_(char *fact, int *n, int *nrhs, float *d, float *e, float *df, float *ef, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *info, int fact_len);
+extern void spttrf_(int *n, float *d, float *e, int *info);
+extern void spttrs_(int *n, int *nrhs, float *d, float *e, float *b, int *ldb, int *info);
+extern void ssbev_(char *jobz, char *uplo, int *n, int *kd, float *ab, int *ldab, float *w, float *z, int *ldz, float *work, int *info, int jobz_len, int uplo_len);
+extern void ssbevd_(char *jobz, char *uplo, int *n, int *kd, float *ab, int *ldab, float *w, float *z, int *ldz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void ssbevx_(char *jobz, char *range, char *uplo, int *n, int *kd, float *ab, int *ldab, float *q, int *ldq, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void ssbgst_(char *vect, char *uplo, int *n, int *ka, int *kb, float *ab, int *ldab, float *bb, int *ldbb, float *x, int *ldx, float *work, int *info, int vect_len, int uplo_len);
+extern void ssbgv_(char *jobz, char *uplo, int *n, int *ka, int *kb, float *ab, int *ldab, float *bb, int *ldbb, float *w, float *z, int *ldz, float *work, int *info, int jobz_len, int uplo_len);
+extern void ssbgvd_(char *jobz, char *uplo, int *n, int *ka, int *kb, float *ab, int *ldab, float *bb, int *ldbb, float *w, float *z, int *ldz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void ssbgvx_(char *jobz, char *range, char *uplo, int *n, int *ka, int *kb, float *ab, int *ldab, float *bb, int *ldbb, float *q, int *ldq, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void ssbtrd_(char *vect, char *uplo, int *n, int *kd, float *ab, int *ldab, float *d, float *e, float *q, int *ldq, float *work, int *info, int vect_len, int uplo_len);
+extern void sspcon_(char *uplo, int *n, float *ap, int *ipiv, float *anorm, float *rcond, float *work, int *iwork, int *info, int uplo_len);
+extern void sspev_(char *jobz, char *uplo, int *n, float *ap, float *w, float *z, int *ldz, float *work, int *info, int jobz_len, int uplo_len);
+extern void sspevd_(char *jobz, char *uplo, int *n, float *ap, float *w, float *z, int *ldz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void sspevx_(char *jobz, char *range, char *uplo, int *n, float *ap, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void sspgst_(int *itype, char *uplo, int *n, float *ap, float *bp, int *info, int uplo_len);
+extern void sspgv_(int *itype, char *jobz, char *uplo, int *n, float *ap, float *bp, float *w, float *z, int *ldz, float *work, int *info, int jobz_len, int uplo_len);
+extern void sspgvd_(int *itype, char *jobz, char *uplo, int *n, float *ap, float *bp, float *w, float *z, int *ldz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void sspgvx_(int *itype, char *jobz, char *range, char *uplo, int *n, float *ap, float *bp, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void ssprfs_(char *uplo, int *n, int *nrhs, float *ap, float *afp, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len);
+extern void sspsv_(char *uplo, int *n, int *nrhs, float *ap, int *ipiv, float *b, int *ldb, int *info, int uplo_len);
+extern void sspsvx_(char *fact, char *uplo, int *n, int *nrhs, float *ap, float *afp, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *iwork, int *info, int fact_len, int uplo_len);
+extern void ssptrd_(char *uplo, int *n, float *ap, float *d, float *e, float *tau, int *info, int uplo_len);
+extern void ssptrf_(char *uplo, int *n, float *ap, int *ipiv, int *info, int uplo_len);
+extern void ssptri_(char *uplo, int *n, float *ap, int *ipiv, float *work, int *info, int uplo_len);
+extern void ssptrs_(char *uplo, int *n, int *nrhs, float *ap, int *ipiv, float *b, int *ldb, int *info, int uplo_len);
+extern void sstebz_(char *range, char *order, int *n, float *vl, float *vu, int *il, int *iu, float *abstol, float *d, float *e, int *m, int *nsplit, float *w, int *iblock, int *isplit, float *work, int *iwork, int *info, int range_len, int order_len);
+extern void sstedc_(char *compz, int *n, float *d, float *e, float *z, int *ldz, float *work, int *lwork, int *iwork, int *liwork, int *info, int compz_len);
+extern void sstegr_(char *jobz, char *range, int *n, float *d, float *e, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, int *isuppz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len);
+extern void sstein_(int *n, float *d, float *e, int *m, float *w, int *iblock, int *isplit, float *z, int *ldz, float *work, int *iwork, int *ifail, int *info);
+extern void ssteqr_(char *compz, int *n, float *d, float *e, float *z, int *ldz, float *work, int *info, int compz_len);
+extern void ssterf_(int *n, float *d, float *e, int *info);
+extern void sstev_(char *jobz, int *n, float *d, float *e, float *z, int *ldz, float *work, int *info, int jobz_len);
+extern void sstevd_(char *jobz, int *n, float *d, float *e, float *z, int *ldz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len);
+extern void sstevr_(char *jobz, char *range, int *n, float *d, float *e, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, int *isuppz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len);
+extern void sstevx_(char *jobz, char *range, int *n, float *d, float *e, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *iwork, int *ifail, int *info, int jobz_len, int range_len);
+extern void ssycon_(char *uplo, int *n, float *a, int *lda, int *ipiv, float *anorm, float *rcond, float *work, int *iwork, int *info, int uplo_len);
+extern void ssyev_(char *jobz, char *uplo, int *n, float *a, int *lda, float *w, float *work, int *lwork, int *info, int jobz_len, int uplo_len);
+extern void ssyevd_(char *jobz, char *uplo, int *n, float *a, int *lda, float *w, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void ssyevr_(char *jobz, char *range, char *uplo, int *n, float *a, int *lda, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, int *isuppz, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len, int uplo_len);
+extern void ssyevx_(char *jobz, char *range, char *uplo, int *n, float *a, int *lda, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *lwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void ssygst_(int *itype, char *uplo, int *n, float *a, int *lda, float *b, int *ldb, int *info, int uplo_len);
+extern void ssygv_(int *itype, char *jobz, char *uplo, int *n, float *a, int *lda, float *b, int *ldb, float *w, float *work, int *lwork, int *info, int jobz_len, int uplo_len);
+extern void ssygvd_(int *itype, char *jobz, char *uplo, int *n, float *a, int *lda, float *b, int *ldb, float *w, float *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void ssygvx_(int *itype, char *jobz, char *range, char *uplo, int *n, float *a, int *lda, float *b, int *ldb, float *vl, float *vu, int *il, int *iu, float *abstol, int *m, float *w, float *z, int *ldz, float *work, int *lwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void ssyrfs_(char *uplo, int *n, int *nrhs, float *a, int *lda, float *af, int *ldaf, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len);
+extern void ssysv_(char *uplo, int *n, int *nrhs, float *a, int *lda, int *ipiv, float *b, int *ldb, float *work, int *lwork, int *info, int uplo_len);
+extern void ssysvx_(char *fact, char *uplo, int *n, int *nrhs, float *a, int *lda, float *af, int *ldaf, int *ipiv, float *b, int *ldb, float *x, int *ldx, float *rcond, float *ferr, float *berr, float *work, int *lwork, int *iwork, int *info, int fact_len, int uplo_len);
+extern void ssytrd_(char *uplo, int *n, float *a, int *lda, float *d, float *e, float *tau, float *work, int *lwork, int *info, int uplo_len);
+extern void ssytrf_(char *uplo, int *n, float *a, int *lda, int *ipiv, float *work, int *lwork, int *info, int uplo_len);
+extern void ssytri_(char *uplo, int *n, float *a, int *lda, int *ipiv, float *work, int *info, int uplo_len);
+extern void ssytrs_(char *uplo, int *n, int *nrhs, float *a, int *lda, int *ipiv, float *b, int *ldb, int *info, int uplo_len);
+extern void stbcon_(char *norm, char *uplo, char *diag, int *n, int *kd, float *ab, int *ldab, float *rcond, float *work, int *iwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void stbrfs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, float *ab, int *ldab, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void stbtrs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, float *ab, int *ldab, float *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void stgevc_(char *side, char *howmny, int *select, int *n, float *a, int *lda, float *b, int *ldb, float *vl, int *ldvl, float *vr, int *ldvr, int *mm, int *m, float *work, int *info, int side_len, int howmny_len);
+extern void stgexc_(int *wantq, int *wantz, int *n, float *a, int *lda, float *b, int *ldb, float *q, int *ldq, float *z, int *ldz, int *ifst, int *ilst, float *work, int *lwork, int *info);
+extern void stgsen_(int *ijob, int *wantq, int *wantz, int *select, int *n, float *a, int *lda, float *b, int *ldb, float *alphar, float *alphai, float *beta, float *q, int *ldq, float *z, int *ldz, int *m, float *pl, float *pr, float *dif, float *work, int *lwork, int *iwork, int *liwork, int *info);
+extern void stgsja_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, int *k, int *l, float *a, int *lda, float *b, int *ldb, float *tola, float *tolb, float *alpha, float *beta, float *u, int *ldu, float *v, int *ldv, float *q, int *ldq, float *work, int *ncycle, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void stgsna_(char *job, char *howmny, int *select, int *n, float *a, int *lda, float *b, int *ldb, float *vl, int *ldvl, float *vr, int *ldvr, float *s, float *dif, int *mm, int *m, float *work, int *lwork, int *iwork, int *info, int job_len, int howmny_len);
+extern void stgsyl_(char *trans, int *ijob, int *m, int *n, float *a, int *lda, float *b, int *ldb, float *c, int *ldc, float *d, int *ldd, float *e, int *lde, float *f, int *ldf, float *scale, float *dif, float *work, int *lwork, int *iwork, int *info, int trans_len);
+extern void stpcon_(char *norm, char *uplo, char *diag, int *n, float *ap, float *rcond, float *work, int *iwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void stprfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, float *ap, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void stptri_(char *uplo, char *diag, int *n, float *ap, int *info, int uplo_len, int diag_len);
+extern void stptrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, float *ap, float *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void strcon_(char *norm, char *uplo, char *diag, int *n, float *a, int *lda, float *rcond, float *work, int *iwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void strevc_(char *side, char *howmny, int *select, int *n, float *t, int *ldt, float *vl, int *ldvl, float *vr, int *ldvr, int *mm, int *m, float *work, int *info, int side_len, int howmny_len);
+extern void strexc_(char *compq, int *n, float *t, int *ldt, float *q, int *ldq, int *ifst, int *ilst, float *work, int *info, int compq_len);
+extern void strrfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, float *x, int *ldx, float *ferr, float *berr, float *work, int *iwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void strsen_(char *job, char *compq, int *select, int *n, float *t, int *ldt, float *q, int *ldq, float *wr, float *wi, int *m, float *s, float *sep, float *work, int *lwork, int *iwork, int *liwork, int *info, int job_len, int compq_len);
+extern void strsna_(char *job, char *howmny, int *select, int *n, float *t, int *ldt, float *vl, int *ldvl, float *vr, int *ldvr, float *s, float *sep, int *mm, int *m, float *work, int *ldwork, int *iwork, int *info, int job_len, int howmny_len);
+extern void strsyl_(char *trana, char *tranb, int *isgn, int *m, int *n, float *a, int *lda, float *b, int *ldb, float *c, int *ldc, float *scale, int *info, int trana_len, int tranb_len);
+extern void strtri_(char *uplo, char *diag, int *n, float *a, int *lda, int *info, int uplo_len, int diag_len);
+extern void strtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, float *a, int *lda, float *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void stzrqf_(int *m, int *n, float *a, int *lda, float *tau, int *info);
+extern void stzrzf_(int *m, int *n, float *a, int *lda, float *tau, float *work, int *lwork, int *info);
+extern void zbdsqr_(char *uplo, int *n, int *ncvt, int *nru, int *ncc, double *d, double *e, doublecomplex *vt, int *ldvt, doublecomplex *u, int *ldu, doublecomplex *c, int *ldc, double *rwork, int *info, int uplo_len);
+extern void zgbbrd_(char *vect, int *m, int *n, int *ncc, int *kl, int *ku, doublecomplex *ab, int *ldab, double *d, double *e, doublecomplex *q, int *ldq, doublecomplex *pt, int *ldpt, doublecomplex *c, int *ldc, doublecomplex *work, double *rwork, int *info, int vect_len);
+extern void zgbcon_(char *norm, int *n, int *kl, int *ku, doublecomplex *ab, int *ldab, int *ipiv, double *anorm, double *rcond, doublecomplex *work, double *rwork, int *info, int norm_len);
+extern void zgbequ_(int *m, int *n, int *kl, int *ku, doublecomplex *ab, int *ldab, double *r, double *c, double *rowcnd, double *colcnd, double *amax, int *info);
+extern void zgbrfs_(char *trans, int *n, int *kl, int *ku, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *afb, int *ldafb, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int trans_len);
+extern void zgbsv_(int *n, int *kl, int *ku, int *nrhs, doublecomplex *ab, int *ldab, int *ipiv, doublecomplex *b, int *ldb, int *info);
+extern void zgbsvx_(char *fact, char *trans, int *n, int *kl, int *ku, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *afb, int *ldafb, int *ipiv, char *equed, double *r, double *c, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void zgbtrf_(int *m, int *n, int *kl, int *ku, doublecomplex *ab, int *ldab, int *ipiv, int *info);
+extern void zgbtrs_(char *trans, int *n, int *kl, int *ku, int *nrhs, doublecomplex *ab, int *ldab, int *ipiv, doublecomplex *b, int *ldb, int *info, int trans_len);
+extern void zgebak_(char *job, char *side, int *n, int *ilo, int *ihi, double *scale, int *m, doublecomplex *v, int *ldv, int *info, int job_len, int side_len);
+extern void zgebal_(char *job, int *n, doublecomplex *a, int *lda, int *ilo, int *ihi, double *scale, int *info, int job_len);
+extern void zgebrd_(int *m, int *n, doublecomplex *a, int *lda, double *d, double *e, doublecomplex *tauq, doublecomplex *taup, doublecomplex *work, int *lwork, int *info);
+extern void zgecon_(char *norm, int *n, doublecomplex *a, int *lda, double *anorm, double *rcond, doublecomplex *work, double *rwork, int *info, int norm_len);
+extern void zgeequ_(int *m, int *n, doublecomplex *a, int *lda, double *r, double *c, double *rowcnd, double *colcnd, double *amax, int *info);
+extern void zgees_(char *jobvs, char *sort, ACML_ZGEES_SELECT select, int *n, doublecomplex *a, int *lda, int *sdim, doublecomplex *w, doublecomplex *vs, int *ldvs, doublecomplex *work, int *lwork, double *rwork, int *bwork, int *info, int jobvs_len, int sort_len);
+extern void zgeesx_(char *jobvs, char *sort, ACML_ZGEESX_SELECT select, char *sense, int *n, doublecomplex *a, int *lda, int *sdim, doublecomplex *w, doublecomplex *vs, int *ldvs, double *rconde, double *rcondv, doublecomplex *work, int *lwork, double *rwork, int *bwork, int *info, int jobvs_len, int sort_len, int sense_len);
+extern void zgeev_(char *jobvl, char *jobvr, int *n, doublecomplex *a, int *lda, doublecomplex *w, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, doublecomplex *work, int *lwork, double *rwork, int *info, int jobvl_len, int jobvr_len);
+extern void zgeevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, doublecomplex *a, int *lda, doublecomplex *w, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, int *ilo, int *ihi, double *scale, double *abnrm, double *rconde, double *rcondv, doublecomplex *work, int *lwork, double *rwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void zgegs_(char *jobvsl, char *jobvsr, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, int *ldvsl, doublecomplex *vsr, int *ldvsr, doublecomplex *work, int *lwork, double *rwork, int *info, int jobvsl_len, int jobvsr_len);
+extern void zgegv_(char *jobvl, char *jobvr, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, doublecomplex *work, int *lwork, double *rwork, int *info, int jobvl_len, int jobvr_len);
+extern void zgehrd_(int *n, int *ilo, int *ihi, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zgelqf_(int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zgels_(char *trans, int *m, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *work, int *lwork, int *info, int trans_len);
+extern void zgelsd_(int *m, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *s, double *rcond, int *rank, doublecomplex *work, int *lwork, double *rwork, int *iwork, int *info);
+extern void zgelss_(int *m, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *s, double *rcond, int *rank, doublecomplex *work, int *lwork, double *rwork, int *info);
+extern void zgelsx_(int *m, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *jpvt, double *rcond, int *rank, doublecomplex *work, double *rwork, int *info);
+extern void zgelsy_(int *m, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *jpvt, double *rcond, int *rank, doublecomplex *work, int *lwork, double *rwork, int *info);
+extern void zgeqlf_(int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zgeqp3_(int *m, int *n, doublecomplex *a, int *lda, int *jpvt, doublecomplex *tau, doublecomplex *work, int *lwork, double *rwork, int *info);
+extern void zgeqpf_(int *m, int *n, doublecomplex *a, int *lda, int *jpvt, doublecomplex *tau, doublecomplex *work, double *rwork, int *info);
+extern void zgeqrf_(int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zgerfs_(char *trans, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int trans_len);
+extern void zgerqf_(int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zgesdd_(char *jobz, int *m, int *n, doublecomplex *a, int *lda, double *s, doublecomplex *u, int *ldu, doublecomplex *vt, int *ldvt, doublecomplex *work, int *lwork, double *rwork, int *iwork, int *info, int jobz_len);
+extern void zgesv_(int *n, int *nrhs, doublecomplex *a, int *lda, int *ipiv, doublecomplex *b, int *ldb, int *info);
+extern void zgesvd_(char *jobu, char *jobvt, int *m, int *n, doublecomplex *a, int *lda, double *s, doublecomplex *u, int *ldu, doublecomplex *vt, int *ldvt, doublecomplex *work, int *lwork, double *rwork, int *info, int jobu_len, int jobvt_len);
+extern void zgesvx_(char *fact, char *trans, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, int *ipiv, char *equed, double *r, double *c, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int trans_len, int equed_len);
+extern void zgetrf_(int *m, int *n, doublecomplex *a, int *lda, int *ipiv, int *info);
+extern void zgetri_(int *n, doublecomplex *a, int *lda, int *ipiv, doublecomplex *work, int *lwork, int *info);
+extern void zgetrs_(char *trans, int *n, int *nrhs, doublecomplex *a, int *lda, int *ipiv, doublecomplex *b, int *ldb, int *info, int trans_len);
+extern void zggbak_(char *job, char *side, int *n, int *ilo, int *ihi, double *lscale, double *rscale, int *m, doublecomplex *v, int *ldv, int *info, int job_len, int side_len);
+extern void zggbal_(char *job, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *ilo, int *ihi, double *lscale, double *rscale, double *work, int *info, int job_len);
+extern void zgges_(char *jobvsl, char *jobvsr, char *sort, ACML_ZGGES_DELCTG delctg, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *sdim, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, int *ldvsl, doublecomplex *vsr, int *ldvsr, doublecomplex *work, int *lwork, double *rwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len);
+extern void zggesx_(char *jobvsl, char *jobvsr, char *sort, ACML_ZGGESX_DELCTG delctg, char *sense, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *sdim, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, int *ldvsl, doublecomplex *vsr, int *ldvsr, double *rconde, double *rcondv, doublecomplex *work, int *lwork, double *rwork, int *iwork, int *liwork, int *bwork, int *info, int jobvsl_len, int jobvsr_len, int sort_len, int sense_len);
+extern void zggev_(char *jobvl, char *jobvr, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, doublecomplex *work, int *lwork, double *rwork, int *info, int jobvl_len, int jobvr_len);
+extern void zggevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, int *ilo, int *ihi, double *lscale, double *rscale, double *abnrm, double *bbnrm, double *rconde, double *rcondv, doublecomplex *work, int *lwork, double *rwork, int *iwork, int *bwork, int *info, int balanc_len, int jobvl_len, int jobvr_len, int sense_len);
+extern void zggglm_(int *n, int *m, int *p, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *d, doublecomplex *x, doublecomplex *y, doublecomplex *work, int *lwork, int *info);
+extern void zgghrd_(char *compq, char *compz, int *n, int *ilo, int *ihi, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *q, int *ldq, doublecomplex *z, int *ldz, int *info, int compq_len, int compz_len);
+extern void zgglse_(int *m, int *n, int *p, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *c, doublecomplex *d, doublecomplex *x, doublecomplex *work, int *lwork, int *info);
+extern void zggqrf_(int *n, int *m, int *p, doublecomplex *a, int *lda, doublecomplex *taua, doublecomplex *b, int *ldb, doublecomplex *taub, doublecomplex *work, int *lwork, int *info);
+extern void zggrqf_(int *m, int *p, int *n, doublecomplex *a, int *lda, doublecomplex *taua, doublecomplex *b, int *ldb, doublecomplex *taub, doublecomplex *work, int *lwork, int *info);
+extern void zggsvd_(char *jobu, char *jobv, char *jobq, int *m, int *n, int *p, int *k, int *l, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *alpha, double *beta, doublecomplex *u, int *ldu, doublecomplex *v, int *ldv, doublecomplex *q, int *ldq, doublecomplex *work, double *rwork, int *iwork, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void zggsvp_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *tola, double *tolb, int *k, int *l, doublecomplex *u, int *ldu, doublecomplex *v, int *ldv, doublecomplex *q, int *ldq, int *iwork, double *rwork, doublecomplex *tau, doublecomplex *work, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void zgtcon_(char *norm, int *n, doublecomplex *dl, doublecomplex *d, doublecomplex *du, doublecomplex *du2, int *ipiv, double *anorm, double *rcond, doublecomplex *work, int *info, int norm_len);
+extern void zgtrfs_(char *trans, int *n, int *nrhs, doublecomplex *dl, doublecomplex *d, doublecomplex *du, doublecomplex *dlf, doublecomplex *df, doublecomplex *duf, doublecomplex *du2, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int trans_len);
+extern void zgtsv_(int *n, int *nrhs, doublecomplex *dl, doublecomplex *d, doublecomplex *du, doublecomplex *b, int *ldb, int *info);
+extern void zgtsvx_(char *fact, char *trans, int *n, int *nrhs, doublecomplex *dl, doublecomplex *d, doublecomplex *du, doublecomplex *dlf, doublecomplex *df, doublecomplex *duf, doublecomplex *du2, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int trans_len);
+extern void zgttrf_(int *n, doublecomplex *dl, doublecomplex *d, doublecomplex *du, doublecomplex *du2, int *ipiv, int *info);
+extern void zgttrs_(char *trans, int *n, int *nrhs, doublecomplex *dl, doublecomplex *d, doublecomplex *du, doublecomplex *du2, int *ipiv, doublecomplex *b, int *ldb, int *info, int trans_len);
+extern void zhbev_(char *jobz, char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *info, int jobz_len, int uplo_len);
+extern void zhbevd_(char *jobz, char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, double *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void zhbevx_(char *jobz, char *range, char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, doublecomplex *q, int *ldq, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zhbgst_(char *vect, char *uplo, int *n, int *ka, int *kb, doublecomplex *ab, int *ldab, doublecomplex *bb, int *ldbb, doublecomplex *x, int *ldx, doublecomplex *work, double *rwork, int *info, int vect_len, int uplo_len);
+extern void zhbgv_(char *jobz, char *uplo, int *n, int *ka, int *kb, doublecomplex *ab, int *ldab, doublecomplex *bb, int *ldbb, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *info, int jobz_len, int uplo_len);
+extern void zhbgvd_(char *jobz, char *uplo, int *n, int *ka, int *kb, doublecomplex *ab, int *ldab, doublecomplex *bb, int *ldbb, double *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void zhbgvx_(char *jobz, char *range, char *uplo, int *n, int *ka, int *kb, doublecomplex *ab, int *ldab, doublecomplex *bb, int *ldbb, doublecomplex *q, int *ldq, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zhbtrd_(char *vect, char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, double *d, double *e, doublecomplex *q, int *ldq, doublecomplex *work, int *info, int vect_len, int uplo_len);
+extern void zhecon_(char *uplo, int *n, doublecomplex *a, int *lda, int *ipiv, double *anorm, double *rcond, doublecomplex *work, int *info, int uplo_len);
+extern void zheev_(char *jobz, char *uplo, int *n, doublecomplex *a, int *lda, double *w, doublecomplex *work, int *lwork, double *rwork, int *info, int jobz_len, int uplo_len);
+extern void zheevd_(char *jobz, char *uplo, int *n, doublecomplex *a, int *lda, double *w, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void zheevr_(char *jobz, char *range, char *uplo, int *n, doublecomplex *a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, int *isuppz, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zheevx_(char *jobz, char *range, char *uplo, int *n, doublecomplex *a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zhegst_(int *itype, char *uplo, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zhegv_(int *itype, char *jobz, char *uplo, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *w, doublecomplex *work, int *lwork, double *rwork, int *info, int jobz_len, int uplo_len);
+extern void zhegvd_(int *itype, char *jobz, char *uplo, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *w, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void zhegvx_(int *itype, char *jobz, char *range, char *uplo, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zherfs_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zhesv_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *work, int *lwork, int *info, int uplo_len);
+extern void zhesvx_(char *fact, char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, int *lwork, double *rwork, int *info, int fact_len, int uplo_len);
+extern void zhetrd_(char *uplo, int *n, doublecomplex *a, int *lda, double *d, double *e, doublecomplex *tau, doublecomplex *work, int *lwork, int *info, int uplo_len);
+extern void zhetrf_(char *uplo, int *n, doublecomplex *a, int *lda, int *ipiv, doublecomplex *work, int *lwork, int *info, int uplo_len);
+extern void zhetri_(char *uplo, int *n, doublecomplex *a, int *lda, int *ipiv, doublecomplex *work, int *info, int uplo_len);
+extern void zhetrs_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, int *ipiv, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zhgeqz_(char *job, char *compq, char *compz, int *n, int *ilo, int *ihi, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *q, int *ldq, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *info, int job_len, int compq_len, int compz_len);
+extern void zhpcon_(char *uplo, int *n, doublecomplex *ap, int *ipiv, double *anorm, double *rcond, doublecomplex *work, int *info, int uplo_len);
+extern void zhpev_(char *jobz, char *uplo, int *n, doublecomplex *ap, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *info, int jobz_len, int uplo_len);
+extern void zhpevd_(char *jobz, char *uplo, int *n, doublecomplex *ap, double *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void zhpevx_(char *jobz, char *range, char *uplo, int *n, doublecomplex *ap, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zhpgst_(int *itype, char *uplo, int *n, doublecomplex *ap, doublecomplex *bp, int *info, int uplo_len);
+extern void zhpgv_(int *itype, char *jobz, char *uplo, int *n, doublecomplex *ap, doublecomplex *bp, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *info, int jobz_len, int uplo_len);
+extern void zhpgvd_(int *itype, char *jobz, char *uplo, int *n, doublecomplex *ap, doublecomplex *bp, double *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int jobz_len, int uplo_len);
+extern void zhpgvx_(int *itype, char *jobz, char *range, char *uplo, int *n, doublecomplex *ap, doublecomplex *bp, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, doublecomplex *work, double *rwork, int *iwork, int *ifail, int *info, int jobz_len, int range_len, int uplo_len);
+extern void zhprfs_(char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *afp, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zhpsv_(char *uplo, int *n, int *nrhs, doublecomplex *ap, int *ipiv, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zhpsvx_(char *fact, char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *afp, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int uplo_len);
+extern void zhptrd_(char *uplo, int *n, doublecomplex *ap, double *d, double *e, doublecomplex *tau, int *info, int uplo_len);
+extern void zhptrf_(char *uplo, int *n, doublecomplex *ap, int *ipiv, int *info, int uplo_len);
+extern void zhptri_(char *uplo, int *n, doublecomplex *ap, int *ipiv, doublecomplex *work, int *info, int uplo_len);
+extern void zhptrs_(char *uplo, int *n, int *nrhs, doublecomplex *ap, int *ipiv, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zhsein_(char *side, char *eigsrc, char *initv, int *select, int *n, doublecomplex *h, int *ldh, doublecomplex *w, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, int *mm, int *m, doublecomplex *work, double *rwork, int *ifaill, int *ifailr, int *info, int side_len, int eigsrc_len, int initv_len);
+extern void zhseqr_(char *job, char *compz, int *n, int *ilo, int *ihi, doublecomplex *h, int *ldh, doublecomplex *w, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, int *info, int job_len, int compz_len);
+extern void zpbcon_(char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, double *anorm, double *rcond, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zpbequ_(char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, double *s, double *scond, double *amax, int *info, int uplo_len);
+extern void zpbrfs_(char *uplo, int *n, int *kd, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *afb, int *ldafb, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zpbstf_(char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, int *info, int uplo_len);
+extern void zpbsv_(char *uplo, int *n, int *kd, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zpbsvx_(char *fact, char *uplo, int *n, int *kd, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *afb, int *ldafb, char *equed, double *s, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void zpbtrf_(char *uplo, int *n, int *kd, doublecomplex *ab, int *ldab, int *info, int uplo_len);
+extern void zpbtrs_(char *uplo, int *n, int *kd, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zpocon_(char *uplo, int *n, doublecomplex *a, int *lda, double *anorm, double *rcond, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zpoequ_(int *n, doublecomplex *a, int *lda, double *s, double *scond, double *amax, int *info);
+extern void zporfs_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zposv_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zposvx_(char *fact, char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, char *equed, double *s, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void zpotrf_(char *uplo, int *n, doublecomplex *a, int *lda, int *info, int uplo_len);
+extern void zpotri_(char *uplo, int *n, doublecomplex *a, int *lda, int *info, int uplo_len);
+extern void zpotrs_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zppcon_(char *uplo, int *n, doublecomplex *ap, double *anorm, double *rcond, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zppequ_(char *uplo, int *n, doublecomplex *ap, double *s, double *scond, double *amax, int *info, int uplo_len);
+extern void zpprfs_(char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *afp, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zppsv_(char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zppsvx_(char *fact, char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *afp, char *equed, double *s, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int uplo_len, int equed_len);
+extern void zpptrf_(char *uplo, int *n, doublecomplex *ap, int *info, int uplo_len);
+extern void zpptri_(char *uplo, int *n, doublecomplex *ap, int *info, int uplo_len);
+extern void zpptrs_(char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zptcon_(int *n, double *d, doublecomplex *e, double *anorm, double *rcond, double *rwork, int *info);
+extern void zpteqr_(char *compz, int *n, double *d, double *e, doublecomplex *z, int *ldz, double *work, int *info, int compz_len);
+extern void zptrfs_(char *uplo, int *n, int *nrhs, double *d, doublecomplex *e, double *df, doublecomplex *ef, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zptsv_(int *n, int *nrhs, double *d, doublecomplex *e, doublecomplex *b, int *ldb, int *info);
+extern void zptsvx_(char *fact, int *n, int *nrhs, double *d, doublecomplex *e, double *df, doublecomplex *ef, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len);
+extern void zpttrf_(int *n, double *d, doublecomplex *e, int *info);
+extern void zpttrs_(char *uplo, int *n, int *nrhs, double *d, doublecomplex *e, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zspcon_(char *uplo, int *n, doublecomplex *ap, int *ipiv, double *anorm, double *rcond, doublecomplex *work, int *info, int uplo_len);
+extern void zsprfs_(char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *afp, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zspsv_(char *uplo, int *n, int *nrhs, doublecomplex *ap, int *ipiv, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zspsvx_(char *fact, char *uplo, int *n, int *nrhs, doublecomplex *ap, doublecomplex *afp, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int fact_len, int uplo_len);
+extern void zsptrf_(char *uplo, int *n, doublecomplex *ap, int *ipiv, int *info, int uplo_len);
+extern void zsptri_(char *uplo, int *n, doublecomplex *ap, int *ipiv, doublecomplex *work, int *info, int uplo_len);
+extern void zsptrs_(char *uplo, int *n, int *nrhs, doublecomplex *ap, int *ipiv, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void zstedc_(char *compz, int *n, double *d, double *e, doublecomplex *z, int *ldz, doublecomplex *work, int *lwork, double *rwork, int *lrwork, int *iwork, int *liwork, int *info, int compz_len);
+extern void zstegr_(char *jobz, char *range, int *n, double *d, double *e, double *vl, double *vu, int *il, int *iu, double *abstol, int *m, double *w, doublecomplex *z, int *ldz, int *isuppz, double *work, int *lwork, int *iwork, int *liwork, int *info, int jobz_len, int range_len);
+extern void zstein_(int *n, double *d, double *e, int *m, double *w, int *iblock, int *isplit, doublecomplex *z, int *ldz, double *work, int *iwork, int *ifail, int *info);
+extern void zsteqr_(char *compz, int *n, double *d, double *e, doublecomplex *z, int *ldz, double *work, int *info, int compz_len);
+extern void zsycon_(char *uplo, int *n, doublecomplex *a, int *lda, int *ipiv, double *anorm, double *rcond, doublecomplex *work, int *info, int uplo_len);
+extern void zsyrfs_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len);
+extern void zsysv_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *work, int *lwork, int *info, int uplo_len);
+extern void zsysvx_(char *fact, char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *af, int *ldaf, int *ipiv, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *rcond, double *ferr, double *berr, doublecomplex *work, int *lwork, double *rwork, int *info, int fact_len, int uplo_len);
+extern void zsytrf_(char *uplo, int *n, doublecomplex *a, int *lda, int *ipiv, doublecomplex *work, int *lwork, int *info, int uplo_len);
+extern void zsytri_(char *uplo, int *n, doublecomplex *a, int *lda, int *ipiv, doublecomplex *work, int *info, int uplo_len);
+extern void zsytrs_(char *uplo, int *n, int *nrhs, doublecomplex *a, int *lda, int *ipiv, doublecomplex *b, int *ldb, int *info, int uplo_len);
+extern void ztbcon_(char *norm, char *uplo, char *diag, int *n, int *kd, doublecomplex *ab, int *ldab, double *rcond, doublecomplex *work, double *rwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void ztbrfs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ztbtrs_(char *uplo, char *trans, char *diag, int *n, int *kd, int *nrhs, doublecomplex *ab, int *ldab, doublecomplex *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ztgevc_(char *side, char *howmny, int *select, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, int *mm, int *m, doublecomplex *work, double *rwork, int *info, int side_len, int howmny_len);
+extern void ztgexc_(int *wantq, int *wantz, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *q, int *ldq, doublecomplex *z, int *ldz, int *ifst, int *ilst, int *info);
+extern void ztgsen_(int *ijob, int *wantq, int *wantz, int *select, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *alpha, doublecomplex *beta, doublecomplex *q, int *ldq, doublecomplex *z, int *ldz, int *m, double *pl, double *pr, double *dif, doublecomplex *work, int *lwork, int *iwork, int *liwork, int *info);
+extern void ztgsja_(char *jobu, char *jobv, char *jobq, int *m, int *p, int *n, int *k, int *l, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, double *tola, double *tolb, double *alpha, double *beta, doublecomplex *u, int *ldu, doublecomplex *v, int *ldv, doublecomplex *q, int *ldq, doublecomplex *work, int *ncycle, int *info, int jobu_len, int jobv_len, int jobq_len);
+extern void ztgsna_(char *job, char *howmny, int *select, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, double *s, double *dif, int *mm, int *m, doublecomplex *work, int *lwork, int *iwork, int *info, int job_len, int howmny_len);
+extern void ztgsyl_(char *trans, int *ijob, int *m, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *c, int *ldc, doublecomplex *d, int *ldd, doublecomplex *e, int *lde, doublecomplex *f, int *ldf, double *scale, double *dif, doublecomplex *work, int *lwork, int *iwork, int *info, int trans_len);
+extern void ztpcon_(char *norm, char *uplo, char *diag, int *n, doublecomplex *ap, double *rcond, doublecomplex *work, double *rwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void ztprfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, doublecomplex *ap, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ztptri_(char *uplo, char *diag, int *n, doublecomplex *ap, int *info, int uplo_len, int diag_len);
+extern void ztptrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, doublecomplex *ap, doublecomplex *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ztrcon_(char *norm, char *uplo, char *diag, int *n, doublecomplex *a, int *lda, double *rcond, doublecomplex *work, double *rwork, int *info, int norm_len, int uplo_len, int diag_len);
+extern void ztrevc_(char *side, char *howmny, int *select, int *n, doublecomplex *t, int *ldt, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, int *mm, int *m, doublecomplex *work, double *rwork, int *info, int side_len, int howmny_len);
+extern void ztrexc_(char *compq, int *n, doublecomplex *t, int *ldt, doublecomplex *q, int *ldq, int *ifst, int *ilst, int *info, int compq_len);
+extern void ztrrfs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *x, int *ldx, double *ferr, double *berr, doublecomplex *work, double *rwork, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ztrsen_(char *job, char *compq, int *select, int *n, doublecomplex *t, int *ldt, doublecomplex *q, int *ldq, doublecomplex *w, int *m, double *s, double *sep, doublecomplex *work, int *lwork, int *info, int job_len, int compq_len);
+extern void ztrsna_(char *job, char *howmny, int *select, int *n, doublecomplex *t, int *ldt, doublecomplex *vl, int *ldvl, doublecomplex *vr, int *ldvr, double *s, double *sep, int *mm, int *m, doublecomplex *work, int *ldwork, double *rwork, int *info, int job_len, int howmny_len);
+extern void ztrsyl_(char *trana, char *tranb, int *isgn, int *m, int *n, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, doublecomplex *c, int *ldc, double *scale, int *info, int trana_len, int tranb_len);
+extern void ztrtri_(char *uplo, char *diag, int *n, doublecomplex *a, int *lda, int *info, int uplo_len, int diag_len);
+extern void ztrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, doublecomplex *a, int *lda, doublecomplex *b, int *ldb, int *info, int uplo_len, int trans_len, int diag_len);
+extern void ztzrqf_(int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, int *info);
+extern void ztzrzf_(int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zungbr_(char *vect, int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info, int vect_len);
+extern void zunghr_(int *n, int *ilo, int *ihi, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zunglq_(int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zungql_(int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zungqr_(int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zungrq_(int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info);
+extern void zungtr_(char *uplo, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *work, int *lwork, int *info, int uplo_len);
+extern void zunmbr_(char *vect, char *side, char *trans, int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int vect_len, int side_len, int trans_len);
+extern void zunmhr_(char *side, char *trans, int *m, int *n, int *ilo, int *ihi, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void zunmlq_(char *side, char *trans, int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void zunmql_(char *side, char *trans, int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void zunmqr_(char *side, char *trans, int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void zunmr3_(char *side, char *trans, int *m, int *n, int *k, int *l, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *info, int side_len, int trans_len);
+extern void zunmrq_(char *side, char *trans, int *m, int *n, int *k, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void zunmrz_(char *side, char *trans, int *m, int *n, int *k, int *l, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int trans_len);
+extern void zunmtr_(char *side, char *uplo, char *trans, int *m, int *n, doublecomplex *a, int *lda, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *lwork, int *info, int side_len, int uplo_len, int trans_len);
+extern void zupgtr_(char *uplo, int *n, doublecomplex *ap, doublecomplex *tau, doublecomplex *q, int *ldq, doublecomplex *work, int *info, int uplo_len);
+extern void zupmtr_(char *side, char *uplo, char *trans, int *m, int *n, doublecomplex *ap, doublecomplex *tau, doublecomplex *c, int *ldc, doublecomplex *work, int *info, int side_len, int uplo_len, int trans_len);
+
+/* FFT routines */
+extern void cfft1d_(int *mode, int *n, complex *x, complex *comm, int *info);
+extern void cfft1dx_(int *mode, float *scale, int *inpl, int *n, complex *x, int *incx, complex *y, int *incy, complex *comm, int *info);
+extern void cfft1m_(int *mode, int *nseq, int *n, complex *x, complex *comm, int *info);
+extern void cfft1mx_(int *mode, float *scale, int *inpl, int *nseq, int *n, complex *x, int *incx1, int *incx2, complex *y, int *incy1, int *incy2, complex *comm, int *info);
+extern void cfft2d_(int *mode, int *m, int *n, complex *x, complex *comm, int *info);
+extern void cfft2dx_(int *mode, float *scale, int *ltrans, int *inpl, int *m, int *n, complex *x, int *incx1, int *incx2, complex *y, int *incy1, int *incy2, complex *comm, int *info);
+extern void cfft3d_(int *mode, int *l, int *m, int *n, complex *x, complex *comm, int *info);
+extern void cfft3dx_(int *mode, float *scale, int *ltrans, int *inpl, int *l, int *m, int *n, complex *x, complex *y, complex *comm, int *info);
+extern void cfft3dy_(int *mode, float *scale, int *inpl, int *l, int *m, int *n, complex *x, int *incx1, int *incx2, int *incx3, complex *y, int *incy1, int *incy2, int *incy3, complex *comm, int *lcomm, int *info);
+extern void csfft_(int *mode, int *n, float *x, float *comm, int *info);
+extern void csfftm_(int *nseq, int *n, float *x, float *comm, int *info);
+extern void dzfft_(int *mode, int *n, double *x, double *comm, int *info);
+extern void dzfftm_(int *nseq, int *n, double *x, double *comm, int *info);
+extern void scfft_(int *mode, int *n, float *x, float *comm, int *info);
+extern void scfftm_(int *nseq, int *n, float *x, float *comm, int *info);
+extern void zdfft_(int *mode, int *n, double *x, double *comm, int *info);
+extern void zdfftm_(int *nseq, int *n, double *x, double *comm, int *info);
+extern void zfft1d_(int *mode, int *n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft1dx_(int *mode, double *scale, int *inpl, int *n, doublecomplex *x, int *incx, doublecomplex *y, int *incy, doublecomplex *comm, int *info);
+extern void zfft1m_(int *mode, int *nseq, int *n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft1mx_(int *mode, double *scale, int *inpl, int *nseq, int *n, doublecomplex *x, int *incx1, int *incx2, doublecomplex *y, int *incy1, int *incy2, doublecomplex *comm, int *info);
+extern void zfft2d_(int *mode, int *m, int *n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft2dx_(int *mode, double *scale, int *ltrans, int *inpl, int *m, int *n, doublecomplex *x, int *incx1, int *incx2, doublecomplex *y, int *incy1, int *incy2, doublecomplex *comm, int *info);
+extern void zfft3d_(int *mode, int *l, int *m, int *n, doublecomplex *x, doublecomplex *comm, int *info);
+extern void zfft3dx_(int *mode, double *scale, int *ltrans, int *inpl, int *l, int *m, int *n, doublecomplex *x, doublecomplex *y, doublecomplex *comm, int *info);
+extern void zfft3dy_(int *mode, double *scale, int *inpl, int *l, int *m, int *n, doublecomplex *x, int *incx1, int *incx2, int *incx3, doublecomplex *y, int *incy1, int *incy2, int *incy3, doublecomplex *comm, int *lcomm, int *info);
+
+/* Sparse BLAS routines */
+extern void caxpyi_(int *nz, complex *a, complex *x, int *indx, complex *y);
+extern complex cdotci_(complex *ret_val, int *nz, complex *x, int *indx, complex *y);
+extern void cdotcisub_(complex *ret_val, int *nz, complex *x, int *indx, complex *y);
+extern complex cdotui_(complex *ret_val, int *nz, complex *x, int *indx, complex *y);
+extern void cdotuisub_(complex *ret_val, int *nz, complex *x, int *indx, complex *y);
+extern void cgthr_(int *nz, complex *y, complex *x, int *indx);
+extern void cgthrz_(int *nz, complex *y, complex *x, int *indx);
+extern void csctr_(int *nz, complex *x, int *indx, complex *y);
+extern void daxpyi_(int *nz, double *a, double *x, int *indx, double *y);
+extern double ddoti_(int *nz, double *x, int *indx, double *y);
+extern void dgthr_(int *nz, double *y, double *x, int *indx);
+extern void dgthrz_(int *nz, double *y, double *x, int *indx);
+extern void droti_(int *nz, double *x, int *indx, double *y, double *c, double *s);
+extern void dsctr_(int *nz, double *x, int *indx, double *y);
+extern void saxpyi_(int *nz, float *a, float *x, int *indx, float *y);
+
+#ifdef FORTRAN_FLOAT_FUNCTIONS_RETURN_DOUBLE
+extern double sdoti_(int *nz, float *x, int *indx, float *y);
+#else
+extern float sdoti_(int *nz, float *x, int *indx, float *y);
+#endif
+
+extern void sgthr_(int *nz, float *y, float *x, int *indx);
+extern void sgthrz_(int *nz, float *y, float *x, int *indx);
+extern void sroti_(int *nz, float *x, int *indx, float *y, float *c, float *s);
+extern void ssctr_(int *nz, float *x, int *indx, float *y);
+extern void zaxpyi_(int *nz, doublecomplex *a, doublecomplex *x, int *indx, doublecomplex *y);
+extern doublecomplex zdotci_(doublecomplex *ret_val, int *nz, doublecomplex *x, int *indx, doublecomplex *y);
+extern void zdotcisub_(doublecomplex *ret_val, int *nz, doublecomplex *x, int *indx, doublecomplex *y);
+extern doublecomplex zdotui_(doublecomplex *ret_val, int *nz, doublecomplex *x, int *indx, doublecomplex *y);
+extern void zdotuisub_(doublecomplex *ret_val, int *nz, doublecomplex *x, int *indx, doublecomplex *y);
+extern void zgthr_(int *nz, doublecomplex *y, doublecomplex *x, int *indx);
+extern void zgthrz_(int *nz, doublecomplex *y, doublecomplex *x, int *indx);
+extern void zsctr_(int *nz, doublecomplex *x, int *indx, doublecomplex *y);
+
+/* Random number generators */
+extern void drandbeta_(int *n, double *a, double *b, int *state, double *x, int *info);
+extern void drandbinomial_(int *n, int *m, double *p, int *state, int *x, int *info);
+extern void drandbinomialreference_(int *m, double *p, double *ref, int *lref, int *info);
+extern void drandblumblumshub_(int *n, int *state, double *x, int *info);
+extern void drandcauchy_(int *n, double *a, double *b, int *state, double *x, int *info);
+extern void drandchisquared_(int *n, int *df, int *state, double *x, int *info);
+extern void dranddiscreteuniform_(int *n, int *a, int *b, int *state, int *x, int *info);
+extern void drandexponential_(int *n, double *a, int *state, double *x, int *info);
+extern void drandf_(int *n, int *df1, int *df2, int *state, double *x, int *info);
+extern void drandgamma_(int *n, double *a, double *b, int *state, double *x, int *info);
+extern void drandgaussian_(int *n, double *xmu, double *var, int *state, double *x, int *info);
+extern void drandgeneraldiscrete_(int *n, double *ref, int *state, int *x, int *info);
+extern void drandgeometric_(int *n, double *p, int *state, int *x, int *info);
+extern void drandgeometricreference_(double *p, double *ref, int *lref, int *info);
+extern void drandhypergeometric_(int *n, int *np, int *ns, int *m, int *state, int *x, int *info);
+extern void drandhypergeometricreference_(int *np, int *ns, int *m, double *ref, int *lref, int *info);
+extern void drandinitialize_(int *genid, int *subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void drandinitializebbs_(int *nbits, int *lp, int *p, int *lq, int *q, int *ls, int *s, int *state, int *lstate, int *info);
+extern void drandinitializeuser_(ACML_DRANDINITIALIZEUSER_UINI uini, ACML_DRANDINITIALIZEUSER_UGEN ugen, int genid, int subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void drandleapfrog_(int *n, int *k, int *state, int *info);
+extern void drandlogistic_(int *n, double *a, double *b, int *state, double *x, int *info);
+extern void drandlognormal_(int *n, double *xmu, double *var, int *state, double *x, int *info);
+extern void drandmultinomial_(int *n, int *m, double *p, int *k, int *state, int *x, int *ldx, int *info);
+extern void drandmultinormalreference_(int *m, double *xmu, double *c, int *ldc, double *ref, int *lref, int *info);
+extern void drandmultinormalr_(int *n, double *ref, int *state, double *x, int *ldx, int *info);
+extern void drandmultistudentstreference_(int *m, int *df, double *xmu, double *c, int *ldc, double *ref, int *lref, int *info);
+extern void drandmultistudentstr_(int *n, double *ref, int *state, double *x, int *ldx, int *info);
+extern void drandnegativebinomial_(int *n, int *m, double *p, int *state, int *x, int *info);
+extern void drandnegativebinomialreference_(int *m, double *p, double *ref, int *lref, int *info);
+extern void drandpoisson_(int *n, double *lambda, int *state, int *x, int *info);
+extern void drandpoissonreference_(double *lambda, double *ref, int *lref, int *info);
+extern void drandskipahead_(int *n, int *state, int *info);
+extern void drandstudentst_(int *n, int *df, int *state, double *x, int *info);
+extern void drandtriangular_(int *n, double *xmin, double *xmed, double *xmax, int *state, double *x, int *info);
+extern void dranduniform_(int *n, double *a, double *b, int *state, double *x, int *info);
+extern void drandvonmises_(int *n, double *vk, int *state, double *x, int *info);
+extern void drandweibull_(int *n, double *a, double *b, int *state, double *x, int *info);
+extern void drandmultinormal_(int *n, int *m, double *xmu, double *c, int *ldc, int *state, double *x, int *ldx, int *info);
+extern void drandmultistudentst_(int *n, int *m, int *df, double *xmu, double *c, int *ldc, int *state, double *x, int *ldx, int *info);
+extern void srandbeta_(int *n, float *a, float *b, int *state, float *x, int *info);
+extern void srandblumblumshub_(int *n, int *state, float *x, int *info);
+extern void srandbinomial_(int *n, int *m, float *p, int *state, int *x, int *info);
+extern void srandbinomialreference_(int *m, float *p, float *ref, int *lref, int *info);
+extern void srandcauchy_(int *n, float *a, float *b, int *state, float *x, int *info);
+extern void srandchisquared_(int *n, int *df, int *state, float *x, int *info);
+extern void sranddiscreteuniform_(int *n, int *a, int *b, int *state, int *x, int *info);
+extern void srandexponential_(int *n, float *a, int *state, float *x, int *info);
+extern void srandf_(int *n, int *df1, int *df2, int *state, float *x, int *info);
+extern void srandgamma_(int *n, float *a, float *b, int *state, float *x, int *info);
+extern void srandgaussian_(int *n, float *xmu, float *var, int *state, float *x, int *info);
+extern void srandgeneraldiscrete_(int *n, float *ref, int *state, int *x, int *info);
+extern void srandgeometric_(int *n, float *p, int *state, int *x, int *info);
+extern void srandgeometricreference_(float *p, float *ref, int *lref, int *info);
+extern void srandhypergeometric_(int *n, int *np, int *ns, int *m, int *state, int *x, int *info);
+extern void srandhypergeometricreference_(int *np, int *ns, int *m, float *ref, int *lref, int *info);
+extern void srandinitialize_(int *genid, int *subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void srandinitializebbs_(int *nbits, int *lp, int *p, int *lq, int *q, int *ls, int *s, int *state, int *lstate, int *info);
+extern void srandinitializeuser_(ACML_SRANDINITIALIZEUSER_UINI uini, ACML_SRANDINITIALIZEUSER_UGEN ugen, int genid, int subid, int *seed, int *lseed, int *state, int *lstate, int *info);
+extern void srandleapfrog_(int *n, int *k, int *state, int *info);
+extern void srandlogistic_(int *n, float *a, float *b, int *state, float *x, int *info);
+extern void srandlognormal_(int *n, float *xmu, float *var, int *state, float *x, int *info);
+extern void srandmultinomial_(int *n, int *m, float *p, int *k, int *state, int *x, int *ldx, int *info);
+extern void srandmultinormalreference_(int *m, float *xmu, float *c, int *ldc, float *ref, int *lref, int *info);
+extern void srandmultinormalr_(int *n, float *ref, int *state, float *x, int *ldx, int *info);
+extern void srandmultistudentstreference_(int *m, int *df, float *xmu, float *c, int *ldc, float *ref, int *lref, int *info);
+extern void srandmultistudentstr_(int *n, float *ref, int *state, float *x, int *ldx, int *info);
+extern void srandnegativebinomial_(int *n, int *m, float *p, int *state, int *x, int *info);
+extern void srandnegativebinomialreference_(int *m, float *p, float *ref, int *lref, int *info);
+extern void srandpoisson_(int *n, float *lambda, int *state, int *x, int *info);
+extern void srandpoissonreference_(float *lambda, float *ref, int *lref, int *info);
+extern void srandskipahead_(int *n, int *state, int *info);
+extern void srandstudentst_(int *n, int *df, int *state, float *x, int *info);
+extern void srandtriangular_(int *n, float *xmin, float *xmed, float *xmax, int *state, float *x, int *info);
+extern void sranduniform_(int *n, float *a, float *b, int *state, float *x, int *info);
+extern void srandvonmises_(int *n, float *vk, int *state, float *x, int *info);
+extern void srandweibull_(int *n, float *a, float *b, int *state, float *x, int *info);
+extern void srandmultinormal_(int *n, int *m, float *xmu, float *c, int *ldc, int *state, float *x, int *ldx, int *info);
+extern void srandmultistudentst_(int *n, int *m, int *df, float *xmu, float *c, int *ldc, int *state, float *x, int *ldx, int *info);
+
+/* ACML version information */
+extern void acmlversion_(int *major, int *minor, int *patch);
+extern void acmlinfo_(void);
+
+/* OMP interfaces */
+extern int acmlgetmaxthreads_(void);
+extern int acmlgetnumthreads_(void);
+extern void acmlsetnumthreads_(int *numthreads);
+extern int acmlgetnumprocs_(void);
+
+/* Putenv and getenv utilities */
+extern void acmlputenv_(char *name, char *value, int name_len, int value_len);
+extern void acmlgetenv_(char *name, char *value, int name_len, int value_len);
+
+/* ------------------------------------------------------------------ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !defined(_ACML_H) */
Index: /win32/run_cmake.bat
===================================================================
--- /win32/run_cmake.bat (revision 35)
+++ /win32/run_cmake.bat (revision 35)
@@ -0,0 +1,4 @@
+@echo off
+cd ..
+cmake -G "Visual Studio 8 2005"
+pause
Index: /win32/itpp-4.0.1/itpp/config_msvc.h
===================================================================
--- /win32/itpp-4.0.1/itpp/config_msvc.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/config_msvc.h (revision 35)
@@ -0,0 +1,279 @@
+/* itpp/config.h.  Generated from config.h.in by configure.  */
+/* itpp/config.h.in.  Generated from configure.ac by autoheader.  */
+
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+/* Define to dummy `main' function (if any) required to link to the Fortran
+   libraries. */
+/* #undef F77_DUMMY_MAIN */
+
+/* Define if F77 and FC dummy `main' functions are identical. */
+/* #undef FC_DUMMY_MAIN_EQ_F77 */
+
+/* Define to 1 if you have the `acosh' function. */
+/* #undef HAVE_ACOSH */
+
+/* Define to 1 if you have the `asinh' function. */
+/* #undef HAVE_ASINH */
+
+/* Define to 1 if you have the `atanh' function. */
+/* #undef HAVE_ATANH */
+
+#if defined(HAVE_ACML) || defined(HAVE_MKL)
+/* Define if you have a BLAS library. */
+#  define HAVE_BLAS 1
+#endif
+
+#ifdef HAVE_ACML
+/* Define if you have an ACML BLAS library. */
+#  define HAVE_BLAS_ACML 1
+#endif
+
+/* Define if you have an ATLAS BLAS library. */
+/* #undef HAVE_BLAS_ATLAS */
+
+#ifdef HAVE_MKL
+/* Define if you have an MKL BLAS library. */
+#  define HAVE_BLAS_MKL 1
+#endif
+
+/* Define to 1 if you have the `cbrt' function. */
+/* #undef HAVE_CBRT */
+
+/* Define to 1 if you have the <cmath> header file. */
+#define HAVE_CMATH 1
+
+/* Define to 1 if you have the <complex> header file. */
+#define HAVE_COMPLEX 1
+
+/* Define to 1 if you have the declaration of `isfinite', and to 0 if you
+   don't. */
+#define HAVE_DECL_ISFINITE 0
+
+/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
+   */
+#define HAVE_DECL_ISINF 0
+
+/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
+   */
+#define HAVE_DECL_ISNAN 0
+
+/* Define to 1 if you have the declaration of `signgam', and to 0 if you
+   don't. */
+#define HAVE_DECL_SIGNGAM 0
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `erf' function. */
+/* #undef HAVE_ERF */
+
+/* Define to 1 if you have the `erfc' function. */
+/* #undef HAVE_ERFC */
+
+/* Define if the compiler supports extern template */
+/* #undef HAVE_EXTERN_TEMPLATE */
+
+#if defined(HAVE_ACML) || defined(HAVE_MKL)
+/* Define if you have FFT library. */
+#  define HAVE_FFT 1
+#endif
+
+/* Define if you have FFTW3 library. */
+/* #undef HAVE_FFTW3 */
+
+#ifdef HAVE_ACML
+/* Define if you have ACML FFT library. */
+#  define HAVE_FFT_ACML 1
+#endif
+
+#ifdef HAVE_MKL
+/* Define if you have MKL FFT library. */
+#  define HAVE_FFT_MKL 1
+#endif
+
+/* Define to 1 if you have the `finite' function. */
+/* #undef HAVE_FINITE */
+
+/* Define to 1 if you have the `fpclass' function. */
+/* #undef HAVE_FPCLASS */
+
+/* Define to 1 if you have the <ieeefp.h> header file. */
+/* #undef HAVE_IEEEFP_H */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+/* #undef HAVE_INTTYPES_H */
+
+/* Define to 1 if you have the `isfinite' function. */
+/* #undef HAVE_ISFINITE */
+
+/* Define to 1 if you have the `isinf' function. */
+/* #undef HAVE_ISINF */
+
+/* Define to 1 if you have the `isnan' function. */
+/* #undef HAVE_ISNAN */
+
+#if defined(HAVE_ACML) || defined(HAVE_MKL)
+/* Define if you have LAPACK library. */
+#  define HAVE_LAPACK 1
+#endif
+
+/* Define to 1 if you have the `lgamma' function. */
+/* #undef HAVE_LGAMMA */
+
+/* Define to 1 if you have the `log1p' function. */
+/* #undef HAVE_LOG1P */
+
+/* Define to 1 if you have the `log2' function. */
+/* #undef HAVE_LOG2 */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `rint' function. */
+/* #undef HAVE_RINT */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `std::isfinite' function. */
+/* #undef HAVE_STD_ISFINITE */
+
+/* Define to 1 if you have the `std::isinf' function. */
+/* #undef HAVE_STD_ISINF */
+
+/* Define to 1 if you have the `std::isnan' function. */
+/* #undef HAVE_STD_ISNAN */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `tgamma' function. */
+/* #undef HAVE_TGAMMA */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if zdotu_ can return result like a function. */
+/* #undef HAVE_ZDOTU_RETURN */
+
+/* Define if zdotu_ can pass result as its first argument. */
+#define HAVE_ZDOTU_VOID 1
+
+/* Define if you want exceptions handling */
+/* #undef ITPP_EXCEPTIONS */
+
+/* Name of package */
+#define PACKAGE "itpp"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "ediap@users.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "IT++"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "IT++ 4.0.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "itpp"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.0.0"
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* The size of `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `short', as computed by sizeof. */
+#define SIZEOF_SHORT 2
+
+/* The size of `unsigned int', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_INT 4
+
+/* The size of `unsigned long', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG 4
+
+/* The size of `unsigned long long', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_LONG_LONG 8
+
+/* The size of `unsigned short', as computed by sizeof. */
+#define SIZEOF_UNSIGNED_SHORT 2
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* #undef TIME_WITH_SYS_TIME */
+
+/* Version number of package */
+#define VERSION "4.0.0"
+
+
+#if defined(HAVE_CMATH)
+#  include <cmath>
+#endif
+
+/* Solaris uses <ieeefp.h> for declaring isnan() and finite() functions */
+#if defined(HAVE_IEEEFP_H)
+#  include <ieeefp.h>
+#endif
+
+/* Microsoft Visual C++ .NET underscore prefixed functions */
+#if defined(_MSC_VER)
+#  include <cfloat>
+#  define HAVE_FINITE 1
+#  define finite(x) _finite(x)
+#  define HAVE_ISFINITE 1
+#  define isfinite(x) _finite(x)
+#  define HAVE_ISNAN 1
+#  define isnan(x) _isnan(x)
+#  define HAVE_FPCLASS 1
+#  define fpclass(x) _fpclass(x)
+#  define FP_NINF _FPCLASS_NINF
+#  define FP_PINF _FPCLASS_PINF
+#  define HAVE_JN 1
+#  define jn(a, b) _jn(a, b)
+#  define HAVE_YN 1
+#  define yn(a, b) _yn(a, b)
+#  define HAVE_J0 1
+#  define j0(a) _j0(a)
+#  define HAVE_J1 1
+#  define j1(a) _j1(a)
+#endif /* defined(_MSC_VER) */
+
+/* IT++ uses only std::min() and std::max() functions, not macros */
+#ifdef min
+#  undef min
+#endif
+#ifdef max
+#  undef max
+#endif
+
+/* Represent GCC version in a concise form */
+#define GCC_VERSION (__GNUC__ * 10000           \
+                     + __GNUC_MINOR__ * 100     \
+                     + __GNUC_PATCHLEVEL__)
+
+#endif /* #ifndef CONFIG_H */
+
Index: /win32/itpp-4.0.1/itpp/base/converters.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/converters.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/converters.h (revision 35)
@@ -0,0 +1,487 @@
+/*!
+ * \file
+ * \brief Definitions of converters between different vector and matrix types
+ * \author Tony Ottosson, Tobias Ringstrom, Pal Frenger and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef CONVERTERS_H
+#define CONVERTERS_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/help_functions.h>
+#include <itpp/base/math/misc.h>
+
+
+namespace itpp {
+
+  //! \addtogroup convertfunc
+  //@{
+
+  // ----------------------------------------------------------------------
+  // Converters for vectors
+  // ----------------------------------------------------------------------
+
+  /*!
+    \relatesalso Vec
+    \brief Converts a Vec<T> to bvec
+  */
+  template <class T>
+  bvec to_bvec(const Vec<T> &v)
+  {
+    bvec temp(v.length());
+    for (int i = 0; i < v.length(); ++i) {
+      temp(i) = static_cast<bin>(v(i));
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Vec
+    \brief Converts a Vec<T> to svec
+  */
+  template <class T>
+  svec to_svec(const Vec<T> &v)
+  {
+    svec temp(v.length());
+    for (int i = 0; i < v.length(); ++i) {
+      temp(i) = static_cast<short>(v(i));
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Vec
+    \brief Converts a Vec<T> to ivec
+  */
+  template <class T>
+  ivec to_ivec(const Vec<T> &v)
+  {
+    ivec temp(v.length());
+    for (int i = 0; i < v.length(); ++i) {
+      temp(i) = static_cast<int>(v(i));
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Vec
+    \brief Converts a Vec<T> to vec
+  */
+  template <class T>
+  vec to_vec(const Vec<T> &v)
+  {
+    vec temp(v.length());
+    for (int i = 0; i < v.length(); ++i) {
+      temp(i) = static_cast<double>(v(i));
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Vec
+    \brief Converts a Vec<T> to cvec
+  */
+  template <class T>
+  cvec to_cvec(const Vec<T> &v)
+  {
+    cvec temp(v.length());
+    for (int i = 0; i < v.length(); ++i) {
+      temp(i) = std::complex<double>(static_cast<double>(v(i)), 0.0);
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Vec
+    \brief Converts real and imaginary Vec<T> to cvec
+  */
+  template <class T>
+  cvec to_cvec(const Vec<T> &real, const Vec<T> &imag)
+  {
+    it_assert(real.length() == imag.length(),
+	      "to_cvec(): real and imaginary parts must have the same length");
+    cvec temp(real.length());
+    for(int i = 0; i < real.length(); ++i) {
+      temp(i) = std::complex<double>(static_cast<double>(real(i)),
+				     static_cast<double>(imag(i)));
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Vec
+    \brief Converts an int to ivec
+  */
+  ivec to_ivec(int s);
+
+  /*!
+    \relatesalso Vec
+    \brief Converts an double to vec
+  */
+  vec to_vec(double s);
+
+  /*!
+    \relatesalso Vec
+    \brief Converts real and imaginary double to cvec
+  */
+  cvec to_cvec(double real, double imag);
+
+  // ----------------------------------------------------------------------
+  // Converters for matrices
+  // ----------------------------------------------------------------------
+
+  /*!
+    \relatesalso Mat
+    \brief Converts a Mat<T> to bmat
+  */
+  template <class T>
+  bmat to_bmat(const Mat<T> &m)
+  {
+    bmat temp(m.rows(), m.cols());
+    for (int i = 0; i < temp.rows(); ++i) {
+      for (int j = 0; j < temp.cols(); ++j) {
+	temp(i, j) = static_cast<bin>(m(i, j));
+      }
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Mat
+    \brief Converts a Mat<T> to smat
+  */
+  template <class T>
+  smat to_smat(const Mat<T> &m)
+  {
+    smat temp(m.rows(), m.cols());
+    for (int i = 0; i < temp.rows(); ++i) {
+      for (int j = 0; j < temp.cols(); ++j) {
+	temp(i, j) = static_cast<short>(m(i, j));
+      }
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Mat
+    \brief Converts a Mat<T> to imat
+  */
+  template <class T>
+  imat to_imat(const Mat<T> &m)
+  {
+    imat temp(m.rows(), m.cols());
+    for (int i = 0; i < temp.rows(); ++i) {
+      for (int j = 0; j < temp.cols(); ++j) {
+	temp(i, j) = static_cast<int>(m(i, j));
+      }
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Mat
+    \brief Converts a Mat<T> to mat
+  */
+  template <class T>
+  mat to_mat(const Mat<T> &m)
+  {
+    mat temp(m.rows(), m.cols());
+    for (int i = 0; i < temp.rows(); ++i) {
+      for (int j = 0; j < temp.cols(); ++j) {
+	temp(i, j) = static_cast<double>(m(i, j));
+      }
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Mat
+    \brief Converts a Mat<T> to cmat
+  */
+  template <class T>
+  cmat to_cmat(const Mat<T> &m)
+  {
+    cmat temp(m.rows(), m.cols());
+    for (int i = 0; i < temp.rows(); ++i) {
+      for (int j = 0; j < temp.cols(); ++j) {
+	temp(i, j) = std::complex<double>(static_cast<double>(m(i, j)), 0.0);
+      }
+    }
+    return temp;
+  }
+
+  /*!
+    \relatesalso Mat
+    \brief Converts real and imaginary Mat<T> to cmat
+  */
+  template <class T>
+  cmat to_cmat(const Mat<T> &real, const Mat<T> &imag)
+  {
+    it_assert_debug((real.rows() == imag.rows())
+                    && (real.cols() == imag.cols()),
+		    "to_cmat(): real and imag part sizes does not match");
+    cmat temp(real.rows(), real.cols());
+    for (int i = 0; i < temp.rows(); ++i) {
+      for (int j = 0; j < temp.cols(); ++j) {
+	temp(i, j) = std::complex<double>(static_cast<double>(real(i, j)),
+                                          static_cast<double>(imag(i, j)));
+      }
+    }
+    return temp;
+  }
+
+
+  /*!
+    \brief Convert a decimal int \a index to bvec using \a length bits in the representation
+  */
+  bvec dec2bin(int length, int index);
+
+  /*!
+    \brief Convert a decimal int \a index to bvec. Value returned in \a v.
+  */
+  void dec2bin(int index, bvec &v);
+
+  /*!
+    \brief Convert a decimal int \a index to bvec with the first bit as MSB if \a msb_first == true
+  */
+  bvec dec2bin(int index, bool msb_first = true);
+
+  /*!
+    \brief Convert a bvec to decimal int with the first bit as MSB if \a msb_first == true
+  */
+  int bin2dec(const bvec &inbvec, bool msb_first = true);
+
+  /*!
+    \brief Convert ivec of octal form to bvec
+
+    Converts from ivec containing {0,1,2,...,7} to bvec containing {0,1}.
+    Removes zeros to the left if keepzeros = 0 (default).
+    Example: oct2bin("3 5 5 1") returns {1 1 1 0 1 1 0 1 0 0 1}.
+  */
+  bvec oct2bin(const ivec &octalindex, short keepzeros = 0);
+
+  /*!
+    \brief Convert bvec to octal ivec
+
+    Converts from  bvec containing {0,1} to ivec containing {0,1,2,...,7}.
+    Adds zeros to the left if inbits.length() is not a factor of 3.
+    Example: bin2oct("1 1 1 0 1 1 0 1 0 0 1") returns {3 5 5 1}.
+  */
+  ivec bin2oct(const bvec &inbits);
+
+  //! Convert bvec to polar binary representation as ivec
+  ivec bin2pol(const bvec &inbvec);
+
+  //! Convert binary polar ivec to bvec
+  bvec pol2bin(const ivec &inpol);
+
+  //! Convert radians to degrees
+  inline double rad_to_deg(double x) { return (180.0 / itpp::pi * x); }
+  //! Convert degrees to radians
+  inline double deg_to_rad(double x) { return (itpp::pi / 180.0 * x); }
+
+
+#ifndef HAVE_RINT
+  //! Round to nearest integer, return result in double
+  inline double rint(double x) { return floor(x + 0.5); }
+#endif
+  //! Round to nearest integer, return result in double
+  inline double round(double x) { return rint(x); }
+  //! Round to nearest integer
+  inline vec round(const vec &x) { return apply_function<double>(round, x); }
+  //! Round to nearest integer
+  inline mat round(const mat &x) { return apply_function<double>(round, x); }
+  //! Round to nearest integer
+  inline int round_i(double x) { return static_cast<int>(rint(x)); }
+  //! Round to nearest integer and return ivec
+  ivec round_i(const vec &x);
+  //! Round to nearest integer and return imat
+  imat round_i(const mat &x);
+
+  //! Round to nearest upper integer
+  inline vec ceil(const vec &x) { return apply_function<double>(std::ceil, x); }
+  //! Round to nearest upper integer
+  inline mat ceil(const mat &x) { return apply_function<double>(std::ceil, x); }
+  //! The nearest larger integer
+  inline int ceil_i(double x) { return static_cast<int>(std::ceil(x)); }
+  //! Round to nearest upper integer
+  ivec ceil_i(const vec &x);
+  //! Round to nearest upper integer
+  imat ceil_i(const mat &x);
+
+  //! Round to nearest lower integer
+  inline vec floor(const vec &x) { return apply_function<double>(std::floor, x); }
+  //! Round to nearest lower integer
+  inline mat floor(const mat &x) { return apply_function<double>(std::floor, x); }
+  //! The nearest smaller integer
+  inline int floor_i(double x) { return static_cast<int>(std::floor(x)); }
+  //! Round to nearest lower integer
+  ivec floor_i(const vec &x);
+  //! Round to nearest lower integer
+  imat floor_i(const mat &x);
+
+
+  //! Round \a x to zero if \a abs(x) is smaller than \a threshold
+  inline double round_to_zero(double x, double threshold = 1e-14)
+  {
+    return ((std::fabs(x) < threshold) ? 0.0 : x);
+  }
+
+  //! Round each part of \a x smaller than \a threshold to zero
+  inline std::complex<double> round_to_zero(const std::complex<double>& x,
+					    double threshold = 1e-14)
+  {
+    return std::complex<double>(round_to_zero(x.real(), threshold),
+				round_to_zero(x.imag(), threshold));
+  }
+
+  //! Round each element to zero if element < threshold
+  inline vec round_to_zero(const vec &x, double threshold = 1e-14)
+  {
+    return apply_function<double>(round_to_zero, x, threshold);
+  }
+
+  //! Round each element to zero if element < threshold
+  inline mat round_to_zero(const mat &x, double threshold = 1e-14)
+  {
+    return apply_function<double>(round_to_zero, x, threshold);
+  }
+
+  //! Round each element to zero if element < threshold
+  cvec round_to_zero(const cvec &x, double threshold = 1e-14);
+
+  //! Round each element to zero if element < threshold
+  cmat round_to_zero(const cmat &x, double threshold = 1e-14);
+
+
+  //! Convert to Gray Code
+  inline int gray_code(int x) { return x^(x >> 1); }
+
+
+  /*!
+    \brief Convert anything to string
+
+    \param i (Input) The value to be converted to a string
+  */
+  template <typename T>
+  std::string to_str(const T &i);
+
+  /*!
+    \brief Convert double to string
+
+    \param[in]  i          The value to be converted to a string
+    \param[in]  precision  The number of digits used to represent the
+    fractional part
+  */
+  std::string to_str(const double &i, const int precision);
+
+  //@}
+
+  template <typename T>
+  std::string to_str(const T &i)
+  {
+    std::ostringstream ss;
+    ss.precision(8);
+    ss.setf(std::ostringstream::scientific,std::ostringstream::floatfield);
+    ss << i;
+    return ss.str();
+  }
+
+  //! \cond
+
+  // ---------------------------------------------------------------------
+  // Instantiations
+  // ---------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  extern template bvec to_bvec(const svec &v);
+  extern template bvec to_bvec(const ivec &v);
+
+  extern template svec to_svec(const bvec &v);
+  extern template svec to_svec(const ivec &v);
+  extern template svec to_svec(const vec &v);
+
+  // Workaround for GCC 3.3.x error when using -finine-functions or -O3 flag
+#if (GCC_VERSION >= 30400)
+  extern template ivec to_ivec(const bvec &v);
+#endif
+  extern template ivec to_ivec(const svec &v);
+  extern template ivec to_ivec(const vec &v);
+
+  extern template vec to_vec(const bvec &v);
+  extern template vec to_vec(const svec &v);
+  extern template vec to_vec(const ivec &v);
+
+  extern template cvec to_cvec(const bvec &v);
+  extern template cvec to_cvec(const svec &v);
+  extern template cvec to_cvec(const ivec &v);
+  extern template cvec to_cvec(const vec &v);
+
+  extern template cvec to_cvec(const bvec &real, const bvec &imag);
+  extern template cvec to_cvec(const svec &real, const svec &imag);
+  extern template cvec to_cvec(const ivec &real, const ivec &imag);
+  extern template cvec to_cvec(const vec &real, const vec &imag);
+
+  extern template bmat to_bmat(const smat &m);
+  extern template bmat to_bmat(const imat &m);
+
+  extern template smat to_smat(const bmat &m);
+  extern template smat to_smat(const imat &m);
+  extern template smat to_smat(const mat &m);
+
+  extern template imat to_imat(const bmat &m);
+  extern template imat to_imat(const smat &m);
+  extern template imat to_imat(const mat &m);
+
+  extern template mat to_mat(const bmat &m);
+#if (GCC_VERSION >= 30400)
+  extern template mat to_mat(const smat &m);
+  extern template mat to_mat(const imat &m);
+#endif
+
+  extern template cmat to_cmat(const bmat &m);
+  extern template cmat to_cmat(const smat &m);
+  extern template cmat to_cmat(const imat &m);
+  extern template cmat to_cmat(const mat &m);
+
+  extern template cmat to_cmat(const bmat &real, const bmat &imag);
+  extern template cmat to_cmat(const smat &real, const smat &imag);
+  extern template cmat to_cmat(const imat &real, const imat &imag);
+  extern template cmat to_cmat(const mat &real, const mat &imag);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // CONVERTERS_H
Index: /win32/itpp-4.0.1/itpp/base/specmat.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/specmat.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/specmat.h (revision 35)
@@ -0,0 +1,416 @@
+/*!
+ * \file
+ * \brief Definitions of special vectors and matrices
+ * \author Tony Ottosson, Tobias Ringstrom, Pal Frenger, Adam Piatyszek and Erik G. Larsson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef SPECMAT_H
+#define SPECMAT_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+    \brief Return a integer vector with indicies where bvec == 1
+    \ingroup miscfunc
+  */
+  ivec find(const bvec &invector);
+
+  /*!
+    \addtogroup specmat
+  */
+
+  //!\addtogroup specmat
+  //!@{
+
+  //! A float vector of ones
+  vec ones(int size);
+  //! A Binary vector of ones
+  bvec ones_b(int size);
+  //! A Int vector of ones
+  ivec ones_i(int size);
+  //! A float Complex vector of ones
+  cvec ones_c(int size);
+
+  //! A float (rows,cols)-matrix of ones
+  mat ones(int rows, int cols);
+  //! A Binary (rows,cols)-matrix of ones
+  bmat ones_b(int rows, int cols);
+  //! A Int (rows,cols)-matrix of ones
+  imat ones_i(int rows, int cols);
+  //! A Double Complex (rows,cols)-matrix of ones
+  cmat ones_c(int rows, int cols);
+
+  //! A Double vector of zeros
+  vec zeros(int size);
+  //! A Binary vector of zeros
+  bvec zeros_b(int size);
+  //! A Int vector of zeros
+  ivec zeros_i(int size);
+  //! A Double Complex vector of zeros
+  cvec zeros_c(int size);
+
+  //! A Double (rows,cols)-matrix of zeros
+  mat zeros(int rows, int cols);
+  //! A Binary (rows,cols)-matrix of zeros
+  bmat zeros_b(int rows, int cols);
+  //! A Int (rows,cols)-matrix of zeros
+  imat zeros_i(int rows, int cols);
+  //! A Double Complex (rows,cols)-matrix of zeros
+  cmat zeros_c(int rows, int cols);
+
+  //! A Double (size,size) unit matrix
+  mat eye(int size);
+  //! A Binary (size,size) unit matrix
+  bmat eye_b(int size);
+  //! A Int (size,size) unit matrix
+  imat eye_i(int size);
+  //! A Double Complex (size,size) unit matrix
+  cmat eye_c(int size);
+  //! A non-copying version of the eye function.
+  template <class T>
+    void eye(int size, Mat<T> &m);
+
+  //! Impulse vector
+  vec impulse(int size);
+  //! Linspace (works in the same way as the matlab version)
+  vec linspace(double from, double to, int length = 100);
+  /*! \brief Zig-zag space function (variation on linspace)
+
+  This function is a variation on linspace().  It traverses the points
+  in different order. For example
+  \code
+  zigzag_space(-5,5,3)
+  \endcode
+  gives the vector
+  \code
+  [-5 5 0 -2.5 2.5 -3.75 -1.25 1.25 3.75]
+  \endcode
+  and
+  \code
+  zigzag_space(-5,5,4)
+  \endcode
+  gives
+  the vector
+  \code
+  [-5 5 0 -2.5 2.5 -3.75 -1.25 1.25 3.75 -4.375 -3.125 -1.875 -0.625 0.625 1.875 3.125 4.375]
+  \endcode
+  and so on.
+
+  I.e. the function samples the interval [t0,t1] with finer and finer
+  density and with points uniformly distributed over the interval,
+  rather than from left to right (as does linspace).
+
+  The result is a vector of length 1+2^K.
+  */
+  vec zigzag_space(double t0, double t1, int K=5);
+
+  /*!
+   * \brief Hadamard matrix
+   *
+   * This function constructs a \a size by \a size Hadammard matrix, where
+   * \a size is a power of 2.
+   */
+  imat hadamard(int size);
+
+  /*!
+    \brief Jacobsthal matrix.
+
+    Constructs an p by p matrix Q where p is a prime (not checked).
+    The elements in Q {qij} is given by qij=X(j-i), where X(x) is the
+    Legendre symbol given as:
+
+    <ul>
+    <li> X(x)=0 if x is a multiple of p, </li>
+    <li> X(x)=1 if x is a quadratic residue modulo p, </li>
+    <li> X(x)=-1 if x is a quadratic nonresidue modulo p. </li>
+    </ul>
+
+    See Wicker "Error Control Systems for digital communication and storage", p. 134
+    for more information on these topics. Do not check that p is a prime.
+  */
+  imat jacobsthal(int p);
+
+  /*!
+    \brief Conference matrix.
+
+    Constructs an n by n matrix C, where n=p^m+1=2 (mod 4) and p is a odd prime (not checked).
+    This code only work with m=1, that is n=p+1 and p odd prime. The valid sizes
+    of n is then n=6, 14, 18, 30, 38, ... (and not 10, 26, ...).
+    C has the property that C*C'=(n-1)I, that is it has orthogonal rows and columns
+    in the same way as Hadamard matricies. However, one element in each row (on the
+    diagonal) is zeros. The others are {-1,+1}.
+
+    For more details see pp. 55-58 in MacWilliams & Sloane "The theory of error correcting codes",
+    North-Holland, 1977.
+  */
+  imat conference(int n);
+
+  /*!
+    \brief Computes the Hermitian Toeplitz matrix.
+
+    Return the Toeplitz matrix constructed given the first column C,
+    and (optionally) the first row R. If the first element of C is not
+    the same as the first element of R, the first element of C is
+    used.  If the second argument is omitted, the first row is taken
+    to be the same as the first column.
+
+    A square Toeplitz matrix has the form:
+    \verbatim
+          c(0)    r(1)     r(2)   ...   r(n)
+          c(1)*   c(0)     r(1)        r(n-1)
+          c(2)*   c(1)*    c(0)        r(n-2)
+           .                             .
+           .                             .
+           .                             .
+
+          c(n)*  c(n-1)*  c(n-2)* ...   c(0)
+    \endverbatim
+  */
+  cmat toeplitz(const cvec &c, const cvec &r);
+  //! Computes the Hermitian Toeplitz matrix.
+  cmat toeplitz(const cvec &c);
+  //! Computes the Hermitian Toeplitz matrix.
+  mat toeplitz(const vec &c, const vec &r);
+  //! Computes the Hermitian Toeplitz matrix.
+  mat toeplitz(const vec &c);
+
+  //!@}
+
+
+  /*!
+    \brief Create a rotation matrix that rotates the given plane \c angle radians. Note that the order of the planes are important!
+    \ingroup miscfunc
+  */
+  mat rotation_matrix(int dim, int plane1, int plane2, double angle);
+
+  /*!
+    \brief Calcualte the Householder vector
+    \ingroup miscfunc
+  */
+  void house(const vec &x, vec &v, double &beta);
+
+  /*!
+    \brief Calculate the Givens rotation values
+    \ingroup miscfunc
+  */
+  void givens(double a, double b, double &c, double &s);
+
+  /*!
+    \brief Calculate the Givens rotation matrix
+    \ingroup miscfunc
+  */
+  void givens(double a, double b, mat &m);
+
+  /*!
+    \brief Calculate the Givens rotation matrix
+    \ingroup miscfunc
+  */
+  mat givens(double a, double b);
+
+  /*!
+    \brief Calculate the transposed Givens rotation matrix
+    \ingroup miscfunc
+  */
+  void givens_t(double a, double b, mat &m);
+
+  /*!
+    \brief Calculate the transposed Givens rotation matrix
+    \ingroup miscfunc
+  */
+  mat givens_t(double a, double b);
+
+  /*!
+    \relates Vec
+    \brief Vector of length 1
+  */
+  template <class T>
+    Vec<T> vec_1(T v0)
+    {
+      Vec<T> v(1);
+      v(0) = v0;
+      return v;
+    }
+
+  /*!
+    \relates Vec
+    \brief Vector of length 2
+  */
+  template <class T>
+    Vec<T> vec_2(T v0, T v1)
+    {
+      Vec<T> v(2);
+      v(0) = v0;
+      v(1) = v1;
+      return v;
+    }
+
+  /*!
+    \relates Vec
+    \brief Vector of length 3
+  */
+  template <class T>
+    Vec<T> vec_3(T v0, T v1, T v2)
+    {
+      Vec<T> v(3);
+      v(0) = v0;
+      v(1) = v1;
+      v(2) = v2;
+      return v;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 1 by 1
+  */
+  template <class T>
+    Mat<T> mat_1x1(T m00)
+    {
+      Mat<T> m(1,1);
+      m(0,0) = m00;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 1 by 2
+  */
+  template <class T>
+    Mat<T> mat_1x2(T m00, T m01)
+    {
+      Mat<T> m(1,2);
+      m(0,0) = m00; m(0,1) = m01;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 2 by 1
+  */
+  template <class T>
+    Mat<T> mat_2x1(T m00,
+		   T m10)
+    {
+      Mat<T> m(2,1);
+      m(0,0) = m00;
+      m(1,0) = m10;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 2 by 2
+  */
+  template <class T>
+    Mat<T> mat_2x2(T m00, T m01,
+		   T m10, T m11)
+    {
+      Mat<T> m(2,2);
+      m(0,0) = m00; m(0,1) = m01;
+      m(1,0) = m10; m(1,1) = m11;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 1 by 3
+  */
+  template <class T>
+    Mat<T> mat_1x3(T m00, T m01, T m02)
+    {
+      Mat<T> m(1,3);
+      m(0,0) = m00; m(0,1) = m01; m(0,2) = m02;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 3 by 1
+  */
+  template <class T>
+    Mat<T> mat_3x1(T m00,
+		   T m10,
+		   T m20)
+    {
+      Mat<T> m(3,1);
+      m(0,0) = m00;
+      m(1,0) = m10;
+      m(2,0) = m20;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 2 by 3
+  */
+  template <class T>
+    Mat<T> mat_2x3(T m00, T m01, T m02,
+		   T m10, T m11, T m12)
+    {
+      Mat<T> m(2,3);
+      m(0,0) = m00; m(0,1) = m01; m(0,2) = m02;
+      m(1,0) = m10; m(1,1) = m11; m(1,2) = m12;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 3 by 2
+  */
+  template <class T>
+    Mat<T> mat_3x2(T m00, T m01,
+		   T m10, T m11,
+		   T m20, T m21)
+    {
+      Mat<T> m(3,2);
+      m(0,0) = m00; m(0,1) = m01;
+      m(1,0) = m10; m(1,1) = m11;
+      m(2,0) = m20; m(2,1) = m21;
+      return m;
+    }
+
+  /*!
+    \relates Mat
+    \brief Matrix of size 3 by 3
+  */
+  template <class T>
+    Mat<T> mat_3x3(T m00, T m01, T m02,
+		   T m10, T m11, T m12,
+		   T m20, T m21, T m22)
+    {
+      Mat<T> m(3,3);
+      m(0,0) = m00; m(0,1) = m01; m(0,2) = m02;
+      m(1,0) = m10; m(1,1) = m11; m(1,2) = m12;
+      m(2,0) = m20; m(2,1) = m21; m(2,2) = m22;
+      return m;
+    }
+
+} //namespace itpp
+
+#endif // #ifndef SPECMAT_H
Index: /win32/itpp-4.0.1/itpp/base/parser.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/parser.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/parser.h (revision 35)
@@ -0,0 +1,231 @@
+/*!
+ * \file
+ * \brief Definition of an argument parser class
+ * \author Thomas Eriksson, Pal Frenger and Johan Bergman
+ *
+ * Thanks to Svante Signell for valuable input
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+// #define MAX_STR_LEN 4096
+
+#include <itpp/base/vec.h>
+#include <itpp/base/mat.h>
+#include <itpp/base/array.h>
+#include <iostream>
+
+
+namespace itpp {
+
+  /*!
+    \addtogroup parser
+
+    \brief Argument Parser
+    \author Thomas Eriksson and Pal Frenger (Thanks to Svante Signell for
+            valuable input), modifications by Johan Bergman
+
+    This class parses strings to variables. The syntax is compatible with Matlab
+    and Octave. It can be used in several different ways. The following test
+    program and test data file gives several examples:
+
+    <ul>
+    <li> Use the Parser class on a parameter file </li>
+    <li> Use the Parser class on the command line input </li>
+    <li> Use the Parser class on a char pointer (usually the command line input) </li>
+    <li> Use the Parser class on a parameter file and a char pointer </li>
+    <li> Use the Parser class on an Array of strings </li>
+    <li> Use the Parser::get() method on a parameter file </li>
+    <li> Use the Parser::exist() method to check if variables exist </li>
+    </ul>
+
+    The test program looks as follows:
+    \include parser_test.cpp
+
+    The data file \c parser_test_data.txt looks as follows:
+    \include parser_test_data.txt
+
+    Beside the type-specific get methods, like get_int(), there is a templated
+    get method called get(), that can handle all variable types that have an
+    istream operator defined, e.g. Arrays. The get() method takes the variable
+    value as an input/output parameter. If the variable name cannot be found,
+    the old value is kept. Here is an example:
+
+    \code
+    // Declare and initialize a variable
+    Array<ivec> var;
+    set_array(var, "{[1] [2 3] [4 5 6]}");
+
+    // Let the Parser p get the variable named my_var_name
+    bool my_var_name_was_found = p.get(var, "my_var_name");
+    \endcode
+
+    In the above example, if \c my_var_name was not found, \c var keeps its old
+    value {[1] [2 3] [4 5 6]}. In non-silent mode, the get() method echoes the
+    variable values to the standard output in Matlab/Octave m-file style.
+   */
+
+  /*!
+    \ingroup parser
+    \brief Argument Parser Class
+    \author Thomas Eriksson and Pal Frenger (Thanks to Svante Signell for
+    valuable input)
+
+    This class parses strings to variables. The syntax is compatible with Matlab
+    and Octave. It can be used in several different ways. See the Detailed Description
+    in the \ref parser module.
+  */
+  class Parser {
+  public:
+
+    //! Default Constructor
+    Parser();
+
+    //! Constructor. Sets input file name.
+    Parser(const std::string &filename);
+
+    //! Constructor. Uses argc and argv (command line arguments)
+    Parser(int argc, char *argv[]);
+
+    //! Constructor. Sets input file name and uses argc and argv (command line arguments)
+    Parser(const std::string &filename, int argc, char *argv[]);
+
+    //! Constructor. Sets and Array of strings
+    Parser(const Array<std::string> &setup);
+
+    //! Initialization function. Sets input file name.
+    void init(const std::string &filename);
+
+    //! Initialization function. Uses argc and argv (command line arguments)
+    void init(int argc, char *argv[]);
+
+    //! Initialization function. Sets input file name and uses argc and argv (command line arguments)
+    void init(const std::string &filename, int argc, char *argv[]);
+
+    //! Initialization function. Sets and Array of strings
+    void init(const Array<std::string> &setup);
+
+    //! Sets silent mode if true, or verbose mode if false
+    void set_silentmode(bool v=true);
+
+    //! Check is \a name exists in the file. Returns \c true if the \a name is found and \c false otherwise.
+    bool exist(const std::string &name);
+
+    //! Get variable value if \a name can be found (and return true), otherwise keep old value (and return false)
+    template<class T>
+    bool get(T &var, const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a bool
+    bool get_bool(const std::string &name,  int num=-1);
+
+    //! Interpret variable \a name as an integer
+    int get_int(const std::string &name,  int num=-1);
+
+    //! Interpret variable \a name as a double
+    double get_double(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a string
+    std::string get_string(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a vec
+    vec get_vec(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a ivec
+    ivec get_ivec(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a svec
+    svec get_svec(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a bvec
+    bvec get_bvec(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a mat
+    mat get_mat(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a imat
+    imat get_imat(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a smat
+    smat get_smat(const std::string &name, int num=-1);
+
+    //! Interpret variable \a name as a bmat
+    bmat get_bmat(const std::string &name, int num=-1);
+
+  protected:
+
+  private:
+
+    //! Find the string \c name
+    std::string findname(const std::string &name,
+			 bool &error_flag,
+			 bool &print_flag,
+			 int num=0,
+			 bool keep_brackets=false);
+
+    void pre_parsing(void);
+
+    Array<std::string> SetupStrings;
+
+    bool VERBOSE;
+  };
+
+  // ----------------------- Implementation starts here -----------------------
+
+  template<class T>
+  bool Parser::get(T &var, const std::string &name, int num)
+  {
+    bool error_flag, print_flag;
+    std::string str = findname(name, error_flag, print_flag, num, true);
+    std::istringstream buffer(str);
+    if (error_flag) {
+      if (VERBOSE) {
+	std::cout << name << " = " << var << ";" << std::endl;
+      }
+    } else {
+      buffer >> var;
+      if (print_flag) {
+	std::cout << name << " = " << var << std::endl;
+      } else if (VERBOSE) {
+	std::cout << name << " = " << var << ";" << std::endl;
+      }
+    }
+    return !error_flag;
+  }
+
+  //! Specialization or \c get() for std::string
+  template<>
+  bool Parser::get(std::string &var, const std::string &name, int num);
+  //! Specialization of \c get() for int
+  template<>
+  bool Parser::get(int &var, const std::string &name, int num);
+  //! Specialization of \c get() for bool
+  template<>
+  bool Parser::get(bool &var, const std::string &name, int num);
+
+} // namespace itpp
+
+#endif // #ifndef PARSER_H
Index: /win32/itpp-4.0.1/itpp/base/copy_vector.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/copy_vector.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/copy_vector.h (revision 35)
@@ -0,0 +1,320 @@
+/*!
+ * \file
+ * \brief Vector copy functions for internal use
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef COPY_VECTOR_H
+#define COPY_VECTOR_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined (HAVE_BLAS)
+#  include <itpp/base/blas.h>
+#endif
+
+#include <itpp/base/binary.h>
+#include <cstring>
+
+
+//! \cond
+
+namespace itpp {
+
+
+  /*
+    Copy vector x to vector y. Both vectors are of size n
+  */
+  inline void copy_vector(const int n, const int *x, int *y) { memcpy(y, x, (unsigned int)n*sizeof(int)); }
+  inline void copy_vector(const int n, const short *x, short *y) { memcpy(y, x, (unsigned int)n*sizeof(short)); }
+  inline void copy_vector(const int n, const bin *x, bin *y) { memcpy(y, x, (unsigned int)n*sizeof(bin)); }
+  inline void copy_vector(const int n, const float *x, float *y) { memcpy(y, x, (unsigned int)n*sizeof(float)); }
+  inline void copy_vector(const int n, const std::complex<float> *x, std::complex<float> *y) { memcpy(y, x, (unsigned int)n*sizeof(std::complex<float>)); }
+
+#if defined (HAVE_BLAS)
+  inline void copy_vector(const int n, const double *x, double *y)
+  {
+    int incr = 1;
+    blas::dcopy_(&n, x, &incr, y, &incr);
+  }
+  inline void copy_vector(const int n, const std::complex<double> *x,
+			  std::complex<double> *y)
+  {
+    int incr = 1;
+    blas::zcopy_(&n, x, &incr, y, &incr);
+  }
+#else
+  inline void copy_vector(const int n, const double *x, double *y) { memcpy(y, x, (unsigned int)n*sizeof(double)); }
+  inline void copy_vector(const int n, const std::complex<double> *x, std::complex<double> *y) { memcpy(y, x, (unsigned int)n*sizeof(std::complex<double>)); }
+#endif
+
+  template<class T> inline
+  void copy_vector(const int n, const T *x, T *y)
+  {
+    for (int i=0; i<n; i++)
+      y[i] = x[i];
+  }
+
+
+
+
+  /*
+    Copy vector x to vector y. Both vectors are of size n
+    vector x elements are stored linearly with element increament incx
+    vector y elements are stored linearly with element increament incx
+  */
+#if defined (HAVE_BLAS)
+  inline void copy_vector(const int n, const double *x, const int incx,
+			  double *y, const int incy)
+  {
+    blas::dcopy_(&n, x, &incx, y, &incy);
+  }
+  inline void copy_vector(const int n, const std::complex<double> *x,
+			  const int incx, std::complex<double> *y,
+			  const int incy)
+  {
+    blas::zcopy_(&n, x, &incx, y, &incy);
+  }
+#endif
+
+  template<class T> inline
+  void copy_vector(const int n, const T *x, const int incx, T *y, const int incy)
+  {
+    for (int i=0;i<n; i++)
+      y[i*incy] = x[i*incx];
+  }
+
+
+  /*
+    Swap vector x to vector y. Both vectors are of size n
+  */
+  inline void swap_vector(const int n, int *x, int *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+  inline void swap_vector(const int n, short *x, short *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+  inline void swap_vector(const int n, bin *x, bin *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+  inline void swap_vector(const int n, float *x, float *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+  inline void swap_vector(const int n, std::complex<float> *x, std::complex<float> *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+
+#if defined (HAVE_BLAS)
+  inline void swap_vector(const int n, double *x, double *y)
+  {
+    int incr = 1;
+    blas::dswap_(&n, x, &incr, y, &incr);
+  }
+  inline void swap_vector(const int n, std::complex<double> *x,
+			  std::complex<double> *y)
+  {
+    int incr = 1;
+    blas::zswap_(&n, x, &incr, y, &incr);
+  }
+#else
+  inline void swap_vector(const int n, double *x, double *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+  inline void swap_vector(const int n, std::complex<double> *x, std::complex<double> *y) { for (int i=0; i<n; i++) std::swap(x[i], y[i]); }
+#endif
+
+  template<class T> inline
+  void swap_vector(const int n, T *x, T *y)
+  {
+    T tmp;
+    for (int i=0; i<n; i++) {
+      tmp = y[i];
+      y[i] = x[i];
+      x[i] = tmp;
+    }
+  }
+
+
+  /*
+    Swap vector x to vector y. Both vectors are of size n
+    vector x elements are stored linearly with element increament incx
+    vector y elements are stored linearly with element increament incx
+  */
+  inline void swap_vector(const int n, int *x, const int incx, int *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+  inline void swap_vector(const int n, short *x, const int incx, short *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+  inline void swap_vector(const int n, bin *x, const int incx, bin *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+  inline void swap_vector(const int n, float *x, const int incx, float *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+  inline void swap_vector(const int n, std::complex<float> *x, const int incx, std::complex<float> *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+
+#if defined (HAVE_BLAS)
+  inline void swap_vector(const int n, double *x, const int incx, double *y,
+			  const int incy)
+  {
+    blas::dswap_(&n, x, &incx, y, &incy);
+  }
+  inline void swap_vector(const int n, std::complex<double> *x, const int incx,
+			  std::complex<double> *y, const int incy)
+  {
+    blas::zswap_(&n, x, &incx, y, &incy);
+  }
+#else
+  inline void swap_vector(const int n, double *x, const int incx, double *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+  inline void swap_vector(const int n, std::complex<double> *x, const int incx, std::complex<double> *y, const int incy) { for (int i=0; i<n; i++) std::swap(x[i*incx], y[i*incy]); }
+#endif
+
+  template<class T> inline
+  void swap_vector(const int n, T *x, const int incx, T *y, const int incy)
+  {
+    T tmp;
+    for (int i=0; i<n; i++) {
+      tmp = y[i*incy];
+      y[i*incy] = x[i*incx];
+      x[i*incx] = tmp;
+    }
+  }
+
+
+  /*
+   * Realise scaling operation: x = alpha*x
+   */
+#if defined(HAVE_BLAS)
+  inline void scal_vector(int n, double alpha, double *x)
+  {
+    int incr = 1;
+    blas::dscal_(&n, &alpha, x, &incr);
+  }
+  inline void scal_vector(int n, std::complex<double> alpha,
+			  std::complex<double> *x)
+  {
+    int incr = 1;
+    blas::zscal_(&n, &alpha, x, &incr);
+  }
+#endif
+
+  template<typename T> inline
+  void scal_vector(int n, T alpha, T *x)
+  {
+    if (alpha != T(1)) {
+      for (int i = 0; i < n; ++i) {
+	x[i] *= alpha;
+      }
+    }
+  }
+
+
+  /*
+   * Realise scaling operation: x = alpha*x
+   * Elements of x are stored linearly with increament incx
+   */
+#if defined(HAVE_BLAS)
+  inline void scal_vector(int n, double alpha, double *x, int incx)
+  {
+    blas::dscal_(&n, &alpha, x, &incx);
+  }
+  inline void scal_vector(int n, std::complex<double> alpha,
+			  std::complex<double> *x, int incx)
+  {
+    blas::zscal_(&n, &alpha, x, &incx);
+  }
+#endif
+
+  template<typename T> inline
+  void scal_vector(int n, T alpha, T *x, int incx)
+  {
+    if (alpha != T(1)) {
+      for (int i = 0; i < n; ++i) {
+	x[i*incx] *= alpha;
+      }
+    }
+  }
+
+
+  /*
+   * Realise the following equation on vectors: y = alpha*x + y
+   */
+#if defined(HAVE_BLAS)
+  inline void axpy_vector(int n, double alpha, const double *x, double *y)
+  {
+    int incr = 1;
+    blas::daxpy_(&n, &alpha, x, &incr, y, &incr);
+  }
+  inline void axpy_vector(int n, std::complex<double> alpha,
+			  const std::complex<double> *x,
+			  std::complex<double> *y)
+  {
+    int incr = 1;
+    blas::zaxpy_(&n, &alpha, x, &incr, y, &incr);
+  }
+#endif
+
+  template<typename T> inline
+  void axpy_vector(int n, T alpha, const T *x, T *y)
+  {
+    if (alpha != T(1)) {
+      for (int i = 0; i < n; ++i) {
+	y[i] += alpha * x[i];
+      }
+    }
+    else {
+      for (int i = 0; i < n; ++i) {
+	y[i] += x[i];
+      }
+    }
+  }
+
+
+  /*
+   * Realise the following equation on vectors: y = alpha*x + y
+   * Elements of x are stored linearly with increament incx
+   * and elements of y are stored linearly with increament incx
+   */
+#if defined(HAVE_BLAS)
+  inline void axpy_vector(int n, double alpha, const double *x, int incx,
+			  double *y, int incy)
+  {
+    blas::daxpy_(&n, &alpha, x, &incx, y, &incy);
+  }
+  inline void axpy_vector(int n, std::complex<double> alpha,
+			  const std::complex<double> *x, int incx,
+			  std::complex<double> *y, int incy)
+  {
+    blas::zaxpy_(&n, &alpha, x, &incx, y, &incy);
+  }
+#endif
+
+  template<typename T> inline
+  void axpy_vector(int n, T alpha, const T *x, int incx, T *y, int incy)
+  {
+    if (alpha != T(1)) {
+      for (int i = 0; i < n; ++i) {
+	y[i*incy] += alpha * x[i*incx];
+      }
+    }
+    else {
+      for (int i = 0; i < n; ++i) {
+	y[i*incy] += x[i*incx];
+      }
+    }
+  }
+
+
+} // namespace itpp
+
+//! \endcond
+
+#endif // #ifndef COPY_VECTOR_H
Index: /win32/itpp-4.0.1/itpp/base/matfunc.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/matfunc.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/matfunc.h (revision 35)
@@ -0,0 +1,1016 @@
+/*!
+ * \file
+ * \brief Various functions on vectors and matrices - header file
+ * \author Tony Ottosson, Adam Piatyszek, Conrad Sanderson, Mark Dobossy
+ *         and Martin Senst
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef MATFUNC_H
+#define MATFUNC_H
+
+#include <itpp/base/mat.h>
+#include <itpp/base/math/log_exp.h>
+#include <itpp/base/math/elem_math.h>
+
+
+namespace itpp {
+
+  /*!
+    \addtogroup matrix_functions
+    \brief Functions on vectors and matrices
+  */
+  //!@{
+
+  //! Length of vector
+  template<class T>
+  int length(const Vec<T> &v) { return v.length(); }
+
+  //! Length of vector
+  template<class T>
+  int size(const Vec<T> &v) { return v.length(); }
+
+  //! Sum of all elements in the vector
+  template<class T>
+  T sum(const Vec<T> &v)
+  {
+    T M = 0;
+
+    for (int i=0;i<v.length();i++)
+      M += v[i];
+
+    return M;
+  }
+
+  /*!
+   * \brief Sum of elements in the matrix \c m, either along columns or rows
+   *
+   * <tt>sum(m) = sum(m, 1)</tt> returns a vector where the elements are sum
+   * over each column, whereas <tt>sum(m, 2)</tt> returns a vector where the
+   * elements are sum over each row.
+   */
+  template<class T>
+  Vec<T> sum(const Mat<T> &m, int dim=1)
+  {
+    it_assert((dim == 1) || (dim == 2), "sum: dimension need to be 1 or 2");
+    Vec<T> out;
+
+    if (dim == 1) {
+      out.set_size(m.cols(), false);
+
+      for (int i=0; i<m.cols(); i++)
+	      out(i) = sum(m.get_col(i));
+    }
+    else {
+      out.set_size(m.rows(), false);
+
+      for (int i=0; i<m.rows(); i++)
+	      out(i) = sum(m.get_row(i));
+    }
+
+    return out;
+  }
+
+
+  //! Sum of all elements in the given matrix. Fast version of sum(sum(X))
+  template<class T>
+  T sumsum(const Mat<T> &X)
+  {
+    const T * X_data = X._data();
+    const int X_datasize = X._datasize();
+    T acc = 0;
+
+    for(int i=0;i<X_datasize;i++)
+      acc += X_data[i];
+
+    return acc;
+  }
+
+
+  //! Sum of square of the elements in a vector
+  template<class T>
+  T sum_sqr(const Vec<T> &v)
+  {
+    T M=0;
+
+    for (int i=0; i<v.length(); i++)
+      M += v[i] * v[i];
+
+    return M;
+  }
+
+  /*!
+   * \brief Sum of the square of elements in the matrix \c m
+   *
+   * <tt>sum(m) = sum(m, 1)</tt> returns a vector where the elements are sum
+   * squared over each column, whereas <tt>sum(m, 2)</tt> returns a vector
+   * where the elements are sum squared over each row
+   */
+  template<class T>
+  Vec<T> sum_sqr(const Mat<T> &m, int dim=1)
+  {
+    it_assert((dim == 1) || (dim == 2), "sum_sqr: dimension need to be 1 or 2");
+    Vec<T> out;
+
+    if (dim == 1) {
+      out.set_size(m.cols(), false);
+
+      for (int i=0; i<m.cols(); i++)
+	out(i) = sum_sqr(m.get_col(i));
+    }
+    else {
+      out.set_size(m.rows(), false);
+
+      for (int i=0; i<m.rows(); i++)
+	out(i) = sum_sqr(m.get_row(i));
+    }
+
+    return out;
+  }
+
+  //! Cumulative sum of all elements in the vector
+  template<class T>
+  Vec<T> cumsum(const Vec<T> &v)
+  {
+    Vec<T> out(v.size());
+
+    out(0)=v(0);
+    for (int i=1; i<v.size(); i++)
+      out(i) = out(i-1) + v(i);
+
+    return out;
+  }
+
+  /*!
+   * \brief Cumulative sum of elements in the matrix \c m
+   *
+   * <tt>cumsum(m) = cumsum(m, 1)</tt> returns a matrix where the elements
+   * are sums over each column, whereas <tt>cumsum(m, 2)</tt> returns a
+   * matrix where the elements are sums over each row
+   */
+  template<class T>
+  Mat<T> cumsum(const Mat<T> &m, int dim=1)
+  {
+    it_assert((dim == 1) || (dim == 2), "cumsum: dimension need to be 1 or 2");
+    Mat<T> out(m.rows(), m.cols());
+
+    if (dim == 1) {
+      for (int i=0; i<m.cols(); i++)
+	out.set_col(i, cumsum(m.get_col(i)));
+    } else {
+      for (int i=0; i<m.rows(); i++)
+	out.set_row(i, cumsum(m.get_row(i)));
+    }
+
+    return out;
+  }
+
+  //! The product of all elements in the vector
+  template<class T>
+  T prod(const Vec<T> &v)
+  {
+    it_assert(v.size() >= 1, "prod: size of vector should be at least 1");
+    T out = v(0);
+
+    for (int i=1; i<v.size(); i++)
+      out *= v(i);
+
+    return out;
+  }
+
+  /*!
+   * \brief Product of elements in the matrix \c m
+   *
+   * <tt>prod(m) = prod(m, 1)</tt> returns a vector where the elements are
+   * products over each column, whereas <tt>prod(m, 2)</tt> returns a vector
+   * where the elements are products over each row
+   */
+  template<class T>
+  Vec<T> prod(const Mat<T> &m, int dim=1)
+  {
+    it_assert((dim == 1) || (dim == 2), "prod: dimension need to be 1 or 2");
+    Vec<T> out(m.cols());
+
+    if (dim == 1) {
+      it_assert((m.cols() >= 1) && (m.rows() >= 1),
+		"prod: number of columns should be at least 1");
+      out.set_size(m.cols(), false);
+
+      for (int i=0; i<m.cols(); i++)
+	out(i) = prod(m.get_col(i));
+    }
+    else {
+      it_assert((m.cols() >= 1) && (m.rows() >= 1),
+		"prod: number of rows should be at least 1");
+      out.set_size(m.rows(), false);
+
+      for (int i=0; i<m.rows(); i++)
+	out(i) = prod(m.get_row(i));
+    }
+    return out;
+  }
+
+  //! Vector cross product. Vectors need to be of size 3
+  template<class T>
+  Vec<T> cross(const Vec<T> &v1, const Vec<T> &v2)
+  {
+    it_assert((v1.size() == 3) && (v2.size() == 3),
+	      "cross: vectors should be of size 3");
+
+    Vec<T> r(3);
+
+    r(0) = v1(1) * v2(2) - v1(2) * v2(1);
+    r(1) = v1(2) * v2(0) - v1(0) * v2(2);
+    r(2) = v1(0) * v2(1) - v1(1) * v2(0);
+
+    return r;
+  }
+
+
+  //! Zero-pad a vector to size n
+  template<class T>
+  Vec<T> zero_pad(const Vec<T> &v, int n)
+  {
+    it_assert(n >= v.size(), "zero_pad() cannot shrink the vector!");
+    Vec<T> v2(n);
+    v2.set_subvector(0, v.size()-1, v);
+    if (n > v.size())
+      v2.set_subvector(v.size(), n-1, T(0));
+
+    return v2;
+  }
+
+  //! Zero-pad a vector to the nearest greater power of two
+  template<class T>
+  Vec<T> zero_pad(const Vec<T> &v)
+  {
+    int n = pow2i(levels2bits(v.size()));
+
+    return (n == v.size()) ? v : zero_pad(v, n);
+  }
+
+  //! Zero-pad a matrix to size rows x cols
+  template<class T>
+  Mat<T> zero_pad(const Mat<T> &m, int rows, int cols)
+  {
+    it_assert((rows >= m.rows()) && (cols >= m.cols()),
+	      "zero_pad() cannot shrink the matrix!");
+    Mat<T> m2(rows, cols);
+    m2.set_submatrix(0,m.rows()-1,0,m.cols()-1, m);
+    if (cols > m.cols()) // Zero
+      m2.set_submatrix(0,m.rows()-1, m.cols(),cols-1, T(0));
+    if (rows > m.rows()) // Zero
+      m2.set_submatrix(m.rows(), rows-1, 0, cols-1, T(0));
+
+    return m2;
+  }
+
+
+  //! Return zero if indexing outside the vector \c v otherwise return the
+  //! element \c index
+  template<class T>
+  T index_zero_pad(const Vec<T> &v, const int index)
+  {
+    if (index >= 0 && index < v.size())
+      return v(index);
+    else
+      return T(0);
+  }
+
+
+  //! Transposition of the matrix \c m returning the transposed matrix in \c out
+  template<class T>
+  void transpose(const Mat<T> &m, Mat<T> &out) { out = m.T(); }
+
+  //! Transposition of the matrix \c m
+  template<class T>
+  Mat<T> transpose(const Mat<T> &m) { return m.T(); }
+
+
+  //! Hermitian transpose (complex conjugate transpose) of the matrix \c m
+  //! returning the transposed matrix in \c out
+  template<class T>
+  void hermitian_transpose(const Mat<T> &m, Mat<T> &out) { out = m.H(); }
+
+  //! Hermitian transpose (complex conjugate transpose) of the matrix \c m
+  template<class T>
+  Mat<T> hermitian_transpose(const Mat<T> &m) { return m.H(); }
+
+
+
+  /*!
+   * \brief Returns true if matrix \c X is hermitian, false otherwise
+   * \author M. Szalay
+   *
+   * A square matrix \f$\mathbf{X}\f$ is hermitian if
+   * \f[
+   * \mathbf{X} = \mathbf{X}^H
+   * \f]
+   */
+  template<class Num_T>
+  bool is_hermitian(const Mat<Num_T>& X) {
+
+    if (X == X.H() )
+      return true;
+    else
+      return false;
+  }
+
+  /*!
+   * \brief Returns true if matrix \c X is unitary, false otherwise
+   * \author M. Szalay
+   *
+   * A square matrix \f$\mathbf{X}\f$ is unitary if
+   * \f[
+   * \mathbf{X}^H = \mathbf{X}^{-1}
+   * \f]
+   */
+  template<class Num_T>
+  bool is_unitary(const Mat<Num_T>& X) {
+
+    if ( inv(X) == X.H() )
+      return true;
+    else
+      return false;
+  }
+
+
+  /*!
+   * \relates Vec
+   * \brief Creates a vector with \c n copies of the vector \c v
+   * \author Martin Senst
+   *
+   * \param v Vector to be repeated
+   * \param n Number of times to repeat \c v
+   */
+  template<class T>
+  Vec<T> repmat(const Vec<T> &v, int n)
+  {
+    it_assert(n > 0, "repmat(): Wrong repetition parameter");
+    int data_length = v.length();
+    it_assert(data_length > 0, "repmat(): Input vector can not be empty");
+    Vec<T> assembly(data_length * n);
+    for (int j = 0; j < n; ++j) {
+      assembly.set_subvector(j * data_length, v);
+    }
+    return assembly;
+  }
+
+
+  /*!
+   * \relates Mat
+   * \brief Creates a matrix with \c m by \c n copies of the matrix \c data
+   * \author Mark Dobossy
+   *
+   * \param data Matrix to be repeated
+   * \param m Number of times to repeat data vertically
+   * \param n Number of times to repeat data horizontally
+   */
+  template<class T>
+  Mat<T> repmat(const Mat<T> &data, int m, int n)
+  {
+    it_assert((m > 0) && (n > 0), "repmat(): Wrong repetition parameters");
+    int data_rows = data.rows();
+    int data_cols = data.cols();
+    it_assert((data_rows > 0) && (data_cols > 0), "repmat(): Input matrix can "
+	      "not be empty");
+    Mat<T> assembly(data_rows*m, data_cols*n);
+    for (int i = 0; i < m; ++i) {
+      for (int j = 0; j < n; ++j) {
+        assembly.set_submatrix(i*data_rows, j*data_cols, data);
+      }
+    }
+    return assembly;
+  }
+
+  /*!
+   * \relates Mat
+   * \brief Returns a matrix with \c m by \c n copies of the vector \c data
+   * \author Adam Piatyszek
+   *
+   * \param v Vector to be repeated
+   * \param m Number of times to repeat data vertically
+   * \param n Number of times to repeat data horizontally
+   * \param transpose Specifies the input vector orientation (column vector
+   * by default)
+   */
+  template<class T> inline
+  Mat<T> repmat(const Vec<T> &v, int m, int n, bool transpose = false)
+  {
+    return repmat((transpose ? v.T() : Mat<T>(v)), m, n);
+  }
+
+
+  /*!
+   * \brief Computes the Kronecker product of two matrices
+   *
+   * <tt>K = kron(X, Y)</tt> returns the Kronecker tensor product of \c X
+   * and \c Y. The result is a large array formed by taking all possible
+   * products between the elements of \c X and those of \c Y. If \c X is
+   * <tt>(m x n)</tt> and \c Y is <tt>(p x q)</tt>, then <tt>kron(X, Y)</tt>
+   * is <tt>(m*p x n*q)</tt>.
+   *
+   * \author Adam Piatyszek
+   */
+  template<class Num_T>
+  Mat<Num_T> kron(const Mat<Num_T>& X, const Mat<Num_T>& Y)
+  {
+    Mat<Num_T> result(X.rows() * Y.rows(), X.cols() * Y.cols());
+
+    for (int i = 0; i < X.rows(); i++)
+      for (int j = 0; j < X.cols(); j++)
+	result.set_submatrix(i * Y.rows(), j * Y.cols(), X(i, j) * Y);
+
+    return result;
+  }
+
+
+  /*!
+   * \brief Square root of the complex square matrix \c A
+   *
+   * This function computes the matrix square root of the complex square
+   * matrix \c A. The implementation is based on the Matlab/Octave \c
+   * sqrtm() function.
+   *
+   * Ref: N. J. Higham, "Numerical Analysis Report No. 336", Manchester
+   * Centre for Computational Mathematics, Manchester, England, January 1999
+   *
+   * \author Adam Piatyszek
+   */
+  cmat sqrtm(const cmat& A);
+
+  /*!
+   * \brief Square root of the real square matrix \c A
+   *
+   * This function computes the matrix square root of the real square matrix
+   * \c A. Please note that the returned matrix is complex. The
+   * implementation is based on the Matlab/Octave \c sqrtm() function.
+   *
+   * Ref: N. J. Higham, "Numerical Analysis Report No. 336", Manchester
+   * Centre for Computational Mathematics, Manchester, England, January 1999
+   *
+   * \author Adam Piatyszek
+   */
+  cmat sqrtm(const mat& A);
+
+  //!@}
+
+
+
+  // -------------------- Diagonal matrix functions -------------------------
+
+  //! \addtogroup diag
+  //!@{
+
+  /*!
+   * \brief Create a diagonal matrix using vector \c v as its diagonal
+   *
+   * All other matrix elements except the ones on its diagonal are set to
+   * zero. An optional parameter \c K can be used to shift the diagonal in
+   * the resulting matrix. By default \c K is equal to zero.
+   *
+   * The size of the diagonal matrix will be \f$n+|K| \times n+|K|\f$, where
+   * \f$n\f$ is the length of the input vector \c v.
+   */
+  template<class T>
+  Mat<T> diag(const Vec<T> &v, const int K = 0)
+  {
+    Mat<T> m(v.size() + std::abs(K), v.size() + std::abs(K));
+    m = T(0);
+    if (K>0)
+      for (int i=v.size()-1; i>=0; i--)
+	m(i,i+K) = v(i);
+    else
+      for (int i=v.size()-1; i>=0; i--)
+	m(i-K,i) = v(i);
+
+    return m;
+  }
+
+  /*!
+   * \brief Create a diagonal matrix using vector \c v as its diagonal
+   *
+   * All other matrix elements except the ones on its diagonal are set to
+   * zero.
+   *
+   * The size of the diagonal matrix will be \f$n \times n\f$, where \f$n\f$
+   * is the length of the input vector \c v.
+   */
+  template<class T>
+  void diag(const Vec<T> &v, Mat<T> &m)
+  {
+    m.set_size(v.size(), v.size(), false);
+    m = T(0);
+    for (int i=v.size()-1; i>=0; i--)
+      m(i,i) = v(i);
+  }
+
+  /*!
+   * \brief Get the diagonal elements of the input matrix \c m
+   *
+   * The size of the output vector with diagonal elements will be
+   * \f$n = min(r, c)\f$, where \f$r \times c\f$ are the dimensions of
+   * matrix \c m.
+  */
+  template<class T>
+  Vec<T> diag(const Mat<T> &m)
+  {
+    Vec<T> t(std::min(m.rows(), m.cols()));
+
+    for (int i=0; i<t.size(); i++)
+      t(i) = m(i,i);
+
+    return t;
+  }
+
+  /*!
+    \brief Returns a matrix with the elements of the input vector \c main on
+    the diagonal and the elements of the input vector \c sup on the diagonal
+    row above.
+
+    If the number of elements in the vector \c main is \f$n\f$, then the
+    number of elements in the input vector \c sup must be \f$n-1\f$. The
+    size of the return matrix will be \f$n \times n\f$.
+  */
+  template<class T>
+  Mat<T> bidiag(const Vec<T> &main, const Vec<T> &sup)
+  {
+    it_assert(main.size() == sup.size()+1, "bidiag()");
+
+    int n=main.size();
+    Mat<T> m(n, n);
+    m = T(0);
+    for (int i=0; i<n-1; i++) {
+      m(i,i) = main(i);
+      m(i,i+1) = sup(i);
+    }
+    m(n-1,n-1) = main(n-1);
+
+    return m;
+  }
+
+  /*!
+    \brief Returns in the output variable \c m a matrix with the elements of
+    the input vector \c main on the diagonal and the elements of the input
+    vector \c sup on the diagonal row above.
+
+    If the number of elements in the vector \c main is \f$n\f$, then the
+    number of elements in the input vector \c sup must be \f$n-1\f$. The
+    size of the output matrix \c m will be \f$n \times n\f$.
+  */
+  template<class T>
+  void bidiag(const Vec<T> &main, const Vec<T> &sup, Mat<T> &m)
+  {
+    it_assert(main.size() == sup.size()+1, "bidiag()");
+
+    int n=main.size();
+    m.set_size(n, n);
+    m = T(0);
+    for (int i=0; i<n-1; i++) {
+      m(i,i) = main(i);
+      m(i,i+1) = sup(i);
+    }
+    m(n-1,n-1) = main(n-1);
+  }
+
+  /*!
+    \brief Returns the main diagonal and the diagonal row above in the two
+    output vectors \c main and \c sup.
+
+    The input matrix \c in must be a square \f$n \times n\f$ matrix. The
+    length of the output vector \c main will be \f$n\f$ and the length of
+    the output vector \c sup will be \f$n-1\f$.
+  */
+  template<class T>
+  void bidiag(const Mat<T> &m, Vec<T> &main, Vec<T> &sup)
+  {
+    it_assert(m.rows() == m.cols(), "bidiag(): Matrix must be square!");
+
+    int n=m.cols();
+    main.set_size(n);
+    sup.set_size(n-1);
+    for (int i=0; i<n-1; i++) {
+      main(i) = m(i,i);
+      sup(i) = m(i,i+1);
+    }
+    main(n-1) = m(n-1,n-1);
+  }
+
+  /*!
+    \brief Returns a matrix with the elements of \c main on the diagonal,
+    the elements of \c sup on the diagonal row above, and the elements of \c
+    sub on the diagonal row below.
+
+    If the length of the input vector \c main is \f$n\f$ then the lengths of
+    the vectors \c sup and \c sub must equal \f$n-1\f$. The size of the
+    return matrix will be \f$n \times n\f$.
+  */
+  template<class T>
+  Mat<T> tridiag(const Vec<T> &main, const Vec<T> &sup, const Vec<T> &sub)
+  {
+    it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()");
+
+    int n=main.size();
+    Mat<T> m(n, n);
+    m = T(0);
+    for (int i=0; i<n-1; i++) {
+      m(i,i) = main(i);
+      m(i,i+1) = sup(i);
+      m(i+1,i) = sub(i);
+    }
+    m(n-1,n-1) = main(n-1);
+
+    return m;
+  }
+
+  /*!
+    \brief Returns in the output matrix \c m a matrix with the elements of
+    \c main on the diagonal, the elements of \c sup on the diagonal row
+    above, and the elements of \c sub on the diagonal row below.
+
+    If the length of the input vector \c main is \f$n\f$ then the lengths of
+    the vectors \c sup and \c sub must equal \f$n-1\f$. The size of the
+    output matrix \c m will be \f$n \times n\f$.
+  */
+  template<class T>
+  void tridiag(const Vec<T> &main, const Vec<T> &sup, const Vec<T> &sub, Mat<T> &m)
+  {
+    it_assert(main.size()==sup.size()+1 && main.size()==sub.size()+1, "bidiag()");
+
+    int n=main.size();
+    m.set_size(n, n);
+    m = T(0);
+    for (int i=0; i<n-1; i++) {
+      m(i,i) = main(i);
+      m(i,i+1) = sup(i);
+      m(i+1,i) = sub(i);
+    }
+    m(n-1,n-1) = main(n-1);
+  }
+
+  /*!
+    \brief Returns the main diagonal, the diagonal row above, and the
+    diagonal row below int the output vectors \c main, \c sup, and \c sub.
+
+    The input matrix \c m must be a square \f$n \times n\f$ matrix. The
+    length of the output vector \c main will be \f$n\f$ and the length of
+    the output vectors \c sup and \c sup will be \f$n-1\f$.
+  */
+  template<class T>
+  void tridiag(const Mat<T> &m, Vec<T> &main, Vec<T> &sup, Vec<T> &sub)
+  {
+    it_assert(m.rows() == m.cols(), "tridiag(): Matrix must be square!");
+
+    int n=m.cols();
+    main.set_size(n);
+    sup.set_size(n-1);
+    sub.set_size(n-1);
+    for (int i=0; i<n-1; i++) {
+      main(i) = m(i,i);
+      sup(i) = m(i,i+1);
+      sub(i) = m(i+1,i);
+    }
+    main(n-1) = m(n-1,n-1);
+  }
+
+
+  /*!
+    \brief The trace of the matrix \c m, i.e. the sum of the diagonal elements.
+  */
+  template<class T>
+  T trace(const Mat<T> &m)
+  {
+    return sum(diag(m));
+  }
+
+  //!@}
+
+
+  // ----------------- reshaping vectors and matrices ------------------------
+
+  //! \addtogroup reshaping
+  //!@{
+
+  //! Reverse the input vector
+  template<class T>
+  Vec<T> reverse(const Vec<T> &in)
+  {
+    int i, s=in.length();
+
+    Vec<T> out(s);
+    for (i=0;i<s;i++)
+      out[i]=in[s-1-i];
+    return out;
+  }
+
+  //! Row vectorize the matrix [(0,0) (0,1) ... (N-1,N-2) (N-1,N-1)]
+  template<class T>
+  Vec<T> rvectorize(const Mat<T> &m)
+  {
+    int i, j, n=0, r=m.rows(), c=m.cols();
+    Vec<T> v(r * c);
+
+    for (i=0; i<r; i++)
+      for (j=0; j<c; j++)
+	v(n++) = m(i,j);
+
+    return v;
+  }
+
+  //! Column vectorize the matrix [(0,0) (1,0) ... (N-2,N-1) (N-1,N-1)]
+  template<class T>
+  Vec<T> cvectorize(const Mat<T> &m)
+  {
+    int i, j, n=0, r=m.rows(), c=m.cols();
+    Vec<T> v(r * c);
+
+    for (j=0; j<c; j++)
+      for (i=0; i<r; i++)
+	v(n++) = m(i,j);
+
+    return v;
+  }
+
+  /*!
+    \brief Reshape the matrix into an rows*cols matrix
+
+    The data is taken columnwise from the original matrix and written
+    columnwise into the new matrix.
+  */
+  template<class T>
+  Mat<T> reshape(const Mat<T> &m, int rows, int cols)
+  {
+    it_assert_debug(m.rows()*m.cols() == rows*cols, "Mat<T>::reshape: Sizes must match");
+    Mat<T> temp(rows, cols);
+    int i, j, ii=0, jj=0;
+    for (j=0; j<m.cols(); j++) {
+      for (i=0; i<m.rows(); i++) {
+	temp(ii++,jj) = m(i,j);
+	if (ii == rows) {
+	  jj++; ii=0;
+	}
+      }
+    }
+    return temp;
+  }
+
+  /*!
+    \brief Reshape the vector into an rows*cols matrix
+
+    The data is element by element from the vector and written columnwise
+    into the new matrix.
+  */
+  template<class T>
+  Mat<T> reshape(const Vec<T> &v, int rows, int cols)
+  {
+    it_assert_debug(v.size() == rows*cols, "Mat<T>::reshape: Sizes must match");
+    Mat<T> temp(rows, cols);
+    int i, j, ii=0;
+    for (j=0; j<cols; j++) {
+      for (i=0; i<rows; i++) {
+	temp(i,j) = v(ii++);
+      }
+    }
+    return temp;
+  }
+
+  //!@}
+
+
+  //! Returns \a true if all elements are ones and \a false otherwise
+  bool all(const bvec &testvec);
+  //! Returns \a true if any element is one and \a false otherwise
+  bool any(const bvec &testvec);
+
+  //! \cond
+
+  // ----------------------------------------------------------------------
+  // Instantiations
+  // ----------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  extern template int length(const vec &v);
+  extern template int length(const cvec &v);
+  extern template int length(const svec &v);
+  extern template int length(const ivec &v);
+  extern template int length(const bvec &v);
+
+  extern template double sum(const vec &v);
+  extern template std::complex<double> sum(const cvec &v);
+  extern template short sum(const svec &v);
+  extern template int sum(const ivec &v);
+  extern template bin sum(const bvec &v);
+
+  extern template double sum_sqr(const vec &v);
+  extern template std::complex<double> sum_sqr(const cvec &v);
+  extern template short sum_sqr(const svec &v);
+  extern template int sum_sqr(const ivec &v);
+  extern template bin sum_sqr(const bvec &v);
+
+  extern template vec cumsum(const vec &v);
+  extern template cvec cumsum(const cvec &v);
+  extern template svec cumsum(const svec &v);
+  extern template ivec cumsum(const ivec &v);
+  extern template bvec cumsum(const bvec &v);
+
+  extern template double prod(const vec &v);
+  extern template std::complex<double> prod(const cvec &v);
+  extern template short prod(const svec &v);
+  extern template int prod(const ivec &v);
+  extern template bin prod(const bvec &v);
+
+  extern template vec cross(const vec &v1, const vec &v2);
+  extern template cvec cross(const cvec &v1, const cvec &v2);
+  extern template ivec cross(const ivec &v1, const ivec &v2);
+  extern template svec cross(const svec &v1, const svec &v2);
+  extern template bvec cross(const bvec &v1, const bvec &v2);
+
+  extern template vec reverse(const vec &in);
+  extern template cvec reverse(const cvec &in);
+  extern template svec reverse(const svec &in);
+  extern template ivec reverse(const ivec &in);
+  extern template bvec reverse(const bvec &in);
+
+  extern template vec zero_pad(const vec &v, int n);
+  extern template cvec zero_pad(const cvec &v, int n);
+  extern template ivec zero_pad(const ivec &v, int n);
+  extern template svec zero_pad(const svec &v, int n);
+  extern template bvec zero_pad(const bvec &v, int n);
+
+  extern template vec zero_pad(const vec &v);
+  extern template cvec zero_pad(const cvec &v);
+  extern template ivec zero_pad(const ivec &v);
+  extern template svec zero_pad(const svec &v);
+  extern template bvec zero_pad(const bvec &v);
+
+  extern template mat zero_pad(const mat &, int, int);
+  extern template cmat zero_pad(const cmat &, int, int);
+  extern template imat zero_pad(const imat &, int, int);
+  extern template smat zero_pad(const smat &, int, int);
+  extern template bmat zero_pad(const bmat &, int, int);
+
+  extern template vec sum(const mat &m, int dim);
+  extern template cvec sum(const cmat &m, int dim);
+  extern template svec sum(const smat &m, int dim);
+  extern template ivec sum(const imat &m, int dim);
+  extern template bvec sum(const bmat &m, int dim);
+
+  extern template double sumsum(const mat &X);
+  extern template std::complex<double> sumsum(const cmat &X);
+  extern template short sumsum(const smat &X);
+  extern template int sumsum(const imat &X);
+  extern template bin sumsum(const bmat &X);
+
+  extern template vec sum_sqr(const mat & m, int dim);
+  extern template cvec sum_sqr(const cmat &m, int dim);
+  extern template svec sum_sqr(const smat &m, int dim);
+  extern template ivec sum_sqr(const imat &m, int dim);
+  extern template bvec sum_sqr(const bmat &m, int dim);
+
+  extern template mat cumsum(const mat &m, int dim);
+  extern template cmat cumsum(const cmat &m, int dim);
+  extern template smat cumsum(const smat &m, int dim);
+  extern template imat cumsum(const imat &m, int dim);
+  extern template bmat cumsum(const bmat &m, int dim);
+
+  extern template vec prod(const mat &m, int dim);
+  extern template cvec prod(const cmat &v, int dim);
+  extern template svec prod(const smat &m, int dim);
+  extern template ivec prod(const imat &m, int dim);
+  extern template bvec prod(const bmat &m, int dim);
+
+  extern template vec diag(const mat &in);
+  extern template cvec diag(const cmat &in);
+  extern template void diag(const vec &in, mat &m);
+  extern template void diag(const cvec &in, cmat &m);
+  extern template mat diag(const vec &v, const int K);
+  extern template cmat diag(const cvec &v, const int K);
+
+  extern template mat bidiag(const vec &, const vec &);
+  extern template cmat bidiag(const cvec &, const cvec &);
+  extern template void bidiag(const vec &, const vec &, mat &);
+  extern template void bidiag(const cvec &, const cvec &, cmat &);
+  extern template void bidiag(const mat &, vec &, vec &);
+  extern template void bidiag(const cmat &, cvec &, cvec &);
+
+  extern template mat tridiag(const vec &main, const vec &, const vec &);
+  extern template cmat tridiag(const cvec &main, const cvec &, const cvec &);
+  extern template void tridiag(const vec &main, const vec &, const vec &, mat &);
+  extern template void tridiag(const cvec &main, const cvec &, const cvec &, cmat &);
+  extern template void tridiag(const mat &m, vec &, vec &, vec &);
+  extern template void tridiag(const cmat &m, cvec &, cvec &, cvec &);
+
+  extern template double trace(const mat &in);
+  extern template std::complex<double> trace(const cmat &in);
+  extern template short trace(const smat &in);
+  extern template int trace(const imat &in);
+  extern template bin trace(const bmat &in);
+
+  extern template void transpose(const mat &m, mat &out);
+  extern template void transpose(const cmat &m, cmat &out);
+  extern template void transpose(const smat &m, smat &out);
+  extern template void transpose(const imat &m, imat &out);
+  extern template void transpose(const bmat &m, bmat &out);
+
+  extern template mat transpose(const mat &m);
+  extern template cmat transpose(const cmat &m);
+  extern template smat transpose(const smat &m);
+  extern template imat transpose(const imat &m);
+  extern template bmat transpose(const bmat &m);
+
+  extern template void hermitian_transpose(const mat &m, mat &out);
+  extern template void hermitian_transpose(const cmat &m, cmat &out);
+  extern template void hermitian_transpose(const smat &m, smat &out);
+  extern template void hermitian_transpose(const imat &m, imat &out);
+  extern template void hermitian_transpose(const bmat &m, bmat &out);
+
+  extern template mat hermitian_transpose(const mat &m);
+  extern template cmat hermitian_transpose(const cmat &m);
+  extern template smat hermitian_transpose(const smat &m);
+  extern template imat hermitian_transpose(const imat &m);
+  extern template bmat hermitian_transpose(const bmat &m);
+
+  extern template bool is_hermitian(const mat &X);
+  extern template bool is_hermitian(const cmat &X);
+
+  extern template bool is_unitary(const mat &X);
+  extern template bool is_unitary(const cmat &X);
+
+  extern template vec rvectorize(const mat &m);
+  extern template cvec rvectorize(const cmat &m);
+  extern template ivec rvectorize(const imat &m);
+  extern template svec rvectorize(const smat &m);
+  extern template bvec rvectorize(const bmat &m);
+
+  extern template vec cvectorize(const mat &m);
+  extern template cvec cvectorize(const cmat &m);
+  extern template ivec cvectorize(const imat &m);
+  extern template svec cvectorize(const smat &m);
+  extern template bvec cvectorize(const bmat &m);
+
+  extern template mat reshape(const mat &m, int rows, int cols);
+  extern template cmat reshape(const cmat &m, int rows, int cols);
+  extern template imat reshape(const imat &m, int rows, int cols);
+  extern template smat reshape(const smat &m, int rows, int cols);
+  extern template bmat reshape(const bmat &m, int rows, int cols);
+
+  extern template mat reshape(const vec &m, int rows, int cols);
+  extern template cmat reshape(const cvec &m, int rows, int cols);
+  extern template imat reshape(const ivec &m, int rows, int cols);
+  extern template smat reshape(const svec &m, int rows, int cols);
+  extern template bmat reshape(const bvec &m, int rows, int cols);
+
+  extern template mat kron(const mat &X, const mat &Y);
+  extern template cmat kron(const cmat &X, const cmat &Y);
+  extern template imat kron(const imat &X, const imat &Y);
+  extern template smat kron(const smat &X, const smat &Y);
+  extern template bmat kron(const bmat &X, const bmat &Y);
+
+  extern template vec repmat(const vec &v, int n);
+  extern template cvec repmat(const cvec &v, int n);
+  extern template ivec repmat(const ivec &v, int n);
+  extern template svec repmat(const svec &v, int n);
+  extern template bvec repmat(const bvec &v, int n);
+
+  extern template mat repmat(const vec &v, int m, int n, bool transpose);
+  extern template cmat repmat(const cvec &v, int m, int n, bool transpose);
+  extern template imat repmat(const ivec &v, int m, int n, bool transpose);
+  extern template smat repmat(const svec &v, int m, int n, bool transpose);
+  extern template bmat repmat(const bvec &v, int m, int n, bool transpose);
+
+  extern template mat repmat(const mat &data, int m, int n);
+  extern template cmat repmat(const cmat &data, int m, int n);
+  extern template imat repmat(const imat &data, int m, int n);
+  extern template smat repmat(const smat &data, int m, int n);
+  extern template bmat repmat(const bmat &data, int m, int n);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // #ifndef MATFUNC_H
Index: /win32/itpp-4.0.1/itpp/base/circular_buffer.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/circular_buffer.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/circular_buffer.h (revision 35)
@@ -0,0 +1,615 @@
+/*!
+ * \file
+ * \brief Circular_Buffer class (container)
+ * \author Tobias Tynderfeldt
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ *
+ * This file is not separated into .h and .cpp files. The reason is
+ * to avoid problems with template initializations of this class.
+ * A \c Circular_Buffer<type> can contain any type and it is not
+ * possible to initialize and pre-compile all types that might be put
+ * into a \c Circular_Buffer.
+ */
+
+#ifndef CIRCULAR_BUFFER_H
+#define CIRCULAR_BUFFER_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/array.h>
+
+
+namespace itpp {
+
+  /*!
+    \brief General circular buffer class
+
+    This class is a general circular buffer class for arbitrary types.
+
+    For rarely used types you will need to instantiate the class by
+    \code
+    template class Circular_Buffer<type>;
+    \endcode
+
+    The following example shows how to define a Circular_Buffer of doubles:
+    \code
+    vec a = randn(3);
+    vec b = randn(8);
+    vec out_vec;
+    Array <double> out_array;
+
+    Circular_Buffer<double> cb1(10);
+
+    //Put the elements of a to the buffer
+    cb1.put(a);
+
+    //Vector output: Peek at the two oldest elements of the buffer (the two first extracted)
+    cb1.peek(out_vec,2);
+    cout << "peek(out_vec,2) = " << out_vec << ": display 2 first elements of the buffer, without affecting the content"  << endl;
+
+    //Vector output: Peek at all elements of the buffer in reverse order
+    cb1.peek_reverse(out_vec);
+    cout << "peek_reverse(out_vec,-1) = " << out_vec << ": display buffer, without affecting the content"  << endl;
+
+    //Array output: Peek at all elements of the buffer in reverse order
+    cb1.peek_reverse(out_array);
+    cout << "peek_reverse(out_array,-1) = " << out_array << ": display buffer, without affecting the content"  << endl;
+
+    //Put the elements of \c b to the buffer
+    cb1.put(b);
+
+    //Extract the oldest element of the buffer
+    cb1.get(out_vec,1);
+    cout << "get(out_vec,1) = " << out_vec << endl ;
+
+    //Extract all element of the buffer
+    cb1.get(out_vec);
+    cout << "get(out_vec) = " << out_vec << endl ;
+    \endcode
+  */
+  template<class T>
+  class Circular_Buffer {
+  public:
+    //! Default constructor
+    Circular_Buffer();
+
+    //! Create a Circular_Buffer of size \c n
+    Circular_Buffer(int n);
+
+    //! Create a copy of \c s
+    Circular_Buffer(const Circular_Buffer<T> &s);
+
+    //! Default destructor
+    virtual ~Circular_Buffer();
+
+    //! Write the element \a in to the buffer
+    void put(const T& in);
+
+    //! Write the vector of elements \a in to the circular buffer
+    void put(const Vec<T>& in);
+
+    //! Write the vector of elements \a in to the circular buffer
+    void put(const Array<T>& in);
+
+    //! Get the oldest element in the circular buffer
+    void get(T& out);
+
+    //! Get the oldest element in the circular buffer
+    T get();
+
+    //! Get the N oldest element in the circular buffer. \c N=-1 returns all elements in the buffer
+    void get(Vec<T>& out, const int N=-1);
+
+    //! Get the N oldest element in the circular buffer. \c N=-1 returns all elements in the buffer
+    void get(Array<T>& out, const int N=-1);
+
+    //! Peek at the oldest element in the circular buffer, without removing it.
+    void peek(T& out) const;
+
+    //! Peek at the oldest element in the circular buffer, without removing it.
+    T peek() const;
+
+    //! Peek at the element with index \a index in the circular buffer, without removing it.
+    void peek(const int index, T& out) const;
+
+    //! Peek at the N first elements of the circular buffer, without removing them. \c N=-1 peeks all elements in the buffer
+    void peek(Vec<T>& out, const int N=-1) const;
+
+    //! Peek at the elements with index \a index in the circular buffer, without removing them.
+    void peek(const ivec& index, Vec<T>& out) const;
+
+    //! Peek at the N first elements of the circular buffer, without removing them. \c N=-1 peeks all elements in the buffer
+    void peek(Array<T>& out, const int N=-1) const;
+
+    //! Peek at the elements with index \a index in the circular buffer, without removing them.
+    void peek(const ivec& index, Array<T>& out) const;
+
+    //! Peek at the latest element in the circular buffer, without removing it.
+    void peek_reverse(T& out) const;
+
+    //! Peek at the latest element in the circular buffer, without removing it.
+    T peek_reverse() const;
+
+    //! Peek at the N latest elements of the circular buffer in reverse order, without removing them. \c N=-1 returns all elements in the buffer
+    void peek_reverse(Vec<T>& out, const int N=-1) const;
+
+    //! Peek at the N latest elements of the circular buffer in reverse order, without removing them. \c N=-1 returns all elements in the buffer
+    void peek_reverse(Array<T>& out, const int N=-1) const;
+
+    //! Empty the circular buffer
+    void clear();
+
+    //! Assignment operator
+    void operator=(const Circular_Buffer<T> &s);
+
+    //! Returns the maximum number of data elements the circular buffer can store
+    int size() const { return _ndata; }
+
+    //! Returns the number of data elements currently stored in the circular buffer
+    int nrof_elements() const { return _rw_dist; }
+
+    //! Resizing a Circular_Buffer<T>.
+    void set_size(int n, bool copy=false);
+
+  private:
+
+    int _write;
+    int _read;
+    int _ndata;
+    int _rw_dist;
+    T *_data;
+
+    void alloc(int n);
+    void free();
+
+  };
+
+  // --------------------------- Implementation starts here ----------------------------------
+
+  template<class T>
+    Circular_Buffer<T>::Circular_Buffer()
+    {
+      _data    = 0;
+      _ndata   = 0;
+      _rw_dist = 0;
+      _read    = 0;
+      _write   = 0;
+    }
+
+  template<class T>
+    Circular_Buffer<T>::Circular_Buffer(int n)
+    {
+      alloc(n);
+      _read    = 0;
+      _write   = 0;
+      _rw_dist = 0;
+    }
+
+  template<class T>
+    Circular_Buffer<T>::Circular_Buffer(const Circular_Buffer<T> &cb)
+    {
+      _data    = NULL;
+      _ndata   = 0;
+      _read    = cb._read;
+      _write   = cb._write;
+      _rw_dist = cb._rw_dist;
+
+      alloc(cb._ndata);
+      for (int i=0; i<cb._ndata; i++) { _data[i] = cb._data[i]; }
+    }
+
+  template<class T>
+    Circular_Buffer<T>::~Circular_Buffer()
+    {
+      free();
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::get(T& out)
+    {
+      it_assert_debug(_rw_dist>0,"Buffer empty. No data left to read from the buffer.");
+      out=_data[_read];
+      _read++;
+      _rw_dist--;
+
+      if (_read==_ndata) { _read=0; }
+    }
+
+  template <class T>
+    T Circular_Buffer<T>::get()
+    {
+      T out;
+
+      get(out);
+      return out;
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::get(Vec<T>& out, const int N)
+    {
+      int N_out;
+
+      if (N==-1)
+	N_out=_rw_dist;
+      else
+	N_out=N;
+
+      out.set_size(N_out);
+
+      for (int i=0;i<N_out;i++)
+	{
+	  it_assert_debug(_rw_dist>0,"Buffer empty. No data left to read from the buffer.");
+	  out(i)=_data[_read];
+	  _read++;
+	  _rw_dist--;
+
+	  if (_read==_ndata)
+	    _read=0;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::get(Array<T>& out, const int N)
+    {
+      int N_out;
+
+      if (N==-1)
+	N_out=_rw_dist;
+      else
+	N_out=N;
+
+      out.set_size(N_out);
+
+      for (int i=0;i<N_out;i++)
+	{
+	  it_assert_debug(_rw_dist>0,"Buffer empty. No data left to read from the buffer.");
+	  out(i)=_data[_read];
+	  _read++;
+	  _rw_dist--;
+
+	  if (_read==_ndata)
+	    _read=0;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek(T& out) const
+    {
+      it_assert_debug(_rw_dist>0,"Attempted to peek at an empty buffer.");
+      out=_data[_read];
+    }
+
+  template <class T>
+    T Circular_Buffer<T>::peek() const
+    {
+      T out;
+
+      peek(out);
+      return out;
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek(const int index, T& out) const
+    {
+      it_assert_debug(_rw_dist>index && index>=0,"The index exceeds the number of elements stored in the buffer.");
+      out=_data[(_read+index)%_ndata];
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek(Vec<T>& out, const int N) const
+    {
+      int N_out;
+      int read_tmp=_read;
+
+      if (N==-1)
+	N_out=_rw_dist;
+      else
+	N_out=N;
+
+      it_assert_debug(_rw_dist>=N_out,"Attempted to peek at more elements than there are stored in the buffer.");
+      out.set_size(N_out);
+
+      for (int i=0;i<N_out;i++)
+	{
+	  out(i)=_data[read_tmp];
+	  read_tmp++;
+	  if (read_tmp==_ndata)
+	    read_tmp=0;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek(const ivec& index, Vec<T>& out) const
+    {
+      out.set_size(index.size());
+
+      for (int i=0;i<index.size();i++)
+	{
+	  it_assert_debug(_rw_dist>=index(i) && index(i)>=0,"Attempted to peek at an element, whose index exceeds the number of buffered elements.");
+	  out(i)=_data[(_read+index(i))%_ndata];
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek(Array<T>& out, const int N) const
+    {
+      int N_out;
+      int read_tmp=_read;
+
+      if (N==-1)
+	N_out=_rw_dist;
+      else
+	N_out=N;
+
+      it_assert_debug(_rw_dist>=N_out,"Attempted to peek at more elements than there are stored in the buffer.");
+      out.set_size(N_out);
+
+      for (int i=0;i<N_out;i++)
+	{
+	  out(i)=_data[read_tmp];
+	  read_tmp++;
+	  if (read_tmp==_ndata)
+	    read_tmp=0;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek(const ivec& index, Array<T>& out) const
+    {
+      out.set_size(index.size());
+
+      for (int i=0;i<index.size();i++)
+	{
+	  it_assert_debug(_rw_dist>=index(i) && index(i)>=0,"Attempted to peek at an element, whose index exceeds the number of buffered elements.");
+	  out(i)=_data[(_read+index(i))%_ndata];
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek_reverse(T& out) const
+    {
+      int read_tmp;
+
+      it_assert_debug(_rw_dist>0,"Attempted to peek at an empty buffer.");
+
+      if (_write>0)
+	read_tmp=_write-1;
+      else
+	read_tmp=_ndata-1;
+
+      out=_data[read_tmp];
+    }
+
+  template <class T>
+    T Circular_Buffer<T>::peek_reverse() const
+    {
+      T out;
+
+      peek_reverse(out);
+      return out;
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek_reverse(Vec<T>& out, const int N) const
+    {
+      int N_out;
+      int read_tmp;
+
+      if (N==-1)
+	N_out=_rw_dist;
+      else
+	N_out=N;
+
+      it_assert_debug(_rw_dist>=N_out,"Attempted to peek at more elements than there are stored in the buffer.");
+      out.set_size(N_out);
+
+      if (_write>0)
+	read_tmp=_write-1;
+      else
+	read_tmp=_ndata-1;
+
+      for (int i=0;i<N_out;i++)
+	{
+	  out(i)=_data[read_tmp];
+	  read_tmp--;
+	  if (read_tmp<0)
+	    read_tmp=_ndata-1;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::peek_reverse(Array<T>& out, const int N) const
+    {
+      int N_out;
+      int read_tmp;
+
+      if (N==-1)
+	N_out=_rw_dist;
+      else
+	N_out=N;
+
+      it_assert_debug(_rw_dist>=N_out,"Attempted to peek at more elements than there are stored in the buffer.");
+      out.set_size(N_out);
+
+      if (_write>0)
+	read_tmp=_write-1;
+      else
+	read_tmp=_ndata-1;
+
+      for (int i=0;i<N_out;i++)
+	{
+	  out(i)=_data[read_tmp];
+	  read_tmp--;
+	  if (read_tmp<0)
+	    read_tmp=_ndata-1;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::put(const T& in)
+    {
+      //Remove the oldest element of the buffer if the buffer is full
+      if (_rw_dist>=_ndata)
+	{
+	  T dummy;
+	  get(dummy);
+	}
+
+      //Write data to the buffer and move the pointer to the next buffer slot
+      _data[_write]=in;
+      _write++;
+      _rw_dist++;
+
+      //Check if the pointer in the circular buffer should go back to zero
+      if (_write>=_ndata)
+	_write=0;
+
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::put(const Vec<T>& in)
+    {
+      for (int i=0;i<in.size();i++)
+	{
+	  //Remove the oldest element of the buffer if the buffer is full
+	  if (_rw_dist>=_ndata)
+	    {
+	      T dummy;
+	      get(dummy);
+	    }
+
+	  //Write data to the buffer and move the pointer to the next buffer slot
+	  _data[_write]=in(i);
+	  _write++;
+	  _rw_dist++;
+
+	  //Check if the pointer in the circular buffer should go back to zero
+	  if (_write>=_ndata)
+	    _write=0;
+	}
+
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::put(const Array<T>& in)
+    {
+      for (int i=0;i<in.size();i++)
+	{
+	  //Remove the oldest element of the buffer if the buffer is full
+	  if (_rw_dist>=_ndata)
+	    {
+	      T dummy;
+	      get(dummy);
+	    }
+
+	  //Write data to the buffer and move the pointer to the next buffer slot
+	  _data[_write]=in(i);
+	  _write++;
+	  _rw_dist++;
+
+	  //Check if the pointer in the circular buffer should go back to zero
+	  if (_write>=_ndata)
+	    _write=0;
+	}
+    }
+
+  template <class T>
+    void Circular_Buffer<T>::clear()
+    {
+      _write   = 0;
+      _read    = 0;
+      _rw_dist = 0;
+    }
+
+  template<class T>
+    void Circular_Buffer<T>::alloc(int n)
+    {
+      if (n == 0) {
+	_ndata = 0;
+	_data  = NULL;
+      }
+      else if (n>0) {
+	_ndata = n;
+	_data = new T[_ndata];
+	it_assert(_data!=0, "Out of memory in Circular_Buffer::alloc");
+      }
+      else {
+	it_error("Circular_Buffer<T>::alloc(int n): n must be positive");
+      }
+    }
+
+  template<class T>
+    void Circular_Buffer<T>::free()
+    {
+      delete [] _data;
+
+      _data    = NULL;
+      _ndata   = 0;
+      _write   = 0;
+      _read    = 0;
+      _rw_dist = 0;
+    }
+
+  template<class T>
+    void Circular_Buffer<T>::operator=(const Circular_Buffer<T> &s)
+    {
+      set_size(s._ndata);
+      for (int i=0; i<_ndata; i++)
+	_data[i] = s._data[i];
+      _read=s._read;
+      _write=s._write;
+      _rw_dist=_write-_read;
+    }
+
+  template<class T>
+    void Circular_Buffer<T>::set_size(int sz, bool copy)
+    {
+      int i, min_nrof_elem;
+      //T *tmp;
+      Vec<T> tmp;
+
+      if (_ndata == sz)
+	return;
+
+      if (copy)
+	{
+	  peek_reverse(tmp,-1);
+	  min_nrof_elem = _rw_dist < sz ? _rw_dist : sz;
+	  alloc(sz);
+	  clear();
+	  for (i=0; i<min_nrof_elem; i++)
+	    put(tmp(min_nrof_elem-1-i));
+	}
+      else
+	{
+	  free();
+	  alloc(sz);
+	}
+
+      _ndata = sz;
+    }
+
+} // namespace itpp
+
+#endif // #ifndef CIRCULAR_BUFFER_H
Index: /win32/itpp-4.0.1/itpp/base/itassert.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/itassert.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/itassert.h (revision 35)
@@ -0,0 +1,191 @@
+/*!
+ * \file
+ * \brief Error handling functions - header file
+ * \author Tobias Ringstrom and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ITASSERT_H
+#define ITASSERT_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <sstream>
+#include <string>
+
+
+namespace itpp {
+
+  /*!
+    \addtogroup errorhandlingfunc
+
+    For the following macros, the argument \c s is a string that is displayed.
+
+    \code
+    it_assert(t,s);           // Abort if t is not true
+    it_assert_debug(t,s);     // Abort if t is not true and NDEBUG is not defined
+    it_error_if(t,s);         // Abort if t is true
+    it_error(s);              // Abort
+    it_info(s);               // Display a message
+    it_info_debug(s);         // Display a message if NDEBUG is not defined
+    it_info_no_endl(s);       // Display a message without appended "std::endl"
+    it_info_no_endl_debug(s); // Display a message without appended "std::endl" if NDEBUG is not defined
+    it_warning(s);            // Display a warning
+    \endcode
+
+    \c it_assert(), \c it_error(), \c it_error_if(), \c it_info(), \c
+    it_info_no_endl() and \c it_warning() are always active, whereas \c
+    it_assert_debug(), \c it_info_debug() and \c it_info_no_endl_debug()
+    depends on the \c NDEBUG compile time definition. If \c NDEBUG is
+    defined, then none of these macros is executed.
+
+    \note \c it_assert0() and \c it_assert1() macros are still defined for
+    backward compatibility, but \c it_assert_debug() should be used instead
+    of them.
+  */
+  //!@{
+
+  //! Helper function for the \c it_assert and \c it_assert_debug macros
+  void it_assert_f(std::string ass, std::string msg, std::string file, int line);
+  //! Helper function for the \c it_error and \c it_error_if macros
+  void it_error_f(std::string msg, std::string file, int line);
+  //! Helper function for the \c it_info and \c it_info_debug macros
+  void it_info_f(std::string msg);
+  //! Helper function for the \c it_warning macro
+  void it_warning_f(std::string msg, std::string file, int line);
+
+  //! Enable/disable using exceptions for error handling.
+  void it_enable_exceptions(bool on);
+  //! Enable warnings
+  void it_enable_warnings();
+  //! Disable warnings
+  void it_disable_warnings();
+  //! Redirect warnings to the ostream warn_stream
+  void it_redirect_warnings(std::ostream *warn_stream);
+
+  //! Style of assert, error and warning messages.
+  enum error_msg_style { Full, Minimum };
+
+  //! Set preffered style of assert, error and warning messages
+  void it_error_msg_style(error_msg_style style);
+
+
+  //! Abort if \c t is not true
+#define it_assert(t,s)						\
+  if (!(t)) {							\
+    std::ostringstream m_sout;					\
+    m_sout << s;						\
+    itpp::it_assert_f(#t,m_sout.str(),__FILE__,__LINE__);	\
+  } else							\
+    ((void) 0)
+
+#if defined(NDEBUG)
+  //! Abort if \c t is not true and NDEBUG is not defined
+#  define it_assert_debug(t,s) ((void) 0)
+#else
+  //! Abort if \c t is not true and NDEBUG is not defined
+#  define it_assert_debug(t,s) it_assert(t,s)
+#endif // if defined(NDEBUG)
+
+  //! Deprecated macro. Please use \c it_assert_debug() instead.
+#define it_assert0(t,s) it_assert_debug(t,s)
+  //! Deprecated macro. Please use \c it_assert_debug() instead.
+#define it_assert1(t,s) it_assert_debug(t,s)
+
+
+  //! Abort if \c t is true
+#define it_error_if(t,s)				\
+  if((t)) {						\
+    std::ostringstream m_sout;				\
+    m_sout << s;					\
+    itpp::it_error_f(m_sout.str(),__FILE__,__LINE__);	\
+  } else						\
+    ((void) 0)
+
+  //! Abort unconditionally
+#define it_error(s)					\
+  if (true) {						\
+    std::ostringstream m_sout;				\
+    m_sout << s;					\
+    itpp::it_error_f(m_sout.str(),__FILE__,__LINE__);	\
+  } else						\
+    ((void) 0)
+
+
+  //! Print information message
+#define it_info(s)				\
+  if (true) {					\
+    std::ostringstream m_sout;			\
+    m_sout << s << std::endl;			\
+    itpp::it_info_f(m_sout.str());		\
+  } else					\
+    ((void) 0)
+
+  //! Print information message withot \c std::endl at the end
+#define it_info_no_endl(s)			\
+  if (true) {					\
+    std::ostringstream m_sout;			\
+    m_sout << s;				\
+    itpp::it_info_f(m_sout.str());		\
+  } else					\
+    ((void) 0)
+
+#if defined(NDEBUG)
+  //! Print information message if NDEBUG is not defined
+#  define it_info_debug(s) ((void) 0)
+  /*!
+    \brief Print information message withot \c std::endl at the end if
+    NDEBUG is not defined
+  */
+#  define it_info_no_endl_debug(s) ((void) 0)
+#else
+  //! Print information message if NDEBUG is not defined
+#  define it_info_debug(s) it_info(s)
+  /*!
+    \brief Print information message withot \c std::endl at the end if
+    NDEBUG is not defined
+  */
+#  define it_info_no_endl_debug(s) it_info_no_endl(s)
+#endif // if defined(NDEBUG)
+
+
+  //! Display a warning message
+#define it_warning(s)					\
+  if (true) {						\
+    std::ostringstream m_sout;				\
+    m_sout << s;					\
+    itpp::it_warning_f(m_sout.str(),__FILE__,__LINE__); \
+  } else						\
+    ((void) 0)
+
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef ITASSERT_H
Index: /win32/itpp-4.0.1/itpp/base/svec.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/svec.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/svec.h (revision 35)
@@ -0,0 +1,1282 @@
+/*!
+ * \file
+ * \brief Sparse Vector Class definitions
+ * \author Tony Ottosson and Tobias Ringstrom
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef SVEC_H
+#define SVEC_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/vec.h>
+#include <itpp/base/math/min_max.h>
+#include <cstdlib>
+
+
+namespace itpp {
+
+  // Declaration of class Vec
+  template <class T> class Vec;
+  // Declaration of class Sparse_Vec
+  template <class T> class Sparse_Vec;
+
+  // ----------------------- Sparse_Vec Friends -------------------------------
+
+  //! v1+v2 where v1 and v2 are sparse vector
+  template <class T>
+    Sparse_Vec<T> operator+(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+  //! v1*v2 where v1 and v2 are sparse vectors
+  template <class T>
+    T operator*(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+  //! v1*v2 where v1 is a sparse vector and v2 is a dense vector
+  template <class T>
+    T operator*(const Sparse_Vec<T> &v1, const Vec<T> &v2);
+
+  //! v1*v2 where v1 is a dense vector and v2 is a sparse vector
+  template <class T>
+    T operator*(const Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+  //! Elementwise multiplication of two sparse vectors returning a sparse vector
+  template <class T>
+    Sparse_Vec<T> elem_mult(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+  //! Elementwise multiplication of a sparse vector and a dense vector returning a dense vector
+  template <class T>
+    Vec<T> elem_mult(const Sparse_Vec<T> &v1, const Vec<T> &v2);
+
+  //! Elementwise multiplication of a sparse vector and a dense vector returning a sparse vector
+  template <class T>
+    Sparse_Vec<T> elem_mult_s(const Sparse_Vec<T> &v1, const Vec<T> &v2);
+
+  //! Elementwise multiplication of a dense vector and a sparse vector returning a dense vector
+  template <class T>
+    Vec<T> elem_mult(const Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+  //! Elementwise multiplication of a dense vector and a sparse vector returning a sparse vector
+  template <class T>
+    Sparse_Vec<T> elem_mult_s(const Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+  /*!
+    \brief Templated sparse vector class
+    \author Tony Ottosson and Tobias Ringstrom
+
+    A sparse vector is a vector where most elements are zero. The
+    maximum number of none-zero elements is a parameter to the
+    constructor. The elements are stored in random order, i.e. they
+    are not sorted.
+
+  */
+  template <class T>
+    class Sparse_Vec {
+    public:
+
+    //! Default constructor
+    Sparse_Vec();
+
+    /*!
+      \brief Initiate an empty sparse vector
+
+      \param sz Size of the sparse vector (i.e. maximum index is (\c sz - 1))
+      \param data_init Maximum number of non-zero elements in the sparse vector (default value 200)
+    */
+    Sparse_Vec(int sz, int data_init=200);
+
+    /*!
+      \brief Initiate a new sparse vector.
+
+      \param v The elements of \c v are copied into the new sparse vector
+    */
+    Sparse_Vec(const Sparse_Vec<T> &v);
+
+    /*!
+      \brief Initiate a new sparse vector from a dense vector.
+
+      \param v The elements of \c v are copied into the new sparse vector
+    */
+    Sparse_Vec(const Vec<T> &v);
+
+    /*!
+      \brief Initiate a new sparse vector from a dense vector. Elements of \c v larger than \c epsilon are copied into the new sparse vector.
+
+      \note If the type T is complex<double>, then the elements of \c v larger than \c abs(epsilon) are copied into the new sparse vector.
+    */
+    Sparse_Vec(const Vec<T> &v, T epsilon);
+
+    //! Destructor
+    ~Sparse_Vec();
+
+    /*!
+      \brief Set the size \c sz of the sparse vector. Default value \c data_init=-1 \c => allocated size for the data is not changed.
+
+      \param sz Size of the sparse vector (i.e. maximum index is (\c sz - 1))
+      \param data_init Maximum number of non-zero elements in the sparse vector (default value -1 \c => allocated size for the data is not changed)
+    */
+    void set_size(int sz, int data_init=-1);
+
+    //! Returns the size of the sparse vector
+    int size() const { return v_size; }
+
+    //! Number of non-zero elements in the sparse vector
+    inline int nnz()
+      {
+	if (check_small_elems_flag) {
+	  remove_small_elements();
+	}
+	return used_size;
+      }
+
+    //! Returns the density of the sparse vector: (number of non-zero elements)/(size of the vector)
+    double density();
+
+    //! Set that all elements smaller than \a epsilon should be set to zero.
+    void set_small_element(const T& epsilon);
+
+    /*!
+      Removes all elements that are smaller than \a epsilon from the non-zero elements.
+
+      \note The small element \a epsilon can be set by the member function set_small_element. If no small value is set, the default value is always \c epsilon=0.
+    */
+    void remove_small_elements();
+
+    /*!
+      \brief Set the maximum number of non-zero elements to \c new_size
+
+      \param new_size The new maximum number of non-zero elements.
+    */
+    void resize_data(int new_size);
+
+    //! Set the maximum number of non-zero elements equal to the actual number of non-zero elements
+    void compact();
+
+    //! Returns a full, dense vector in \c v
+    void full(Vec<T> &v) const;
+
+    //! Returns a full, dense vector
+    Vec<T> full() const;
+
+    //! Returns the element with index \c i
+    T operator()(int i) const;
+
+    //! Set element \c i equal to \c v
+    void set(int i, T v);
+
+    //! Set the elements of the sparse vector with indices \c index_vec to the values in \c v
+    void set(const ivec &index_vec, const Vec<T> &v);
+
+    //! Set a new element with index \c i equal to \c v
+    void set_new(int i, T v);
+
+    //! Set new elements with indices \c index_vec equal to the values in \c v (no check whether the same index is used several times)
+    void set_new(const ivec &index_vec, const Vec<T> &v);
+
+    //! Add element \c i with \c v
+    void add_elem(const int i, const T v);
+
+    //! Add \c v to the elements specified by \c index_vec with \c v
+    void add(const ivec &index_vec, const Vec<T> &v);
+
+    //! Set the sparse vector to the all zero vector (removes all non-zero elements)
+    void zeros();
+
+    //! Set the i-th element to zero (i.e. clear that element if it contains a non-zero value)
+    void zero_elem(const int i);
+
+    //! Clear all non-zero elements of the sparse vector
+    void clear();
+
+    //! Clear the i-th element (if it contains a non-zero value)
+    void clear_elem(const int i);
+
+    /*!
+      \brief Extract the reference to the p-th non-zero data element
+    */
+    inline void get_nz_data(int p, T& data_out)
+      {
+	if (check_small_elems_flag) {
+	  remove_small_elements();
+	}
+	data_out = data[p];
+      }
+
+    //! Returns the p-th non-zero data element
+    inline T get_nz_data(int p)
+      {
+	if (check_small_elems_flag) {
+	  remove_small_elements();
+	}
+	return data[p];
+      }
+
+    //! Returns the vector index of the p-th non-zero element
+    inline int get_nz_index(int p)
+      {
+	if (check_small_elems_flag) {
+	  remove_small_elements();
+	}
+	return index[p];
+      }
+
+    //! Returns the p-th non-zero value in \c dat and the corresponding vector index in \c idx
+    inline void get_nz(int p, int &idx, T &dat)
+      {
+	if (check_small_elems_flag) {
+	  remove_small_elements();
+	}
+	idx=index[p];
+	dat=data[p];
+      }
+
+    //! Retrun the indices of non-zero values
+    ivec get_nz_indices();
+
+    //! Return sparse subvector from index \c i1 to index \c i2
+    Sparse_Vec<T> get_subvector(int i1, int i2) const;
+
+    //! Returns the sum of all values squared
+    T sqr() const;
+
+    //! Assign sparse vector the value and length of the sparse vector \c v
+    void operator=(const Sparse_Vec<T> &v);
+    //! Assign sparse vector the value and length of the dense vector \c v
+    void operator=(const Vec<T> &v);
+
+   //! Returns the sign inverse of all elements in the sparse vector
+    Sparse_Vec<T> operator-() const;
+
+    //! Compare two sparse vectors. False if wrong sizes or different values
+    bool operator==(const Sparse_Vec<T> &v);
+
+    //! Add sparse vector \c v to all non-zero elements of the sparse vector
+    void operator+=(const Sparse_Vec<T> &v);
+
+    //! Add vector \c v to all non-zero elements of the sparse vector
+    void operator+=(const Vec<T> &v);
+
+    //! Subtract sparse vector \c v from all non-zero elements of the sparse vector
+    void operator-=(const Sparse_Vec<T> &v);
+
+    //! Subtract vector \c v from all non-zero elements of the sparse vector
+    void operator-=(const Vec<T> &v);
+
+    //! Multiply the scalar \c v to all non-zero elements of the sparse vector
+    void operator*=(const T &v);
+
+    //! Divide all non-zero elements of the sparse vector with the scalar \c v
+    void operator/=(const T &v);
+
+   //! Addition v1+v2 where v1 and v2 are sparse vector
+    friend Sparse_Vec<T> operator+<>(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2);
+    //! Scalar product v1*v2 where v1 and v2 are sparse vectors
+    friend T operator*<>(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2);
+    //! Scalar product v1*v2 where v1 is a sparse vector and v2 is a dense vector
+    friend T operator*<>(const Sparse_Vec<T> &v1, const Vec<T> &v2);
+    //! Scalar product v1*v2 where v1 is a dense vector and v2 is a sparse vector
+    friend T operator*<>(const Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+    //! Element wise multiplication of two sparse vectors
+    friend Sparse_Vec<T> elem_mult <>(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+    //! Element wise multiplication of a sparse vector and a dense vector
+    friend Vec<T> elem_mult <>(const Sparse_Vec<T> &v1, const Vec<T> &v2);
+
+    //! Element wise multiplication of a sparse vector and a dense vector returning a sparse vector
+    friend Sparse_Vec<T> elem_mult_s <>(const Sparse_Vec<T> &v1, const Vec<T> &v2);
+
+    //! Element wise multiplication of a a dense vector and a sparse vector
+    friend Vec<T> elem_mult <>(const Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+    //! Element wise multiplication of a a dense vector and a sparse vector returning a sparse vector
+    friend Sparse_Vec<T> elem_mult_s <>(const Vec<T> &v1, const Sparse_Vec<T> &v2);
+
+    private:
+    void init();
+    void alloc();
+    void free();
+
+    int v_size, used_size, data_size;
+    T *data;
+    int *index;
+    T eps;
+    bool check_small_elems_flag;
+  };
+
+
+  /*!
+    \relates Sparse_Vec
+    \brief Type definition of an integer sparse vector
+  */
+  typedef Sparse_Vec<int> sparse_ivec;
+
+  /*!
+    \relates Sparse_Vec
+    \brief Type definition of a double sparse vector
+  */
+  typedef Sparse_Vec<double> sparse_vec;
+
+  /*!
+    \relates Sparse_Vec
+    \brief Type definition of a complex<double> sparse vector
+  */
+  typedef Sparse_Vec<std::complex<double> > sparse_cvec;
+
+  // ----------------------- Implementation starts here --------------------------------
+
+  template <class T>
+    void Sparse_Vec<T>::init()
+    {
+      v_size = 0;
+      used_size = 0;
+      data_size = 0;
+      data = 0;
+      index = 0;
+      eps = 0;
+      check_small_elems_flag = true;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::alloc()
+    {
+      if (data_size != 0) {
+	data = new T[data_size];
+	index = new int[data_size];
+      }
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::free()
+    {
+      delete [] data;
+      data = 0;
+      delete [] index;
+      index = 0;
+    }
+
+  template <class T>
+    Sparse_Vec<T>::Sparse_Vec()
+    {
+      init();
+    }
+
+  template <class T>
+    Sparse_Vec<T>::Sparse_Vec(int sz, int data_init)
+    {
+      init();
+      v_size = sz;
+      used_size = 0;
+      data_size = data_init;
+      alloc();
+    }
+
+  template <class T>
+    Sparse_Vec<T>::Sparse_Vec(const Sparse_Vec<T> &v)
+    {
+      init();
+      v_size = v.v_size;
+      used_size = v.used_size;
+      data_size = v.data_size;
+      eps = v.eps;
+      check_small_elems_flag = v.check_small_elems_flag;
+      alloc();
+
+      for (int i=0; i<used_size; i++) {
+	data[i] = v.data[i];
+	index[i] = v.index[i];
+      }
+    }
+
+  template <class T>
+    Sparse_Vec<T>::Sparse_Vec(const Vec<T> &v)
+    {
+      init();
+      v_size = v.size();
+      used_size = 0;
+      data_size = std::min(v.size(), 10000);
+      alloc();
+
+      for (int i=0; i<v_size; i++) {
+	if (v(i) != T(0)) {
+	  if (used_size == data_size)
+	    resize_data(data_size*2);
+	  data[used_size] = v(i);
+	  index[used_size] = i;
+	  used_size++;
+	}
+      }
+      compact();
+    }
+
+  template <class T>
+    Sparse_Vec<T>::Sparse_Vec(const Vec<T> &v, T epsilon)
+    {
+      init();
+      v_size = v.size();
+      used_size = 0;
+      data_size = std::min(v.size(), 10000);
+      eps = epsilon;
+      alloc();
+
+    double e = std::abs(epsilon);
+    for (int i=0; i<v_size; i++) {
+	if (std::abs(v(i)) > e) {
+	  if (used_size == data_size)
+	    resize_data(data_size*2);
+	  data[used_size] = v(i);
+	  index[used_size] = i;
+	  used_size++;
+	}
+      }
+      compact();
+    }
+
+  template <class T>
+    Sparse_Vec<T>::~Sparse_Vec()
+    {
+      free();
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::set_size(int new_size, int data_init)
+    {
+      v_size = new_size;
+      used_size = 0;
+      if (data_init != -1){
+	free();
+	data_size = data_init;
+	alloc();
+      }
+    }
+
+  template <class T>
+    double Sparse_Vec<T>::density()
+    {
+      if (check_small_elems_flag) {
+	remove_small_elements();
+      }
+      //return static_cast<double>(used_size) / v_size;
+      return double(used_size) / v_size;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::set_small_element(const T& epsilon)
+    {
+      eps=epsilon;
+      remove_small_elements();
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::remove_small_elements()
+    {
+      int i;
+      int nrof_removed_elements = 0;
+      double e;
+
+      //Remove small elements
+      e = std::abs(eps);
+      for (i=0;i<used_size;i++) {
+	if (std::abs(data[i]) <= e) {
+	  nrof_removed_elements++;
+	}
+	else if (nrof_removed_elements > 0) {
+	  data[i-nrof_removed_elements] = data[i];
+	  index[i-nrof_removed_elements] = index[i];
+	}
+      }
+
+      //Set new size after small elements have been removed
+      used_size -= nrof_removed_elements;
+
+      //Set the flag to indicate that all small elements have been removed
+      check_small_elems_flag = false;
+    }
+
+
+  template <class T>
+    void Sparse_Vec<T>::resize_data(int new_size)
+    {
+      it_assert(new_size>=used_size, "Sparse_Vec<T>::resize_data(int new_size): New size is to small");
+
+      if (new_size != data_size) {
+	if (new_size == 0)
+	  free();
+	else {
+	  T *tmp_data = data;
+	  int *tmp_pos = index;
+	  data_size = new_size;
+	  alloc();
+	  for (int p=0; p<used_size; p++) {
+	    data[p] = tmp_data[p];
+	    index[p] = tmp_pos[p];
+	  }
+	  delete [] tmp_data;
+	  delete [] tmp_pos;
+	}
+      }
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::compact()
+    {
+      if (check_small_elems_flag) {
+	remove_small_elements();
+      }
+      resize_data(used_size);
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::full(Vec<T> &v) const
+    {
+      v.set_size(v_size);
+
+      v = T(0);
+      for (int p=0; p<used_size; p++)
+	v(index[p]) = data[p];
+    }
+
+  template <class T>
+    Vec<T> Sparse_Vec<T>::full() const
+    {
+      Vec<T> r(v_size);
+      full(r);
+      return r;
+    }
+
+  // This is slow. Implement a better search
+  template <class T>
+    T Sparse_Vec<T>::operator()(int i) const
+    {
+      it_assert_debug(i >= 0 && i < v_size, "The index of the element is out of range");
+
+      bool found = false;
+      int p;
+      for (p=0; p<used_size; p++) {
+	if (index[p] == i) {
+	  found = true;
+	  break;
+	}
+      }
+      return found ? data[p] : T(0);
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::set(int i, T v)
+    {
+      it_assert_debug(i >= 0 && i < v_size, "The index of the element is out of range");
+
+      bool found = false;
+      bool larger_than_eps;
+      int p;
+
+      for (p=0; p<used_size; p++) {
+	if (index[p] == i) {
+	  found = true;
+	  break;
+	}
+      }
+
+      larger_than_eps = (std::abs(v) > std::abs(eps));
+
+      if (found && larger_than_eps)
+	data[p] = v;
+      else if (larger_than_eps) {
+	if (used_size == data_size)
+	  resize_data(data_size*2+100);
+	data[used_size] = v;
+	index[used_size] = i;
+	used_size++;
+      }
+
+      //Check if the stored element is smaller than eps. In that case it should be removed.
+      if (std::abs(v) <= std::abs(eps)) {
+	remove_small_elements();
+      }
+
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::set_new(int i, T v)
+    {
+      it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector");
+
+      //Check that the new element is larger than eps!
+      if (std::abs(v) > std::abs(eps)) {
+	if (used_size == data_size)
+	  resize_data(data_size*2+100);
+	data[used_size] = v;
+	index[used_size] = i;
+	used_size++;
+      }
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::add_elem(const int i, const T v)
+    {
+      bool found = false;
+      int p;
+
+      it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector");
+
+      for (p=0; p<used_size; p++) {
+	if (index[p] == i) {
+	  found = true;
+	  break;
+	}
+      }
+      if (found)
+	data[p] += v;
+      else {
+	if (used_size == data_size)
+	  resize_data(data_size*2+100);
+	data[used_size] = v;
+	index[used_size] = i;
+	used_size++;
+      }
+
+      check_small_elems_flag = true;
+
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::add(const ivec& index_vec, const Vec<T>& v)
+    {
+      bool found = false;
+      int i,p,q;
+      int nrof_nz=v.size();
+
+      it_assert_debug(v_size>max(index_vec),"The indices exceeds the size of the sparse vector");
+
+      //Elements are added if they have identical indices
+      for (q=0; q<nrof_nz; q++){
+	i=index_vec(q);
+	for (p=0; p<used_size; p++) {
+	  if (index[p] == i) {
+	    found = true;
+	    break;
+	  }
+	}
+	if (found)
+	  data[p] += v(q);
+	else {
+	  if (used_size == data_size)
+	    resize_data(data_size*2+100);
+	  data[used_size] = v(q);
+	  index[used_size] = i;
+	  used_size++;
+	}
+	found = false;
+      }
+
+      check_small_elems_flag = true;
+
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::zeros()
+    {
+      used_size = 0;
+      check_small_elems_flag = false;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::zero_elem(const int i)
+    {
+      bool found = false;
+      int p;
+
+      it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector");
+
+      for (p=0; p<used_size; p++) {
+	if (index[p] == i) {
+	  found = true;
+	  break;
+	}
+      }
+      if (found) {
+	data[p] = data[used_size-1];
+	index[p] = index[used_size-1];
+	used_size--;
+      }
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::clear()
+    {
+      used_size = 0;
+      check_small_elems_flag = false;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::clear_elem(const int i)
+    {
+      bool found = false;
+      int p;
+
+      it_assert_debug(v_size > i, "The index of the element exceeds the size of the sparse vector");
+
+      for (p=0; p<used_size; p++) {
+	if (index[p] == i) {
+	  found = true;
+	  break;
+	}
+      }
+      if (found) {
+	data[p] = data[used_size-1];
+	index[p] = index[used_size-1];
+	used_size--;
+      }
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::set(const ivec& index_vec, const Vec<T>& v)
+    {
+      it_assert_debug(v_size>max(index_vec),"The indices exceeds the size of the sparse vector");
+
+      //Clear all old non-zero elements
+      clear();
+
+      //Add the new non-zero elements
+      add(index_vec,v);
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::set_new(const ivec& index_vec, const Vec<T>& v)
+    {
+      int q;
+      int nrof_nz=v.size();
+
+      it_assert_debug(v_size>max(index_vec),"The indices exceeds the size of the sparse vector");
+
+      //Clear all old non-zero elements
+      clear();
+
+      for (q=0; q<nrof_nz; q++){
+	if (std::abs(v[q]) > std::abs(eps)) {
+	  if (used_size == data_size)
+	    resize_data(data_size*2+100);
+	  data[used_size] = v(q);
+	  index[used_size] = index_vec(q);
+	  used_size++;
+	}
+      }
+    }
+
+  template <class T>
+  ivec Sparse_Vec<T>::get_nz_indices()
+  {
+    int n = nnz();
+    ivec r(n);
+    for (int i = 0; i < n; i++) {
+      r(i) = get_nz_index(i);
+    }
+    return r;
+  }
+
+  template <class T>
+    Sparse_Vec<T> Sparse_Vec<T>::get_subvector(int i1, int i2) const
+    {
+      it_assert_debug(v_size > i1 && v_size > i2 && i1<=i2 && i1>=0, "The index of the element exceeds the size of the sparse vector");
+
+      Sparse_Vec<T> r(i2-i1+1);
+
+      for (int p=0; p<used_size; p++) {
+	if (index[p] >= i1 && index[p] <= i2) {
+	  if (r.used_size == r.data_size)
+	    r.resize_data(r.data_size*2+100);
+	  r.data[r.used_size] = data[p];
+	  r.index[r.used_size] = index[p]-i1;
+	  r.used_size++;
+	}
+      }
+      r.eps = eps;
+      r.check_small_elems_flag = check_small_elems_flag;
+      r.compact();
+
+      return r;
+    }
+
+  template <class T>
+    T Sparse_Vec<T>::sqr() const
+    {
+      T sum(0);
+      for (int p=0; p<used_size; p++)
+	sum += data[p] * data[p];
+
+      return sum;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator=(const Sparse_Vec<T> &v)
+    {
+      free();
+      v_size = v.v_size;
+      used_size = v.used_size;
+      data_size = v.data_size;
+      eps = v.eps;
+      check_small_elems_flag = v.check_small_elems_flag;
+      alloc();
+
+      for (int i=0; i<used_size; i++) {
+	data[i] = v.data[i];
+	index[i] = v.index[i];
+      }
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator=(const Vec<T> &v)
+    {
+      free();
+      v_size = v.size();
+      used_size = 0;
+      data_size = std::min(v.size(), 10000);
+      eps = T(0);
+      check_small_elems_flag = false;
+      alloc();
+
+      for (int i=0; i<v_size; i++) {
+	if (v(i) != T(0)) {
+	  if (used_size == data_size)
+	    resize_data(data_size*2);
+	  data[used_size] = v(i);
+	  index[used_size] = i;
+	  used_size++;
+	}
+      }
+      compact();
+    }
+
+  template <class T>
+    Sparse_Vec<T> Sparse_Vec<T>::operator-() const
+    {
+      Sparse_Vec r(v_size, used_size);
+
+      for (int p=0; p<used_size; p++) {
+	r.data[p] = -data[p];
+	r.index[p] = index[p];
+      }
+      r.used_size = used_size;
+
+      return r;
+    }
+
+  template <class T>
+    bool Sparse_Vec<T>::operator==(const Sparse_Vec<T> &v)
+    {
+      int p,q;
+      bool found=false;
+
+      //Remove small elements before comparing the two sparse_vectors
+      if (check_small_elems_flag)
+	remove_small_elements();
+
+      if (v_size!=v.v_size) {
+	//Return false if vector sizes are unequal
+	return false;
+      } else {
+	for(p=0;p<used_size;p++) {
+	  for(q=0;q<v.used_size;q++) {
+	    if (index[p] == v.index[q]) {
+	      found = true;
+	      break;
+	    }
+	  }
+	  if (found==false)
+	    //Return false if non-zero element not found, or if elements are unequal
+	    return false;
+	  else if (data[p]!=v.data[q])
+	    //Return false if non-zero element not found, or if elements are unequal
+	    return false;
+	  else
+	    //Check next non-zero element
+	    found = false;
+	}
+      }
+
+      /*Special handling if sizes do not match.
+	Required since v may need to do remove_small_elements() for true comparison*/
+      if (used_size!=v.used_size) {
+	if (used_size > v.used_size) {
+	  //Return false if number of non-zero elements is less in v
+	  return false;
+	}
+	else {
+	  //Ensure that the remaining non-zero elements in v are smaller than v.eps
+	  int nrof_small_elems = 0;
+	  for(q=0;q<v.used_size;q++) {
+	    if (std::abs(v.data[q]) <= std::abs(v.eps))
+	      nrof_small_elems++;
+	  }
+	  if (v.used_size-nrof_small_elems != used_size)
+	    //Return false if the number of "true" non-zero elements are unequal
+	    return false;
+	}
+      }
+
+      //All elements checks => return true
+      return true;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator+=(const Sparse_Vec<T> &v)
+    {
+      int i,p;
+      T tmp_data;
+      int nrof_nz_v=v.used_size;
+
+      it_assert_debug(v_size == v.size(), "Attempted addition of unequal sized sparse vectors");
+
+      for (p=0; p<nrof_nz_v; p++) {
+	i = v.index[p];
+	tmp_data = v.data[p];
+	//get_nz(p,i,tmp_data);
+	add_elem(i,tmp_data);
+      }
+
+      check_small_elems_flag = true;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator+=(const Vec<T> &v)
+    {
+      int i;
+
+      it_assert_debug(v_size == v.size(), "Attempted addition of unequal sized sparse vectors");
+
+      for (i=0; i<v.size(); i++)
+	if (v(i)!=T(0))
+	  add_elem(i,v(i));
+
+      check_small_elems_flag = true;
+    }
+
+
+  template <class T>
+    void Sparse_Vec<T>::operator-=(const Sparse_Vec<T> &v)
+    {
+      int i,p;
+      T tmp_data;
+      int nrof_nz_v=v.used_size;
+
+      it_assert_debug(v_size == v.size(), "Attempted subtraction of unequal sized sparse vectors");
+
+      for (p=0; p<nrof_nz_v; p++) {
+	i = v.index[p];
+	tmp_data = v.data[p];
+	//v.get_nz(p,i,tmp_data);
+	add_elem(i,-tmp_data);
+      }
+
+      check_small_elems_flag = true;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator-=(const Vec<T> &v)
+    {
+      int i;
+
+      it_assert_debug(v_size == v.size(), "Attempted subtraction of unequal sized sparse vectors");
+
+      for (i=0; i<v.size(); i++)
+	if (v(i)!=T(0))
+	  add_elem(i,-v(i));
+
+      check_small_elems_flag = true;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator*=(const T &v)
+    {
+      int p;
+
+      for (p=0; p<used_size; p++) {
+	data[p]*=v;}
+
+      check_small_elems_flag = true;
+    }
+
+  template <class T>
+    void Sparse_Vec<T>::operator/=(const T &v)
+    {
+      int p;
+      for (p=0; p<used_size; p++) {
+	data[p]/=v;}
+
+      if (std::abs(eps) > 0) {
+	check_small_elems_flag = true;
+      }
+    }
+
+  template <class T>
+    T operator*(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2)
+    {
+      it_assert_debug(v1.v_size == v2.v_size, "Sparse_Vec<T> * Sparse_Vec<T>");
+
+      T sum(0);
+      Vec<T> v1f(v1.v_size);
+      v1.full(v1f);
+      for (int p=0; p<v2.used_size; p++) {
+	if (v1f[v2.index[p]] != T(0))
+	  sum += v1f[v2.index[p]] * v2.data[p];
+      }
+
+      return sum;
+    }
+
+  template <class T>
+    T operator*(const Sparse_Vec<T> &v1, const Vec<T> &v2)
+    {
+      it_assert_debug(v1.size() == v2.size(), "Multiplication of unequal sized vectors attempted");
+
+      T sum(0);
+      for (int p1=0; p1<v1.used_size; p1++)
+	sum += v1.data[p1] * v2[v1.index[p1]];
+
+      return sum;
+    }
+
+  template <class T>
+    T operator*(const Vec<T> &v1, const Sparse_Vec<T> &v2)
+    {
+      it_assert_debug(v1.size() == v2.size(), "Multiplication of unequal sized vectors attempted");
+
+      T sum(0);
+      for (int p2=0; p2<v2.used_size; p2++)
+	sum += v1[v2.index[p2]] * v2.data[p2];
+
+      return sum;
+    }
+
+  template <class T>
+    Sparse_Vec<T> elem_mult(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2)
+    {
+      it_assert_debug(v1.v_size == v2.v_size, "elem_mult(Sparse_Vec<T>, Sparse_Vec<T>)");
+
+      Sparse_Vec<T> r(v1.v_size);
+      ivec pos(v1.v_size);
+      pos = -1;
+      for (int p1=0; p1<v1.used_size; p1++)
+	pos[v1.index[p1]] = p1;
+      for (int p2=0; p2<v2.used_size; p2++) {
+	if (pos[v2.index[p2]] != -1) {
+	  if (r.used_size == r.data_size)
+	    r.resize_data(r.used_size*2+100);
+	  r.data[r.used_size] = v1.data[pos[v2.index[p2]]] * v2.data[p2];
+	  r.index[r.used_size] = v2.index[p2];
+	  r.used_size++;
+	}
+      }
+      r.compact();
+
+      return r;
+    }
+
+  template <class T>
+    Vec<T> elem_mult(const Sparse_Vec<T> &v1, const Vec<T> &v2)
+    {
+      it_assert_debug(v1.v_size == v2.size(), "elem_mult(Sparse_Vec<T>, Vec<T>)");
+
+      Vec<T> r(v1.v_size);
+      r = T(0);
+      for (int p1=0; p1<v1.used_size; p1++)
+	r[v1.index[p1]] = v1.data[p1] * v2[v1.index[p1]];
+
+      return r;
+    }
+
+  template <class T>
+    Sparse_Vec<T> elem_mult_s(const Sparse_Vec<T> &v1, const Vec<T> &v2)
+    {
+      it_assert_debug(v1.v_size == v2.size(), "elem_mult(Sparse_Vec<T>, Vec<T>)");
+
+      Sparse_Vec<T> r(v1.v_size);
+      for (int p1=0; p1<v1.used_size; p1++) {
+	if (v2[v1.index[p1]] != T(0)) {
+	  if (r.used_size == r.data_size)
+	    r.resize_data(r.used_size*2+100);
+	  r.data[r.used_size] = v1.data[p1] * v2[v1.index[p1]];
+	  r.index[r.used_size] = v1.index[p1];
+	  r.used_size++;
+	}
+      }
+      r.compact();
+
+      return r;
+    }
+
+  template <class T>
+    Vec<T> elem_mult(const Vec<T> &v1, const Sparse_Vec<T> &v2)
+    {
+      it_assert_debug(v1.size() == v2.v_size, "elem_mult(Vec<T>, Sparse_Vec<T>)");
+
+      Vec<T> r(v2.v_size);
+      r = T(0);
+      for (int p2=0; p2<v2.used_size; p2++)
+	r[v2.index[p2]] = v1[v2.index[p2]] * v2.data[p2];
+
+      return r;
+    }
+
+  template <class T>
+    Sparse_Vec<T> elem_mult_s(const Vec<T> &v1, const Sparse_Vec<T> &v2)
+    {
+      it_assert_debug(v1.size() == v2.v_size, "elem_mult(Vec<T>, Sparse_Vec<T>)");
+
+      Sparse_Vec<T> r(v2.v_size);
+      for (int p2=0; p2<v2.used_size; p2++) {
+	if (v1[v2.index[p2]] != T(0)) {
+	  if (r.used_size == r.data_size)
+	    r.resize_data(r.used_size*2+100);
+	  r.data[r.used_size] = v1[v2.index[p2]] * v2.data[p2];
+	  r.index[r.used_size] = v2.index[p2];
+	  r.used_size++;
+	}
+      }
+      r.compact();
+
+      return r;
+    }
+
+  template <class T>
+    Sparse_Vec<T> operator+(const Sparse_Vec<T> &v1, const Sparse_Vec<T> &v2)
+    {
+      it_assert_debug(v1.v_size == v2.v_size, "Sparse_Vec<T> + Sparse_Vec<T>");
+
+      Sparse_Vec<T> r(v1);
+      ivec pos(v1.v_size);
+      pos = -1;
+      for (int p1=0; p1<v1.used_size; p1++)
+	pos[v1.index[p1]] = p1;
+      for (int p2=0; p2<v2.used_size; p2++) {
+	if (pos[v2.index[p2]] == -1) {// A new entry
+	  if (r.used_size == r.data_size)
+	    r.resize_data(r.used_size*2+100);
+	  r.data[r.used_size] = v2.data[p2];
+	  r.index[r.used_size] = v2.index[p2];
+	  r.used_size++;
+	}
+	else
+	  r.data[pos[v2.index[p2]]] += v2.data[p2];
+      }
+      r.check_small_elems_flag = true;  // added dec 7, 2006
+      r.compact();
+
+      return r;
+    }
+
+  //! Convert a dense vector \c v into its sparse representation
+  template <class T>
+    inline Sparse_Vec<T> sparse(const Vec<T> &v)
+    {
+      Sparse_Vec<T> s(v);
+      return s;
+    }
+
+  //! Convert a dense vector \c v into its sparse representation
+  template <class T>
+    inline Sparse_Vec<T> sparse(const Vec<T> &v, T epsilon)
+    {
+      Sparse_Vec<T> s(v, epsilon);
+      return s;
+    }
+
+  //! Convert a sparse vector \c s into its dense representation
+  template <class T>
+    inline Vec<T> full(const Sparse_Vec<T> &s)
+    {
+      Vec<T> v;
+      s.full(v);
+      return v;
+    }
+
+  //! \cond
+
+  // ---------------------------------------------------------------------
+  // Instantiations
+  // ---------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  extern template class Sparse_Vec<int>;
+  extern template class Sparse_Vec<double>;
+  extern template class Sparse_Vec<std::complex<double> >;
+
+  extern template sparse_ivec operator+(const sparse_ivec &,
+                                        const sparse_ivec &);
+  extern template sparse_vec operator+(const sparse_vec &,
+                                       const sparse_vec &);
+  extern template sparse_cvec operator+(const sparse_cvec &,
+                                        const sparse_cvec &);
+
+  extern template int operator*(const sparse_ivec &, const sparse_ivec &);
+  extern template double operator*(const sparse_vec &, const sparse_vec &);
+  extern template std::complex<double> operator*(const sparse_cvec &,
+                                                 const sparse_cvec &);
+
+  extern template int operator*(const sparse_ivec &, const ivec &);
+  extern template double operator*(const sparse_vec &, const vec &);
+  extern template std::complex<double> operator*(const sparse_cvec &,
+                                                 const cvec &);
+
+  extern template int operator*(const ivec &, const sparse_ivec &);
+  extern template double operator*(const vec &, const sparse_vec &);
+  extern template std::complex<double> operator*(const cvec &,
+                                                 const sparse_cvec &);
+
+  extern template sparse_ivec elem_mult(const sparse_ivec &,
+                                        const sparse_ivec &);
+  extern template sparse_vec elem_mult(const sparse_vec &, const sparse_vec &);
+  extern template sparse_cvec elem_mult(const sparse_cvec &,
+                                        const sparse_cvec &);
+
+  extern template ivec elem_mult(const sparse_ivec &, const ivec &);
+  extern template vec elem_mult(const sparse_vec &, const vec &);
+  extern template cvec elem_mult(const sparse_cvec &, const cvec &);
+
+  extern template sparse_ivec elem_mult_s(const sparse_ivec &, const ivec &);
+  extern template sparse_vec elem_mult_s(const sparse_vec &, const vec &);
+  extern template sparse_cvec elem_mult_s(const sparse_cvec &, const cvec &);
+
+  extern template ivec elem_mult(const ivec &, const sparse_ivec &);
+  extern template vec elem_mult(const vec &, const sparse_vec &);
+  extern template cvec elem_mult(const cvec &, const sparse_cvec &);
+
+  extern template sparse_ivec elem_mult_s(const ivec &, const sparse_ivec &);
+  extern template sparse_vec elem_mult_s(const vec &, const sparse_vec &);
+  extern template sparse_cvec elem_mult_s(const cvec &, const sparse_cvec &);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // #ifndef SVEC_H
+
Index: /win32/itpp-4.0.1/itpp/base/ittypes.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/ittypes.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/ittypes.h (revision 35)
@@ -0,0 +1,84 @@
+/*!
+ * \file
+ * \brief IT++ types definitions
+ * \author Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ITTYPES_H
+#define ITTYPES_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#ifndef NO_INT_SIZE_CHECK
+#if (SIZEOF_SHORT != 2) || (SIZEOF_UNSIGNED_SHORT != 2) \
+  || (SIZEOF_INT != 4) || (SIZEOF_UNSIGNED_INT != 4)
+#  error								\
+  This platform uses different sizes for "short" and "int" standard	\
+  types than expected 2 and 4 bytes, respectively. This causes		\
+  incompatibilities of some parts of IT++ with most of 32- and 64-bit	\
+  platforms. Especially binary I/O operations will be incompatible.	\
+  Please report this problem to IT++ developers. If you are OK with it	\
+  you can add "-DNO_INT_SIZE_CHECK" to your CPPFLAGS and recompile the	\
+  library.
+#endif
+#endif // ifndef NO_INT_SIZE_CHECK
+
+#if defined(HAVE_STDINT_H)
+#  include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+#  include <inttypes.h>
+#else
+
+// Common typedefs for most 32- and 64-bit architechures
+typedef signed char             int8_t;	    //!< 8-bit signed integer
+typedef unsigned char           uint8_t;    //!< 8-bit unsigned integer
+typedef signed short            int16_t;    //!< 16-bit signed integer
+typedef unsigned short          uint16_t;   //!< 16-bit unsigned integer
+typedef signed int              int32_t;    //!< 32-bit signed integer
+typedef unsigned int            uint32_t;   //!< 32-bit unsigned integer
+
+#if defined(_MSC_VER)
+typedef __int64                 int64_t;    //!< 64-bit signed integer
+typedef unsigned __int64        uint64_t;   //!< 64-bit unsigned integer
+#elif (SIZEOF_LONG == 8) && (SIZEOF_UNSIGNED_LONG == 8)
+typedef signed long             int64_t;    //!< 64-bit signed integer
+typedef unsigned long           uint64_t;   //!< 64-bit unsigned integer
+#elif (SIZEOF_LONG_LONG == 8) && (SIZEOF_UNSIGNED_LONG_LONG == 8)
+typedef signed long long        int64_t;    //!< 64-bit signed integer
+typedef unsigned long long      uint64_t;   //!< 64-bit unsigned integer
+#else
+#  error						\
+  64-bit integer type not detected on this platform.	\
+  Please report the problem to IT++ developers.
+#endif // defined(_MSC_VER)
+
+#endif // defined(HAVE_STDINT_H)
+
+#endif /* ITTYPES_H */
Index: /win32/itpp-4.0.1/itpp/base/math/error.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/error.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/error.h (revision 35)
@@ -0,0 +1,157 @@
+/*!
+ * \file
+ * \brief Error functions - header file
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ERROR_H
+#define ERROR_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/help_functions.h>
+
+
+//!\addtogroup errorfunc
+//!@{
+
+#ifndef HAVE_ERF
+//! \brief Error function
+double erf(double x);
+#endif
+
+#ifndef HAVE_ERFC
+//! Complementary error function
+double erfc(double x);
+#endif
+
+//!@}
+
+
+namespace itpp {
+
+  //!\addtogroup errorfunc
+  //!@{
+
+  /*!
+   * \brief Error function for complex argument
+   * \author Adam Piatyszek
+   *
+   * This function calculates a well known error function \c erf(z)
+   * for complex \c z. The implementation is based on unofficial
+   * implementation for Octave. Here is a part of the author's note
+   * from original sources:
+   *
+   * Put together by John Smith john at arrows dot demon dot co dot uk,
+   * using ideas by others.
+   *
+   * Calculate \c erf(z) for complex \c z.
+   * Three methods are implemented; which one is used depends on z.
+   *
+   * The code includes some hard coded constants that are intended to
+   * give about 14 decimal places of accuracy. This is appropriate for
+   * 64-bit floating point numbers.
+   */
+  std::complex<double> erf(const std::complex<double>& z);
+
+  //! Inverse of error function
+  double erfinv(double x);
+
+  //! Q-function
+  double Qfunc(double x);
+
+
+  // ----------------------------------------------------------------------
+  // functions for matrices and vectors
+  // ----------------------------------------------------------------------
+
+  //! Error function
+  inline vec erf(const vec &x)
+  {
+    return apply_function<double>(::erf, x);
+  }
+  //! Error function
+  inline mat erf(const mat &x)
+  {
+    return apply_function<double>(::erf, x);
+  }
+  //! Error function
+  inline cvec erf(const cvec &x)
+  {
+    return apply_function<std::complex<double> >(erf, x);
+  }
+  //! Error function
+  inline cmat erf(const cmat &x)
+  {
+    return apply_function<std::complex<double> >(erf, x);
+  }
+
+  //! Inverse of error function
+  inline vec erfinv(const vec &x)
+  {
+    return apply_function<double>(erfinv, x);
+  }
+  //! Inverse of error function
+  inline mat erfinv(const mat &x)
+  {
+    return apply_function<double>(erfinv, x);
+  }
+
+  //! Complementary error function
+  inline vec erfc(const vec &x)
+  {
+    return apply_function<double>(::erfc, x);
+  }
+  //! Complementary error function
+  inline mat erfc(const mat &x)
+  {
+    return apply_function<double>(::erfc, x);
+  }
+
+  //! Q-function
+  inline vec Qfunc(const vec &x)
+  {
+    return apply_function<double>(Qfunc, x);
+  }
+
+  //! Q-function
+  inline mat Qfunc(const mat &x)
+  {
+    return apply_function<double>(Qfunc, x);
+  }
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef ERROR_H
+
+
+
+
Index: /win32/itpp-4.0.1/itpp/base/math/elem_math.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/elem_math.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/elem_math.h (revision 35)
@@ -0,0 +1,279 @@
+/*!
+ * \file
+ * \brief Elementary mathematical functions - header file
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ELEM_MATH_H
+#define ELEM_MATH_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/help_functions.h>
+#include <itpp/base/converters.h>
+#include <cstdlib>
+
+
+//!\addtogroup miscfunc
+//!@{
+
+#ifndef HAVE_TGAMMA
+//! True gamma function
+double tgamma(double x);
+#endif
+
+#if !defined(HAVE_LGAMMA) || (HAVE_DECL_SIGNGAM != 1)
+//! Lograrithm of an absolute gamma function
+double lgamma(double x);
+//! Global variable needed by \c lgamma function
+extern int signgam;
+#endif
+
+#ifndef HAVE_CBRT
+//! Cubic root
+double cbrt(double x);
+#endif
+
+//!@}
+
+namespace itpp {
+
+  //!\addtogroup miscfunc
+  //!@{
+
+  // -------------------- sqr function --------------------
+
+  //! Square of x
+  inline double sqr(double x) { return (x * x); }
+  //! Square of complex-valued x, ||x||^2
+  inline double sqr(const std::complex<double>& x)
+  {
+    return (x.real() * x.real() + x.imag() * x.imag());
+  }
+  //! Square of elements
+  inline vec sqr(const vec &x) { return apply_function<double>(sqr, x); }
+  //! Square of elements
+  inline mat sqr(const mat &x) { return apply_function<double>(sqr, x); }
+  //! Square of elements
+  vec sqr(const cvec &x);
+  //! Square of elements
+  mat sqr(const cmat &x);
+
+
+  // -------------------- abs function --------------------
+
+  //! Absolute value
+  inline vec abs(const vec &x) { return apply_function<double>(std::fabs, x); }
+  //! Absolute value
+  inline mat abs(const mat &x) { return apply_function<double>(std::fabs, x); }
+  //! Absolute value
+  inline ivec abs(const ivec &x) { return apply_function<int>(std::abs, x); }
+  //! Absolute value
+  inline imat abs(const imat &x) { return apply_function<int>(std::abs, x); }
+  //! Absolute value
+  vec abs(const cvec &x);
+  //! Absolute value
+  mat abs(const cmat &x);
+
+
+  // -------------------- sign/sgn functions --------------------
+
+  //! Signum function
+  inline double sign(double x)
+  {
+    return (x == 0.0 ? 0.0 : (x < 0.0 ? -1.0 : 1.0));
+  }
+  //! Signum function
+  inline vec sign(const vec &x) { return apply_function<double>(sign, x); }
+  //! Signum function
+  inline mat sign(const mat &x) { return apply_function<double>(sign, x); }
+
+  //! Signum function
+  inline double sgn(double x) { return sign(x); }
+  //! Signum function
+  inline vec sgn(const vec &x) { return apply_function<double>(sign, x); }
+  //! Signum function
+  inline mat sgn(const mat &x) { return apply_function<double>(sign, x); }
+
+  //! Signum function
+  inline int sign_i(int x)
+  {
+    return (x == 0 ? 0 : (x < 0 ? -1 : 1));
+  }
+  //! Signum function
+  inline ivec sign_i(const ivec &x) { return apply_function<int>(sign_i, x); }
+  //! Signum function
+  inline imat sign_i(const imat &x) { return apply_function<int>(sign_i, x); }
+
+  //! Signum function
+  inline int sgn_i(int x) { return sign_i(x); }
+  //! Signum function
+  inline ivec sgn_i(const ivec &x) { return apply_function<int>(sign_i, x); }
+  //! Signum function
+  inline imat sgn_i(const imat &x) { return apply_function<int>(sign_i, x); }
+
+  //! Signum function
+  inline int sign_i(double x)
+  {
+    return (x == 0.0 ? 0 : (x < 0.0 ? -1 : 1));
+  }
+
+  // -------------------- sqrt function --------------------
+
+  //! Square root of the elements
+  inline vec sqrt(const vec &x) { return apply_function<double>(std::sqrt, x); }
+  //! Square root of the elements
+  inline mat sqrt(const mat &x) { return apply_function<double>(std::sqrt, x); }
+
+
+  // -------------------- gamma function --------------------
+
+  //! Deprecated gamma function - please use tgamma() instead
+  inline double gamma(double x) { return tgamma(x); }
+  //! Deprecated gamma function for vectors. Will be changed to tgamma().
+  inline vec gamma(const vec &x) { return apply_function<double>(tgamma, x); }
+  //! Deprecated gamma function for matrices. Will be changed to tgamma().
+  inline mat gamma(const mat &x) { return apply_function<double>(tgamma, x); }
+
+
+  // -------------------- rem function --------------------
+
+  //! The reminder of the division x/y
+  inline double rem(double x, double y) { return fmod(x, y); }
+  //! Elementwise reminder of the division x/y for vec and double
+  inline vec rem(const vec &x, double y)
+  {
+    return apply_function<double>(rem, x, y);
+  }
+  //! Elementwise reminder of the division x/y for double and vec
+  inline vec rem(double x, const vec &y)
+  {
+    return apply_function<double>(rem, x, y);
+  }
+  //! Elementwise reminder of the division x/y for mat and double
+  inline mat rem(const mat &x, double y)
+  {
+    return apply_function<double>(rem, x, y);
+  }
+  //! Elementwise reminder of the division x/y for double and mat
+  inline mat rem(double x, const mat &y)
+  {
+    return apply_function<double>(rem, x, y);
+  }
+
+  // -------------------- mod function --------------------
+
+  //! Calculates the modulus, i.e. the signed reminder after division
+  inline int mod(int k, int n)
+  {
+    return (n == 0) ? k : (k - n * floor_i(static_cast<double>(k) / n ));
+  }
+
+
+  // -------------------- factorial coefficient function --------------------
+
+  //! Calculates factorial coefficient for index <= 170.
+  double fact(int index);
+
+
+  // -------------------- binomial coefficient function --------------------
+
+  //! Compute the binomial coefficient "n over k".
+  double binom(int n, int k);
+
+  //! Compute the binomial coefficient "n over k".
+  int binom_i(int n, int k);
+
+  //! Compute the base 10 logarithm of the binomial coefficient "n over k".
+  double log_binom(int n, int k);
+
+
+  // -------------------- greatest common divisor function --------------------
+
+  /*!
+   * \brief Compute the greatest common divisor (GCD) \a g of the elements
+   * \a a and \a b.
+   *
+   * \a a and \a b must be non-negative integers. \a gdc(0, 0) is 0 by
+   * convention; all other GCDs are positive integers.
+   */
+  int gcd(int a, int b);
+
+
+  // -------------------- complex related functions --------------------
+
+  //! Real part of complex values
+  vec real(const cvec &x);
+  //! Real part of complex values
+  mat real(const cmat &x);
+  //! Imaginary part of complex values
+  vec imag(const cvec &x);
+  //! Imaginary part of complex values
+  mat imag(const cmat &x);
+
+  //! Argument (angle)
+  vec arg(const cvec &x);
+  //! Argument (angle)
+  mat arg(const cmat &x);
+  //! Angle
+  inline vec angle(const cvec &x) { return arg(x); }
+  //! Angle
+  inline mat angle(const cmat &x) { return arg(x); }
+
+  // Added due to a failure in MSVC++ .NET 2005, which crashes on this
+  // code.
+#ifndef _MSC_VER
+  //! Conjugate of complex value
+  inline cvec conj(const cvec &x)
+  {
+    return apply_function<std::complex<double> >(std::conj, x);
+  }
+  //! Conjugate of complex value
+  inline cmat conj(const cmat &x)
+  {
+    return apply_function<std::complex<double> >(std::conj, x);
+  }
+#else
+  //! Conjugate of complex value
+  cvec conj(const cvec &x);
+
+  //! Conjugate of complex value
+  cmat conj(const cmat &x);
+#endif
+
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef ELEM_MATH_H
+
+
+
+
Index: /win32/itpp-4.0.1/itpp/base/math/misc.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/misc.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/misc.h (revision 35)
@@ -0,0 +1,182 @@
+/*!
+ * \file
+ * \brief Miscellaneous functions - header file
+ * \author Tony Ottosson, Adam Piatyszek and Conrad Sanderson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef MISC_H
+#define MISC_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <complex>
+#include <string>
+#include <limits>
+
+
+namespace std {
+
+  //! \cond
+
+#ifndef HAVE_STD_ISINF
+#if (HAVE_DECL_ISINF == 1) || defined(HAVE_ISINF)
+  inline int isinf(double x) { return ::isinf(x); }
+#elif defined(FPCLASS)
+  inline int isinf(double x)
+  {
+    if (::fpclass(a) == FP_NINF) return -1;
+    else if (::fpclass(a) == FP_PINF) return 1;
+    else return 0;
+  }
+#else
+  inline int isinf(double x)
+  {
+    if ((x == x) && ((x - x) != 0.0)) return (x < 0.0 ? -1 : 1);
+    else return 0;
+  }
+#endif // #if (HAVE_DECL_ISINF == 1) || defined(HAVE_ISINF)
+#  define HAVE_STD_ISINF 1
+#endif // #ifndef HAVE_STD_ISINF
+
+#ifndef HAVE_STD_ISNAN
+#if (HAVE_DECL_ISNAN == 1) || defined(HAVE_ISNAN)
+  inline int isnan(double x) { return ::isnan(x); }
+#else
+  inline int isnan(double x) { return ((x != x) ? 1 : 0); }
+#endif // #if (HAVE_DECL_ISNAN == 1) || defined(HAVE_ISNAN)
+#  define HAVE_STD_ISNAN 1
+#endif // #ifndef HAVE_STD_ISNAN
+
+#ifndef HAVE_STD_ISFINITE
+#if (HAVE_DECL_ISFINITE == 1) || defined(HAVE_ISFINITE)
+  inline int isfinite(double x) { return ::isfinite(x); }
+#elif defined(HAVE_FINITE)
+  inline int isfinite(double x) { return ::finite(x); }
+#else
+  inline int isfinite(double x)
+  {
+    return ((!std::isnan(x) && !std::isinf(x)) ? 1 : 0);
+  }
+#endif // #if (HAVE_DECL_ISFINITE == 1) || defined(HAVE_ISFINITE)
+#  define HAVE_STD_ISFINITE 1
+#endif // #ifndef HAVE_STD_ISFINITE
+
+  //! \endcond
+
+  //! Output stream operator for complex numbers
+  template <class T>
+  std::ostream& operator<<(std::ostream &os, const std::complex<T> &x)
+  {
+    os << x.real();
+    ios::fmtflags saved_format = os.setf(ios::showpos);
+    os << x.imag();
+    os.setf(saved_format, ios::showpos);
+    return os << 'i';
+  }
+
+  //! Input stream operator for complex numbers
+  template <class T>
+  std::istream& operator>>(std::istream &is, std::complex<T> &x)
+  {
+    T re, im;
+    char c;
+    is >> c;
+    if (c == '(') {
+      is >> re >> c;
+      if (c == ',') {
+        is >> im >> c;
+        if (c == ')') {
+          x = complex<T>(re, im);
+        } else {
+          is.setstate(ios_base::failbit);
+        }
+      } else if (c == ')') {
+        x = complex<T>(re, T(0));
+      } else {
+        is.setstate(ios_base::failbit);
+      }
+    } else {
+      is.putback(c);
+      is >> re;
+      if (!is.eof() && ((c = is.peek()) == '+' || c == '-')) {
+        is >> im >> c;
+        if (c == 'i') {
+          x = complex<T>(re, im);
+        } else {
+          is.setstate(ios_base::failbit);
+        }
+      } else {
+        x = complex<T>(re, T(0));
+      }
+    }
+    return is;
+  }
+
+} // namespace std
+
+
+namespace itpp {
+
+  //! Constant Pi
+  const double pi = 3.14159265358979323846;
+
+  //! Constant 2*Pi
+  const double m_2pi = 2 * pi;
+
+  //! Constant eps
+  const double eps = std::numeric_limits<double>::epsilon();
+
+  //! \addtogroup miscfunc
+  //!@{
+
+  //! Return true if x is an integer
+  inline bool is_int(double x)
+  {
+    double dummy;
+    return (modf(x, &dummy) == 0.0);
+  }
+
+  //! Return true if x is an even integer
+  inline bool is_even(int x) { return ((x&1) == 0); }
+
+
+  //! Returns IT++ library version number, e.g. "3.7.1".
+  std::string itpp_version();
+
+
+  //! Returns machine endianness: big-endian = true; little-endian = false
+  bool check_big_endianness();
+
+  //!@}
+
+} //namespace itpp
+
+
+#endif // #ifndef MISC_H
Index: /win32/itpp-4.0.1/itpp/base/math/log_exp.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/log_exp.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/log_exp.h (revision 35)
@@ -0,0 +1,360 @@
+/*!
+ * \file
+ * \brief Logarithmic and exponenential functions - header file
+ * \author Tony Ottosson, Adam Piatyszek and Conrad Sanderson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef LOG_EXP_H
+#define LOG_EXP_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/help_functions.h>
+#include <limits>
+
+
+/*!
+ * \addtogroup logexpfunc
+ * @{
+ */
+
+#ifndef HAVE_LOG1P
+//! Lograrithm of an argument \c x plus one
+inline double log1p(double x) { return std::log(1.0 + x); }
+#endif
+
+#ifndef HAVE_LOG2
+#undef log2                     // This is required at least for Cygwin
+//! Base-2 logarithm
+inline double log2(double x)
+{
+  return (std::log(x) * 1.442695040888963387004650940070860087871551513671875);
+}
+#endif
+
+/*!
+ * @}
+ */
+
+
+namespace itpp {
+
+  //!\addtogroup logexpfunc
+  //!@{
+
+  // ----------------------------------------------------------------------
+  // scalar functions
+  // ----------------------------------------------------------------------
+
+  //! Base-b logarithm
+  inline double logb(double b, double x)
+  {
+    return (std::log(x) / std::log(b));
+  }
+
+  //! Calculate two to the power of x (2^x); x is integer
+  inline int pow2i(int x) { return ((x < 0) ? 0 : (1 << x)); }
+  //! Calculate two to the power of x (2^x)
+  inline double pow2(double x) { return pow(2.0, x); }
+
+  //! Calculate ten to the power of x (10^x)
+  inline double pow10(double x) { return pow(10.0, x); }
+
+  //! Decibel of x (10*log10(x))
+  inline double dB(double x) { return 10.0 * log10(x); }
+  //! Inverse of decibel of x
+  inline double inv_dB(double x) { return pow(10.0, 0.1 * x); }
+
+  //! Calculate the number of bits needed to represent an inteager \c n
+  inline int int2bits(int n)
+  {
+    it_assert(n >= 0, "int2bits(): Improper argument value");
+
+    if (n == 0)
+      return 1;
+
+    int b = 0;
+    while (n) {
+      n >>= 1;
+      ++b;
+    }
+    return b;
+  }
+
+  //! Calculate the number of bits needed to represent \c n different values (levels).
+  inline int levels2bits(int n)
+  {
+    it_assert(n > 0,"levels2bits(): Improper argument value");
+    return int2bits(--n);
+  }
+
+  //! Deprecated function. Please use int2bits() or levels2bits() instead.
+  inline int needed_bits(int n)
+  {
+    it_warning("needed_bits(): This function is depreceted. Depending on your needs, please use int2bits() or levels2bits() instead.");
+    return int2bits(n);
+  }
+
+  //! Constant definition to speed up trunc_log() and trunc_exp()
+  const double log_double_max = std::log(std::numeric_limits<double>::max());
+  //! Constant definition to speed up trunc_log(), trunc_exp() and log_add()
+  const double log_double_min = std::log(std::numeric_limits<double>::min());
+
+  /*!
+    \brief Truncated natural logarithm function
+
+    This truncated function provides a solution in the cases when the
+    logarithm argument is less or equal to zero or infinity. The function
+    checks for such extreme values and use some kind of truncation
+    (saturation) before calculating the logarithm.
+
+    The truncated logarithm function can be used for calculation of
+    log-likelihood in soft demodulators, when numerical instability problem
+    might occur.
+  */
+  inline double trunc_log(double x)
+  {
+    if (std::numeric_limits<double>::is_iec559) {
+      if (x == std::numeric_limits<double>::infinity())
+	return log_double_max;
+      if (x <= 0)
+	return log_double_min;
+    }
+    return std::log(x);
+  }
+
+  /*!
+    \brief Truncated exponential function
+
+    This truncated function provides a solution in the case when the
+    exponent function results in infinity. The function checks for an
+    extreme value and use truncation (saturation) before calculating
+    the result.
+
+    The truncated exponential function can be used  when numerical
+    instability problem occurs for a standard exp function.
+  */
+  inline double trunc_exp(double x)
+  {
+    if (std::numeric_limits<double>::is_iec559
+	&& (x >= log_double_max))
+      return std::numeric_limits<double>::max();
+    return std::exp(x);
+  }
+
+
+  //! Safe substitute for <tt>log(exp(log_a) + exp(log_b))</tt>
+  inline double log_add(double log_a, double log_b)
+  {
+    if (log_a < log_b) {
+      double tmp = log_a;
+      log_a = log_b;
+      log_b = tmp;
+    }
+    double negdelta = log_b - log_a;
+    if (negdelta < log_double_min)
+      return log_a;
+    else
+      return (log_a + log1p(std::exp(negdelta)));
+  }
+
+
+  // ----------------------------------------------------------------------
+  // functions on vectors and matrices
+  // ----------------------------------------------------------------------
+
+  //! Exp of the elements of a vector \c x
+  inline vec exp(const vec &x)
+  {
+    return apply_function<double>(std::exp, x);
+  }
+  //! Exp of the elements of a complex vector \c x
+  inline cvec exp(const cvec &x)
+  {
+    return apply_function<std::complex<double> >(std::exp, x);
+  }
+  //! Exp of the elements of a matrix \c m
+  inline mat exp(const mat &m)
+  {
+    return apply_function<double>(std::exp, m);
+  }
+  //! Exp of the elements of a complex matrix \c m
+  inline cmat exp(const cmat &m)
+  {
+    return apply_function<std::complex<double> >(std::exp, m);
+  }
+
+  //! Calculates x to the power of y (x^y)
+  inline vec pow(const double x, const vec &y)
+  {
+    return apply_function<double>(std::pow, x, y);
+  }
+  //! Calculates x to the power of y (x^y)
+  inline mat pow(const double x, const mat &y)
+  {
+    return apply_function<double>(std::pow, x, y);
+  }
+  //! Calculates x to the power of y (x^y)
+  inline vec pow(const vec &x, const double y)
+  {
+    return apply_function<double>(std::pow, x, y);
+  }
+  //! Calculates x to the power of y (x^y)
+  inline mat pow(const mat &x, const double y)
+  {
+    return apply_function<double>(std::pow, x, y);
+  }
+
+  //! Calculates two to the power of x (2^x)
+  inline vec pow2(const vec &x)
+  {
+    return apply_function<double>(pow2, x);
+  }
+  //! Calculates two to the power of x (2^x)
+  inline mat pow2(const mat &x)
+  {
+    return apply_function<double>(pow2, x);
+  }
+
+  //! Calculates ten to the power of x (10^x)
+  inline vec pow10(const vec &x)
+  {
+    return apply_function<double>(pow10, x);
+  }
+  //! Calculates ten to the power of x (10^x)
+  inline mat pow10(const mat &x)
+  {
+    return apply_function<double>(pow10, x);
+  }
+
+  //! The natural logarithm of the elements
+  inline vec log(const vec &x)
+  {
+    return apply_function<double>(std::log, x);
+  }
+  //! The natural logarithm of the elements
+  inline mat log(const mat &x)
+  {
+    return apply_function<double>(std::log, x);
+  }
+  //! The natural logarithm of the elements
+  inline cvec log(const cvec &x)
+  {
+    return apply_function<std::complex<double> >(std::log, x);
+  }
+  //! The natural logarithm of the elements
+  inline cmat log(const cmat &x)
+  {
+    return apply_function<std::complex<double> >(std::log, x);
+  }
+
+  //! log-2 of the elements
+  inline vec log2(const vec &x)
+  {
+    return apply_function<double>(::log2, x);
+  }
+  //! log-2 of the elements
+  inline mat log2(const mat &x)
+  {
+    return apply_function<double>(::log2, x);
+  }
+
+  //! log-10 of the elements
+  inline vec log10(const vec &x)
+  {
+    return apply_function<double>(std::log10, x);
+  }
+  //! log-10 of the elements
+  inline mat log10(const mat &x)
+  {
+    return apply_function<double>(std::log10, x);
+  }
+
+  //! log-b of \c x
+  inline vec logb(double b, const vec &x)
+  {
+    return apply_function<double>(itpp::logb, b, x);
+  }
+  //! log-b of \c x
+  inline mat logb(double b, const mat &x)
+  {
+    return apply_function<double>(itpp::logb, b, x);
+  }
+
+  //! Calculates 10*log10(x)
+  inline vec dB(const vec &x)
+  {
+    return apply_function<double>(dB, x);
+  }
+  //! Calculates 10*log10(x)
+  inline mat dB(const mat &x)
+  {
+    return apply_function<double>(dB, x);
+  }
+
+  //! Calulates the inverse of dB, 10^(x/10)
+  inline vec inv_dB(const vec &x)
+  {
+    return apply_function<double>(inv_dB, x);
+  }
+  //! Calculates the inverse of dB, 10^(x/10)
+  inline mat inv_dB(const mat &x)
+  {
+    return apply_function<double>(inv_dB, x);
+  }
+
+  //! Deprecated function. Please use int2bits() or levels2bits() instead.
+  inline ivec needed_bits(const ivec& v)
+  {
+    it_warning("needed_bits(): This function is depreceted. Depending on your needs, please use int2bits() or levels2bits() instead.");
+    return apply_function<int>(int2bits, v);
+  }
+
+  //! Calculate the number of bits needed to represent each inteager in a vector
+  inline ivec int2bits(const ivec& v)
+  {
+    return apply_function<int>(int2bits, v);
+  }
+
+  //! Calculate the number of bits needed to represent a numer of levels saved in a vector
+  inline ivec levels2bits(const ivec& v)
+  {
+    return apply_function<int>(levels2bits, v);
+  }
+
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef LOG_EXP_H
+
+
+
+
Index: /win32/itpp-4.0.1/itpp/base/math/integration.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/integration.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/integration.h (revision 35)
@@ -0,0 +1,127 @@
+/*!
+ * \file
+ * \brief Definition of numerical integration
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef INTEGRATION_H
+#define INTEGRATION_H
+
+#include <limits>
+
+
+namespace itpp {
+
+  /*!
+    \addtogroup integration
+    \brief Numerical integration routines
+  */
+
+  //@{
+
+  /*!
+    1-dimensional numerical Simpson quadrature integration
+
+    Calculate the 1-dimensional integral
+    \f[
+    \int_a^b f(x) dx
+    \f]
+
+    Uses an adaptive Simpson quadrature method. See [Gander] for more
+    details. The integrand is specified as a function \code double
+    f(double) \endcode.
+
+    Example:
+    \code
+    #include "itpp/itbase.h"
+
+    double f(const double x)
+    {
+      return x*log(x);
+    }
+
+    int main()
+    {
+      double res = quad( f, 1.5, 3.5);
+      cout << "res = " << res << endl;
+
+      return 0;
+    }
+    \endcode
+
+    References:
+
+    [Gander] Gander, W. and W. Gautschi, "Adaptive Quadrature -
+    Revisited", BIT, Vol. 40, 2000, pp. 84-101.
+		This document is also available at http://www.inf.ethz.ch/personal/gander.
+  */
+  double quad(double (*f)(double), double a, double b,
+	      double tol = std::numeric_limits<double>::epsilon());
+
+  /*!
+    1-dimensional numerical adaptive Lobatto quadrature integration
+
+    Calculate the 1-dimensional integral
+    \f[
+    \int_a^b f(x) dx
+    \f]
+
+    Uses an adaptive Lobatto quadrature method. See [Gander] for more
+    details. The integrand is specified as a function \code double
+    f(double) \endcode.
+
+    Example:
+    \code
+    #include "itpp/itbase.h"
+
+    double f(const double x)
+    {
+      return x*log(x);
+    }
+
+    int main()
+    {
+      double res = quadl( f, 1.5, 3.5);
+      cout << "res = " << res << endl;
+
+      return 0;
+    }
+    \endcode
+
+    References:
+
+    [Gander] Gander, W. and W. Gautschi, "Adaptive Quadrature -
+    Revisited", BIT, Vol. 40, 2000, pp. 84-101.
+  	This document is also available at http:// www.inf.ethz.ch/personal/gander.
+  */
+  double quadl(double (*f)(double), double a, double b,
+	       double tol = std::numeric_limits<double>::epsilon());
+
+  //@}
+
+} // namespace itpp
+
+#endif // #ifndef INTEGRATION_H
Index: /win32/itpp-4.0.1/itpp/base/math/trig_hyp.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/trig_hyp.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/trig_hyp.h (revision 35)
@@ -0,0 +1,149 @@
+/*!
+ * \file
+ * \brief Trigonometric and hyperbolic functions - header file
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef TRIG_HYP_H
+#define TRIG_HYP_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/help_functions.h>
+
+
+//! \addtogroup hypfunc
+//!@{
+
+#ifndef HAVE_ASINH
+//! Arcus sinhyp
+inline double asinh(double x)
+{
+  return ((x >= 0) ? log(x + sqrt(x * x + 1)) : -log( -x + sqrt(x * x + 1)));
+}
+#endif
+
+#ifndef HAVE_ACOSH
+//! Arcus coshyp
+inline double acosh(double x)
+{
+  it_error_if(x < 1, "acosh(): Argument must be greater then 1.");
+  return log(x + sqrt(x * x - 1.0));
+}
+#endif
+
+#ifndef HAVE_ATANH
+//! Arcus tanhyp
+inline double atanh(double x)
+{
+  it_error_if(fabs(x) >= 1,"atanh(): Argument out of range.");
+  return 0.5 * log((x + 1) / (x - 1));
+}
+#endif
+
+//!@}
+
+
+namespace itpp {
+
+  //!\addtogroup trifunc
+  //!@{
+
+  //! Sinc function: sinc(x) = sin(pi*x)/pi*x
+  inline double sinc(double x)
+  {
+    return ((x == 0) ? 1.0 : sin(itpp::pi * x) / itpp::pi / x);
+  }
+
+  //! Sine function
+  inline vec sin(const vec &x) { return apply_function<double>(std::sin, x); }
+  //! Sine function
+  inline mat sin(const mat &x) { return apply_function<double>(std::sin, x); }
+  //! Cosine function
+  inline vec cos(const vec &x) { return apply_function<double>(std::cos, x); }
+  //! Cosine function
+  inline mat cos(const mat &x) { return apply_function<double>(std::cos, x); }
+  //! Tan function
+  inline vec tan(const vec &x) { return apply_function<double>(std::tan, x); }
+  //! Tan function
+  inline mat tan(const mat &x) { return apply_function<double>(std::tan, x); }
+  //! Inverse sine function
+  inline vec asin(const vec &x) { return apply_function<double>(std::asin, x); }
+  //! Inverse sine function
+  inline mat asin(const mat &x) { return apply_function<double>(std::asin, x); }
+  //! Inverse cosine function
+  inline vec acos(const vec &x) { return apply_function<double>(std::acos, x); }
+  //! Inverse cosine function
+  inline mat acos(const mat &x) { return apply_function<double>(std::acos, x); }
+  //! Inverse tan function
+  inline vec atan(const vec &x) { return apply_function<double>(std::atan, x); }
+  //! Inverse tan function
+  inline mat atan(const mat &x) { return apply_function<double>(std::atan, x); }
+  //! Sinc function, sin(pi*x)/(pi*x)
+  inline vec sinc(const vec &x) { return apply_function<double>(sinc, x); }
+  //! Sinc function, sin(pi*x)/(pi*x)
+  inline mat sinc(const mat &x) { return apply_function<double>(sinc, x); }
+
+  //!@}
+
+
+  //!\addtogroup hypfunc
+  //!@{
+
+  //! Sine hyperbolic function
+  inline vec sinh(const vec &x) { return apply_function<double>(std::sinh, x); }
+  //! Sine hyperbolic function
+  inline mat sinh(const mat &x) { return apply_function<double>(std::sinh, x); }
+  //! Cosine hyperbolic function
+  inline vec cosh(const vec &x) { return apply_function<double>(std::cosh, x); }
+  //! Cosine hyperbolic function
+  inline mat cosh(const mat &x) { return apply_function<double>(std::cosh, x); }
+  //! Tan hyperbolic function
+  inline vec tanh(const vec &x) { return apply_function<double>(std::tanh, x); }
+  //! Tan hyperbolic function
+  inline mat tanh(const mat &x) { return apply_function<double>(std::tanh, x); }
+  //! Inverse sine hyperbolic function
+  inline vec asinh(const vec &x) { return apply_function<double>(::asinh, x); }
+  //! Inverse sine hyperbolic function
+  inline mat asinh(const mat &x) { return apply_function<double>(::asinh, x); }
+  //! Inverse cosine hyperbolic function
+  inline vec acosh(const vec &x) { return apply_function<double>(::acosh, x); }
+  //! Inverse cosine hyperbolic function
+  inline mat acosh(const mat &x) { return apply_function<double>(::acosh, x); }
+  //! Inverse tan hyperbolic function
+  inline vec atanh(const vec &x) { return apply_function<double>(::atanh, x); }
+  //! Inverse tan hyperbolic function
+  inline mat atanh(const mat &x) { return apply_function<double>(::atanh, x); }
+
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef TRIG_HYP_H
Index: /win32/itpp-4.0.1/itpp/base/math/min_max.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/math/min_max.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/math/min_max.h (revision 35)
@@ -0,0 +1,265 @@
+/*!
+ * \file
+ * \brief Minimum and maximum functions on vectors and matrices
+ * \author Tony Ottosson, Johan Bergman and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef MIN_MAX_H
+#define MIN_MAX_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+   * \addtogroup miscfunc
+   * @{
+   */
+
+  //! Maximum value of vector
+  template<class T>
+  T max(const Vec<T> &v)
+  {
+    T maxdata = v(0);
+    for (int i = 1; i < v.length(); i++)
+      if (v(i) > maxdata)
+	maxdata = v(i);
+    return maxdata;
+  }
+
+  //! Maximum value of vector, also returns the index position of max value
+  template<class T>
+  T max(const Vec<T> &v, int& index)
+  {
+    T maxdata = v(0);
+    index = 0;
+    for (int i = 1; i < v.length(); i++)
+      if (v(i) > maxdata) {
+	maxdata = v(i);
+	index = i;
+      }
+    return maxdata;
+  }
+
+  /*!
+   * Maximum values over each row/column in the matrix \c m
+   *
+   * <tt>max(m) = max(m, 1)</tt> returns a vector where the elements are
+   * maximum over each column, whereas <tt>max(m, 2)</tt> returns a vector
+   * where the elements are maximum over each row.
+   */
+  template<class T>
+  Vec<T> max(const Mat<T> &m, int dim = 1)
+  {
+    it_assert((dim == 1) || (dim == 2), "max(): dimension need to be 1 or 2");
+    Vec<T> out;
+    if (dim == 1) {
+      out.set_size(m.cols(), false);
+      for (int i = 0; i < m.cols(); i++)
+	out(i) = max(m.get_col(i));
+    }
+    else {
+      out.set_size(m.rows(), false);
+      for (int i = 0; i < m.rows(); i++)
+	out(i) = max(m.get_row(i));
+    }
+    return out;
+  }
+
+  /*!
+   * Maximum values over each row/column in the matrix \c m
+   *
+   * <tt>max(m) = max(m, 1)</tt> returns a vector where the elements are
+   * maximum over each column, whereas <tt>max(m, 2)</tt> returns a vector
+   * where the elements are maximum over each row.
+   *
+   * Also returns a vector of indices with positions of maximum value within
+   * a column/row.
+   */
+  template<class T>
+  Vec<T> max(const Mat<T> &m, ivec &index, int dim = 1)
+  {
+    it_assert((dim == 1) || (dim == 2), "max(): dimension need to be 1 or 2");
+    Vec<T> out;
+    if (dim == 1) {
+      out.set_size(m.cols(), false);
+      index.set_size(m.cols(), false);
+      for (int i = 0; i < m.cols(); i++)
+	out(i) = max(m.get_col(i), index(i));
+    }
+    else {
+      out.set_size(m.rows(), false);
+      index.set_size(m.rows(), false);
+      for (int i = 0; i < m.rows(); i++)
+	out(i) = max(m.get_row(i), index(i));
+    }
+    return out;
+  }
+
+  //! Minimum value of vector
+  template<class T>
+  T min(const Vec<T> &in)
+  {
+    T mindata = in[0];
+    for (int i = 1; i < in.length(); i++)
+      if (in[i] < mindata)
+	mindata = in[i];
+    return mindata;
+  }
+
+  //! Minimum value of vector, also returns the index position of min value
+  template<class T>
+  T min(const Vec<T> &in, int& index)
+  {
+    T mindata = in[0];
+    index = 0;
+    for (int i = 1; i < in.length(); i++)
+      if (in[i] < mindata) {
+	mindata = in[i];
+	index = i;
+      }
+    return mindata;
+  }
+
+
+  /*!
+   * Minimum values over each row/column in the matrix \c m
+   *
+   * <tt>min(m) = min(m, 1)</tt> returns a vector where the elements are
+   * minimum over each column, whereas <tt>min(m, 2)</tt> returns a vector
+   * where the elements are minimum over each row.
+   */
+  template<class T>
+  Vec<T> min(const Mat<T> &m, int dim=1)
+  {
+    it_assert((dim == 1) || (dim == 2), "min(): dimension need to be 1 or 2");
+    Vec<T> out;
+    if (dim == 1) {
+      out.set_size(m.cols(), false);
+      for (int i = 0; i < m.cols(); i++)
+	out(i) = min(m.get_col(i));
+    }
+    else {
+      out.set_size(m.rows(), false);
+      for (int i = 0; i < m.rows(); i++)
+	out(i) = min(m.get_row(i));
+    }
+    return out;
+  }
+
+
+  /*!
+   * Minimum values over each row/column in the matrix \c m
+   *
+   * <tt>min(m) = min(m, 1)</tt> returns a vector where the elements are
+   * minimum over each column, whereas <tt>min(m, 2)</tt> returns a vector
+   * where the elements are minimum over each row.
+   *
+   * Also returns a vector of indices with positions of minimum value within
+   * a column/row.
+   */
+  template<class T>
+  Vec<T> min(const Mat<T> &m,  ivec &index, int dim=1)
+  {
+    it_assert((dim == 1) || (dim == 2), "min(): dimension need to be 1 or 2");
+    Vec<T> out;
+    if (dim == 1) {
+      out.set_size(m.cols(), false);
+      index.set_size(m.cols(), false);
+      for (int i = 0; i < m.cols(); i++)
+	out(i) = min(m.get_col(i), index(i));
+    }
+    else {
+      out.set_size(m.rows(), false);
+      index.set_size(m.rows(), false);
+      for (int i = 0; i < m.rows(); i++)
+	out(i) = min(m.get_row(i), index(i));
+    }
+    return out;
+  }
+
+
+  //! Return the postion of the maximum element in the vector
+  template<class T>
+  int max_index(const Vec<T> &in)
+  {
+    int	maxindex = 0;
+    for (int i = 1; i < in.length(); i++)
+      if (in[i] > in[maxindex])
+	maxindex = i;
+    return maxindex;
+  }
+
+  //! Return the postion of the maximum element in the matrix
+  template<class T>
+  void max_index(const Mat<T> &m, int &row, int &col)
+  {
+    T maxdata = m(0, 0);
+    row = col = 0;
+    for (int i = 0; i < m.rows(); i++)
+      for (int j = 0; j < m.cols(); j++)
+	if (m(i, j) > maxdata) {
+	  row = i;
+	  col = j;
+	  maxdata = m(i, j);
+	}
+  }
+
+  //! Return the postion of the minimum element in the vector
+  template<class T>
+  int min_index(const Vec<T> &in)
+  {
+    int minindex = 0;
+    for (int i = 1; i < in.length(); i++)
+      if (in[i] < in[minindex])
+	minindex = i;
+    return minindex;
+  }
+
+  //! Return the postion of the minimum element in the matrix
+  template<class T>
+  void min_index(const Mat<T> &m, int &row, int &col)
+  {
+    T mindata = m(0, 0);
+    row = col = 0;
+    for (int i = 0; i < m.rows(); i++)
+      for (int j = 0; j < m.cols(); j++)
+	if (m(i, j) < mindata) {
+	  row = i;
+	  col = j;
+	  mindata = m(i, j);
+	}
+  }
+
+  /*!
+   * @}
+   */
+
+} //namespace itpp
+
+
+#endif /* MIN_MAX_H */
Index: /win32/itpp-4.0.1/itpp/base/smat.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/smat.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/smat.h (revision 35)
@@ -0,0 +1,1074 @@
+/*!
+ * \file
+ * \brief Sparse Matrix Class Definitions
+ * \author Tony Ottosson and Tobias Ringstrom
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef SMAT_H
+#define SMAT_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/svec.h>
+
+
+namespace itpp {
+
+  // Declaration of class Vec
+  template <class T> class Vec;
+  // Declaration of class Mat
+  template <class T> class Mat;
+  // Declaration of class Sparse_Vec
+  template <class T> class Sparse_Vec;
+  // Declaration of class Sparse_Mat
+  template <class T> class Sparse_Mat;
+
+  // ------------------------ Sparse_Mat Friends -------------------------------------
+
+  //! m1+m2 where m1 and m2 are sparse matrices
+  template <class T>
+    Sparse_Mat<T> operator+(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+  //! c*m where c is a scalar and m is a sparse matrix
+  template <class T>
+    Sparse_Mat<T> operator*(const T &c, const Sparse_Mat<T> &m);
+
+  //! m1*m2 where m1 and m2 are sparse matrices
+  template <class T>
+    Sparse_Mat<T> operator*(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+  //! m*v where m is a sparse matrix and v is a sparse vector
+  template <class T>
+    Sparse_Vec<T> operator*(const Sparse_Mat<T> &m, const Sparse_Vec<T> &v);
+
+  //! m*v where m is a sparse matrix and v is a full column vector
+  template <class T>
+    Vec<T> operator*(const Sparse_Mat<T> &m, const Vec<T> &v);
+
+  //! v'*m where m is a sparse matrix and v is a full column vector
+  template <class T>
+    Vec<T> operator*(const Vec<T> &v, const Sparse_Mat<T> &m);
+
+  //! m'*m where m is a sparse matrix
+  template <class T>
+    Mat<T> trans_mult(const Sparse_Mat<T> &m);
+
+  //! m'*m where m is a sparse matrix
+  template <class T>
+    Sparse_Mat<T> trans_mult_s(const Sparse_Mat<T> &m);
+
+  //! m1'*m2 where m1 and m2 are sparse matrices
+  template <class T>
+    Sparse_Mat<T> trans_mult(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+  //! m'*v where m is a sparse matrix and v is a full column vector
+  template <class T>
+    Vec<T> trans_mult(const Sparse_Mat<T> &m, const Vec<T> &v);
+
+  //! m1*m2' where m1 and m2 are sparse matrices
+  template <class T>
+    Sparse_Mat<T> mult_trans(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+  /*!
+    \brief Templated Sparse Matrix Class
+    \author Tony Ottosson and Tobias Ringstrom
+
+    A sparse matrix is a matrix where most elements are zero. The
+    maximum number of non-zero elements in each column is a parameter
+    to the constructor.
+
+    The implementation is based on representing all columns as sparse
+    vectors. Thus, column access generally is much faster than row
+    access. The elements in each vector are stored in random order,
+    i.e. they are not sorted.
+  */
+  template <class T>
+    class Sparse_Mat {
+    public:
+
+    //! Default constructor
+    Sparse_Mat();
+
+    /*!
+      \brief Initiate an empty sparse matrix
+
+      A Sparse_Mat consists of colums that have the type Sparse_Vec. The maximum number of non-zero elements is each column
+      is denoted \c row_data_init.
+
+      \param rows Number of rows in the matrix
+      \param cols Number of columns in the matrix
+      \param row_data_init The maximum number of non-zero elements in each column (default value is 200)
+    */
+    Sparse_Mat(int rows, int cols, int row_data_init=200);
+
+    //! Initiate a new sparse matrix. The elements of \c m are copied into the new sparse matrix
+    Sparse_Mat(const Sparse_Mat<T> &m);
+
+    //! Initiate a new sparse matrix from a dense matrix. The elements of \c m are copied into the new sparse matrix
+    Sparse_Mat(const Mat<T> &m);
+
+    /*!
+      \brief Initiate a new sparse matrix from a dense matrix. Elements of \c m larger than \c epsilon are copied into the new sparse matrix.
+
+      \note If the type T is double complex, then the elements of \c m larger than \c abs(epsilon) are copied into the new sparse matrix.
+    */
+    Sparse_Mat(const Mat<T> &m, T epsilon);
+
+    //! Destructor
+    ~Sparse_Mat();
+
+    /*!
+      \brief Set the size of the sparse matrix
+
+      A Sparse_Mat consists of colums that have the type Sparse_Vec. The maximum number of non-zero elements is each column
+      is denoted \c row_data_init, with default value =-1 indicating that the number of data elements is not changed.
+
+      \param rows Number of rows in the matrix
+      \param cols Number of columns in the matrix
+      \param row_data_init The maximum number of non-zero elements in each column (default value -1 \c => allocated size for the data is not changed)
+    */
+    void set_size(int rows, int cols, int row_data_init=-1);
+
+    //! Returns the number of rows of the sparse matrix
+    int rows() const { return n_rows; }
+
+    //! Returns the number of columns of the sparse matrix
+    int cols() const { return n_cols; }
+
+    //! The number of non-zero elements in the sparse matrix
+    int nnz();
+
+    //! Returns the density of the sparse matrix: (number of non-zero elements)/(total number of elements)
+    double density();
+
+    //! Set the maximum number of non-zero elements in each column equal to the actual number of non-zero elements in each column
+    void compact();
+
+    //! Returns a full, dense matrix in \c m
+    void full(Mat<T> &m) const;
+
+    //! Returns a full, dense matrix
+    Mat<T> full() const;
+
+    //! Returns element of row \c r and column \c c
+    T operator()(int r, int c) const;
+
+    //! Set element (\c r, \c c ) equal to \c v
+    void set(int r, int c, T v);
+
+    //! Set a new element with index (\c r, \c c ) equal to \c v
+    void set_new(int r, int c, T v);
+
+    //! Add the element in row \c r and column \c c with \c v
+    void add_elem(const int r, const int c, const T v);
+
+    //! Set the sparse matrix to the all zero matrix (removes all non-zero elements)
+    void zeros();
+
+    //! Set the element in row \c r and column \c c to zero (i.e. clear that element if it contains a non-zero value)
+    void zero_elem(const int r, const int c);
+
+    //! Clear all non-zero elements of the sparse matrix
+    void clear();
+
+    //! Clear the element in row \c r and column \c c (if it contains a non-zero value)
+    void clear_elem(const int r, const int c);
+
+    //! Set submatrix defined by rows r1,r2 and columns c1,c2 to matrix m
+    void set_submatrix(int r1, int r2, int c1, int c2, const Mat<T> &m);
+
+    //! Set submatrix defined by upper-left element (\c r,\c c) and the size of matrix \c m to \c m
+    void set_submatrix(int r, int c, const Mat<T>& m);
+
+    //! Returns the sub-matrix from rows \c r1 to \c r2 and columns \c c1 to \c c2
+    Sparse_Mat<T> get_submatrix(int r1, int r2, int c1, int c2) const;
+
+    //! Returns the sub-matrix from columns \c c1 to \c c2 (all rows)
+    Sparse_Mat<T> get_submatrix_cols(int c1, int c2) const;
+
+    //! Returns column \c c of the Sparse_Mat in the Sparse_Vec \c v
+    void get_col(int c, Sparse_Vec<T> &v) const;
+
+    //! Returns column \c c of the Sparse_Mat
+    Sparse_Vec<T> get_col(int c) const;
+
+    //! Set column \c c of the Sparse_Mat
+    void set_col(int c, const Sparse_Vec<T> &v);
+
+    /*! Transpose the sparse matrix, return the result in \c m
+
+    Note: this function can be slow for large matrices.
+     */
+    void transpose(Sparse_Mat<T> &m) const;
+
+    /*! Returns the transpose of the sparse matrix
+
+    Note: this function can be slow for large matrices.
+    */
+    Sparse_Mat<T> transpose() const;
+
+    /*! Returns the transpose of the sparse matrix
+
+    Note: this function can be slow for large matrices.
+    */
+    // Sparse_Mat<T> T() const { return this->transpose(); };
+
+    //! Assign sparse matrix the value and dimensions of the sparse matrix \c m
+    void operator=(const Sparse_Mat<T> &m);
+
+    //! Assign sparse matrix the value and dimensions of the dense matrix \c m
+    void operator=(const Mat<T> &m);
+
+    //! Returns the sign inverse of all elements in the sparse matrix
+    Sparse_Mat<T> operator-() const;
+
+    //! Compare two sparse matricies. False if wrong sizes or different values
+    bool operator==(const Sparse_Mat<T> &m) const;
+
+    //! Add sparse matrix \c v to all non-zero elements of the sparse matrix
+    void operator+=(const Sparse_Mat<T> &v);
+
+    //! Add matrix \c v to all non-zero elements of the sparse matrix
+    void operator+=(const Mat<T> &v);
+
+    //! Subtract sparse matrix \c v from all non-zero elements of the sparse matrix
+    void operator-=(const Sparse_Mat<T> &v);
+
+    //! Subtract matrix \c v from all non-zero elements of the sparse matrix
+    void operator-=(const Mat<T> &v);
+
+    //! Multiply all non-zero elements of the sparse matrix with the scalar \c v
+    void operator*=(const T &v);
+
+    //! Divide all non-zero elements of the sparse matrix with the scalar \c v
+    void operator/=(const T &v);
+
+    //! Addition m1+m2 where m1 and m2 are sparse matrices
+    friend Sparse_Mat<T> operator+<>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+    //! Multiplication c*m where c is a scalar and m is a sparse matrix
+    friend Sparse_Mat<T> operator*<>(const T &c, const Sparse_Mat<T> &m);
+
+    //! Multiplication m1*m2 where m1 and m2 are sparse matrices
+    friend Sparse_Mat<T> operator*<>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+    //! Multiplication m*v where m is a sparse matrix and v is a sparse vector
+    friend Sparse_Vec<T> operator*<>(const Sparse_Mat<T> &m, const Sparse_Vec<T> &v);
+
+    //! Multiplication m*v where m is a sparse matrix and v is a full column vector
+    friend Vec<T> operator*<>(const Sparse_Mat<T> &m, const Vec<T> &v);
+
+    //! Multiplication v'*m where m is a sparse matrix and v is a full column vector
+    friend Vec<T> operator*<>(const Vec<T> &v, const Sparse_Mat<T> &m);
+
+    //! Multiplication m'*m where m is a sparse matrix. Returns a full, dense matrix
+    friend Mat<T> trans_mult <>(const Sparse_Mat<T> &m);
+
+    //! Multiplication m'*m where m is a sparse matrix, Returns a sparse matrix
+    friend Sparse_Mat<T> trans_mult_s <>(const Sparse_Mat<T> &m);
+
+    //! Multiplication m1'*m2 where m1 and m2 are sparse matrices
+    friend Sparse_Mat<T> trans_mult <>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+    //! Multiplication m'*v where m is a sparse matrix and v is a full column vector
+    friend Vec<T> trans_mult <>(const Sparse_Mat<T> &m, const Vec<T> &v);
+
+    //! Multiplication m1*m2' where m1 and m2 are sparse matrices
+    friend Sparse_Mat<T> mult_trans <>(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2);
+
+    private:
+    void init();
+    void alloc_empty();
+    void alloc(int row_data_size=200);
+    void free();
+
+    int n_rows, n_cols;
+    Sparse_Vec<T> *col;
+  };
+
+  /*!
+    \relates Sparse_Mat
+    \brief Sparse integer matrix
+  */
+  typedef Sparse_Mat<int> sparse_imat;
+
+  /*!
+    \relates Sparse_Mat
+    \brief Sparse double matrix
+  */
+  typedef Sparse_Mat<double> sparse_mat;
+
+  /*!
+    \relates Sparse_Mat
+    \brief Sparse complex<double> matrix
+  */
+  typedef Sparse_Mat<std::complex<double> > sparse_cmat;
+
+  //---------------------- Implementation starts here --------------------------------
+
+  template <class T>
+    void Sparse_Mat<T>::init()
+    {
+      n_rows = 0;
+      n_cols = 0;
+      col = 0;
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::alloc_empty()
+    {
+      if (n_cols == 0)
+	col = 0;
+      else
+	col = new Sparse_Vec<T>[n_cols];
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::alloc(int row_data_init)
+    {
+      if (n_cols == 0)
+	col = 0;
+      else
+	col = new Sparse_Vec<T>[n_cols];
+      for (int c=0; c<n_cols; c++)
+	col[c].set_size(n_rows, row_data_init);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::free()
+    {
+      delete [] col;
+      col = 0;
+    }
+
+  template <class T>
+    Sparse_Mat<T>::Sparse_Mat()
+    {
+      init();
+    }
+
+  template <class T>
+    Sparse_Mat<T>::Sparse_Mat(int rows, int cols, int row_data_init)
+    {
+      init();
+      n_rows = rows;
+      n_cols = cols;
+      alloc(row_data_init);
+    }
+
+  template <class T>
+    Sparse_Mat<T>::Sparse_Mat(const Sparse_Mat<T> &m)
+    {
+      init();
+      n_rows = m.n_rows;
+      n_cols = m.n_cols;
+      alloc_empty();
+
+      for (int c=0; c<n_cols; c++)
+	col[c] = m.col[c];
+    }
+
+  template <class T>
+    Sparse_Mat<T>::Sparse_Mat(const Mat<T> &m)
+    {
+      init();
+      n_rows = m.rows();
+      n_cols = m.cols();
+      alloc();
+
+      for (int c=0; c<n_cols; c++) {
+	for (int r=0; r<n_rows; r++) {
+	  //if (abs(m(r,c)) != T(0))
+	  if (m(r,c) != T(0))
+	    col[c].set_new(r, m(r,c));
+	}
+	col[c].compact();
+      }
+    }
+
+  template <class T>
+    Sparse_Mat<T>::Sparse_Mat(const Mat<T> &m, T epsilon)
+    {
+      init();
+      n_rows = m.rows();
+      n_cols = m.cols();
+      alloc();
+
+      for (int c=0; c<n_cols; c++) {
+	for (int r=0; r<n_rows; r++) {
+		if (std::abs(m(r,c)) > std::abs(epsilon))
+	    col[c].set_new(r, m(r,c));
+	}
+	col[c].compact();
+      }
+    }
+
+  template <class T>
+    Sparse_Mat<T>::~Sparse_Mat()
+    {
+      free();
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::set_size(int rows, int cols, int row_data_init)
+    {
+      n_rows = rows;
+
+      //Allocate new memory for data if the number of columns has changed or if row_data_init != -1
+      if (cols!=n_cols||row_data_init!=-1) {
+	n_cols = cols;
+	free();
+	alloc(row_data_init);
+      }
+    }
+
+  template <class T>
+    int Sparse_Mat<T>::nnz()
+    {
+      int n=0;
+      for (int c=0; c<n_cols; c++)
+	n += col[c].nnz();
+
+      return n;
+    }
+
+  template <class T>
+    double Sparse_Mat<T>::density()
+    {
+      //return static_cast<double>(nnz())/(n_rows*n_cols);
+      return double(nnz())/(n_rows*n_cols);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::compact()
+    {
+      for (int c=0; c<n_cols; c++)
+	col[c].compact();
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::full(Mat<T> &m) const
+    {
+      m.set_size(n_rows, n_cols);
+      m = T(0);
+      for (int c=0; c<n_cols; c++) {
+	for (int p=0; p<col[c].nnz(); p++)
+	  m(col[c].get_nz_index(p),c) = col[c].get_nz_data(p);
+      }
+    }
+
+  template <class T>
+    Mat<T> Sparse_Mat<T>::full() const
+    {
+      Mat<T> r(n_rows, n_cols);
+      full(r);
+      return r;
+    }
+
+  template <class T>
+    T Sparse_Mat<T>::operator()(int r, int c) const
+    {
+      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
+      return col[c](r);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::set(int r, int c, T v)
+    {
+      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
+      col[c].set(r, v);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::set_new(int r, int c, T v)
+    {
+      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
+      col[c].set_new(r, v);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::add_elem(int r, int c, T v)
+    {
+      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
+      col[c].add_elem(r, v);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::zeros()
+    {
+      for (int c=0; c<n_cols; c++)
+	col[c].zeros();
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::zero_elem(const int r, const int c)
+    {
+      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
+      col[c].zero_elem(r);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::clear()
+    {
+      for (int c=0; c<n_cols; c++)
+	col[c].clear();
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::clear_elem(const int r, const int c)
+    {
+      it_assert_debug(r>=0&&r<n_rows&&c>=0&&c<n_cols, "Incorrect input indexes given");
+      col[c].clear_elem(r);
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::set_submatrix(int r1, int r2, int c1, int c2, const Mat<T>& m)
+  {
+    if (r1 == -1) r1 = n_rows-1;
+    if (r2 == -1) r2 = n_rows-1;
+    if (c1 == -1) c1 = n_cols-1;
+    if (c2 == -1) c2 = n_cols-1;
+
+    it_assert_debug(r1>=0 && r2>=0 && r1<n_rows && r2<n_rows &&
+	       c1>=0 && c2>=0 && c1<n_cols && c2<n_cols, "Sparse_Mat<Num_T>::set_submatrix(): index out of range");
+
+    it_assert_debug(r2>=r1 && c2>=c1, "Sparse_Mat<Num_T>::set_submatrix: r2<r1 or c2<c1");
+    it_assert_debug(m.rows() == r2-r1+1 && m.cols() == c2-c1+1, "Mat<Num_T>::set_submatrix(): sizes don't match");
+
+    for (int i=0 ; i<m.rows() ; i++) {
+      for (int j=0 ; j<m.cols() ; j++) {
+        set(r1+i, c1+j, m(i,j));
+      }
+    }
+  }
+
+  template <class T>
+    void Sparse_Mat<T>::set_submatrix(int r, int c, const Mat<T>& m)
+  {
+    it_assert_debug(r>=0 && r+m.rows()<=n_rows &&
+               c>=0 && c+m.cols()<=n_cols, "Sparse_Mat<Num_T>::set_submatrix(): index out of range");
+
+    for (int i=0 ; i<m.rows() ; i++) {
+      for (int j=0 ; j<m.cols() ; j++) {
+        set(r+i, c+j, m(i,j));
+      }
+    }
+  }
+
+  template <class T>
+    Sparse_Mat<T> Sparse_Mat<T>::get_submatrix(int r1, int r2, int c1, int c2) const
+    {
+      it_assert_debug(r1<=r2 && r1>=0 && r1<n_rows && c1<=c2 && c1>=0 && c1<n_cols,
+		"Sparse_Mat<T>::get_submatrix(): illegal input variables");
+
+      Sparse_Mat<T> r(r2-r1+1, c2-c1+1);
+
+      for (int c=c1; c<=c2; c++)
+	r.col[c-c1] = col[c].get_subvector(r1, r2);
+      r.compact();
+
+      return r;
+    }
+
+  template <class T>
+    Sparse_Mat<T> Sparse_Mat<T>::get_submatrix_cols(int c1, int c2) const
+    {
+      it_assert_debug(c1<=c2 && c1>=0 && c1<n_cols, "Sparse_Mat<T>::get_submatrix_cols()");
+      Sparse_Mat<T> r(n_rows, c2-c1+1, 0);
+
+      for (int c=c1; c<=c2; c++)
+	r.col[c-c1] = col[c];
+      r.compact();
+
+      return r;
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::get_col(int c, Sparse_Vec<T> &v) const
+    {
+      it_assert(c>=0 && c<n_cols, "Sparse_Mat<T>::get_col()");
+      v = col[c];
+    }
+
+  template <class T>
+    Sparse_Vec<T> Sparse_Mat<T>::get_col(int c) const
+    {
+      it_assert(c>=0 && c<n_cols, "Sparse_Mat<T>::get_col()");
+      return col[c];
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::set_col(int c, const Sparse_Vec<T> &v)
+    {
+      it_assert(c>=0 && c<n_cols, "Sparse_Mat<T>::set_col()");
+      col[c] = v;
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::transpose(Sparse_Mat<T> &m) const
+  {
+    m.set_size(n_cols, n_rows);
+    for (int c=0; c<n_cols; c++) {
+      for (int p=0; p<col[c].nnz(); p++)
+        m.col[col[c].get_nz_index(p)].set_new(c, col[c].get_nz_data(p));
+    }
+  }
+
+  template <class T>
+    Sparse_Mat<T> Sparse_Mat<T>::transpose() const
+  {
+    Sparse_Mat<T> m;
+    transpose(m);
+    return m;
+  }
+
+  template <class T>
+    void Sparse_Mat<T>::operator=(const Sparse_Mat<T> &m)
+    {
+      free();
+      n_rows = m.n_rows;
+      n_cols = m.n_cols;
+      alloc_empty();
+
+      for (int c=0; c<n_cols; c++)
+	col[c] = m.col[c];
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator=(const Mat<T> &m)
+    {
+      free();
+      n_rows = m.rows();
+      n_cols = m.cols();
+      alloc();
+
+      for (int c=0; c<n_cols; c++) {
+	for (int r=0; r<n_rows; r++) {
+	  if (m(r,c) != T(0))
+	    col[c].set_new(r, m(r,c));
+	}
+	col[c].compact();
+      }
+    }
+
+  template <class T>
+    Sparse_Mat<T> Sparse_Mat<T>::operator-() const
+    {
+      Sparse_Mat r(n_rows, n_cols, 0);
+
+      for (int c=0; c<n_cols; c++) {
+	r.col[c].resize_data(col[c].nnz());
+	for (int p=0; p<col[c].nnz(); p++)
+	  r.col[c].set_new(col[c].get_nz_index(p), -col[c].get_nz_data(p));
+      }
+
+      return r;
+    }
+
+  template <class T>
+    bool Sparse_Mat<T>::operator==(const Sparse_Mat<T> &m) const
+    {
+      if (n_rows!=m.n_rows || n_cols!=m.n_cols)
+	return false;
+      for (int c=0; c<n_cols; c++) {
+	if (!(col[c] == m.col[c]))
+	  return false;
+      }
+      // If they passed all tests, they must be equal
+      return true;
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator+=(const Sparse_Mat<T> &m)
+    {
+      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Addition of unequal sized matrices is not allowed");
+
+      Sparse_Vec<T> v;
+      for (int c=0; c<n_cols; c++) {
+	m.get_col(c,v);
+	col[c]+=v;
+      }
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator+=(const Mat<T> &m)
+    {
+      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Addition of unequal sized matrices is not allowed");
+
+      for (int c=0; c<n_cols; c++)
+	col[c]+=(m.get_col(c));
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator-=(const Sparse_Mat<T> &m)
+    {
+      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Subtraction of unequal sized matrices is not allowed");
+
+      Sparse_Vec<T> v;
+      for (int c=0; c<n_cols; c++) {
+	m.get_col(c,v);
+	col[c]-=v;
+      }
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator-=(const Mat<T> &m)
+    {
+      it_assert_debug(m.rows()==n_rows&&m.cols()==n_cols, "Subtraction of unequal sized matrices is not allowed");
+
+      for (int c=0; c<n_cols; c++)
+	col[c]-=(m.get_col(c));
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator*=(const T &m)
+    {
+      for (int c=0; c<n_cols; c++)
+	col[c]*=m;
+    }
+
+  template <class T>
+    void Sparse_Mat<T>::operator/=(const T &m)
+    {
+      for (int c=0; c<n_cols; c++)
+	col[c]/=m;
+    }
+
+  template <class T>
+    Sparse_Mat<T> operator+(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
+    {
+      it_assert_debug(m1.n_cols == m2.n_cols && m1.n_rows == m2.n_rows , "Sparse_Mat<T> + Sparse_Mat<T>");
+
+      Sparse_Mat<T> m(m1.n_rows, m1.n_cols, 0);
+
+      for (int c=0; c<m.n_cols; c++)
+	m.col[c] = m1.col[c] + m2.col[c];
+
+      return m;
+    }
+
+  // This function added by EGL, May'05
+  template <class T>
+    Sparse_Mat<T> operator*(const T &c, const Sparse_Mat<T> &m)
+    {
+      int i,j;
+      Sparse_Mat<T> ret(m.n_rows,m.n_cols);
+      for (j=0; j<m.n_cols; j++) {
+	for (i=0; i<m.col[j].nnz(); i++) {
+	  T x = c*m.col[j].get_nz_data(i);
+	  int k = m.col[j].get_nz_index(i);
+	  ret.set_new(k,j,x);
+	}
+      }
+      return ret;
+    }
+
+  template <class T>
+    Sparse_Mat<T> operator*(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
+    {
+      it_assert_debug(m1.n_cols == m2.n_rows, "Sparse_Mat<T> * Sparse_Mat<T>");
+
+      Sparse_Mat<T> ret(m1.n_rows, m2.n_cols);
+
+      for (int c=0; c<m2.n_cols; c++) {
+	Sparse_Vec<T> &m2colc=m2.col[c];
+	for (int p2=0; p2<m2colc.nnz(); p2++) {
+	  Sparse_Vec<T> &mcol = m1.col[m2colc.get_nz_index(p2)];
+	  T x = m2colc.get_nz_data(p2);
+	  for (int p1=0; p1<mcol.nnz(); p1++) {
+	    int r = mcol.get_nz_index(p1);
+	    T inc = mcol.get_nz_data(p1) *x;
+	    ret.col[c].add_elem(r,inc);
+	  }
+	}
+      }
+      // old code
+/*       for (int c=0; c<m2.n_cols; c++) { */
+/* 	for (int p2=0; p2<m2.col[c].nnz(); p2++) { */
+/* 	  Sparse_Vec<T> &mcol = m1.col[m2.col[c].get_nz_index(p2)]; */
+/* 	  for (int p1=0; p1<mcol.nnz(); p1++) { */
+/* 	    int r = mcol.get_nz_index(p1); */
+/* 	    T inc = mcol.get_nz_data(p1) * m2.col[c].get_nz_data(p2); */
+/* 	    ret.col[c].add_elem(r,inc); */
+/* 	  } */
+/* 	} */
+/*       } */
+      ret.compact();
+      return ret;
+    }
+
+
+  // This is apparently buggy.
+/*   template <class T> */
+/*     Sparse_Mat<T> operator*(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2) */
+/*     { */
+/*       it_assert_debug(m1.n_cols == m2.n_rows, "Sparse_Mat<T> * Sparse_Mat<T>"); */
+
+/*       Sparse_Mat<T> ret(m1.n_rows, m2.n_cols); */
+/*       ivec occupied_by(ret.n_rows), pos(ret.n_rows); */
+/*       for (int rp=0; rp<m1.n_rows; rp++) */
+/* 	occupied_by[rp] = -1; */
+/*       for (int c=0; c<ret.n_cols; c++) { */
+/* 	Sparse_Vec<T> &m2col = m2.col[c]; */
+/* 	for (int p2=0; p2<m2col.nnz(); p2++) { */
+/* 	  Sparse_Vec<T> &m1col = m1.col[m2col.get_nz_index(p2)]; */
+/* 	  for (int p1=0; p1<m1col.nnz(); p1++) { */
+/* 	    int r = m1col.get_nz_index(p1); */
+/* 	    T inc = m1col.get_nz_data(p1) * m2col.get_nz_data(p2); */
+/* 	    if (occupied_by[r] == c) { */
+/* 	      int index=ret.col[c].get_nz_index(pos[r]); */
+/* 	      ret.col[c].add_elem(index,inc); */
+/* 	    } */
+/* 	    else { */
+/* 	      occupied_by[r] = c; */
+/* 	      pos[r] = ret.col[c].nnz(); */
+/* 	      ret.col[c].set_new(r, inc); */
+/* 	    } */
+/* 	  } */
+/* 	} */
+/*       } */
+/*       ret.compact(); */
+
+/*       return ret; */
+/*     } */
+
+
+  // This function added by EGL, May'05
+  template <class T>
+    Sparse_Vec<T> operator*(const Sparse_Mat<T> &m, const Sparse_Vec<T> &v)
+    {
+      it_assert_debug(m.n_cols == v.size(), "Sparse_Mat<T> * Sparse_Vec<T>");
+
+      Sparse_Vec<T> ret(m.n_rows);
+
+      /* The two lines below added because the input parameter "v" is
+	 declared const, but the some functions (e.g., nnz()) change
+	 the vector... Is there a better workaround? */
+      Sparse_Vec<T> vv = v;
+
+      for (int p2=0; p2<vv.nnz(); p2++) {
+	Sparse_Vec<T> &mcol = m.col[vv.get_nz_index(p2)];
+	T x = vv.get_nz_data(p2);
+	for (int p1=0; p1<mcol.nnz(); p1++) {
+	  int r = mcol.get_nz_index(p1);
+	  T inc = mcol.get_nz_data(p1) * x;
+	  ret.add_elem(r,inc);
+	}
+      }
+      ret.compact();
+      return ret;
+    }
+
+
+  template <class T>
+    Vec<T> operator*(const Sparse_Mat<T> &m, const Vec<T> &v)
+    {
+      it_assert_debug(m.n_cols == v.size(), "Sparse_Mat<T> * Vec<T>");
+
+      Vec<T> r(m.n_rows);
+      r.clear();
+
+      for (int c=0; c<m.n_cols; c++) {
+	for (int p=0; p<m.col[c].nnz(); p++)
+	  r(m.col[c].get_nz_index(p)) += m.col[c].get_nz_data(p) * v(c);
+      }
+
+      return r;
+    }
+
+  template <class T>
+    Vec<T> operator*(const Vec<T> &v, const Sparse_Mat<T> &m)
+    {
+      it_assert_debug(v.size() == m.n_rows, "Vec<T> * Sparse_Mat<T>");
+
+      Vec<T> r(m.n_cols);
+      r.clear();
+
+      for (int c=0; c<m.n_cols; c++)
+	r[c] = v * m.col[c];
+
+      return r;
+    }
+
+  template <class T>
+    Mat<T> trans_mult(const Sparse_Mat<T> &m)
+    {
+      Mat<T> ret(m.n_cols, m.n_cols);
+      Vec<T> col;
+      for (int c=0; c<ret.cols(); c++) {
+	m.col[c].full(col);
+	for (int r=0; r<c; r++) {
+	  T tmp = m.col[r] * col;
+	  ret(r,c) = tmp;
+	  ret(c,r) = tmp;
+	}
+	ret(c,c) = m.col[c].sqr();
+      }
+
+      return ret;
+    }
+
+  template <class T>
+    Sparse_Mat<T> trans_mult_s(const Sparse_Mat<T> &m)
+    {
+      Sparse_Mat<T> ret(m.n_cols, m.n_cols);
+      Vec<T> col;
+      T tmp;
+      for (int c=0; c<ret.n_cols; c++) {
+	m.col[c].full(col);
+	for (int r=0; r<c; r++) {
+	  tmp = m.col[r] * col;
+	  if (tmp != T(0)) {
+	    ret.col[c].set_new(r, tmp);
+	    ret.col[r].set_new(c, tmp);
+	  }
+	}
+	tmp = m.col[c].sqr();
+	if (tmp != T(0))
+	  ret.col[c].set_new(c, tmp);
+      }
+
+      return ret;
+    }
+
+  template <class T>
+    Sparse_Mat<T> trans_mult(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
+    {
+      it_assert_debug(m1.n_rows == m2.n_rows, "trans_mult()");
+
+      Sparse_Mat<T> ret(m1.n_cols, m2.n_cols);
+      Vec<T> col;
+      for (int c=0; c<ret.n_cols; c++) {
+        m2.col[c].full(col);
+        for (int r=0; r<ret.n_rows; r++)
+          ret.col[c].set_new(r, m1.col[r] * col);
+      }
+
+      return ret;
+    }
+
+  template <class T>
+    Vec<T> trans_mult(const Sparse_Mat<T> &m, const Vec<T> &v)
+    {
+      Vec<T> r(m.n_cols);
+      for (int c=0; c<m.n_cols; c++)
+	r(c) = m.col[c] * v;
+
+      return r;
+    }
+
+  template <class T>
+    Sparse_Mat<T> mult_trans(const Sparse_Mat<T> &m1, const Sparse_Mat<T> &m2)
+    {
+      return trans_mult(m1.transpose(),m2.transpose());
+    }
+
+  //! Convert a dense matrix \c m into its sparse representation
+  template <class T>
+    inline Sparse_Mat<T> sparse(const Mat<T> &m, T epsilon)
+    {
+      Sparse_Mat<T> s(m, epsilon);
+      return s;
+    }
+
+  //! Convert a sparse matrix \c s into its dense representation
+  template <class T>
+    inline Mat<T> full(const Sparse_Mat<T> &s)
+    {
+      Mat<T> m;
+      s.full(m);
+      return m;
+    }
+
+  //! Transpose a sparse matrix \c s
+  template <class T>
+    inline Sparse_Mat<T> transpose(const Sparse_Mat<T> &s)
+    {
+      Sparse_Mat<T> m;
+      s.transpose(m);
+      return m;
+    }
+
+  //! \cond
+
+  // ---------------------------------------------------------------------
+  // Instantiations
+  // ---------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  extern template class Sparse_Mat<int>;
+  extern template class Sparse_Mat<double>;
+  extern template class Sparse_Mat<std::complex<double> >;
+
+  extern template sparse_imat operator+(const sparse_imat &, const sparse_imat &);
+  extern template sparse_mat operator+(const sparse_mat &, const sparse_mat &);
+  extern template sparse_cmat operator+(const sparse_cmat &, const sparse_cmat &);
+
+  extern template sparse_imat operator*(const sparse_imat &, const sparse_imat &);
+  extern template sparse_mat operator*(const sparse_mat &, const sparse_mat &);
+  extern template sparse_cmat operator*(const sparse_cmat &, const sparse_cmat &);
+
+  extern template ivec operator*(const ivec &, const sparse_imat &);
+  extern template vec operator*(const vec &, const sparse_mat &);
+  extern template cvec operator*(const cvec &, const sparse_cmat &);
+
+  extern template ivec operator*(const sparse_imat &, const ivec &);
+  extern template vec operator*(const sparse_mat &, const vec &);
+  extern template cvec operator*(const sparse_cmat &, const cvec &);
+
+  extern template imat trans_mult(const sparse_imat &);
+  extern template mat trans_mult(const sparse_mat &);
+  extern template cmat trans_mult(const sparse_cmat &);
+
+  extern template sparse_imat trans_mult_s(const sparse_imat &);
+  extern template sparse_mat trans_mult_s(const sparse_mat &);
+  extern template sparse_cmat trans_mult_s(const sparse_cmat &);
+
+  extern template sparse_imat trans_mult(const sparse_imat &, const sparse_imat &);
+  extern template sparse_mat trans_mult(const sparse_mat &, const sparse_mat &);
+  extern template sparse_cmat trans_mult(const sparse_cmat &, const sparse_cmat &);
+
+  extern template ivec trans_mult(const sparse_imat &, const ivec &);
+  extern template vec trans_mult(const sparse_mat &, const vec &);
+  extern template cvec trans_mult(const sparse_cmat &, const cvec &);
+
+  extern template sparse_imat mult_trans(const sparse_imat &, const sparse_imat &);
+  extern template sparse_mat mult_trans(const sparse_mat &, const sparse_mat &);
+  extern template sparse_cmat mult_trans(const sparse_cmat &, const sparse_cmat &);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // #ifndef SMAT_H
+
Index: /win32/itpp-4.0.1/itpp/base/stack.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/stack.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/stack.h (revision 35)
@@ -0,0 +1,227 @@
+/*!
+ * \file
+ * \brief Stack class (container)
+ * \author Thomas Eriksson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ *
+ * This file is not separated into a .h and a .cpp file. The reason is
+ * to avoid problems with template initializations of this class.
+ * An \c Stack<type> can contain any type and it is not possible to
+ * initialize and pre-compile all types that might be put into an
+ * \c Stack.
+ */
+
+#ifndef STACK_H
+#define STACK_H
+
+#include <itpp/base/itassert.h>
+
+
+namespace itpp {
+
+  /*!
+    \brief General stack class
+
+    This class is a general stack class for arbitrary types.
+
+    For rarely used types you will need to instantiate the class by
+    \code
+    template class Stack<type>;
+    \endcode
+
+    The following example shows how to define a Stack of vectors:
+    \code
+    vec a = randn(10);
+    vec b = randn(20);
+    Stack<vec> my_stack(10);
+    my_stack.push(a);
+    my_stack.push(b);
+
+    cout << my_stack.pop() << " " << my_stack.pop() << endl ;
+    \endcode
+  */
+  template<class T>
+    class Stack {
+    public:
+    //! Default constructor
+    Stack();
+    //! Create a Stack of size \c n
+    Stack(int n);
+    //! Create a copy of \c s
+    Stack(const Stack<T> &s);
+    //! Default destructor
+    virtual ~Stack();
+
+    //! Pop the topmost element of the stack
+    T pop();
+    //! Peek at the topmost element of the stack, without removing it
+    T peek() const;
+    //! Push an element at top of stack
+    void push(T v);
+    //! Empty the stack
+    void clear();
+
+    //! Assignment operator
+    void operator=(const Stack<T> &s);
+
+    //! Returns the maximum number of data elements the stack can store
+    int size() const { return ndata; }
+    //! Returns the number of data elements currently in the stack
+    int no_elements() const { return valptr; }
+    //! Resizing a Stack<T>.
+    void set_size(int n, bool copy=false);
+
+    private:
+    int valptr;
+    int ndata;
+    T *data;
+
+    private:
+    void alloc(int n);
+    void free();
+  };
+
+  // --------------------------- Implementation starts here ----------------------------------
+
+  template<class T>
+    Stack<T>::Stack()
+    {
+      data = 0;
+      ndata = 0;
+      valptr = 0;
+    }
+
+  template<class T>
+    Stack<T>::Stack(int n)
+    {
+      alloc(n);
+      valptr=0;
+    }
+
+  template<class T>
+    Stack<T>::Stack(const Stack<T> &s)
+    {
+      data=NULL;
+      ndata=0;
+      valptr=s.valptr;
+      alloc(s.ndata);
+      for (int i=0; i<s.ndata; i++)
+	data[i] = s.data[i];
+    }
+
+  template<class T>
+    Stack<T>::~Stack()
+    {
+      free();
+    }
+
+  template <class T>
+    T Stack<T>::pop()
+    {
+      it_error_if(valptr==0,"Stack<T>::pop: Empty stack");
+      valptr--;
+      return data[valptr];
+    }
+
+  template <class T>
+    T Stack<T>::peek() const
+    {
+      it_error_if(valptr==0,"Stack<T>::peek: Empty stack");
+      return data[valptr-1];
+    }
+
+  template <class T>
+    void Stack<T>::push(T v)
+    {
+      it_error_if(valptr>=ndata,"Stack<T>::push: Full stack");
+      data[valptr]=v;
+      valptr++;
+    }
+
+  template <class T>
+    void Stack<T>::clear()
+    {
+      valptr=0;
+    }
+
+  template<class T>
+    void Stack<T>::alloc(int n)
+    {
+      if (n == 0) {
+	data = NULL;
+	ndata = 0;
+      }
+      else {
+	data = new T[n];
+	it_assert_debug(data!=0, "Out of memory in Stack::alloc");
+      }
+      ndata = n;
+    }
+
+  template<class T>
+    void Stack<T>::free()
+    {
+
+      delete [] data;
+
+      data = 0;
+      ndata = 0;
+    }
+
+  template<class T>
+    void Stack<T>::operator=(const Stack<T> &s)
+    {
+      set_size(s.ndata);
+      for (int i=0; i<ndata; i++)
+	data[i] = s.data[i];
+      valptr=0;
+    }
+
+  template<class T>
+    void Stack<T>::set_size(int sz, bool copy)
+    {
+      int i, min;
+      T *tmp;
+
+      if (ndata == sz)
+	return;
+
+      if (copy) {
+	tmp = data;
+	min = ndata < sz ? ndata : sz;
+	alloc(sz);
+	for (i=0; i<min; i++)
+	  data[i] = tmp[i];
+	delete [] tmp;
+      } else {
+	free();
+	alloc(sz);
+      }
+      ndata = sz;
+    }
+
+} // namespace itpp
+
+#endif // #ifndef STACK_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/det.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/det.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/det.h (revision 35)
@@ -0,0 +1,70 @@
+/*!
+ * \file
+ * \brief Definitions of determinant calculations
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef DET_H
+#define DET_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+    \brief Determinant of real square matrix.
+    \ingroup determinant
+
+    Calculate determinant of the real matrix \f$\mathbf{X}\f$
+
+    Uses LU-factorisation.
+    \f[
+    \det(\mathbf{X}) = \det(\mathbf{P}^T \mathbf{L}) \det(\mathbf{U}) = \det(\mathbf{P}^T) \prod(\mathrm{diag}(\mathbf{U}))
+    \f]
+    and the determinant of the permuation matrix is \f$ \pm 1\f$ dependening on the number of row permuations
+  */
+  double det(const mat &X);
+
+
+  /*!
+    \brief Determinant of complex square matrix.
+    \ingroup determinant
+
+    Calculate determinant of the complex matrix \f$\mathbf{X}\f$
+
+    Uses LU-factorisation.
+    \f[
+    \det(\mathbf{X}) = \det(\mathbf{P}^T \mathbf{L}) \det(\mathbf{U}) = \det(\mathbf{P}^T) \prod(\mathrm{diag}(\mathbf{U}))
+    \f]
+    and the determinant of the permuation matrix is \f$ \pm 1\f$ dependening on the number of row permuations
+  */
+  std::complex<double> det(const cmat &X);
+
+
+} // namespace itpp
+
+#endif // #ifndef DET_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/inv.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/inv.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/inv.h (revision 35)
@@ -0,0 +1,86 @@
+/*!
+ * \file
+ * \brief Definitions of matrix inversion routines
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef INV_H
+#define INV_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+    \brief Inverse of real square matrix.
+    \ingroup inverse
+
+    Calculate the inverse of the real matrix \f$\mathbf{X}\f$
+
+    Solves the equation system \f$ \mathbf{Y} \mathbf{X} = \mathbf{I}\f$ using LU-factorization.
+    IT++ needs to be compiled with the LAPACK for the inverse to be available.
+  */
+  bool inv(const mat &X, mat &Y);
+
+  /*!
+    \brief Inverse of real square matrix.
+    \ingroup inverse
+
+    Calculate the inverse of the real matrix \f$\mathbf{X}\f$
+
+    Solves the equation system \f$ \mathbf{Y} \mathbf{X} = \mathbf{I}\f$ using LU-factorization.
+    IT++ needs to be compiled with LAPACK support for the inverse to be available.
+  */
+  mat inv(const mat &X);
+
+
+  /*!
+    \brief Inverse of complex square matrix.
+    \ingroup inverse
+
+    Calculate the inverse of the complex matrix \f$\mathbf{X}\f$
+
+    Solves the equation system \f$ \mathbf{Y} \mathbf{X} = \mathbf{I}\f$ using LU-factorization.
+    IT++ needs to be compiled with LAPACK support for the inverse to be available.
+  */
+  bool inv(const cmat &X, cmat &Y);
+
+  /*!
+    \brief Inverse of real square matrix.
+    \ingroup inverse
+
+    Calculate the inverse of the complex matrix \f$\mathbf{X}\f$
+
+    Solves the equation system \f$ \mathbf{Y} \mathbf{X} = \mathbf{I}\f$ using LU-factorization.
+    IT++ needs to be compiled with the LAPACK for the inverse to be available.
+  */
+  cmat inv(const cmat &X);
+
+
+} // namespace itpp
+
+#endif // #ifndef INV_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/svd.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/svd.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/svd.h (revision 35)
@@ -0,0 +1,184 @@
+/*!
+ * \file
+ * \brief Definitions of Singular Value Decompositions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef SVD_H
+#define SVD_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Get singular values \c s of a real matrix \c A using SVD
+   *
+   * This function calculates singular values \f$s\f$ from the SVD
+   * decomposition of a real matrix \f$A\f$. The SVD algorithm computes the
+   * decomposition of a real \f$m \times n\f$ matrix \f$\mathbf{A}\f$ so
+   * that
+   * \f[
+   * \mathrm{diag}(\mathbf{U}^T \mathbf{A} \mathbf{V}) = \mathbf{s}
+   * = \sigma_1, \ldots, \sigma_p
+   * \f]
+   * where \f$\sigma_1 \geq \sigma_2 \geq \ldots \sigma_p \geq 0\f$ are the
+   * singular values of \f$\mathbf{A}\f$.
+   * Or put differently:
+   * \f[
+   * \mathbf{A} = \mathbf{U} \mathbf{S} \mathbf{V}^T
+   * \f]
+   * where \f$ \mathrm{diag}(\mathbf{S}) = \mathbf{s} \f$
+   *
+   * \note An external LAPACK library is required by this function.
+   */
+  bool svd(const mat &A, vec &s);
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Get singular values \c s of a complex matrix \c A using SVD
+   *
+   * This function calculates singular values \f$s\f$ from the SVD
+   * decomposition of a complex matrix \f$A\f$. The SVD algorithm computes
+   * the decomposition of a complex \f$m \times n\f$ matrix \f$\mathbf{A}\f$
+   * so that
+   * \f[
+   * \mathrm{diag}(\mathbf{U}^H \mathbf{A} \mathbf{V}) = \mathbf{s}
+   * = \sigma_1, \ldots, \sigma_p
+   * \f]
+   * where \f$\sigma_1 \geq \sigma_2 \geq \ldots \sigma_p \geq 0\f$
+   * are the singular values of \f$\mathbf{A}\f$.
+   * Or put differently:
+   * \f[
+   * \mathbf{A} = \mathbf{U} \mathbf{S} \mathbf{V}^H
+   * \f]
+   * where \f$ \mathrm{diag}(\mathbf{S}) = \mathbf{s} \f$
+   *
+   * \note An external LAPACK library is required by this function.
+   */
+  bool svd(const cmat &A, vec &s);
+
+/*!
+   * \ingroup matrixdecomp
+   * \brief Return singular values of a real matrix \c A using SVD
+   *
+   * This function returns singular values from the SVD decomposition
+   * of a real matrix \f$A\f$. The SVD algorithm computes the decomposition
+   * of a real \f$m \times n\f$ matrix \f$\mathbf{A}\f$ so that
+   * \f[
+   * \mathrm{diag}(\mathbf{U}^T \mathbf{A} \mathbf{V}) = \mathbf{s}
+   * = \sigma_1, \ldots, \sigma_p
+   * \f]
+   * where \f$\sigma_1 \geq \sigma_2 \geq \ldots \sigma_p \geq 0\f$ are the
+   * singular values of \f$\mathbf{A}\f$.
+   * Or put differently:
+   * \f[
+   * \mathbf{A} = \mathbf{U} \mathbf{S} \mathbf{V}^T
+   * \f]
+   * where \f$ \mathrm{diag}(\mathbf{S}) = \mathbf{s} \f$
+   *
+   * \note An external LAPACK library is required by this function.
+   */
+  vec svd(const mat &A);
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Return singular values of a complex matrix \c A using SVD
+   *
+   * This function returns singular values from the SVD
+   * decomposition of a complex matrix \f$A\f$. The SVD algorithm computes
+   * the decomposition of a complex \f$m \times n\f$ matrix \f$\mathbf{A}\f$
+   * so that
+   * \f[
+   * \mathrm{diag}(\mathbf{U}^H \mathbf{A} \mathbf{V}) = \mathbf{s}
+   * = \sigma_1, \ldots, \sigma_p
+   * \f]
+   * where \f$\sigma_1 \geq \sigma_2 \geq \ldots \sigma_p \geq 0\f$
+   * are the singular values of \f$\mathbf{A}\f$.
+   * Or put differently:
+   * \f[
+   * \mathbf{A} = \mathbf{U} \mathbf{S} \mathbf{V}^H
+   * \f]
+   * where \f$ \mathrm{diag}(\mathbf{S}) = \mathbf{s} \f$
+   *
+   * \note An external LAPACK library is required by this function.
+   */
+  vec svd(const cmat &A);
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Perform Singular Value Decomposition (SVD) of a real matrix \c A
+   *
+   * This function returns two orthonormal matrices \f$U\f$ and \f$V\f$
+   * and a vector of singular values \f$s\f$.
+   * The SVD algorithm computes the decomposition of a real \f$m \times n\f$
+   * matrix \f$\mathbf{A}\f$ so that
+   * \f[
+   * \mathrm{diag}(\mathbf{U}^T \mathbf{A} \mathbf{V}) = \mathbf{s}
+   * = \sigma_1, \ldots, \sigma_p
+   * \f]
+   * where the elements of \f$\mathbf{s}\f$, \f$\sigma_1 \geq \sigma_2 \geq
+   * \ldots \sigma_p \geq 0\f$ are the singular values of \f$\mathbf{A}\f$.
+   * Or put differently:
+   * \f[
+   * \mathbf{A} = \mathbf{U} \mathbf{S} \mathbf{V}^T
+   * \f]
+   * where \f$ \mathrm{diag}(\mathbf{S}) = \mathbf{s} \f$
+   *
+   * \note An external LAPACK library is required by this function.
+   */
+  bool svd(const mat &A, mat &U, vec &s, mat &V);
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Perform Singular Value Decomposition (SVD) of a complex matrix \c A
+   *
+   * This function returns two orthonormal matrices \f$U\f$ and \f$V\f$
+   * and a vector of singular values \f$s\f$.
+   * The SVD algorithm computes the decomposition of a complex \f$m \times n\f$
+   * matrix \f$\mathbf{A}\f$ so that
+   * \f[
+   * \mathrm{diag}(\mathbf{U}^H \mathbf{A} \mathbf{V}) = \mathbf{s}
+   * = \sigma_1, \ldots, \sigma_p
+   * \f]
+   * where the elements of \f$\mathbf{s}\f$, \f$\sigma_1 \geq \sigma_2 \geq
+   * \ldots \sigma_p \geq 0\f$ are the singular values of \f$\mathbf{A}\f$.
+   * Or put differently:
+   * \f[
+   * \mathbf{A} = \mathbf{U} \mathbf{S} \mathbf{V}^H
+   * \f]
+   * where \f$ \mathrm{diag}(\mathbf{S}) = \mathbf{s} \f$
+   *
+   * \note An external LAPACK library is required by this function.
+   */
+  bool svd(const cmat &A, cmat &U, vec &s, cmat &V);
+
+
+} // namespace itpp
+
+#endif // #ifndef SVD_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/lu.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/lu.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/lu.h (revision 35)
@@ -0,0 +1,107 @@
+/*!
+ * \file
+ * \brief Definitions of LU factorisation functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef LU_H
+#define LU_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+
+  /*! \addtogroup matrixdecomp
+   */
+  //!@{
+  /*!
+    \brief LU factorisation of real matrix
+
+    The LU factorization of the real matrix \f$\mathbf{X}\f$ of size \f$n \times n\f$ is given
+    by
+    \f[
+    \mathbf{X} = \mathbf{P}^T \mathbf{L} \mathbf{U} ,
+    \f]
+    where \f$\mathbf{L}\f$ and \f$\mathbf{U}\f$ are lower and upper triangular matrices
+    and \f$\mathbf{P}\f$ is a permutation matrix.
+
+    The interchange permutation vector \a p is such that \a k and \a p(k) should be
+    changed for all \a k. Given this vector a permuation matrix can be constructed using the
+    function
+    \code
+    bmat permuation_matrix(const ivec &p)
+    \endcode
+
+    If \a X is an \a n by \a n matrix \a lu(X,L,U,p) computes the LU decomposition.
+    \a L is a lower trangular, \a U an upper triangular matrix.
+    \a p is the interchange permutation vector such that \a k and \a p(k) should be
+    changed for all \a k.
+
+    Returns true is calculation succeeds. False otherwise.
+  */
+  bool lu(const mat &X, mat &L, mat &U, ivec &p);
+
+
+  /*!
+    \brief LU factorisation of real matrix
+
+    The LU factorization of the complex matrix \f$\mathbf{X}\f$ of size \f$n \times n\f$ is given
+    by
+    \f[
+    \mathbf{X} = \mathbf{P}^T \mathbf{L} \mathbf{U} ,
+    \f]
+    where \f$\mathbf{L}\f$ and \f$\mathbf{U}\f$ are lower and upper triangular matrices
+    and \f$\mathbf{P}\f$ is a permutation matrix.
+
+    The interchange permutation vector \a p is such that \a k and \a p(k) should be
+    changed for all \a k. Given this vector a permuation matrix can be constructed using the
+    function
+    \code
+    bmat permuation_matrix(const ivec &p)
+    \endcode
+
+    If \a X is an \a n by \a n matrix \a lu(X,L,U,p) computes the LU decomposition.
+    \a L is a lower trangular, \a U an upper triangular matrix.
+    \a p is the interchange permutation vector such that elements \a k and row \a p(k) should be
+    interchanged.
+
+    Returns true is calculation succeeds. False otherwise.
+  */
+  bool lu(const cmat &X, cmat &L, cmat &U, ivec &p);
+
+
+  //! Makes swapping of vector b according to the inerchange permutation vector p.
+  void interchange_permutations(vec &b, const ivec &p);
+
+  //! Make permutation matrix P from the interchange permutation vector p.
+  bmat permutation_matrix(const ivec &p);
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef LU_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/cholesky.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/cholesky.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/cholesky.h (revision 35)
@@ -0,0 +1,103 @@
+/*!
+ * \file
+ * \brief Definitions of Cholesky factorisation functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef CHOLESKY_H
+#define CHOLESKY_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*! \addtogroup matrixdecomp
+   */
+  //!@{
+
+  /*!
+    \brief Cholesky factorisation of real symmetric and positive definite matrix
+
+    The Cholesky factorisation of a real symmetric positive-definite matrix \f$\mathbf{X}\f$
+    of size \f$n \times n\f$ is given by
+    \f[
+    \mathbf{X} = \mathbf{F}^T \mathbf{F}
+    \f]
+    where \f$\mathbf{F}\f$ is an upper trangular \f$n \times n\f$ matrix.
+
+    Returns true if calcuation succeeded. False otherwise.
+  */
+  bool chol(const mat &X, mat &F);
+
+  /*!
+    \brief Cholesky factorisation of real symmetric and positive definite matrix
+
+    The Cholesky factorisation of a real symmetric positive-definite matrix \f$\mathbf{X}\f$
+    of size \f$n \times n\f$ is given by
+    \f[
+    \mathbf{X} = \mathbf{F}^T \mathbf{F}
+    \f]
+    where \f$\mathbf{F}\f$ is an upper trangular \f$n \times n\f$ matrix.
+  */
+  mat chol(const mat &X);
+
+
+  /*!
+    \brief Cholesky factorisation of complex hermitian and positive-definite matrix
+
+    The Cholesky factorisation of a hermitian positive-definite matrix \f$\mathbf{X}\f$
+    of size \f$n \times n\f$ is given by
+    \f[
+    \mathbf{X} = \mathbf{F}^H \mathbf{F}
+    \f]
+    where \f$\mathbf{F}\f$ is an upper trangular \f$n \times n\f$ matrix.
+
+    Returns true if calcuation succeeded. False otherwise.
+
+    If \c X is positive definite, true is returned and \c F=chol(X)
+    produces an upper triangular \c F. If also \c X is symmetric then \c F'*F = X.
+    If \c X is not positive definite, false is returned.
+  */
+  bool chol(const cmat &X, cmat &F);
+
+  /*!
+    \brief Cholesky factorisation of complex hermitian and positive-definite matrix
+
+    The Cholesky factorisation of a hermitian positive-definite matrix \f$\mathbf{X}\f$
+    of size \f$n \times n\f$ is given by
+    \f[
+    \mathbf{X} = \mathbf{F}^H \mathbf{F}
+    \f]
+    where \f$\mathbf{F}\f$ is an upper trangular \f$n \times n\f$ matrix.
+  */
+  cmat chol(const cmat &X);
+
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef CHOLESKY_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/qr.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/qr.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/qr.h (revision 35)
@@ -0,0 +1,109 @@
+/*!
+ * \file
+ * \brief Definitions of QR factorisation functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef QR_H
+#define QR_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+
+  /*! \addtogroup matrixdecomp
+   */
+  //!@{
+  /*!
+    \brief QR factorisation of real matrix
+
+    The QR factorization of the real matrix \f$\mathbf{A}\f$ of size \f$m \times n\f$ is given
+    by
+    \f[
+    \mathbf{A} = \mathbf{Q} \mathbf{R} ,
+    \f]
+    where \f$\mathbf{Q}\f$ is an \f$m \times m\f$ orthogonal matrix and \f$\mathbf{R}\f$ is an \f$m \times n\f$ upper triangular matrix.
+
+    Returns true is calculation succeeds. False otherwise.
+    Uses the LAPACK routine DGEQRF and DORGQR.
+  */
+  bool qr(const mat &A, mat &Q, mat &R);
+
+  /*!
+    \brief QR factorisation of real matrix with pivoting
+
+    The QR factorization of the real matrix \f$\mathbf{A}\f$ of size \f$m \times n\f$ is given
+    by
+    \f[
+    \mathbf{A} \mathbf{P} = \mathbf{Q} \mathbf{R} ,
+    \f]
+    where \f$\mathbf{Q}\f$ is an \f$m \times m\f$ orthogonal matrix, \f$\mathbf{R}\f$ is an \f$m \times n\f$ upper triangular matrix
+    and \f$\mathbf{P}\f$ is an \f$n \times n\f$ permutation matrix.
+
+    Returns true is calculation succeeds. False otherwise.
+    Uses the LAPACK routines DGEQP3 and DORGQR.
+  */
+  bool qr(const mat &A, mat &Q, mat &R, bmat &P);
+
+  /*!
+    \brief QR factorisation of a complex matrix
+
+    The QR factorization of the complex matrix \f$\mathbf{A}\f$ of size \f$m \times n\f$ is given
+    by
+    \f[
+    \mathbf{A} = \mathbf{Q} \mathbf{R} ,
+    \f]
+    where \f$\mathbf{Q}\f$ is an \f$m \times m\f$ unitary matrix and \f$\mathbf{R}\f$ is an \f$m \times n\f$ upper triangular matrix.
+
+    Returns true is calculation succeeds. False otherwise.
+    Uses the LAPACK routines ZGEQRF and ZUNGQR.
+  */
+  bool qr(const cmat &A, cmat &Q, cmat &R);
+
+  /*!
+    \brief QR factorisation of a complex matrix with pivoting
+
+    The QR factorization of the complex matrix \f$\mathbf{A}\f$ of size \f$m \times n\f$ is given
+    by
+    \f[
+    \mathbf{A} \mathbf{P} = \mathbf{Q} \mathbf{R} ,
+    \f]
+    where \f$\mathbf{Q}\f$ is an \f$m \times m\f$ unitary matrix, \f$\mathbf{R}\f$ is an \f$m \times n\f$ upper triangular matrix
+    and \f$\mathbf{P}\f$ is an \f$n \times n\f$ permutation matrix.
+
+    Returns true is calculation succeeds. False otherwise.
+    Uses the LAPACK routines ZGEQP3 and ZUNGQR.
+  */
+  bool qr(const cmat &A, cmat &Q, cmat &R, bmat &P);
+
+  //!@}
+
+
+} // namespace itpp
+
+#endif // #ifndef QR_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/schur.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/schur.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/schur.h (revision 35)
@@ -0,0 +1,116 @@
+/*!
+ * \file
+ * \brief Definitions of Schur decomposition functions
+ * \author Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef SCHUR_H
+#define SCHUR_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Schur decomposition of a real matrix
+   *
+   * This function computes the Schur form of a square real matrix
+   * \f$ \mathbf{A} \f$. The Schur decomposition satisfies the
+   * following equation:
+   * \f[ \mathbf{U} \mathbf{T} \mathbf{U}^{T} = \mathbf{A} \f]
+   * where: \f$ \mathbf{U} \f$ is a unitary, \f$ \mathbf{T} \f$ is upper
+   * quasi-triangular, and \f$ \mathbf{U}^{T} \f$ is the transposed
+   * \f$ \mathbf{U} \f$ matrix.
+   *
+   * The upper quasi-triangular matrix may have \f$ 2 \times 2 \f$ blocks on
+   * its diagonal.
+   *
+   * Uses the LAPACK routine DGEES.
+   */
+  bool schur(const mat &A, mat &U, mat &T);
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Schur decomposition of a real matrix
+   *
+   * This function computes the Schur form of a square real matrix
+   * \f$ \mathbf{A} \f$. The Schur decomposition satisfies the
+   * following equation:
+   * \f[ \mathbf{U} \mathbf{T} \mathbf{U}^{T} = \mathbf{A} \f]
+   * where: \f$ \mathbf{U} \f$ is a unitary, \f$ \mathbf{T} \f$ is upper
+   * quasi-triangular, and \f$ \mathbf{U}^{T} \f$ is the transposed
+   * \f$ \mathbf{U} \f$ matrix.
+   *
+   * The upper quasi-triangular matrix may have \f$ 2 \times 2 \f$ blocks on
+   * its diagonal.
+   *
+   * \return  Real Schur matrix \f$ \mathbf{T} \f$
+   *
+   * uses the LAPACK routine DGEES.
+   */
+  mat schur(const mat &A);
+
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Schur decomposition of a complex matrix
+   *
+   * This function computes the Schur form of a square complex matrix
+   * \f$ \mathbf{A} \f$. The Schur decomposition satisfies
+   * the following equation:
+   * \f[ \mathbf{U} \mathbf{T} \mathbf{U}^{H} = \mathbf{A} \f]
+   * where: \f$ \mathbf{U} \f$ is a unitary, \f$ \mathbf{T} \f$ is upper
+   * triangular, and \f$ \mathbf{U}^{H} \f$ is the Hermitian
+   * transposition of the \f$ \mathbf{U} \f$ matrix.
+   *
+   * Uses the LAPACK routine ZGEES.
+   */
+  bool schur(const cmat &A, cmat &U, cmat &T);
+
+  /*!
+   * \ingroup matrixdecomp
+   * \brief Schur decomposition of a complex matrix
+   *
+   * This function computes the Schur form of a square complex matrix
+   * \f$ \mathbf{A} \f$. The Schur decomposition satisfies
+   * the following equation:
+   * \f[ \mathbf{U} \mathbf{T} \mathbf{U}^{H} = \mathbf{A} \f]
+   * where: \f$ \mathbf{U} \f$ is a unitary, \f$ \mathbf{T} \f$ is upper
+   * triangular, and \f$ \mathbf{U}^{H} \f$ is the Hermitian
+   * transposition of the \f$ \mathbf{U} \f$ matrix.
+   *
+   * \return  Complex Schur matrix \f$ \mathbf{T} \f$
+   *
+   * Uses the LAPACK routine ZGEES.
+   */
+  cmat schur(const cmat &A);
+
+
+} // namespace itpp
+
+#endif // #ifndef SCHUR_H
Index: /win32/itpp-4.0.1/itpp/base/algebra/ls_solve.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/ls_solve.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/ls_solve.h (revision 35)
@@ -0,0 +1,411 @@
+/*!
+ * \file
+ * \brief Definitions of functions for solving linear equation systems
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef LS_SOLVE_H
+#define LS_SOLVE_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+
+  /*! \addtogroup linearequations
+   */
+  //!@{
+
+  /*! \brief Solve linear equation system by LU factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DGESV.
+  */
+  bool ls_solve(const mat &A, const vec &b, vec &x);
+
+  /*! \brief Solve linear equation system by LU factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DGESV.
+  */
+  vec ls_solve(const mat &A, const vec &b);
+
+  /*! \brief Solve multiple linear equations by LU factorisation.
+
+  Solves the linear system \f$AX=B\f$. Here \f$A\f$ is a nonsingular \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DGESV.
+  */
+  bool ls_solve(const mat &A, const mat &B, mat &X);
+
+  /*! \brief Solve multiple linear equations by LU factorisation.
+
+  Solves the linear system \f$AX=B\f$. Here \f$A\f$ is a nonsingular \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DGESV.
+  */
+  mat ls_solve(const mat &A, const mat &B);
+
+
+  /*! \brief Solve linear equation system by LU factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZGESV.
+  */
+  bool ls_solve(const cmat &A, const cvec &b, cvec &x);
+
+  /*! \brief Solve linear equation system by LU factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZGESV.
+  */
+  cvec ls_solve(const cmat &A, const cvec &b);
+
+  /*! \brief Solve multiple linear equations by LU factorisation.
+
+  Solves the linear system \f$AX=B\f$. Here \f$A\f$ is a nonsingular \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZGESV.
+  */
+  bool ls_solve(const cmat &A, const cmat &B, cmat &X);
+
+  /*! \brief Solve multiple linear equations by LU factorisation.
+
+  Solves the linear system \f$AX=B\f$. Here \f$A\f$ is a nonsingular \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZGESV.
+  */
+  cmat ls_solve(const cmat &A, const cmat &B);
+
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a symmetric postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DPOSV.
+  */
+  bool ls_solve_chol(const mat &A, const vec &b, vec &x);
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a symmetric postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DPOSV.
+  */
+  vec ls_solve_chol(const mat &A, const vec &b);
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$AX=B\f$, where \f$A\f$ is a symmetric postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DPOSV.
+  */
+  bool ls_solve_chol(const mat &A, const mat &B, mat &X);
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$AX=B\f$, where \f$A\f$ is a symmetric postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine DPOSV.
+  */
+  mat ls_solve_chol(const mat &A, const mat &B);
+
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a Hermitian postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZPOSV.
+  */
+  bool ls_solve_chol(const cmat &A, const cvec &b, cvec &x);
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$Ax=b\f$, where \f$A\f$ is a Hermitian postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZPOSV.
+  */
+  cvec ls_solve_chol(const cmat &A, const cvec &b);
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$AX=B\f$, where \f$A\f$ is a Hermitian postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZPOSV.
+  */
+  bool ls_solve_chol(const cmat &A, const cmat &B, cmat &X);
+
+  /*! \brief Solve linear equation system by Cholesky factorisation.
+
+  Solves the linear system \f$AX=B\f$, where \f$A\f$ is a Hermitian postive definite \f$n \times n\f$ matrix.
+  Uses the LAPACK routine ZPOSV.
+  */
+  cmat ls_solve_chol(const cmat &A, const cmat &B);
+
+
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and is built upon the LAPACK routine DGELS.
+  */
+  bool ls_solve_od(const mat &A, const vec &b, vec &x);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine DGELS.
+  */
+  vec ls_solve_od(const mat &A, const vec &b);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine DGELS.
+  */
+  bool ls_solve_od(const mat &A, const mat &B, mat &X);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine DGELS.
+  */
+  mat ls_solve_od(const mat &A, const mat &B);
+
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and is built upon the LAPACK routine ZGELS.
+  */
+  bool ls_solve_od(const cmat &A, const cvec &b, cvec &x);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine ZGELS.
+  */
+  cvec ls_solve_od(const cmat &A, const cvec &b);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine ZGELS.
+  */
+  bool ls_solve_od(const cmat &A, const cmat &B, cmat &X);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the overdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \geq n\f$.
+  Uses QR-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine ZGELS.
+  */
+  cmat ls_solve_od(const cmat &A, const cmat &B);
+
+
+
+  /*! \brief Solves underdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and is built upon the LAPACK routine DGELS.
+  */
+  bool ls_solve_ud(const mat &A, const vec &b, vec &x);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine DGELS.
+  */
+  vec ls_solve_ud(const mat &A, const vec &b);
+
+  /*! \brief Solves underdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine DGELS.
+  */
+  bool ls_solve_ud(const mat &A, const mat &B, mat &X);
+
+  /*! \brief Solves underdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine DGELS.
+  */
+  mat ls_solve_ud(const mat &A, const mat &B);
+
+
+  /*! \brief Solves underdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and is built upon the LAPACK routine ZGELS.
+  */
+  bool ls_solve_ud(const cmat &A, const cvec &b, cvec &x);
+
+  /*! \brief Solves overdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$Ax=b\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine ZGELS.
+  */
+  cvec ls_solve_ud(const cmat &A, const cvec &b);
+
+  /*! \brief Solves underdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine ZGELS.
+  */
+  bool ls_solve_ud(const cmat &A, const cmat &B, cmat &X);
+
+  /*! \brief Solves underdetermined linear equation systems.
+
+  Solves the underdetermined linear system \f$AX=B\f$, where \f$A\f$ is a \f$m \times n\f$ matrix and \f$m \leq n\f$.
+  Uses LQ-factorization and assumes that \f$A\f$ is full rank. Based on the LAPACK routine ZGELS.
+  */
+  cmat ls_solve_ud(const cmat &A, const cmat &B);
+
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,b,x), ls_solve_od(A,b,x) or ls_solve_ud(A,b,x)
+  */
+  bool backslash(const mat &A, const vec &b, vec &x);
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,b), ls_solve_od(A,b) or ls_solve_ud(A,b)
+  */
+  vec backslash(const mat &A, const vec &b);
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,B,X), ls_solve_od(A,B,X), or ls_solve_ud(A,B,X).
+  */
+  bool backslash(const mat &A, const mat &B, mat &X);
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,B), ls_solve_od(A,B), or ls_solve_ud(A,B).
+  */
+  mat backslash(const mat &A, const mat &B);
+
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,b,x), ls_solve_od(A,b,x) or ls_solve_ud(A,b,x)
+  */
+  bool backslash(const cmat &A, const cvec &b, cvec &x);
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,b), ls_solve_od(A,b) or ls_solve_ud(A,b)
+  */
+  cvec backslash(const cmat &A, const cvec &b);
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,B,X), ls_solve_od(A,B,X), or ls_solve_ud(A,B,X).
+  */
+  bool backslash(const cmat &A, const cmat &B, cmat &X);
+
+  /*! \brief A general linear equation system solver.
+
+  Tries to emulate the backslash operator in Matlab by calling
+  ls_solve(A,B), ls_solve_od(A,B), or ls_solve_ud(A,B).
+  */
+  cmat backslash(const cmat &A, const cmat &B);
+
+
+
+  /*! \brief Forward substitution of square matrix.
+
+  Solves Lx=b, where L is a lower triangular n by n matrix.
+  Assumes that L is nonsingular. Requires n^2 flops.
+  Uses Alg. 3.1.1 in Golub & van Loan "Matrix computations", 3rd ed., p. 89.
+  */
+  vec forward_substitution(const mat &L, const vec &b);
+
+  /*! \brief Forward substitution of square matrix.
+
+  Solves Lx=b, where L is a lower triangular n by n matrix.
+  Assumes that L is nonsingular. Requires n^2 flops.
+  Uses Alg. 3.1.1 in Golub & van Loan "Matrix computations", 3rd ed., p. 89.
+  */
+  void forward_substitution(const mat &L, const vec &b, vec &x);
+
+  /*! \brief Forward substitution of band matricies.
+
+  Solves Lx=b, where L is a lower triangular n by n band-matrix with lower
+  bandwidth p.
+  Assumes that L is nonsingular. Requires about 2np flops (if n >> p).
+  Uses Alg. 4.3.2 in Golub & van Loan "Matrix computations", 3rd ed., p. 153.
+  */
+  vec forward_substitution(const mat &L, int p, const vec &b);
+
+  /*! \brief Forward substitution of band matricies.
+
+  Solves Lx=b, where L is a lower triangular n by n band-matrix with
+  lower bandwidth p.
+  Assumes that L is nonsingular. Requires about 2np flops (if n >> p).
+  Uses Alg. 4.3.2 in Golub & van Loan "Matrix computations", 3rd ed., p. 153.
+  */
+  void forward_substitution(const mat &L, int p, const vec &b, vec &x);
+
+  /*! \brief Backward substitution of square matrix.
+
+  Solves Ux=b, where U is a upper triangular n by n matrix.
+  Assumes that U is nonsingular. Requires n^2 flops.
+  Uses Alg. 3.1.2 in Golub & van Loan "Matrix computations", 3rd ed., p. 89.
+  */
+  vec backward_substitution(const mat &U, const vec &b);
+
+  /*! \brief Backward substitution of square matrix.
+
+  Solves Ux=b, where U is a upper triangular n by n matrix.
+  Assumes that U is nonsingular. Requires n^2 flops.
+  Uses Alg. 3.1.2 in Golub & van Loan "Matrix computations", 3rd ed., p. 89.
+  */
+  void backward_substitution(const mat &U, const vec &b, vec &x);
+
+  /*! \brief Backward substitution of band matrix.
+
+  Solves Ux=b, where U is a upper triangular n by n matrix band-matrix with
+  upper bandwidth q.
+  Assumes that U is nonsingular. Requires about 2nq flops (if n >> q).
+  Uses Alg. 4.3.3 in Golub & van Loan "Matrix computations", 3rd ed., p. 153.
+  */
+  vec backward_substitution(const mat &U, int q, const vec &b);
+
+  /*! \brief Backward substitution of band matrix.
+
+  Solves Ux=b, where U is a upper triangular n by n matrix band-matrix with
+  upper bandwidth q.
+  Assumes that U is nonsingular. Requires about 2nq flops (if n >> q).
+  Uses Alg. 4.3.3 in Golub & van Loan "Matrix computations", 3rd ed., p. 153.
+  */
+  void backward_substitution(const mat &U, int q, const vec &b, vec &x);
+
+  //!@}
+
+} //namespace itpp
+
+#endif // #ifndef LS_SOLVE_H
+
+
+
Index: /win32/itpp-4.0.1/itpp/base/algebra/eigen.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/algebra/eigen.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/algebra/eigen.h (revision 35)
@@ -0,0 +1,232 @@
+/*!
+ * \file
+ * \brief Definitions of eigenvalue decomposition functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef EIGEN_H
+#define EIGEN_H
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues and eigenvectors of a symmetric real matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the real and symmetric \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    The eigenvectors are the columns of the matrix V.
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine DSYEV.
+  */
+  bool eig_sym(const mat &A, vec &d, mat &V);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues of a symmetric real matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the real and symmetric \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine DSYEV.
+  */
+  bool eig_sym(const mat &A, vec &d);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues of a symmetric real matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the real and symmetric \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+
+    Uses the LAPACK routine DSYEV.
+  */
+  vec eig_sym(const mat &A);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues and eigenvectors of a hermitian complex matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the complex and hermitian \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    The eigenvectors are the columns of the matrix V.
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine ZHEEV.
+  */
+  bool eig_sym(const cmat &A, vec &d, cmat &V);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues of a hermitian complex matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the complex and hermitian \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine ZHEEV.
+  */
+  bool eig_sym(const cmat &A, vec &d);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues of a hermitian complex matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the complex and hermitian \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+
+    Uses the LAPACK routine ZHEEV.
+  */
+  vec eig_sym(const cmat &A);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Caclulates the eigenvalues and eigenvectors of a real non-symmetric matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the real \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    The eigenvectors are the columns of the matrix V.
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine DGEEV.
+  */
+  bool eig(const mat &A, cvec &d, cmat &V);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Caclulates the eigenvalues of a real non-symmetric matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the real \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine DGEEV.
+  */
+  bool eig(const mat &A, cvec &d);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Caclulates the eigenvalues of a real non-symmetric matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the real \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+
+    Uses the LAPACK routine DGEEV.
+  */
+  cvec eig(const mat &A);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues and eigenvectors of a complex non-hermitian matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the complex \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    The eigenvectors are the columns of the matrix V.
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine ZGEEV.
+  */
+  bool eig(const cmat &A, cvec &d, cmat &V);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues of a complex non-hermitian matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the complex \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+    True is returned if the calculation was successful. Otherwise false.
+
+    Uses the LAPACK routine ZGEEV.
+  */
+  bool eig(const cmat &A, cvec &d);
+
+  /*!
+    \ingroup matrixdecomp
+    \brief Calculates the eigenvalues of a complex non-hermitian matrix
+
+    The Eigenvalues \f$\mathbf{d}(d_0, d_1, \ldots, d_{n-1})\f$ and the eigenvectors
+    \f$\mathbf{v}_i, \: i=0, \ldots, n-1\f$ of the complex \f$n \times n\f$
+    matrix \f$\mathbf{A}\f$ satisfies
+    \f[
+    \mathbf{A} \mathbf{v}_i = d_i \mathbf{v}_i\: i=0, \ldots, n-1.
+    \f]
+
+    Uses the LAPACK routine ZGEEV.
+  */
+  cvec eig(const cmat &A);
+
+} // namespace itpp
+
+#endif // #ifndef EIGEN_H
Index: /win32/itpp-4.0.1/itpp/base/factory.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/factory.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/factory.h (revision 35)
@@ -0,0 +1,243 @@
+/*!
+ * \file
+ * \brief Base class for class factories and memory allocation functions
+ * \author Johan Bergman and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef FACTORY_H
+#define FACTORY_H
+
+#include <complex>
+#include <itpp/base/binary.h>
+
+namespace itpp {
+
+  // Forward declarations
+  template<class T> class Array;
+  template<class Num_T> class Mat;
+  template<class Num_T> class Vec;
+
+  /*!
+    \brief Base class for class factories
+
+    A class factory (or virtual constructor) is a class that can create instances
+    of another class. Factory is a base class for such factories. When declaring
+    an Array, Vec or Mat, a factory can be passed as an (optional) constructor
+    argument:
+    \code
+    // Declare a Vec<type> with size=10 and factory=DEFAULT_FACTORY
+    Vec<type> a(10);
+
+    // Declare a Vec<type> with size=10 and factory=f
+    Factory f;
+    Vec<type> b(10, f);
+    \endcode
+
+    By default, the factory (\c DEFAULT_FACTORY and \c f in the above examples)
+    is not used at all! However, by overloading a help function called
+    \e create_elements we can force Array/Vec/Mat to use the factory for element
+    creation (instead of using the default constructor for the element type).
+
+    \note It is the \e numeric elements that will be created by the factory,
+    i.e. for an Array<Mat<T> >, the factory will be used for creating the Mat
+    elements rather than the Array elements.
+
+    Here is an example that (partly) defines a user-defined numeric type My_Type,
+    a corresponding factory My_Factory and a corresponding help function
+    create_elements<My_Type> that will be used by Array, Vec and Mat for element
+    creation.
+    \code
+    class My_Type {
+    public:
+    // Default constructor
+    My_Type() : data(0) {}
+    // Constructor
+    My_Type(int d) : data(d) {}
+    .
+    .
+    .
+    protected:
+    int data;
+    };
+
+    class My_Factory : public Factory {
+    public:
+    // Constructor
+    explicit My_Factory(int d) : init_data(d) {}
+    // Destructor
+    virtual ~My_Factory() {}
+    // Create an n-length array of My_Type
+    virtual void create(My_Type* &ptr, int n) const {ptr = new My_Type[n](init_data);}
+    protected:
+    int init_data;
+    };
+
+    // Create an n-length array of My_Type using My_Factory f
+    template<>
+    void create_elements<My_Type>(My_Type* &ptr, int n, const Factory &f)
+    {
+    if (const My_Factory *my_factory_ptr = dynamic_cast<const My_Factory*>(&f)) {
+    // Yes, f seems to be a My_Factory. Now call the My_Factory::create method
+    my_factory_ptr->create(ptr, n);
+    }
+    else {
+    // No, f does not seem to be a My_Factory. As a fallback solution,
+    // assume that f is DEFAULT_FACTORY and use the default constructor
+    ptr = new My_Type[n];
+    }
+    }
+    \endcode
+
+    Now,
+    \code
+    // Declare a My_Factory for init_data = 123
+    My_Factory my123_factory(123);
+
+    // Declare a Vec<My_Type> with size 10 that uses My_Type() for element creation
+    Vec<My_Type> v1(10);
+
+    // Declare a Vec<My_Type> with size 10 that uses My_Type(123) for element creation
+    Vec<My_Type> v1(10, my123_factory);
+    \endcode
+
+    For a more interesting example, see Fix_Factory.
+  */
+  class Factory {
+  public:
+    //! Default constructor
+    Factory() {}
+    //! Destructor
+    virtual ~Factory() {}
+  };
+
+  //! Default (dummy) factory
+  const Factory DEFAULT_FACTORY;
+
+
+  //! Create an n-length array of T to be used as Array, Vec or Mat elements
+  template<class T>
+  void create_elements(T* &ptr, int n, const Factory &)
+  {
+    void *p = operator new(sizeof(T) * n);
+    ptr = reinterpret_cast<T*>(p);
+    for (int i = 0; i < n; i++) {
+      new (ptr + i) T();
+    }
+  }
+
+
+  //! Specialization for unsigned char data arrays (used in GF2Mat)
+  template<>
+  void create_elements<unsigned char>(unsigned char* &ptr, int n,
+				      const Factory &);
+  //! Specialization for binary data arrays
+  template<>
+  void create_elements<bin>(bin* &ptr, int n, const Factory &);
+  //! Specialization for short integer data arrays
+  template<>
+  void create_elements<short int>(short int* &ptr, int n, const Factory &);
+  //! Specialization for integer data arrays
+  template<>
+  void create_elements<int>(int* &ptr, int n, const Factory &);
+  //! Specialization for 16-byte aligned double data arrays
+  template<>
+  void create_elements<double>(double* &ptr, int n, const Factory &);
+  //! Specialization for 16-byte aligned complex double data arrays
+  template<>
+  void create_elements<std::complex<double> >(std::complex<double>* &ptr, int n, const Factory &);
+
+
+  //! Destroy an array of Array, Vec or Mat elements
+  template<class T>
+  void destroy_elements(T* &ptr, int n)
+  {
+    if (ptr) {
+      for (int i = 0; i < n; ++i) {
+	ptr[i].~T();
+      }
+      void *p = reinterpret_cast<void*>(ptr);
+      operator delete(p);
+      ptr = 0;
+    }
+  }
+
+  //! Specialization for unsigned char data arrays (used in GF2Mat)
+  template<>
+  void destroy_elements<unsigned char>(unsigned char* &ptr, int n);
+  //! Specialization for binary data arrays
+  template<>
+  void destroy_elements<bin>(bin* &ptr, int n);
+  //! Specialization for short integer data arrays
+  template<>
+  void destroy_elements<short int>(short int* &ptr, int n);
+  //! Specialization for integer data arrays
+  template<>
+  void destroy_elements<int>(int* &ptr, int n);
+  //! Specialisation for 16-byte aligned double data arrays
+  template<>
+  void destroy_elements<double>(double* &ptr, int n);
+  //! Specialisation for 16-byte aligned complex double data arrays
+  template<>
+  void destroy_elements<std::complex<double> >(std::complex<double>* &ptr,
+					       int n);
+
+
+  //! Create an n-length array of Array<T> to be used as Array elements
+  template<class T>
+  void create_elements(Array<T>* &ptr, int n, const Factory &f)
+  {
+    void *p = operator new(sizeof(Array<T>) * n);
+    ptr = reinterpret_cast<Array<T>*>(p);
+    for (int i = 0; i < n; ++i) {
+      new (ptr + i) Array<T>(f);
+    }
+  }
+
+  //! Create an n-length array of Mat<T> to be used as Array elements
+  template<class T>
+  void create_elements(Mat<T>* &ptr, int n, const Factory &f)
+  {
+    void *p = operator new(sizeof(Mat<T>) * n);
+    ptr = reinterpret_cast<Mat<T>*>(p);
+    for (int i = 0; i < n; ++i) {
+      new (ptr + i) Mat<T>(f);
+    }
+  }
+
+  //! Create an n-length array of Vec<T> to be used as Array elements
+  template<class T>
+  void create_elements(Vec<T>* &ptr, int n, const Factory &f)
+  {
+    void *p = operator new(sizeof(Vec<T>) * n);
+    ptr = reinterpret_cast<Vec<T>*>(p);
+    for (int i = 0; i < n; ++i) {
+      new (ptr + i) Vec<T>(f);
+    }
+  }
+
+} // namespace itpp
+
+#endif // #ifndef FACTORY_H
Index: /win32/itpp-4.0.1/itpp/base/fastmath.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/fastmath.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/fastmath.h (revision 35)
@@ -0,0 +1,54 @@
+/*!
+ * \file
+ * \brief Definitions of special operations on vectors and matricies optimized
+ * for speed
+ * \author Tony Ottosson and Tobias Ringstrom
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef FASTMATH_H
+#define FASTMATH_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  /*!
+    \relatesalso Mat
+    \brief Calculates m=m-v*v'*m
+  */
+  void sub_v_vT_m(mat &m, const vec &v);
+
+  /*!
+    \relatesalso Mat
+    \brief Calculates m=m-m*v*v'
+  */
+  void sub_m_v_vT(mat &m, const vec &v);
+
+} // namespace itpp
+
+#endif // #ifndef FASTMATH_H
Index: /win32/itpp-4.0.1/itpp/base/binfile.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/binfile.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/binfile.h (revision 35)
@@ -0,0 +1,339 @@
+/*!
+ * \file
+ * \brief Binary file formats definitions
+ * \author Tony Ottosson, Thomas Eriksson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef BINFILE_H
+#define BINFILE_H
+
+#include <itpp/base/ittypes.h>
+#include <fstream>
+
+
+namespace itpp {
+
+  /*!
+    \brief Checks if a filename already exists on the disk
+    \ingroup itfile
+  */
+  bool exist(const std::string& name);
+
+  /*!
+    \brief Base class for binary file classes
+    \ingroup itfile
+
+    This class serves as a base class for the classes \c bofstream,
+    \c bifstream, and \c bfstream. It controls the endianity (i.e. the
+    byte order of multibyte numbers on the disk) of the inhereted classes.
+  */
+  class bfstream_base {
+  public:
+    /*!
+      \brief Definition of the endian data type
+
+      The Endianness defines the order in which multibyte numbers are stored
+      in the file. The two orders are called "Little Endian" (\c l_endian )
+      and "Big Endian" (\c b_endian ).
+
+      "Little Endian" means that the low-order byte of the number is stored
+      at the lowest adress (i.e. the little end comes first). "Big Endian"
+      means that the high-order byte of the number is stored in memory at
+      the lowest address (i.e. the big end comes first)
+    */
+    enum endian { l_endian, b_endian };
+
+    /*!
+      \brief Class Constructor
+
+      \param e Defines the endianity of the class. Possible values are \c
+      l_endian for little endian or \c b_endian for big endian. The default
+      value is \c b_endian.
+    */
+    bfstream_base(endian e = b_endian);
+
+    /*!
+      \brief Returns the endianity of the class
+    */
+    endian get_endianity() const
+    {
+      if (switch_endianity) {
+        if (native_endianity == l_endian)
+          return b_endian;
+        else
+          return l_endian;
+      }
+      else
+        return native_endianity;
+    }
+
+    /*!
+      \brief Returns the native endianity for this computer architecture
+
+      Intel processors use "Little Endian" byte ordering while e.g. Motorola
+      processors use "Big Endian" byte ordering.
+    */
+    endian get_native_endianity() const { return native_endianity; }
+
+    /*!
+      \brief Set the endianity for this class
+    */
+    void set_endianity(endian e)
+    {
+      if (native_endianity == e)
+        switch_endianity = false;
+      else
+        switch_endianity = true;
+    }
+
+    /*!
+      \brief Set the endianity of this class to the native endianity for
+      this computer architecture
+    */
+    void set_native_endianity() { switch_endianity = false; }
+
+  protected:
+    //! Indicates if the endianity of the processed data needs to be changed
+    bool switch_endianity;
+    //! The native endianity for this computer architecture
+    endian native_endianity;
+  };
+
+  /*!
+    \brief Binary Outfile Class
+    \ingroup itfile
+  */
+  class bofstream : public bfstream_base, public std::ofstream {
+  public:
+    /*!
+      \brief Class constructor that opens a file and sets the endianity
+
+      \param name The name of the file to open
+      \param e Defines the endianity of the class. Possible values are
+      \c l_endian for "Little Endian" or \c b_endian for "Big Endian". The
+      default value is \c b_endian.
+    */
+    bofstream(const std::string& name, endian e = b_endian);
+
+    //! Class Constructor
+    bofstream();
+
+    //! Class Destructor
+    ~bofstream() { }
+
+    /*!
+      \brief Open a file for writing and set the endianity
+
+      \param name The name of the file to open
+      \param e Defines the endianity of the class (default value is
+      \c b_endian )
+    */
+    void open(const std::string& name, endian e = b_endian);
+
+    //! Writes a signed char variable to the binary output file
+    bofstream& operator<<(char a);
+    //! Writes an unsigned char variable to the binary output file
+    bofstream& operator<<(unsigned char a);
+    //! Writes a 16-bit signed integer variable to the binary output file
+    bofstream& operator<<(int16_t a);
+    //! Writes a 16-bit unsigned integer variable to the binary output file
+    bofstream& operator<<(uint16_t a);
+    //! Writes a 32-bit signed integer variable to the binary output file
+    bofstream& operator<<(int32_t a);
+    //! Writes a 32-bit unsigned integer variable to the binary output file
+    bofstream& operator<<(uint32_t a);
+    //! Writes a 64-bit signed integer variable to the binary output file
+    bofstream& operator<<(int64_t a);
+    //! Writes a 64-bit unsigned ingeger variable to the binary output file
+    bofstream& operator<<(uint64_t a);
+    //! Writes a float variable to the binary output file
+    bofstream& operator<<(float a);
+    //! Writes a double variable to the binary output file
+    bofstream& operator<<(double a);
+    //! Writes a char* string to the binary output file
+    bofstream& operator<<(const char* a);
+    //! Writes a string variable to the binary output file
+    bofstream& operator<<(const std::string& a);
+  };
+
+  /*!
+    \brief Binary Infile Class
+    \ingroup itfile
+  */
+  class bifstream : public bfstream_base, public std::ifstream {
+  public:
+    /*!
+      \brief Class constructor that opens a file and sets the endianity
+
+      \param name The name of the file to open
+      \param e Defines the endianity of the class. Possible values are
+      \c l_endian for "Little Endian" or \c b_endian for "Big Endian". The
+      default value is \c b_endian.
+    */
+    bifstream(const std::string& name, endian e = b_endian);
+
+    //! Class Constructor
+    bifstream();
+
+    //! Class Destructor
+    ~bifstream() { }
+
+    /*!
+      \brief Open a file for reading and set the endianity
+
+      \param name The name of the file to open
+      \param e Defines the endianity of the class (default value is
+      \c b_endian )
+    */
+    void open(const std::string& name, endian e = b_endian);
+
+    //! Returns the length in bytes of the file
+    int length();
+
+    //! Reads a signed char variable from the binary output file
+    bifstream& operator>>(char& a);
+    //! Reads an unsigned char variable from the binary output file
+    bifstream& operator>>(unsigned char& a);
+    //! Reads a 16-bit signed integer variable from the binary output file
+    bifstream& operator>>(int16_t& a);
+    //! Reads a 16-bit unsigned integer variable from the binary output file
+    bifstream& operator>>(uint16_t& a);
+    //! Reads a 32-bit signed integer variable from the binary output file
+    bifstream& operator>>(int32_t& a);
+    //! Reads a 32-bit unsigned integer variable from the binary output file
+    bifstream& operator>>(uint32_t& a);
+    //! Reads a 64-bit signed integer variable from the binary output file
+    bifstream& operator>>(int64_t& a);
+    //! Reads a 64-bit unsigned ingeger variable from the binary output file
+    bifstream& operator>>(uint64_t& a);
+    //! Reads a float variable from the binary output file
+    bifstream& operator>>(float& a);
+    //! Reads a double variable from the binary output file
+    bifstream& operator>>(double& a);
+    //! Reads a char* string from the binary output file
+    bifstream& operator>>(char* a);
+    //! Reads a string variable from the binary output file
+    bifstream& operator>>(std::string& a);
+  };
+
+  /*!
+    \brief Binary in/out-file Class
+    \ingroup itfile
+  */
+  class bfstream : public bfstream_base, public std::fstream {
+  public:
+    /*!
+      \brief Class constructor that opens a file and sets the endianity
+
+      \param name The name of the file to open
+      \param e Defines the endianity of the class. Possible values are
+      \c l_endian for "Little Endian" or \c b_endian for "Big Endian".
+      The default value is \c b_endian.
+    */
+    bfstream(const std::string& name, endian e = b_endian);
+
+    //! Class Constructor
+    bfstream();
+
+    //! Class Destructor
+    ~bfstream() { }
+
+    /*!
+      \brief Open a file for reading and writing and set the endianity
+
+      \param name The name of the file to open
+      \param trunc Rewrite the file if it exists (default value is \c false)
+      \param e Defines the endianity of the class (default value is
+      \c b_endian )
+    */
+    void open(const std::string& name, bool trunc = false, endian e = b_endian);
+
+    /*!
+      \brief Open a file for reading only and set the endianity
+
+      \param name The name of the file to open
+      \param e Defines the endianity of the class (default value is
+      \c b_endian )
+    */
+    void open_readonly(const std::string& name, endian e = b_endian);
+
+    //! Returns the length in bytes of the file
+    int length();
+
+    //! Writes an signed char variable to the binary output file
+    bfstream& operator<<(char a);
+    //! Writes an unsigned char variable to the binary output file
+    bfstream& operator<<(unsigned char a);
+    //! Writes a 16-bit signed integer variable to the binary output file
+    bfstream& operator<<(int16_t a);
+    //! Writes a 16-bit unsigned integer variable to the binary output file
+    bfstream& operator<<(uint16_t a);
+    //! Writes a 32-bit signed integer variable to the binary output file
+    bfstream& operator<<(int32_t a);
+    //! Writes a 32-bit unsigned integer variable to the binary output file
+    bfstream& operator<<(uint32_t a);
+    //! Writes a 64-bit signed integer variable to the binary output file
+    bfstream& operator<<(int64_t a);
+    //! Writes a 64-bit unsigned ingeger variable to the binary output file
+    bfstream& operator<<(uint64_t a);
+    //! Writes a float variable to the binary output file
+    bfstream& operator<<(float a);
+    //! Writes a double variable to the binary output file
+    bfstream& operator<<(double a);
+    //! Writes a char* string to the binary output file
+    bfstream& operator<<(const char* a);
+    //! Writes a string variable to the binary output file
+    bfstream& operator<<(const std::string& a);
+
+    //! Reads a char variable from the binary output file
+    bfstream& operator>>(char& a);
+    //! Reads an unsigned char variable from the binary output file
+    bfstream& operator>>(unsigned char& a);
+    //! Reads a 16-bit signed integer variable from the binary output file
+    bfstream& operator>>(int16_t& a);
+    //! Reads a 16-bit unsigned integer variable from the binary output file
+    bfstream& operator>>(uint16_t& a);
+    //! Reads a 32-bit signed integer variable from the binary output file
+    bfstream& operator>>(int32_t& a);
+    //! Reads a 32-bit unsigned integer variable from the binary output file
+    bfstream& operator>>(uint32_t& a);
+    //! Reads a 64-bit signed integer variable from the binary output file
+    bfstream& operator>>(int64_t& a);
+    //! Reads a 64-bit unsigned ingeger variable from the binary output file
+    bfstream& operator>>(uint64_t& a);
+    //! Reads a float variable from the binary output file
+    bfstream& operator>>(float& a);
+    //! Reads a double variable from the binary output file
+    bfstream& operator>>(double& a);
+    //! Reads a char* string from the binary output file
+    bfstream& operator>>(char* a);
+    //! Reads a string variable from the binary output file
+    bfstream& operator>>(std::string& a);
+  };
+
+} //namespace itpp
+
+#endif // #ifndef BINFILE_H
Index: /win32/itpp-4.0.1/itpp/base/itfile.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/itfile.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/itfile.h (revision 35)
@@ -0,0 +1,1148 @@
+/*!
+ * \file
+ * \brief Definition of classes for the IT++ file format
+ * \author Tony Ottosson, Tobias Ringstrom and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ITFILE_H
+#define ITFILE_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/array.h>
+#include <itpp/base/binfile.h>
+#include <itpp/base/ittypes.h>
+
+
+namespace itpp {
+
+  /*!
+    \addtogroup itfile
+    \brief The IT++ file format
+    \author Tony Ottosson, Tobias Ringstrom and Adam Piatyszek
+
+    The IT++ file format is a file format that can be used to save (load)
+    variables to (from) files. These files can also be read an written by
+    Matlab or Octave using the m-files \c itload.m and \c itsave.m.
+
+    The class it_ifile is used for reading only, whereas the class it_file
+    can be used for both reading and writing.
+
+    Saving of a variable is done in two steps. The first step is to supply
+    the name and optionally description of the variable to be saved. This
+    can be done either by calling the function it_file::set_next_name() or
+    by using the helper class Name:
+
+    \code
+    vec v("1 2 3");
+    bvec b = "0 1 0 1";
+    it_file f("file.it");
+    f << Name("v", "A double vector of tree values") << v;
+    f.set_next_name("b");
+    f << b;
+    \endcode
+
+    The reading is done in a similar way:
+
+    \code
+    vec v;
+    bvec b;
+    it_ifile f("file.it");
+    f >> Name("v") >> v;
+    f.seek("b");
+    f >> b;
+    \endcode
+
+    \note Since version 3, IT++ file format uses the IEEE little endian byte
+    ordering ("ieee-le" in Matlab/Octave). This version is not backward
+    compatible with previous versions. If you need to read/write data in
+    IT++ file format version 2, you can use the it_ifile_old and it_file_old
+    classes. Please have in mind that these "old" classes are deprecated and
+    will be removed from the IT++ library in future.
+
+    \warning Do not use the names that begin with an existing type.
+  */
+
+  /*!
+    \brief Base class for it_ifile and it_file.
+    \ingroup itfile
+  */
+  class it_file_base {
+  public:
+    //! Data header structure
+    struct data_header {
+      //! Number of bytes of the header
+      uint64_t hdr_bytes;
+      //! Number of bytes of the data
+      uint64_t data_bytes;
+      //! Number of bytes of the header + data
+      uint64_t block_bytes;
+      //! Data name
+      std::string name;
+      //! Data type, e.g. int32, float32, etc. type = "" means deleted
+      std::string type;
+      //! Data description
+      std::string desc;
+    };
+
+  protected:
+    //! File header structure
+    struct file_header {
+      //! IT++ file marker: "IT++"
+      char magic[4];
+      //! IT++ file format version
+      char version;
+    };
+    //! IT++ file marker: "IT++"
+    static char file_magic[4];
+    //! IT++ file version
+    static char file_version;
+  };
+
+
+  /*!
+    \brief The IT++ file format reading class.
+    \ingroup itfile
+  */
+  class it_ifile : public it_file_base {
+  public:
+    //! Default constructor
+    it_ifile();
+    //! Constructor that calls open(filename)
+    explicit it_ifile(const std::string& filename);
+    //! Destructor
+    virtual ~it_ifile() { }
+    //! Open an existing file in read-only mode
+    void open(const std::string& filename);
+    //! Close the file
+    virtual void close();
+    //! Returns pointer to the underlying \c bfstream used
+    bfstream& low_level() { return s; }
+
+    //! Read and check the file header. Return true if the header is valid and false otherwise.
+    bool read_check_file_header();
+    //! Read data header and return the result in the variable \c h
+    void read_data_header(data_header& h);
+
+    //! Read a char value at the current file pointer position
+    void low_level_read(char& x);
+    //! Read a 64-bit unsigned integer value at the current file pointer position
+    void low_level_read(uint64_t& x);
+    //! Read a bool value at the current file pointer position
+    void low_level_read(bool &x);
+
+    //! Read a binary value at the current file pointer position
+    void low_level_read(bin& x);
+    //! Read a short value at the current file pointer position
+    void low_level_read(short& x);
+    //! Read an integer value at the current file pointer position
+    void low_level_read(int& x);
+    //! Read a float value at the current file pointer position
+    void low_level_read(float& x);
+    //! Read a double value at the current file pointer position
+    void low_level_read(double& x);
+    //! Read a float complex value at the current file pointer position
+    void low_level_read(std::complex<float>& x);
+    //! Read a double complex value at the current file pointer position
+    void low_level_read(std::complex<double>& x);
+
+    //! Read a vector of binary values at the current file pointer position
+    void low_level_read(bvec& v);
+    //! Read a vector of short integer values at the current file pointer position
+    void low_level_read(svec& v);
+    //! Read a vector of integer values at the current file pointer position
+    void low_level_read(ivec& v);
+    //! Read a vector of float values at the current file pointer position
+    void low_level_read_lo(vec& v);
+    //! Read a vector of double values at the current file pointer position
+    void low_level_read_hi(vec& v);
+    //! Read a vector of float complex values at the current file pointer position
+    void low_level_read_lo(cvec& v);
+    //! Read a vector of double complex values at the current file pointer position
+    void low_level_read_hi(cvec& v);
+
+    //! Read a string at the current file pointer position
+    void low_level_read(std::string& str);
+
+    //! Read a matrix of binary values at the current file pointer position
+    void low_level_read(bmat& m);
+    //! Read a matrix of short integer values at the current file pointer position
+    void low_level_read(smat& m);
+    //! Read a matrix of integer values at the current file pointer position
+    void low_level_read(imat& m);
+    //! Read a matrix of float values at the current file pointer position
+    void low_level_read_lo(mat& m);
+    //! Read a matrix of double values at the current file pointer position
+    void low_level_read_hi(mat& m);
+    //! Read a matrix of float complex values at the current file pointer position
+    void low_level_read_lo(cmat& m);
+    //! Read a matrix of double complex values at the current file pointer position
+    void low_level_read_hi(cmat& m);
+
+    //! Read an Array of binary values at the current file pointer position
+    void low_level_read(Array<bin>& v);
+    //! Read an Array of short integer values at the current file pointer position
+    void low_level_read(Array<short>& v);
+    //! Read an Array of integer values at the current file pointer position
+    void low_level_read(Array<int>& v);
+    //! Read an Array of float values at the current file pointer position
+    void low_level_read(Array<float>& v);
+    //! Read an Array of float values at the current file pointer position
+    void low_level_read_lo(Array<double>& v);
+    //! Read an Array of double values at the current file pointer position
+    void low_level_read_hi(Array<double>& v);
+    //! Read an Array of float complex values at the current file pointer position
+    void low_level_read(Array<std::complex<float> >& v);
+    //! Read an Array of float complex values at the current file pointer position
+    void low_level_read_lo(Array<std::complex<double> >& v);
+    //! Read an Array of double complex values at the current file pointer position
+    void low_level_read_hi(Array<std::complex<double> >& v);
+
+    //! Find the variable \c name
+    bool seek(const std::string& name);
+    //! Find the variable number \c n
+    bool seek(int n);
+    //! Get information about the current variable
+    void info(std::string& name, std::string& type, std::string& desc,
+	      uint64_t& bytes);
+
+  protected:
+    //! Protected binary file stream
+    bfstream s;
+  };
+
+
+  /*!
+    \brief The IT++ file format reading and writing class
+    \ingroup itfile
+  */
+  class it_file : public it_ifile {
+  public:
+    //! ACTION: Add documentation for this typedef
+    typedef it_file& (*it_manip)(it_file&);
+
+    //! Default constructor
+    it_file();
+
+    /*!
+      \brief Constructor that calls open()
+
+      If the file does not exist it will be created. If \c trunc is true,
+      the file will be truncated.
+    */
+    explicit it_file(const std::string& filename, bool trunc = false);
+
+    //! Destructor
+    virtual ~it_file() { }
+
+    /*!
+      \brief Open a file for reading and writing
+
+      If the file does not exist it will be created. If \c trunc is true,
+      the file will be truncated.
+    */
+    void open(const std::string& filename, bool trunc = false);
+
+    //! Close the file
+    void close();
+    //! Flush the data to disk
+    void flush();
+
+    //! Returns pointer to the underlying \c bfstream used
+    bfstream& low_level() { return s; }
+
+    //! Set the precision. Low precision means floats, high means doubles.
+    void set_low_precision(bool p = true)  { low_prec = p; }
+    //! Get the precision
+    bool get_low_precision() const { return low_prec; }
+
+    //! Set the name and optionally description of the next variable to be saved
+    void set_next_name(const std::string& name,
+		       const std::string& description = "")
+    { next_name = name; next_desc = description; }
+
+    //! Write the header for the \c it_file
+    void write_file_header();
+    //! Write the data header for a variable, specifying the type and size of the data to follow.
+    void write_data_header(const std::string& type, uint64_t size);
+    //! Write the data header for a variable, specifying the type, name, size and optionally description of the data to follow.
+    void write_data_header(const std::string& type, const std::string& name,
+			   uint64_t size, const std::string& description = "");
+
+    //! Write a char value at the current file pointer position
+    void low_level_write(char x);
+    //! Write an unsigned integer 64-bit value at the current file pointer position
+    void low_level_write(uint64_t x);
+    //! Write a bool value at the current file pointer position
+    void low_level_write(bool x);
+
+    //! Write a binary value at the current file pointer position
+    void low_level_write(bin x);
+    //! Write a short value at the current file pointer position
+    void low_level_write(short x);
+    //! Write an integer value at the current file pointer position
+    void low_level_write(int x);
+    //! Write a float value at the current file pointer position
+    void low_level_write(float x);
+    //! Write a double value at the current file pointer position
+    void low_level_write(double x);
+    //! Write a float complex value at the current file pointer position
+    void low_level_write(const std::complex<float>& x);
+    //! Write a double complex value at the current file pointer position
+    void low_level_write(const std::complex<double>& x);
+
+    //! Write a bvec at the current file pointer position
+    void low_level_write(const bvec& v);
+    //! Write an svec at the current file pointer position
+    void low_level_write(const svec& v);
+    //! Write an ivec at the current file pointer position
+    void low_level_write(const ivec& v);
+    //! Write a vec at the current file pointer position
+    void low_level_write(const vec& v);
+    //! Write a cvec at the current file pointer position
+    void low_level_write(const cvec& v);
+
+    //! Write a string at the current file pointer position
+    void low_level_write(const std::string& str);
+
+    //! Write a bmat at the current file pointer position
+    void low_level_write(const bmat& m);
+    //! Write an smat at the current file pointer position
+    void low_level_write(const smat& m);
+    //! Write an imat at the current file pointer position
+    void low_level_write(const imat& m);
+    //! Write a mat at the current file pointer position
+    void low_level_write(const mat& m);
+    //! Write a cmat at the current file pointer position
+    void low_level_write(const cmat& m);
+
+    //! Write a bin Array at the current file pointer position
+    void low_level_write(const Array<bin>& v);
+    //! Write a short Array at the current file pointer position
+    void low_level_write(const Array<short>& v);
+    //! Write an integer Array at the current file pointer position
+    void low_level_write(const Array<int>& v);
+    //! Write a float Array at the current file pointer position
+    void low_level_write(const Array<float>& v);
+    //! Write a double Array at the current file pointer position
+    void low_level_write(const Array<double>& v);
+    //! Write a float complex Array at the current file pointer position
+    void low_level_write(const Array<std::complex<float> >& v);
+    //! Write a double complex Array at the current file pointer position
+    void low_level_write(const Array<std::complex<double> >& v);
+
+    //!ACTTION: ADD DOCUMENTATION FOR THIS MEMBER !!!!!!!!
+    it_file& operator<<(it_manip func) { return (*func)(*this); }
+
+    //! Removes the variable \c name from the file
+    void remove(const std::string& name);
+    //! Returns true if the variable \c name exists in the file
+    bool exists(const std::string& name);
+    //! Remove slack space from the file
+    void pack();
+
+  protected:
+    //! Remove the current variable, denoted by \c next_name
+    void remove();
+    //! Write data header \c h at the current file position
+    void write_data_header_here(const data_header& h);
+
+    //! Low precision flag. If true, use float type, otherwise double
+    bool low_prec;
+    //! Name to be used for saving the next variable
+    std::string next_name;
+    //! Description to be used for saving the next variable
+    std::string next_desc;
+
+  private:
+    // Name of the opened file. Needed by the pack() method.
+    std::string fname;
+  };
+
+
+  /*!
+    \brief Flush operator
+    \ingroup itfile
+
+    Flushes the data. Usage:
+    \code
+    vec v1("1 2 3"), v2;
+    it_file f("file.it");
+    f << Name("v") << v1 << flush;
+    \endcode
+  */
+  inline it_file& flush(it_file& f)
+  {
+    f.flush();
+    return f;
+  }
+
+  /*!
+    \brief Automatic naming when saving
+    \ingroup itfile
+
+    An easy way to give a variable a name and optionally description when
+    saving. Usage:
+    \code
+    vec v1("1 2 3"), v2;
+    it_file f("file.it");
+    f << Name("v", "A vector of consecutive double values") << v1;
+    f >> Name("v") >> v2;
+    \endcode
+  */
+  class Name {
+  public:
+    //! Constructor
+    Name(const std::string& n, const std::string& d = ""): name(n), desc(d) {}
+    //! The name string
+    const std::string& name;
+    //! The descripion
+    const std::string& desc;
+  };
+
+
+  /*! \addtogroup itfile */
+  //!@{
+
+  //! Finds the variable \c Name in the \c it_ifile. Returns file pointer for reading.
+  inline it_ifile& operator>>(it_ifile& f, const Name& s)
+  {
+    f.seek(s.name);
+    return f;
+  }
+
+  //! Finds the variable \c Name in the \c it_file. Returns file pointer for writing.
+  inline it_file& operator<<(it_file& f, const Name& s)
+  {
+    f.set_next_name(s.name, s.desc);
+    return f;
+  }
+
+  //! Read the char variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, char& v);
+  //! Read the bool variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile &f, bool &v);
+
+  //! Read the binary variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, bin& v);
+  //! Read the short variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, short& v);
+  //! Read the integer variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, int& v);
+  //! Read the float variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, float& v);
+  //! Read the double variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, double& v);
+  //! Read the float complex variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, std::complex<float>& v);
+  //! Read the double complex variable \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, std::complex<double>& v);
+
+  //! Read the bvec \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, bvec& v);
+  //! Read the svec \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, svec& v);
+  //! Read the ivec \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, ivec& v);
+  //! Read the vec \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, vec& v);
+  //! Read the cvec \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, cvec& v);
+
+  //! Read the string \c str from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, std::string& str);
+
+  //! Read the bmat \c m from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, bmat& m);
+  //! Read the smat \c m from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, smat& m);
+  //! Read the imat \c m from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, imat& m);
+  //! Read the mat \c m from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, mat& m);
+  //! Read the cmat \c m from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, cmat& m);
+
+  //! Read the binary Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<bin>& v);
+  //! Read the short integer Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<short>& v);
+  //! Read the integer Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<int>& v);
+  //! Read the float Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<float>& v);
+  //! Read the double Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<double>& v);
+  //! Read the float complex Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<std::complex<float> >& v);
+  //! Read the double complex Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<std::complex<double> >& v);
+
+  //! Read the bvec Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<bvec>& v);
+  //! Read the svec Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<svec>& v);
+  //! Read the ivec Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<ivec>& v);
+  //! Read the vec Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<vec>& v);
+  //! Read the cvec Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<cvec>& v);
+
+  //! Read the string Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<std::string>& v);
+
+  //! Read the bmat Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<bmat>& v);
+  //! Read the bmat Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<smat>& v);
+  //! Read the imat Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<imat>& v);
+  //! Read the mat Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<mat>& v);
+  //! Read the cmat Array \c v from the \c it_ifile pointer
+  it_ifile& operator>>(it_ifile& f, Array<cmat>& v);
+
+
+  //! Write the char variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, char x);
+  //! Write the bool variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file &f, bool x);
+
+  //! Write the binary variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, bin x);
+  //! Write the short variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, short x);
+  //! Write the integer variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, int x);
+  //! Write the float variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, float x);
+  //! Write the double variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, double x);
+  //! Write the float complex variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, std::complex<float> x);
+  //! Write the double complex variable \c x to the \c it_file pointer
+  it_file& operator<<(it_file& f, std::complex<double> x);
+
+  //! Write the bvec \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const bvec& v);
+  //! Write the svec \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const svec& v);
+  //! Write the ivec \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const ivec& v);
+  //! Write the vec \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const vec& v);
+  //! Write the cvec \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const cvec& v);
+
+  //! Write the string \c str to the \c it_file pointer
+  it_file& operator<<(it_file& f, const std::string& str);
+
+  //! Write the bmat \c m to the \c it_file pointer
+  it_file& operator<<(it_file& f, const bmat& m);
+  //! Write the smat \c m to the \c it_file pointer
+  it_file& operator<<(it_file& f, const smat& m);
+  //! Write the imat \c m to the \c it_file pointer
+  it_file& operator<<(it_file& f, const imat& m);
+  //! Write the mat \c m to the \c it_file pointer
+  it_file& operator<<(it_file& f, const mat& m);
+  //! Write the cmat \c m to the \c it_file pointer
+  it_file& operator<<(it_file& f, const cmat& m);
+
+  //! Write the bin Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<bin>& v);
+  //! Write the short int Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<short>& v);
+  //! Write the int Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<int>& v);
+  //! Write the float Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<float>& v);
+  //! Write the double Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<double>& v);
+  //! Write the float complex Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<std::complex<float> >& v);
+  //! Write the double complex Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<std::complex<double> >& v);
+
+  //! Write the bvec Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<bvec>& v);
+  //! Write the svec Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<svec>& v);
+  //! Write the ivec Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<ivec>& v);
+  //! Write the vec Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<vec>& v);
+  //! Write the cvec Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<cvec>& v);
+
+  //! Write the string Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<std::string>& v);
+
+  //! Write the bmat Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<bmat>& v);
+  //! Write the smat Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<smat>& v);
+  //! Write the imat Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<imat>& v);
+  //! Write the mat Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<mat>& v);
+  //! Write the cmat Array \c v to the \c it_file pointer
+  it_file& operator<<(it_file& f, const Array<cmat>& v);
+
+  //! Save the variable v in the file name.it as the name name.
+  template <class T>
+  void it_save_var_as(const T& v, const std::string& name)
+  {
+    it_file f(name + ".it");
+    f << Name(name) << v;
+    f.close();
+  }
+
+  //! Load the variable v from the file name.it as the name name.
+  template <class T>
+  void it_load_var_as(T& v, const std::string& name)
+  {
+    it_ifile f(name + ".it");
+    f.seek(name);
+    f >> v;
+    f.close();
+  }
+
+  //! A convenient macro. Calling it_save_var(M) saves M as 'M' in the file 'M.it'.
+#define it_save_var(v) it_save_var_as(v,#v)
+  //! A convenient macro. Calling it_load_var(M) loads M as 'M' in the file 'M.it'.
+#define it_load_var(v) it_load_var_as(v,#v)
+
+  //!@}
+
+
+  // ----------------------------------------------------------------------
+  // Deprecated implementation of IT++ file format version 2
+  // Will be removed in future versions
+  // ----------------------------------------------------------------------
+
+  /*!
+    \brief Base class for it_ifile_old and it_file_old.
+
+    \warning This class is deprecated and will be removed in future.
+    \ingroup itfile
+  */
+  class it_file_base_old {
+  public:
+
+    //! Data header structure
+    struct data_header {
+      //! 0=little, 1=big
+      char endianity;
+      /*! size variables
+       * @{ */
+      uint32_t hdr_bytes, data_bytes, block_bytes;
+      /*! @} */
+      //! data name
+      std::string name;
+      //! data type, e.g. int32, float32, etc. type = "" means deleted
+      std::string type;
+    };
+
+  protected:
+
+    //! File header structure
+    struct file_header {
+      //! ACTION: Add documentation
+      char magic[4];
+      //! ACTION: Add documentation
+      char version;
+    };
+    //! ACTION: Add documentation
+    static char file_magic[4];
+    //! ACTION: Add documentation
+    static char file_version;
+  };
+
+  /*!
+    \brief The old (version 2) IT++ file format reading class.
+
+    \warning This class is deprecated and will be removed in future.
+    \ingroup itfile
+  */
+  class it_ifile_old : public it_file_base_old {
+  public:
+    //!Constructor.
+    it_ifile_old();
+    //!Constructor. Calls open().
+    explicit it_ifile_old(const std::string& name);
+    //!Destructor.
+    virtual ~it_ifile_old() { }
+    //!Open a file.  The file must exist.
+    void open(const std::string& name);
+    //!Close a file.
+    virtual void close();
+    //!Returns pointer to the underlying \c bfstream used
+    bfstream& low_level() { return s; }
+
+    //!Reads and checks the file data header. Returns true if the header is valid and false otherwise.
+    bool read_check_file_header();
+    //!Read the data header and return the result in the variable \c h
+    void read_data_header(data_header& h);
+    //!Read a char value at the current file pointer position
+    void low_level_read(char& x);
+    //!Read a binary value at the current file pointer position
+    void low_level_read(bin& x);
+    //!Read a short value at the current file pointer position
+    void low_level_read(short& x);
+    //!Read an integer value at the current file pointer position
+    void low_level_read(int& x);
+    //!Read a float value at the current file pointer position
+    void low_level_read(float& x);
+    //!Read a double value at the current file pointer position
+    void low_level_read(double& x);
+    //!Read a float complex value at the current file pointer position
+    void low_level_read(std::complex<float>& x);
+    //!Read a double complex value at the current file pointer position
+    void low_level_read(std::complex<double>& x);
+    //!Read a vector of float values at the current file pointer position
+    void low_level_read_lo(vec& v);
+    //!Read a vector of double values at the current file pointer position
+    void low_level_read_hi(vec& v);
+    //!Read a vector of integer values at the current file pointer position
+    void low_level_read(ivec& v);
+    //!Read a vector of binary values at the current file pointer position
+    void low_level_read(bvec& v);
+    //!Read a vector of float complex values at the current file pointer position
+    void low_level_read_lo(cvec& v);
+    //!Read a vector of double complex values at the current file pointer position
+    void low_level_read_hi(cvec& v);
+    //!Read a string at the current file pointer position
+    void low_level_read(std::string& str);
+    //!Read a matrix of float values at the current file pointer position
+    void low_level_read_lo(mat& m);
+    //!Read a matrix of double values at the current file pointer position
+    void low_level_read_hi(mat& m);
+    //!Read a matrix of integer values at the current file pointer position
+    void low_level_read(imat& m);
+    //!Read a matrix of binary values at the current file pointer position
+    void low_level_read(bmat& m);
+    //!Read a matrix of float complex values at the current file pointer position
+    void low_level_read_lo(cmat& m);
+    //!Read a matrix of double complex values at the current file pointer position
+    void low_level_read_hi(cmat& m);
+
+    //!Read an Array of float values at the current file pointer position
+    void low_level_read_lo(Array<float>& v);
+    //!Read an Array of float values at the current file pointer position
+    void low_level_read_lo(Array<double>& v);
+    //!Read an Array of double values at the current file pointer position
+    void low_level_read_hi(Array<double>& v);
+    //!Read an Array of integer values at the current file pointer position
+    void low_level_read(Array<int>& v);
+    //!Read an Array of binary values at the current file pointer position
+    void low_level_read(Array<bin>& v);
+    //!Read an Array of float complex values at the current file pointer position
+    void low_level_read_lo(Array<std::complex<float> >& v);
+    //!Read an Array of float complex values at the current file pointer position
+    void low_level_read_lo(Array<std::complex<double> >& v);
+    //!Read an Array of double complex values at the current file pointer position
+    void low_level_read_hi(Array<std::complex<double> >& v);
+
+    //! Find the variable \c  name.
+    bool seek(const std::string& name);
+
+    //! Find the variable number \c n.
+    bool seek(int n);
+    //! Get information about the current variable.
+    void info(std::string& name, std::string& type, int& bytes);
+
+  protected:
+    //! Protected binary file stream
+    bfstream s;
+  };
+
+  /*!
+    \brief The old (version 2) IT++ file format reading and writing class.
+
+    \warning This class is deprecated and will be removed in future.
+    \ingroup itfile
+  */
+  class it_file_old : public it_ifile_old {
+  public:
+    //! ACTION: Add documentation for this typedef
+    typedef it_file_old& (*it_manip)(it_file_old&);
+
+    //! Constructor.
+    it_file_old();
+
+    /*!
+      \brief Constructor.
+
+      If the file does not exist it will be created.  If \c trunc is true,
+      the file will be truncated.
+    */
+    explicit it_file_old(const std::string& name, bool trunc=false);
+
+    //! Destructor.
+    virtual ~it_file_old() { }
+
+    /*!
+      \brief Open a file for reading and writing.
+
+      If the file does not exist it will be created.  If \c  trunc is true,
+      the file will be truncated.
+    */
+    void open(const std::string& name, bool trunc=false);
+
+    //! Close the file.
+    void close();
+
+    //! Flush the data to disk.
+    void flush();
+
+    //! Returns pointer to the underlying \c bfstream used
+    bfstream& low_level() { return s; }
+
+    //! Set the precision. Low precision means floats, high means doubles.
+    void set_low_precision(bool p=true)  { low_prec = p; }
+
+    //! Get the precision.
+    bool get_low_precision() { return low_prec; }
+
+    //! Set the name of the next name to be saved. See also the \c Name class.
+    void set_next_name(const std::string& n) { next_name=n; }
+
+    //!Write the header for the \c it_file_old
+    void write_file_header();
+    //!Write the data header for a variable, specifying the type and size of the data to follow.
+    void write_data_header(const std::string& type, uint32_t size);
+    //!Write the data header for a variable, specifying the type, name, and size of the data to follow.
+    void write_data_header(const std::string& type, const std::string& name,
+			   uint32_t size);
+    //!Write a char value at the current file pointer position
+    void low_level_write(char x);
+    //!Write a binary value at the current file pointer position
+    void low_level_write(bin x);
+    //!Write a short value at the current file pointer position
+    void low_level_write(short x);
+    //!Write an integer value at the current file pointer position
+    void low_level_write(int x);
+    //!Write a float value at the current file pointer position
+    void low_level_write(float x);
+    //!Write a double value at the current file pointer position
+    void low_level_write(double x);
+    //!Write a float complex value at the current file pointer position
+    void low_level_write(const std::complex<float>& x);
+    //!Write a double complex value at the current file pointer position
+    void low_level_write(const std::complex<double>& x);
+    //!Write a vec at the current file pointer position
+    void low_level_write(const vec& v);
+    //!Write an ivec at the current file pointer position
+    void low_level_write(const ivec& v);
+    //!Write a bvec at the current file pointer position
+    void low_level_write(const bvec& v);
+    //!Write a cvec at the current file pointer position
+    void low_level_write(const cvec& v);
+    //!Write a string at the current file pointer position
+    void low_level_write(const std::string& str);
+    //!Write a mat at the current file pointer position
+    void low_level_write(const mat& m);
+    //!Write a imat at the current file pointer position
+    void low_level_write(const imat& m);
+    //!Write a bmat at the current file pointer position
+    void low_level_write(const bmat& m);
+    //!Write a cmat at the current file pointer position
+    void low_level_write(const cmat& m);
+    //!Write a float Array at the current file pointer position
+    void low_level_write(const Array<float>& v);
+    //!Write a double Array at the current file pointer position
+    void low_level_write(const Array<double>& v);
+    //!Write a integer Array at the current file pointer position
+    void low_level_write(const Array<int>& v);
+    //!Write a bin Array at the current file pointer position
+    void low_level_write(const Array<bin>& v);
+    //!Write a float complex Array at the current file pointer position
+    void low_level_write(const Array<std::complex<float> >& v);
+    //!Write a double complex Array at the current file pointer position
+    void low_level_write(const Array<std::complex<double> >& v);
+
+    //!ACTTION: ADD DOCUMENTATION FOR THIS MEMBER !!!!!!!!
+    it_file_old& operator<<(it_manip func) { return (*func)(*this); }
+
+    //! Removes the variable \c name from the file.
+    void remove(const std::string& name);
+    //! Returns true if the variable \c name exists in the file.
+    bool exists(const std::string& name);
+    //! Remove slack space from the file.
+    void pack();
+
+  protected:
+    //! ACTION: Add documenation for this protected member
+    void remove();
+    //! ACTION: Add documenation for this protected member
+    void write_data_header_here(const data_header& h);
+
+    //! ACTION: Add documenation for this protected member
+    bool low_prec;
+    //! ACTION: Add documenation for this protected member
+    std::string next_name;
+  };
+
+  /*!
+    \brief Flush operator.
+    \ingroup itfile
+
+    Flushes the data. Usage:
+
+    \code
+    vec v1("1 2 3"), v2;
+    it_file_old f("file.it");
+    f << Name("v") << v1 << flush;
+    \endcode
+  */
+  inline it_file_old& flush(it_file_old& f)
+    {
+      f.flush();
+      return f;
+    }
+
+
+  /*! \addtogroup itfile */
+  //!@{
+
+  //!Finds the variable \c Name in the \c it_ifile_old. Returns file pointer for reading.
+  inline it_ifile_old& operator>>(it_ifile_old& f, const Name& s)
+    {
+      f.seek(s.name);
+      return f;
+    }
+
+  //!Finds the variable \c Name in the \c it_file_old. Returns file pointer for writing.
+  inline it_file_old& operator<<(it_file_old& f, const Name& s)
+    {
+      f.set_next_name(s.name);
+      return f;
+    }
+
+  //!Read the char variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, char& v);
+
+  //!Read the binary variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, bin& v);
+
+  //!Read the short variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, short& v);
+
+  //!Read the integer variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, int& v);
+
+  //!Read the float variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, float& v);
+
+  //!Read the double variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, double& v);
+
+  //!Read the float complex variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, std::complex<float>& v);
+
+  //!Read the double complex variable \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, std::complex<double>& v);
+
+  //!Read the vec \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, vec& v);
+
+  //!Read the ivec \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, ivec& v);
+
+  //!Read the bvec \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, bvec& v);
+
+  //!Read the cvec \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, cvec& v);
+
+  //!Read the string \c str from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, std::string& str);
+
+  //!Read the mat \c m from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, mat& m);
+
+  //!Read the imat \c m from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, imat& m);
+
+  //!Read the bmat \c m from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, bmat& m);
+
+  //!Read the cmat \c m from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, cmat& m);
+
+  //!Read the float Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<float>& v);
+
+  //!Read the double Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<double>& v);
+
+  //!Read the integer Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<int>& v);
+
+  //!Read the binary Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<bin>& v);
+
+  //!Read the float complex Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<std::complex<float> >& v);
+
+  //!Read the double complex Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<std::complex<double> >& v);
+
+  //!Read the vec Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<vec>& v);
+
+  //!Read the ivec Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<ivec>& v);
+
+  //!Read the bvec Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<bvec>& v);
+
+  //!Read the cvec Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<cvec>& v);
+
+  //!Read the string Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<std::string>& v);
+
+  //!Read the mat Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<mat>& v);
+
+  //!Read the imat Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<imat>& v);
+
+  //!Read the bmat Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<bmat>& v);
+
+  //!Read the cmat Array \c v from the \c it_ifile_old pointer
+  it_ifile_old& operator>>(it_ifile_old& f, Array<cmat>& v);
+
+
+  //!Write the char variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, char x);
+
+  //!Write the binary variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, bin x);
+
+  //!Write the short variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, short x);
+
+  //!Write the integer variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, int x);
+
+  //!Write the float variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, float x);
+
+  //!Write the double variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, double x);
+
+  //!Write the float complex variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, std::complex<float> x);
+
+  //!Write the double complex variable \c x to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, std::complex<double> x);
+
+  //!Write the vec \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const vec& v);
+
+  //!Write the ivec \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const ivec& v);
+
+  //!Write the bvec \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const bvec& v);
+
+  //!Write the cvec \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const cvec& v);
+
+  //!Write the string \c str to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const std::string& str);
+
+  //!Write the mat \c m to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const mat& m);
+
+  //!Write the imat \c m to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const imat& m);
+
+  //!Write the bmat \c m to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const bmat& m);
+
+  //!Write the cmat \c m to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const cmat& m);
+
+  //!Write the float Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<float>& v);
+
+  //!Write the double Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<double>& v);
+
+  //!Write the int Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<int>& v);
+
+  //!Write the bin Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<bin>& v);
+
+  //!Write the float complex Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<std::complex<float> >& v);
+
+  //!Write the double complex Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<std::complex<double> >& v);
+
+  //!Write the vec Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<vec>& v);
+
+  //!Write the ivec Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<ivec>& v);
+
+  //!Write the bvec Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<bvec>& v);
+
+  //!Write the cvec Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<cvec>& v);
+
+  //!Write the string Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<std::string>& v);
+
+  //!Write the mat Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<mat>& v);
+
+  //!Write the imat Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<imat>& v);
+
+  //!Write the bmat Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<bmat>& v);
+
+  //!Write the cmat Array \c v to the \c it_file_old pointer
+  it_file_old& operator<<(it_file_old& f, const Array<cmat>& v);
+
+  //!@}
+
+  // ----------------------------------------------------------------------
+  // End of the deprecated implementation of IT++ file format version 2
+  // Will be removed in future versions
+  // ----------------------------------------------------------------------
+
+} // namespace itpp
+
+#endif // #ifndef IT_FILE_H
+
Index: /win32/itpp-4.0.1/itpp/base/bessel.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/bessel.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/bessel.h (revision 35)
@@ -0,0 +1,139 @@
+/*!
+ * \file
+ * \brief Definitions of Bessel functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef BESSEL_H
+#define BESSEL_H
+
+#include <itpp/base/vec.h>
+
+
+namespace itpp {
+
+  /*! \addtogroup besselfunctions
+   */
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of first kind of order \a nu for \a nu integer
+
+    The bessel function of first kind is defined as:
+    \f[
+    J_{\nu}(x) = \sum_{k=0}^{\infty} \frac{ (-1)^{k} }{k! \Gamma(\nu+k+1) } \left(\frac{x}{2}\right)^{\nu+2k}
+    \f]
+    where \f$\nu\f$ is the order and \f$ 0 < x < \infty \f$.
+  */
+  double besselj(int nu, double x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of first kind of order \a nu for \a nu integer
+  */
+  vec besselj(int nu, const vec &x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of first kind of order \a nu. \a nu is real.
+  */
+  double besselj(double nu, double x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of first kind of order \a nu. \a nu is real.
+  */
+  vec besselj(double nu, const vec &x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of second kind of order \a nu. \a nu is integer.
+
+    The Bessel function of second kind is defined as:
+    \f[
+    Y_{\nu}(x) = \frac{J_{\nu}(x) \cos(\nu\pi) - J_{-\nu}(x)}{\sin(\nu\pi)}
+    \f]
+    where \f$\nu\f$ is the order and \f$ 0 < x < \infty \f$.
+  */
+  double bessely(int nu, double x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of second kind of order \a nu. \a nu is integer.
+  */
+  vec bessely(int nu, const vec &x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of second kind of order \a nu. \a nu is real.
+  */
+  double bessely(double nu, double x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Bessel function of second kind of order \a nu. \a nu is real.
+  */
+  vec bessely(double nu, const vec &x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Modified Bessel function of first kind of order \a nu. \a nu is \a double. \a x is \a double.
+
+    The Modified Bessel function of first kind is defined as:
+    \f[
+    I_{\nu}(x) = i^{-\nu} J_{\nu}(ix)
+    \f]
+    where \f$\nu\f$ is the order and \f$ 0 < x < \infty \f$.
+  */
+  double besseli(double nu, double x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Modified Bessel function of first kind of order \a nu. \a nu is \a double. \a x is \a double.
+  */
+  vec besseli(double nu, const vec &x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Modified Bessel function of second kind of order \a nu. \a nu is double. \a x is double.
+
+    The Modified Bessel function of second kind is defined as:
+    \f[
+    K_{\nu}(x) = \frac{\pi}{2} i^{\nu+1} [J_{\nu}(ix) + i Y_{\nu}(ix)]
+    \f]
+    where \f$\nu\f$ is the order and \f$ 0 < x < \infty \f$.
+  */
+  double besselk(int nu, double x);
+
+  /*!
+    \ingroup besselfunctions
+    \brief Modified Bessel function of second kind of order \a nu. \a nu is double. \a x is double.
+  */
+  vec besselk(int nu, const vec &x);
+
+} //namespace itpp
+
+#endif // #ifndef BESSEL_H
Index: /win32/itpp-4.0.1/itpp/base/vec.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/vec.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/vec.h (revision 35)
@@ -0,0 +1,2046 @@
+/*!
+ * \file
+ * \brief Templated Vector Class Definitions
+ * \author Tony Ottosson, Tobias Ringstrom, Adam Piatyszek and Conrad Sanderson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef VEC_H
+#define VEC_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/itassert.h>
+#include <itpp/base/math/misc.h>
+#include <itpp/base/copy_vector.h>
+#include <itpp/base/factory.h>
+
+
+namespace itpp {
+
+  // Declaration of Vec
+  template<class Num_T> class Vec;
+  // Declaration of Mat
+  template<class Num_T> class Mat;
+  // Declaration of bin
+  class bin;
+
+  //-----------------------------------------------------------------------------------
+  // Declaration of Vec Friends
+  //-----------------------------------------------------------------------------------
+
+  //! Addition of two vectors
+  template<class Num_T> const Vec<Num_T> operator+(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Addition of a vector and a scalar
+  template<class Num_T> const Vec<Num_T> operator+(const Vec<Num_T> &v, const Num_T t);
+  //! Addition of a scalar and a vector
+  template<class Num_T> const Vec<Num_T> operator+(const Num_T t, const Vec<Num_T> &v);
+
+  //! Subtraction of a vector from a vector
+  template<class Num_T> const Vec<Num_T> operator-(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Subtraction of a scalar from a vector
+  template<class Num_T> const Vec<Num_T> operator-(const Vec<Num_T> &v, const Num_T t);
+  //! Subtraction of vector from scalar. Results in a vector
+  template<class Num_T> const Vec<Num_T> operator-(const Num_T t, const Vec<Num_T> &v);
+  //! Negation of vector
+  template<class Num_T> const Vec<Num_T> operator-(const Vec<Num_T> &v);
+
+  //! Inner (dot) product of two vectors v1 and v2
+  template<class Num_T> Num_T dot(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Inner (dot) product of two vectors v1 and v2
+  template<class Num_T> Num_T operator*(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  /*!
+   * \brief Outer product of two vectors v1 and v2
+   *
+   * When \a v1 and \a v2 are complex vectors (cvec), the third boolean
+   * argument \a hermitian can be set to \a true to conjugate \a v2
+   * (Matlab's v1 * v2' operation). This parameter is ignored for types
+   * other then cvec.
+   */
+  template<class Num_T>
+  const Mat<Num_T> outer_product(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+				 bool hermitian = false);
+  //! Multiplication of a vector and a scalar
+  template<class Num_T> const Vec<Num_T> operator*(const Vec<Num_T> &v, const Num_T t);
+  //! Multiplication of a scalar and a vector. Results in a vector
+  template<class Num_T> const Vec<Num_T> operator*(const Num_T t, const Vec<Num_T> &v);
+
+  //! Element-wise multiplication of the two vectors.  Same functionality as Matlab/Octave expression a .* b
+  template<class Num_T> const Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b);
+  //! Element-wise multiplication of the three vectors
+  template<class Num_T> const Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c);
+  //! Element-wise multiplication of the four vectors
+  template<class Num_T> const Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, const Vec<Num_T> &d);
+
+  //! Element-wise multiplication of the two vectors, storing the result in vector \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_mult_out(const Vec<Num_T> &a, const Vec<Num_T> &b, Vec<Num_T> &out);
+  //! Element-wise multiplication of the three vectors, storing the result in vector \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_mult_out(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, Vec<Num_T> &out);
+  //! Element-wise multiplication of the four vectors, storing the result in vector \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_mult_out(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, const Vec<Num_T> &d, Vec<Num_T> &out);
+
+  //! In-place element-wise multiplication of two vectors. Fast version of b = elem_mult(a,b)
+  template<class Num_T> void elem_mult_inplace(const Vec<Num_T> &a, Vec<Num_T> &b);
+  //! Element-wise multiplication of two vectors, followed by summation of the resultant elements. Fast version of sum(elem_mult(a,b))
+  template<class Num_T> Num_T elem_mult_sum(const Vec<Num_T> &a, const Vec<Num_T> &b);
+
+  //! Division of all elements in \c v with \c t
+  template<class Num_T> const Vec<Num_T> operator/(const Vec<Num_T> &v, const Num_T t);
+  //! Division of \c t with all elements in \c v
+  template<class Num_T> const Vec<Num_T> operator/(const Num_T t, const Vec<Num_T> &v);
+
+  //! Elementwise division of two vectors. Same functionality as Matlab/Octave expression a ./ b
+  template<class Num_T> const Vec<Num_T> elem_div(const Vec<Num_T> &a, const Vec<Num_T> &b);
+  //! Elementwise division of scalar \c t and vector \c v
+  template<class Num_T> const Vec<Num_T> elem_div(const Num_T t, const Vec<Num_T> &v);
+  //! Elementwise division of two vectors, storing the result in vector \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_div_out(const Vec<Num_T> &a, const Vec<Num_T> &b, Vec<Num_T> &out);
+  //! Elementwise division of two vectors, followed by summation of the resultant elements. Fast version of sum(elem_div(a,b))
+  template<class Num_T> Num_T elem_div_sum(const Vec<Num_T> &a, const Vec<Num_T> &b);
+
+  //! Append element \c a to the end of the vector \c v
+  template<class Num_T> const Vec<Num_T> concat(const Vec<Num_T> &v, const Num_T a);
+  //! Concat element \c a to the beginning of the vector \c v
+  template<class Num_T> const Vec<Num_T> concat(const Num_T a, const Vec<Num_T> &v);
+  //! Concat vectors \c v1 and \c v2
+  template<class Num_T> const Vec<Num_T> concat(const Vec<Num_T> &v1,const Vec<Num_T> &v2);
+  //! Concat vectors \c v1, \c v2 and \c v3
+  template<class Num_T> const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2, const Vec<Num_T> &v3);
+  //! Concat vectors \c v1, \c v2, \c v3 and \c v4
+  template<class Num_T> const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2, const Vec<Num_T> &v3, const Vec<Num_T> &v4);
+  //! Concat vectors \c v1, \c v2 \c v3, \c v4 and \c v5
+  template<class Num_T> const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2, const Vec<Num_T> &v3, const Vec<Num_T> &v4, const Vec<Num_T> &v5);
+
+  //-----------------------------------------------------------------------------------
+  // Declaration of Vec
+  //-----------------------------------------------------------------------------------
+
+  /*!
+    \ingroup arr_vec_mat
+    \brief Vector Class (Templated)
+    \author Tony Ottosson, Tobias Ringstrom, Adam Piatyszek and Conrad Sanderson
+
+    Vectors can be of arbitrarily types, but conversions and functions are
+    prepared for \c bin, \c short, \c int, \c double, and \c complex<double>
+    vectors and these are predefined as: \c bvec, \c svec, \c ivec, \c vec,
+    and \c cvec. \c double and \c complex<double> are \c double and
+    \c complex<double> respectively.
+
+    Examples:
+
+    Vector Constructors:
+    When constructing a vector without a length (memory) use
+    \code vec temp; \endcode
+    For construction of a vector of a given length use
+    \code vec temp(length); \endcode
+    It is also possible to assign the constructed vector the value and size
+    of another vector by
+    \code vec temp(invector); \endcode
+    If you have explicit values you would like to assign to the vector it is
+    possible to do this using strings as:
+    \code
+    vec a("0 0.7 5 9.3"); // that is a = [0, 0.7, 5, 9.3]
+    vec a="0 0.7 5 9.3";  // the constructor are called implicitly
+    ivec b="0:5";  // that is b = [0, 1, 2, 3, 4, 5]
+    vec c="3:2.5:13";  // that is c = [3, 5.5, 8, 10.5, 13]
+    \endcode
+    It is also possible to change length by
+    \code temp.set_size(new_length, false); \endcode
+    where \c false is used to indicate that the old values in \c temp
+    is not copied. If you like to preserve the values use \c true.
+
+    There are a number of methods to access parts of a vector. Examples are
+    \code
+    a(5);     // Element number 5
+    a(5,9);  // Elements 5, 6, 7, 8, and 9
+    a.left(10);  // The 10 most left elements (the first)
+    a.right(10); // The 10 most right elements (the last)
+    a.mid(5, 7); // 7 elements starting from element 5
+    \endcode
+
+    It is also possible to modify parts of a vector as e.g. in
+    \code
+    a.del(5);    // deletes element number 5
+    a.ins(3.4, 9); // inserts the element 3.4 at position 9
+    a.replace_mid(12, b); // replaces elements from 12 with the vector b
+    \endcode
+
+    It is of course also possible to perform the common linear algebra
+    methods such as addition, subtraction, and scalar product (*). Observe
+    though, that vectors are assumed to be column-vectors in operations with
+    matrices.
+
+    Most elementary functions such as sin(), cosh(), log(), abs(), ..., are
+    available as operations on the individual elements of the vectors. Please
+    see the individual functions for more details.
+
+    By default, the Vec elements are created using the default constructor for
+    the element type. This can be changed by specifying a suitable Factory in
+    the Vec constructor call; see Detailed Description for Factory.
+  */
+  template<class Num_T>
+  class Vec {
+  public:
+    //! The type of the vector values
+    typedef Num_T value_type;
+
+    //! Default constructor. An element factory \c f can be specified.
+    explicit Vec(const Factory &f = DEFAULT_FACTORY);
+    //! Constructor with size parameter. An element factory \c f can be specified.
+    explicit Vec(int size, const Factory &f = DEFAULT_FACTORY);
+    //! Copy constructor
+    Vec(const Vec<Num_T> &v);
+    //! Copy constructor, which takes an element factory \c f as an additional argument.
+    Vec(const Vec<Num_T> &v, const Factory &f);
+    //! Constructor taking a char string as input. An element factory \c f can be specified.
+    Vec(const char *values, const Factory &f = DEFAULT_FACTORY);
+    //! Constructor taking a string as input. An element factory \c f can be specified.
+    Vec(const std::string &values, const Factory &f = DEFAULT_FACTORY);
+    //! Constructor taking a C-array as input. Copies all data. An element factory \c f can be specified.
+    Vec(const Num_T *c_array, int size, const Factory &f = DEFAULT_FACTORY);
+
+    //! Destructor
+    ~Vec();
+
+    //! The size of the vector
+    int length() const { return datasize; }
+    //! The size of the vector
+    int size() const { return datasize; }
+
+    //! Set length of vector. if copy = true then keeping the old values
+    void set_size(int size, const bool copy=false);
+    //! Set length of vector. if copy = true then keeping the old values
+    void set_length(int size, const bool copy=false) { set_size(size, copy); }
+    //! Set the vector to the all zero vector
+    void zeros();
+    //! Set the vector to the all zero vector
+    void clear() { zeros(); }
+    //! Set the vector to the all one vector
+    void ones();
+    //! Set the vector equal to the values in the \c str string
+    void set(const char *str);
+    //! Set the vector equal to the values in the \c str string
+    void set(const std::string &str);
+
+    //! C-style index operator. First element is 0
+    const Num_T &operator[](int i) const;
+    //! Index operator. First element is 0
+    const Num_T &operator()(int i) const;
+    //! C-style index operator. First element is 0
+    Num_T &operator[](int i);
+    //! Index operator. First element is 0
+    Num_T &operator()(int i);
+    //! Sub-vector with elements from \c i1 to \c i2. Index -1 indicates the last element.
+    const Vec<Num_T> operator()(int i1, int i2) const;
+    //! Sub-vector where the elements are given by the list \c indexlist
+    const Vec<Num_T> operator()(const Vec<int> &indexlist) const;
+
+    //! Accessor-style method. First element is 0
+    const Num_T &get(int i) const;
+    //! Sub-vector with elements from \c i1 to \c i2. Index -1 indicates the last element.
+    const Vec<Num_T> get(int i1, int i2) const;
+    //! Modifier-style method. First element is 0
+    void set(int i, const Num_T &v);
+
+    //! Matrix transpose. Converts to a matrix with the vector in the first row
+    Mat<Num_T> transpose() const;
+    //! Matrix transpose. Converts to a matrix with the vector in the first row
+    Mat<Num_T> T() const { return this->transpose(); }
+    //! Hermitian matrix transpose. Converts to a matrix with the conjugate of the vector in the first row
+    Mat<Num_T> hermitian_transpose() const;
+    //! Hermitian matrix transpose. Converts to a matrix with the conjugate of the vector in the first row
+    Mat<Num_T> H() const { return this->hermitian_transpose(); }
+
+    //! Addition of vector
+    Vec<Num_T>& operator+=(const Vec<Num_T> &v);
+    //! Addition of scalar
+    Vec<Num_T>& operator+=(const Num_T t);
+    //! Addition of two vectors
+    friend const Vec<Num_T> operator+<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+    //! Addition of a vector and a scalar
+    friend const Vec<Num_T> operator+<>(const Vec<Num_T> &v, const Num_T t);
+    //! Addition of a scalar and a vector
+    friend const Vec<Num_T> operator+<>(const Num_T t, const Vec<Num_T> &v);
+
+    //! Subtraction of vector
+    Vec<Num_T>& operator-=(const Vec<Num_T> &v);
+    //! Subtraction of scalar
+    Vec<Num_T>& operator-=(const Num_T t);
+    //! Subtraction of \c v2 from \c v1
+    friend const Vec<Num_T> operator-<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+    //! Subtraction of scalar from vector
+    friend const Vec<Num_T> operator-<>(const Vec<Num_T> &v, const Num_T t);
+    //! Sutraction of vector from scalar
+    friend const Vec<Num_T> operator-<>(const Num_T t, const Vec<Num_T> &v);
+    //! Negation of vector
+    friend const Vec<Num_T> operator-<>(const Vec<Num_T> &v);
+
+    //! Multiply with a scalar
+    Vec<Num_T>& operator*=(const Num_T t);
+    //! Inner (dot) product
+    friend Num_T operator*<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+    //! Inner (dot) product
+    friend Num_T dot <>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+    //! Outer product of two vectors v1 and v2
+    friend const Mat<Num_T> outer_product <>(const Vec<Num_T> &v1,
+					     const Vec<Num_T> &v2,
+					     bool hermitian);
+    //! Elementwise multiplication of vector and scalar
+    friend const Vec<Num_T> operator*<>(const Vec<Num_T> &v, const Num_T t);
+    //! Elementwise multiplication of vector and scalar
+    friend const Vec<Num_T> operator*<>(const Num_T t, const Vec<Num_T> &v);
+
+    //! Elementwise multiplication
+    friend const Vec<Num_T> elem_mult <>(const Vec<Num_T> &a, const Vec<Num_T> &b);
+    //! Elementwise multiplication of three vectors
+    friend const Vec<Num_T> elem_mult <>(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c);
+    //! Elementwise multiplication of four vectors
+    friend const Vec<Num_T> elem_mult <>(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, const Vec<Num_T> &d);
+
+    //! Elementwise multiplication, storing the result in vector \c out (which is re-sized if necessary)
+    friend void elem_mult_out <>(const Vec<Num_T> &a, const Vec<Num_T> &b, Vec<Num_T> &out);
+    //! Elementwise multiplication of three vectors, storing the result in vector \c out (which is re-sized if necessary)
+    friend void elem_mult_out <>(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, Vec<Num_T> &out);
+    //! Elementwise multiplication of four vectors, storing the result in vector \c out (which is re-sized if necessary)
+    friend void elem_mult_out <>(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, const Vec<Num_T> &d, Vec<Num_T> &out);
+
+    //! In-place element-wise multiplication of two vectors. Fast version of b = elem_mult(a,b)
+    friend void elem_mult_inplace <>(const Vec<Num_T> &a, Vec<Num_T> &b);
+    //! Element-wise multiplication of two vectors, followed by summation of the resultant elements. Fast version of sum(elem_mult(a,b))
+    friend Num_T elem_mult_sum <>(const Vec<Num_T> &a, const Vec<Num_T> &b);
+
+    //! Elementwise division
+    Vec<Num_T>& operator/=(const Num_T t);
+    //! Elementwise division
+    Vec<Num_T>& operator/=(const Vec<Num_T> &v);
+
+    //! Elementwise division
+    friend const Vec<Num_T> operator/<>(const Vec<Num_T> &v, const Num_T t);
+    //! Elementwise division
+    friend const Vec<Num_T> operator/<>(const Num_T t, const Vec<Num_T> &v);
+
+    //! Elementwise division
+    friend const Vec<Num_T> elem_div <>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+    //! Elementwise division
+    friend const Vec<Num_T> elem_div <>(const Num_T t, const Vec<Num_T> &v);
+    //! Elementwise division
+    friend void elem_div_out <>(const Vec<Num_T> &v1, const Vec<Num_T> &v2, Vec<Num_T> &out);
+    //! Elementwise division, followed by summation of the resultant elements. Fast version of sum(elem_mult(a,b))
+    friend Num_T elem_div_sum <>(const Vec<Num_T> &a, const Vec<Num_T> &b);
+
+    //! Get the elements in the vector where \c binlist is \c 1
+    Vec<Num_T> get(const Vec<bin> &binlist) const;
+    //! Get the right \c nr elements from the vector
+    Vec<Num_T> right(int nr) const;
+    //! Get the left \c nr elements from the vector
+    Vec<Num_T> left(int nr) const;
+    //! Get the middle part of vector from \c start including \c nr elements
+    Vec<Num_T> mid(int start, int nr) const;
+    //! Split the vector into two parts at element \c pos. Return the first part and keep the second.
+    Vec<Num_T> split(int pos);
+    //! Shift in element \c In at position 0 \c n times
+    void shift_right(const Num_T In, int n=1);
+    //! Shift in vector \c In at position 0
+    void shift_right(const Vec<Num_T> &In);
+    //! Shift out the \c n left elements and a the same time shift in the element \c at last position \c n times
+    void shift_left(const Num_T In, int n=1);
+    //! Shift in vector \c In at last position
+    void shift_left(const Vec<Num_T> &In);
+
+    //! Append element \c a to the end of the vector \c v
+    friend const Vec<Num_T> concat<>(const Vec<Num_T> &v, const Num_T a);
+    //! Concat element \c a to the beginning of the vector \c v
+    friend const Vec<Num_T> concat<>(const Num_T a, const Vec<Num_T> &v);
+    //! Concat vectors \c v1 and \c v2
+    friend const Vec<Num_T> concat<>(const Vec<Num_T> &v1,const Vec<Num_T> &v2);
+    //! Concat vectors \c v1, \c v2 and \c v3
+    friend const Vec<Num_T> concat<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+				     const Vec<Num_T> &v3);
+    //! Concat vectors \c v1, \c v2, \c v3 and \c v4
+    friend const Vec<Num_T> concat<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+				     const Vec<Num_T> &v3, const Vec<Num_T> &v4);
+    //! Concat vectors \c v1, \c v2, \c v3, \c v4 and \c v5
+    friend const Vec<Num_T> concat<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+				     const Vec<Num_T> &v3, const Vec<Num_T> &v4,
+				     const Vec<Num_T> &v5);
+
+    //! Set subvector defined by indicies \c i1 to \c i2 to vector \c v
+    void set_subvector(int i1, int i2, const Vec<Num_T> &v);
+    //! Set subvector defined by first index \c i and size of vector \c v to \c v
+    void set_subvector(int i, const Vec<Num_T> &v);
+    //! Set subvector defined by indicies i1 to i2 to constant t
+    void set_subvector(int i1, int i2, const Num_T t);
+    //! Replace the elements from \c pos by the vector \c v
+    void replace_mid(int pos, const Vec<Num_T> &v);
+    //! Delete element number \c index
+    void del(int index);
+    //! Delete elements from \c i1 to \c i2
+    void del(int i1, int i2);
+    //! Insert element \c in at \c index
+    void ins(int index, const Num_T in);
+    //! Insert vector \c in at \c index
+    void ins(int index, const Vec<Num_T> &in);
+
+    //! Assign all elements in vector to \c t
+    Vec<Num_T>& operator=(const Num_T t);
+    //! Assign vector the value and length of \c v
+    Vec<Num_T>& operator=(const Vec<Num_T> &v);
+    //! Assign vector equal to the 1-dimensional matrix \c m
+    Vec<Num_T>& operator=(const Mat<Num_T> &m);
+    //! Assign vector the values in the string \c values
+    Vec<Num_T>& operator=(const char *values);
+
+    //! Elementwise equal to the scalar
+    Vec<bin> operator==(const Num_T value) const;
+    //! Elementwise not-equal to the scalar
+    Vec<bin> operator!=(const Num_T value) const;
+    //! Elementwise less than the scalar
+    Vec<bin> operator<(const Num_T value) const;
+    //! Elementwise less than and equal to the scalar
+    Vec<bin> operator<=(const Num_T value) const;
+    //! Elementwise greater than the scalar
+    Vec<bin> operator>(const Num_T value) const;
+    //! Elementwise greater than and equal to the scalar
+    Vec<bin> operator>=(const Num_T value) const;
+
+    //! Compare two vectors. False if wrong sizes or different values
+    bool operator==(const Vec<Num_T> &v) const;
+    //! Compare two vectors. True if different
+    bool operator!=(const Vec<Num_T> &v) const;
+
+    //! Index operator without boundary check. Not recommended to use.
+    Num_T &_elem(int i) { return data[i]; }
+    //! Index operator without boundary check. Not recommended to use.
+    const Num_T &_elem(int i) const { return data[i]; }
+
+    //! Get the pointer to the internal structure. Not recommended to use.
+    Num_T *_data() { return data; }
+    //! Get the pointer to the internal structure. Not recommended to use.
+    const Num_T *_data() const { return data; }
+
+  protected:
+    //! Allocate storage for a vector of length \c size.
+    void alloc(int size);
+    //! Free the storage space allocated by the vector
+    void free();
+
+    //! The current number of elements in the vector
+    int datasize;
+    //! A pointer to the data area
+    Num_T *data;
+    //! Element factory (set to DEFAULT_FACTORY to use Num_T default constructors only)
+    const Factory &factory;
+  private:
+    // This function is used in set() methods to replace commas with spaces
+    std::string replace_commas(const std::string &str);
+  };
+
+  //-----------------------------------------------------------------------------------
+  // Type definitions of vec, cvec, ivec, svec, and bvec
+  //-----------------------------------------------------------------------------------
+
+  /*!
+    \relates Vec
+    \brief Definition of double vector type
+  */
+  typedef Vec<double> vec;
+
+  /*!
+    \relates Vec
+    \brief Definition of complex<double> vector type
+  */
+  typedef Vec<std::complex<double> > cvec;
+
+  /*!
+    \relates Vec
+    \brief Definition of integer vector type
+  */
+  typedef Vec<int> ivec;
+
+  /*!
+    \relates Vec
+    \brief Definition of short vector type
+  */
+  typedef Vec<short int> svec;
+
+  /*!
+    \relates Vec
+    \brief Definition of binary vector type
+  */
+  typedef Vec<bin> bvec;
+
+} //namespace itpp
+
+
+#include <itpp/base/mat.h>
+
+namespace itpp {
+
+  //-----------------------------------------------------------------------------------
+  // Declaration of input and output streams for Vec
+  //-----------------------------------------------------------------------------------
+
+  /*!
+    \relates Vec
+    \brief Stream output of vector
+  */
+  template<class Num_T>
+  std::ostream &operator<<(std::ostream &os, const Vec<Num_T> &v);
+
+  /*!
+    \relates Vec
+    \brief Stream input of vector
+
+    The input can be on the form "1 2 3" or "[1 2 3]", i.e. with or without
+    brackets. The first form is compatible with the set method, while the
+    second form is compatible with the ostream operator. The elements can be
+    separated by blank space or commas. "[]" means an empty vector. "1:4"
+    means "1 2 3 4". "1:3:10" means every third integer from 1 to 10, i.e.
+    "1 4 7 10".
+  */
+  template<class Num_T>
+  std::istream &operator>>(std::istream &is, Vec<Num_T> &v);
+
+  //-----------------------------------------------------------------------------------
+  // Implementation of templated Vec members and friends
+  //-----------------------------------------------------------------------------------
+
+  template<class Num_T> inline
+  void Vec<Num_T>::alloc(int size)
+  {
+    if (size > 0) {
+      create_elements(data, size, factory);
+      datasize = size;
+    }
+    else {
+      data = 0;
+      datasize = 0;
+    }
+  }
+
+  template<class Num_T> inline
+  void Vec<Num_T>::free()
+  {
+    destroy_elements(data, datasize);
+    datasize = 0;
+  }
+
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(const Factory &f) : datasize(0), data(0), factory(f) {}
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(int size, const Factory &f) : datasize(0), data(0), factory(f)
+  {
+    it_assert_debug(size>=0, "Negative size in Vec::Vec(int)");
+    alloc(size);
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(const Vec<Num_T> &v) : datasize(0), data(0), factory(v.factory)
+  {
+    alloc(v.datasize);
+    copy_vector(datasize, v.data, data);
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(const Vec<Num_T> &v, const Factory &f) : datasize(0), data(0), factory(f)
+  {
+    alloc(v.datasize);
+    copy_vector(datasize, v.data, data);
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(const char *values, const Factory &f) : datasize(0), data(0), factory(f)
+  {
+    set(values);
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(const std::string &values, const Factory &f) : datasize(0), data(0), factory(f)
+  {
+    set(values);
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>::Vec(const Num_T *c_array, int size, const Factory &f) : datasize(0), data(0), factory(f)
+  {
+    alloc(size);
+    copy_vector(size, c_array, data);
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>::~Vec()
+  {
+    free();
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::set_size(int size, bool copy)
+  {
+    it_assert_debug(size >= 0, "Vec::set_size(): New size must not be negative");
+    if (datasize == size)
+      return;
+    if (copy) {
+      // create a temporary pointer to the allocated data
+      Num_T* tmp = data;
+      // store the current number of elements
+      int old_datasize = datasize;
+      // check how many elements we need to copy
+      int min = datasize < size ? datasize : size;
+      // allocate new memory
+      alloc(size);
+      // copy old elements into a new memory region
+      copy_vector(min, tmp, data);
+      // initialize the rest of resized vector
+      for (int i = min; i < size; ++i)
+	data[i] = Num_T(0);
+      // delete old elements
+      destroy_elements(tmp, old_datasize);
+    }
+    else {
+      free();
+      alloc(size);
+    }
+  }
+
+  template<class Num_T> inline
+  const Num_T& Vec<Num_T>::operator[](int i) const
+  {
+    it_assert_debug((i >= 0) && (i < datasize), "Vec::operator[]: Index out of range");
+    return data[i];
+  }
+
+  template<class Num_T> inline
+  const Num_T& Vec<Num_T>::operator()(int i) const
+  {
+    it_assert_debug((i >= 0) && (i < datasize), "Vec::operator(): Index out of range");
+    return data[i];
+  }
+
+  template<class Num_T> inline
+  Num_T& Vec<Num_T>::operator[](int i)
+  {
+    it_assert_debug((i >= 0) && (i < datasize), "Vec::operator[]: Index out of range");
+    return data[i];
+  }
+
+  template<class Num_T> inline
+  Num_T& Vec<Num_T>::operator()(int i)
+  {
+    it_assert_debug((i >= 0) && (i < datasize), "Vec::operator(): Index out of range");
+    return data[i];
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> Vec<Num_T>::operator()(int i1, int i2) const
+  {
+    int ii1=i1, ii2=i2;
+
+    if (ii1 == -1) ii1 = datasize-1;
+    if (ii2 == -1) ii2 = datasize-1;
+
+    it_assert_debug(ii1>=0 && ii2>=0 && ii1<datasize && ii2<datasize, "Vec::operator()(i1,i2): indicies out of range");
+    it_assert_debug(ii2>=ii1, "Vec::op(i1,i2): i2 >= i1 necessary");
+
+    Vec<Num_T> s(ii2-ii1+1);
+    copy_vector(s.datasize, data+ii1, s.data);
+
+    return s;
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> Vec<Num_T>::operator()(const Vec<int> &indexlist) const
+  {
+    Vec<Num_T> temp(indexlist.length());
+    for (int i=0;i<indexlist.length();i++) {
+      it_assert((indexlist(i)>=0) && (indexlist(i) < datasize), "Vec::operator()(ivec &): index outside range");
+      temp(i)=data[indexlist(i)];
+    }
+    return temp;
+  }
+
+
+  template<class Num_T> inline
+  const Num_T& Vec<Num_T>::get(int i) const
+  {
+    it_assert_debug((i >= 0) && (i < datasize), "method get()");
+    return data[i];
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> Vec<Num_T>::get(int i1, int i2) const
+  {
+    return (*this)(i1, i2);
+  }
+
+
+  template<class Num_T> inline
+  void Vec<Num_T>::zeros()
+  {
+    for (int i = 0; i < datasize; i++)
+      data[i] = Num_T(0);
+  }
+
+  template<class Num_T> inline
+  void Vec<Num_T>::ones()
+  {
+    for (int i = 0; i < datasize; i++)
+      data[i] = Num_T(1);
+  }
+
+  template<class Num_T> inline
+  void Vec<Num_T>::set(int i, const Num_T &v)
+  {
+    it_assert_debug((i >= 0) && (i < datasize), "method set()");
+    data[i] = v;
+  }
+
+  //! \cond
+  template<>
+  void Vec<double>::set(const std::string &str);
+  template<>
+  void Vec<std::complex<double> >::set(const std::string &str);
+  template<>
+  void Vec<int>::set(const std::string &str);
+  template<>
+  void Vec<short int>::set(const std::string &str);
+  template<>
+  void Vec<bin>::set(const std::string &str);
+  //! \endcond
+
+  template<class Num_T>
+  void Vec<Num_T>::set(const std::string &str)
+  {
+    it_error("Vec::set(): Only `double', `complex<double>', `int', "
+	     "`short int' and `bin' types supported");
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::set(const char *str)
+  {
+    set(std::string(str));
+  }
+
+
+  template<class Num_T>
+  Mat<Num_T> Vec<Num_T>::transpose() const
+  {
+    Mat<Num_T> temp(1, datasize);
+    copy_vector(datasize, data, temp._data());
+    return temp;
+  }
+
+  template<>
+  Mat<std::complex<double> > Vec<std::complex<double> >::hermitian_transpose() const;
+
+  template<class Num_T>
+  Mat<Num_T> Vec<Num_T>::hermitian_transpose() const
+  {
+    Mat<Num_T> temp(1, datasize);
+    copy_vector(datasize, data, temp._data());
+    return temp;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator+=(const Vec<Num_T> &v)
+  {
+    if (datasize == 0) { // if not assigned a size.
+      if (this != &v) { // check for self addition
+	alloc(v.datasize);
+	copy_vector(datasize, v.data, data);
+      }
+    } else {
+      it_assert_debug(datasize == v.datasize, "Vec::operator+=: Wrong sizes");
+      for (int i = 0; i < datasize; i++)
+	data[i] += v.data[i];
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator+=(const Num_T t)
+  {
+    for (int i=0;i<datasize;i++)
+      data[i]+=t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator+(const Vec<Num_T> &v1, const Vec<Num_T> &v2)
+  {
+    int i;
+    Vec<Num_T> r(v1.datasize);
+
+    it_assert_debug(v1.datasize==v2.datasize, "Vec::operator+: wrong sizes");
+    for (i=0; i<v1.datasize; i++)
+      r.data[i] = v1.data[i] + v2.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator+(const Vec<Num_T> &v, const Num_T t)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = v.data[i] + t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator+(const Num_T t, const Vec<Num_T> &v)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = t + v.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator-=(const Vec<Num_T> &v)
+  {
+    if (datasize == 0) { // if not assigned a size.
+      if (this != &v) { // check for self decrementation
+	alloc(v.datasize);
+	for (int i = 0; i < v.datasize; i++)
+	  data[i] = -v.data[i];
+      }
+    } else {
+      it_assert_debug(datasize == v.datasize, "Vec::operator-=: Wrong sizes");
+      for (int i = 0; i < datasize; i++)
+	data[i] -= v.data[i];
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator-=(const Num_T t)
+  {
+    for (int i=0;i<datasize;i++)
+      data[i]-=t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator-(const Vec<Num_T> &v1, const Vec<Num_T> &v2)
+  {
+    int i;
+    Vec<Num_T> r(v1.datasize);
+
+    it_assert_debug(v1.datasize==v2.datasize, "Vec::operator-: wrong sizes");
+    for (i=0; i<v1.datasize; i++)
+      r.data[i] = v1.data[i] - v2.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator-(const Vec<Num_T> &v, const Num_T t)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = v.data[i] - t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator-(const Num_T t, const Vec<Num_T> &v)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = t - v.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator-(const Vec<Num_T> &v)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = -v.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator*=(const Num_T t)
+  {
+    scal_vector(datasize, t, data);
+    return *this;
+  }
+
+#if defined(HAVE_BLAS)
+  template<> inline
+  double dot(const vec &v1, const vec &v2)
+  {
+    it_assert_debug(v1.datasize == v2.datasize, "vec::dot: wrong sizes");
+    int incr = 1;
+    return blas::ddot_(&v1.datasize, v1.data, &incr, v2.data, &incr);
+  }
+
+  template<> inline
+  std::complex<double> dot(const cvec &v1, const cvec &v2)
+  {
+    it_assert_debug(v1.datasize == v2.datasize, "cvec::dot: wrong sizes");
+    int incr = 1;
+    std::complex<double> output;
+#if defined(HAVE_ZDOTU_RETURN)
+    output = blas::zdotu_(&v1.datasize, v1.data, &incr, v2.data, &incr);
+#elif defined(HAVE_ZDOTU_VOID)
+    blas::zdotu_(&output, &v1.datasize, v1.data, &incr, v2.data, &incr);
+#else
+    blas::zdotusub_(&output, &v1.datasize, v1.data, &incr, v2.data, &incr);
+#endif // HAVE_ZDOTU_RETURN
+    return output;
+  }
+#endif // HAVE_BLAS
+
+  template<class Num_T> inline
+  Num_T dot(const Vec<Num_T> &v1, const Vec<Num_T> &v2)
+  {
+    int i;
+    Num_T r=Num_T(0);
+
+    it_assert_debug(v1.datasize==v2.datasize, "Vec::dot: wrong sizes");
+    for (i=0; i<v1.datasize; i++)
+      r += v1.data[i] * v2.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Num_T operator*(const Vec<Num_T> &v1, const Vec<Num_T> &v2)
+  {
+    return dot(v1, v2);
+  }
+
+
+#if defined(HAVE_BLAS)
+  template<> inline
+  const mat outer_product(const vec &v1, const vec &v2, bool hermitian)
+  {
+    it_assert_debug((v1.datasize > 0) && (v2.datasize > 0),
+		    "Vec::outer_product():: Input vector of zero size");
+
+    mat out(v1.datasize, v2.datasize);
+    out.zeros();
+    double alpha = 1.0;
+    int incr = 1;
+    blas::dger_(&v1.datasize, &v2.datasize, &alpha, v1.data, &incr,
+		v2.data, &incr, out._data(), &v1.datasize);
+    return out;
+  }
+
+  template<> inline
+  const cmat outer_product(const cvec &v1, const cvec &v2, bool hermitian)
+  {
+    it_assert_debug((v1.datasize > 0) && (v2.datasize > 0),
+		    "Vec::outer_product():: Input vector of zero size");
+
+    cmat out(v1.datasize, v2.datasize);
+    out.zeros();
+    std::complex<double> alpha(1.0);
+    int incr = 1;
+    if (hermitian) {
+      blas::zgerc_(&v1.datasize, &v2.datasize, &alpha, v1.data, &incr,
+		   v2.data, &incr, out._data(), &v1.datasize);
+    }
+    else {
+      blas::zgeru_(&v1.datasize, &v2.datasize, &alpha, v1.data, &incr,
+		   v2.data, &incr, out._data(), &v1.datasize);
+    }
+    return out;
+  }
+#else
+  //! Outer product of two vectors v1 and v2
+  template<> inline
+  const cmat outer_product(const cvec &v1, const cvec &v2, bool hermitian)
+  {
+    it_assert_debug((v1.datasize > 0) && (v2.datasize > 0),
+		    "Vec::outer_product():: Input vector of zero size");
+
+    cmat out(v1.datasize, v2.datasize);
+    if (hermitian) {
+      for (int i = 0; i < v1.datasize; ++i) {
+	for (int j = 0; j < v2.datasize; ++j) {
+	  out(i, j) = v1.data[i] * conj(v2.data[j]);
+	}
+      }
+    }
+    else {
+      for (int i = 0; i < v1.datasize; ++i) {
+	for (int j = 0; j < v2.datasize; ++j) {
+	  out(i, j) = v1.data[i] * v2.data[j];
+	}
+      }
+    }
+    return out;
+  }
+#endif // HAVE_BLAS
+
+  template<class Num_T> inline
+  const Mat<Num_T> outer_product(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+				 bool hermitian)
+  {
+    int i, j;
+
+    it_assert_debug((v1.datasize > 0) && (v2.datasize > 0),
+		    "Vec::outer_product:: Input vector of zero size");
+
+    Mat<Num_T> r(v1.datasize, v2.datasize);
+    for (i=0; i<v1.datasize; i++) {
+      for (j=0; j<v2.datasize; j++) {
+	r(i,j) = v1.data[i] * v2.data[j];
+      }
+    }
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator*(const Vec<Num_T> &v, const Num_T t)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = v.data[i] * t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator*(const Num_T t, const Vec<Num_T> &v)
+  {
+    return operator*(v, t);
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b)
+  {
+    Vec<Num_T> out;
+    elem_mult_out(a,b,out);
+    return out;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c)
+  {
+    Vec<Num_T> out;
+    elem_mult_out(a,b,c,out);
+    return out;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, const Vec<Num_T> &d)
+  {
+    Vec<Num_T> out;
+    elem_mult_out(a,b,c,d,out);
+    return out;
+  }
+
+  template<class Num_T> inline
+  void elem_mult_out(const Vec<Num_T> &a, const Vec<Num_T> &b, Vec<Num_T> &out)
+  {
+    it_assert_debug(a.datasize==b.datasize, "Vec::elem_mult_out: wrong sizes");
+
+    if(out.datasize != a.datasize)
+      out.set_size(a.size());
+
+    for(int i=0; i<a.datasize; i++)
+      out.data[i] = a.data[i] * b.data[i];
+  }
+
+  template<class Num_T> inline
+  void elem_mult_out(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, Vec<Num_T> &out)
+  {
+    it_assert_debug(a.datasize==b.datasize==c.datasize, "Vec::elem_mult_out: wrong sizes");
+
+    if(out.datasize != a.datasize)
+      out.set_size(a.size());
+
+    for(int i=0; i<a.datasize; i++)
+      out.data[i] = a.data[i] * b.data[i] * c.data[i];
+  }
+
+  template<class Num_T> inline
+  void elem_mult_out(const Vec<Num_T> &a, const Vec<Num_T> &b, const Vec<Num_T> &c, const Vec<Num_T> &d, Vec<Num_T> &out)
+  {
+    it_assert_debug(a.datasize==b.datasize==c.datasize==d.datasize, "Vec::elem_mult_out: wrong sizes");
+
+    if(out.datasize != a.datasize)
+      out.set_size(a.size());
+
+    for(int i=0; i<a.datasize; i++)
+      out.data[i] = a.data[i] * b.data[i] * c.data[i] * d.data[i];
+  }
+
+  template<class Num_T> inline
+  void elem_mult_inplace(const Vec<Num_T> &a, Vec<Num_T> &b)
+  {
+    it_assert_debug(a.datasize==b.datasize, "Vec::elem_mult_inplace: wrong sizes");
+
+    for(int i=0; i<a.datasize; i++)
+      b.data[i] *= a.data[i];
+  }
+
+  template<class Num_T> inline
+  Num_T elem_mult_sum(const Vec<Num_T> &a, const Vec<Num_T> &b)
+  {
+    it_assert_debug(a.datasize==b.datasize, "Vec::elem_mult_sum: wrong sizes");
+
+    Num_T acc = 0;
+
+    for(int i=0; i<a.datasize; i++)
+      acc += a.data[i] * b.data[i];
+
+    return acc;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator/(const Vec<Num_T> &v, const Num_T t)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = v.data[i] / t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> operator/(const Num_T t, const Vec<Num_T> &v)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = t / v.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator/=(const Num_T t)
+  {
+    for (int i = 0; i < datasize; ++i) {
+      data[i] /= t;
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator/=(const Vec<Num_T> &v)
+  {
+    it_assert_debug(datasize == v.datasize, "Vec::operator/=(): wrong sizes");
+    for (int i = 0; i < datasize; ++i) {
+      data[i] /= v.data[i];
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> elem_div(const Vec<Num_T> &a, const Vec<Num_T> &b)
+  {
+    Vec<Num_T> out;
+    elem_div_out(a,b,out);
+    return out;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> elem_div(const Num_T t, const Vec<Num_T> &v)
+  {
+    int i;
+    Vec<Num_T> r(v.datasize);
+
+    for (i=0; i<v.datasize; i++)
+      r.data[i] = t / v.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  void elem_div_out(const Vec<Num_T> &a, const Vec<Num_T> &b, Vec<Num_T> &out)
+  {
+    it_assert_debug(a.datasize==b.datasize, "Vecelem_div_out: wrong sizes");
+
+    if(out.datasize != a.datasize)
+      out.set_size(a.size());
+
+    for(int i=0; i<a.datasize; i++)
+      out.data[i] = a.data[i] / b.data[i];
+  }
+
+  template<class Num_T> inline
+  Num_T elem_div_sum(const Vec<Num_T> &a, const Vec<Num_T> &b)
+  {
+    it_assert_debug(a.datasize==b.datasize, "Vec::elem_div_sum: wrong sizes");
+
+    Num_T acc = 0;
+
+    for(int i=0; i<a.datasize; i++)
+      acc += a.data[i] / b.data[i];
+
+    return acc;
+  }
+
+  template<class Num_T>
+  Vec<Num_T> Vec<Num_T>::get(const Vec<bin> &binlist) const
+  {
+    int size = binlist.size();
+    it_assert_debug(datasize == size, "Vec::get(bvec &): wrong sizes");
+    Vec<Num_T> temp(size);
+    int j = 0;
+    for (int i = 0; i < size; ++i) {
+      if (binlist(i) == bin(1)) {
+	temp(j) = data[i];
+	j++;
+      }
+    }
+    temp.set_size(j, true);
+    return temp;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T> Vec<Num_T>::right(int nr) const
+  {
+    it_assert_debug(nr <= datasize, "Vec::right(): index out of range");
+    Vec<Num_T> temp(nr);
+    if (nr > 0) {
+      copy_vector(nr, &data[datasize-nr], temp.data);
+    }
+    return temp;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T> Vec<Num_T>::left(int nr) const
+  {
+    it_assert_debug(nr <= datasize, "Vec::left(): index out of range");
+    Vec<Num_T> temp(nr);
+    if (nr > 0) {
+      copy_vector(nr, data, temp.data);
+    }
+    return temp;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T> Vec<Num_T>::mid(int start, int nr) const
+  {
+    it_assert_debug((start >= 0) && ((start+nr) <= datasize),
+		    "Vec::mid(): indexing out of range");
+    Vec<Num_T> temp(nr);
+    if (nr > 0) {
+      copy_vector(nr, &data[start], temp.data);
+    }
+    return temp;
+  }
+
+  template<class Num_T>
+  Vec<Num_T> Vec<Num_T>::split(int pos)
+  {
+    it_assert_debug((pos >= 0) && (pos <= datasize), "Vec::split(): index out of range");
+    Vec<Num_T> temp1(pos);
+    Vec<Num_T> temp2(datasize-pos);
+    copy_vector(pos, data, temp1.data);
+    copy_vector(datasize-pos, &data[pos], temp2.data);
+    (*this) = temp2;
+    return temp1;
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::shift_right(const Num_T In, int n)
+  {
+    int i=datasize;
+
+    it_assert_debug(n>=0, "Vec::shift_right: index out of range");
+    while (--i >= n)
+      data[i] = data[i-n];
+    while (i >= 0)
+      data[i--] = In;
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::shift_right(const Vec<Num_T> &In)
+  {
+    int	i;
+
+    for (i=datasize-1; i>=In.datasize; i--)
+      data[i]=data[i-In.datasize];
+    for (i=0; i<In.datasize; i++)
+      data[i]=In[i];
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::shift_left(const Num_T In, int n)
+  {
+    int i;
+
+    it_assert_debug(n>=0, "Vec::shift_left: index out of range");
+    for (i=0; i<datasize-n; i++)
+      data[i] = data[i+n];
+    while (i < datasize)
+      data[i++] = In;
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::shift_left(const Vec<Num_T> &In)
+  {
+    int	i;
+
+    for (i=0; i<datasize-In.datasize; i++)
+      data[i]=data[i+In.datasize];
+    for (i=datasize-In.datasize; i<datasize; i++)
+      data[i]=In[i-datasize+In.datasize];
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> concat(const Vec<Num_T> &v, const Num_T a)
+  {
+    int size = v.size();
+    Vec<Num_T> temp(size+1);
+    copy_vector(size, v.data, temp.data);
+    temp(size) = a;
+    return temp;
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> concat(const Num_T a, const Vec<Num_T> &v)
+  {
+    int size = v.size();
+    Vec<Num_T> temp(size+1);
+    temp(0) = a;
+    copy_vector(size, v.data, &temp.data[1]);
+    return temp;
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2)
+  {
+    int size1 = v1.size();
+    int size2 = v2.size();
+    Vec<Num_T> temp(size1+size2);
+    copy_vector(size1, v1.data, temp.data);
+    copy_vector(size2, v2.data, &temp.data[size1]);
+    return temp;
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+			  const Vec<Num_T> &v3)
+  {
+    int size1 = v1.size();
+    int size2 = v2.size();
+    int size3 = v3.size();
+    Vec<Num_T> temp(size1+size2+size3);
+    copy_vector(size1, v1.data, temp.data);
+    copy_vector(size2, v2.data, &temp.data[size1]);
+    copy_vector(size3, v3.data, &temp.data[size1+size2]);
+    return temp;
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+			  const Vec<Num_T> &v3, const Vec<Num_T> &v4)
+  {
+    int size1 = v1.size();
+    int size2 = v2.size();
+    int size3 = v3.size();
+    int size4 = v4.size();
+    Vec<Num_T> temp(size1+size2+size3+size4);
+    copy_vector(size1, v1.data, temp.data);
+    copy_vector(size2, v2.data, &temp.data[size1]);
+    copy_vector(size3, v3.data, &temp.data[size1+size2]);
+    copy_vector(size4, v4.data, &temp.data[size1+size2+size3]);
+    return temp;
+  }
+
+  template<class Num_T>
+  const Vec<Num_T> concat(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+			  const Vec<Num_T> &v3, const Vec<Num_T> &v4,
+			  const Vec<Num_T> &v5)
+  {
+    int size1 = v1.size();
+    int size2 = v2.size();
+    int size3 = v3.size();
+    int size4 = v4.size();
+    int size5 = v5.size();
+    Vec<Num_T> temp(size1+size2+size3+size4+size5);
+    copy_vector(size1, v1.data, temp.data);
+    copy_vector(size2, v2.data, &temp.data[size1]);
+    copy_vector(size3, v3.data, &temp.data[size1+size2]);
+    copy_vector(size4, v4.data, &temp.data[size1+size2+size3]);
+    copy_vector(size5, v5.data, &temp.data[size1+size2+size3+size4]);
+    return temp;
+  }
+
+  template<class Num_T> inline
+  void Vec<Num_T>::set_subvector(int i1, int i2, const Vec<Num_T> &v)
+  {
+    if (i1 == -1) i1 = datasize-1;
+    if (i2 == -1) i2 = datasize-1;
+
+    it_assert_debug(i1>=0 && i2>=0 && i1<datasize && i2<datasize, "Vec::set_subvector(): indicies out of range");
+    it_assert_debug(i2>=i1, "Vec::set_subvector(): i2 >= i1 necessary");
+    it_assert_debug(i2-i1+1 == v.datasize, "Vec::set_subvector(): wrong sizes");
+
+    copy_vector(v.datasize, v.data, data+i1);
+  }
+
+  template<class Num_T> inline
+  void Vec<Num_T>:: set_subvector(int i, const Vec<Num_T> &v)
+  {
+    it_assert_debug(i>=0, "Vec::set_subvector(): index out of range");
+    it_assert_debug(i+v.datasize <= datasize, "Vec::set_subvector(): too long input vector");
+    copy_vector(v.datasize, v.data, data+i);
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::set_subvector(int i1, int i2, const Num_T t)
+  {
+    if (i1 == -1) i1 = datasize-1;
+    if (i2 == -1) i2 = datasize-1;
+
+    it_assert_debug(i1>=0 && i2>=0 && i1<datasize && i2<datasize, "Vec::set_subvector(): indicies out of range");
+    it_assert_debug(i2>=i1, "Vec::set_subvector(): i2 >= i1 necessary");
+
+    for (int i=i1;i<=i2;i++)
+      data[i] = t;
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::replace_mid(int pos, const Vec<Num_T> &v)
+  {
+    it_assert_debug((pos>=0) && ((pos+v.length())<=datasize), "Vec::replace_mid: indexing out of range");
+    copy_vector(v.datasize, v.data, &data[pos]);
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::del(int index)
+  {
+    it_assert_debug((index >= 0) && (index < datasize),
+		    "Vec::del(): index out of range");
+    Vec<Num_T> temp(*this);
+    set_size(datasize-1, false);
+    copy_vector(index, temp.data, data);
+    copy_vector(datasize-index, &temp.data[index+1], &data[index]);
+  }
+
+  template<class Num_T>
+  void  Vec<Num_T>::del(int i1, int i2)
+  {
+    it_assert_debug((i1 >= 0) && (i2 < datasize) && (i1 < i2),
+		    "Vec::del(): index out of range");
+    Vec<Num_T> temp(*this);
+    int new_size = datasize-(i2-i1+1);
+    set_size(new_size, false);
+    copy_vector(i1, temp.data, data);
+    copy_vector(datasize-i1, &temp.data[i2+1], &data[i1]);
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::ins(int index, const Num_T in)
+  {
+    it_assert_debug((index>=0) && (index<=datasize), "Vec::ins: index out of range");
+    Vec<Num_T> Temp(*this);
+
+    set_size(datasize+1, false);
+    copy_vector(index, Temp.data, data);
+    data[index]=in;
+    copy_vector(Temp.datasize-index, Temp.data+index, data+index+1);
+  }
+
+  template<class Num_T>
+  void Vec<Num_T>::ins(int index, const Vec<Num_T> &in)
+  {
+    it_assert_debug((index>=0) && (index<=datasize), "Vec::ins: index out of range");
+    Vec<Num_T> Temp(*this);
+
+    set_size(datasize+in.length(), false);
+    copy_vector(index, Temp.data, data);
+    copy_vector(in.size(), in.data, &data[index]);
+    copy_vector(Temp.datasize-index, Temp.data+index, data+index+in.size());
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator=(const Num_T t)
+  {
+    for (int i=0;i<datasize;i++)
+      data[i] = t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator=(const Vec<Num_T> &v)
+  {
+    if (this != &v) {
+      set_size(v.datasize, false);
+      copy_vector(datasize, v.data, data);
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator=(const Mat<Num_T> &m)
+  {
+    it_assert_debug( (m.cols() == 1 && datasize == m.rows()) ||
+		(m.rows() == 1 && datasize == m.cols()), "Vec::operator=(Mat<Num_T>): wrong size");
+
+    if (m.cols() == 1) {
+      set_size(m.rows(), false);
+      copy_vector(m.rows(), m._data(), data);
+    } else if (m.rows() == 1) {
+      set_size(m.cols(), false);
+      copy_vector(m.cols(), m._data(), m.rows(), data, 1);
+    } else
+      it_error("Vec::operator=(Mat<Num_T>): wrong size");
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Vec<Num_T>& Vec<Num_T>::operator=(const char *values)
+  {
+    set(values);
+    return *this;
+  }
+
+  template<>
+  bvec Vec<std::complex<double> >::operator==(std::complex<double>) const;
+
+  template<class Num_T>
+  bvec Vec<Num_T>::operator==(const Num_T value) const
+  {
+    it_assert(datasize > 0, "Vec::operator==: vector must have size > 0");
+    Vec<Num_T> invector(*this);
+    bvec temp(invector.length());
+
+    for (int i=0;i<invector.length();i++)
+      temp(i)=(invector(i)==value);
+
+    return temp;
+  }
+
+  template<>
+  bvec Vec<std::complex<double> >::operator!=(std::complex<double>) const;
+
+  template<class Num_T>
+  bvec Vec<Num_T>::operator!=(const Num_T value) const
+  {
+    it_assert(datasize > 0, "Vec::operator!=: vector must have size > 0");
+    Vec<Num_T> invector(*this);
+    bvec temp(invector.length());
+
+    for (int i=0;i<invector.length();i++)
+      temp(i)=(invector(i)!=value);
+
+    return temp;
+  }
+
+  template<>
+  bvec Vec<std::complex<double> >::operator<(std::complex<double>) const;
+
+  template<class Num_T>
+  bvec Vec<Num_T>::operator<(const Num_T value) const
+  {
+    it_assert(datasize > 0, "Vec::operator<: vector must have size > 0");
+    Vec<Num_T> invector(*this);
+    bvec temp(invector.length());
+
+    for (int i=0;i<invector.length();i++)
+      temp(i)=(invector(i)<value);
+
+    return temp;
+  }
+
+  template<>
+  bvec Vec<std::complex<double> >::operator<=(std::complex<double>) const;
+
+  template<class Num_T>
+  bvec Vec<Num_T>::operator<=(const Num_T value) const
+  {
+    it_assert(datasize > 0, "Vec::operator<=: vector must have size > 0");
+    Vec<Num_T> invector(*this);
+    bvec temp(invector.length());
+
+    for (int i=0;i<invector.length();i++)
+      temp(i)=(invector(i)<=value);
+
+    return temp;
+  }
+
+  template<>
+  bvec Vec<std::complex<double> >::operator>(std::complex<double>) const;
+
+  template<class Num_T>
+  bvec Vec<Num_T>::operator>(const Num_T value) const
+  {
+    it_assert(datasize > 0, "Vec::operator>: vector must have size > 0");
+    Vec<Num_T> invector(*this);
+    bvec temp(invector.length());
+
+    for (int i=0;i<invector.length();i++)
+      temp(i)=(invector(i)>value);
+
+    return temp;
+  }
+
+  template<>
+  bvec Vec<std::complex<double> >::operator>=(std::complex<double>) const;
+
+  template<class Num_T>
+  bvec Vec<Num_T>::operator>=(const Num_T value) const
+  {
+    it_assert(datasize > 0, "Vec::operator>=: vector must have size > 0");
+    Vec<Num_T> invector(*this);
+    bvec temp(invector.length());
+
+    for (int i=0;i<invector.length();i++)
+      temp(i)=(invector(i)>=value);
+
+    return temp;
+  }
+
+  template<class Num_T>
+  bool Vec<Num_T>::operator==(const Vec<Num_T> &invector) const
+  {
+    // OBS ! if wrong size, return false
+    if (datasize!=invector.datasize) return false;
+    for (int i=0;i<datasize;i++) {
+      if (data[i]!=invector.data[i]) return false;
+    }
+    return true;
+  }
+
+  template<class Num_T>
+  bool Vec<Num_T>::operator!=(const Vec<Num_T> &invector) const
+  {
+    if (datasize!=invector.datasize) return true;
+    for (int i=0;i<datasize;i++) {
+      if (data[i]!=invector.data[i]) return true;
+    }
+    return false;
+  }
+
+  //! Output stream operator of a vector \c v
+  template<class Num_T>
+  std::ostream &operator<<(std::ostream &os, const Vec<Num_T> &v)
+  {
+    int i, sz=v.length();
+
+    os << "[" ;
+    for (i=0; i<sz; i++) {
+      os << v(i) ;
+      if (i < sz-1)
+	os << " ";
+    }
+    os << "]" ;
+
+    return os;
+  }
+
+  //! Input stream operator to read a vector
+  template<class Num_T>
+  std::istream &operator>>(std::istream &is, Vec<Num_T> &v)
+  {
+    std::ostringstream buffer;
+    bool started = false;
+    bool finished = false;
+    bool brackets = false;
+    char c;
+
+    while (!finished) {
+      if (is.eof()) {
+        finished = true;
+      } else {
+        c = is.get();
+
+        if (is.eof() || (c == '\n')) {
+          if (brackets) {
+            // Right bracket missing
+            is.setstate(std::ios_base::failbit);
+            finished = true;
+          } else if (!((c == '\n') && !started)) {
+            finished = true;
+          }
+        } else if ((c == ' ') || (c == '\t')) {
+          if (started) {
+            buffer << ' ';
+          }
+        } else if (c == '[') {
+          if (started) {
+            // Unexpected left bracket
+            is.setstate(std::ios_base::failbit);
+            finished = true;
+          } else {
+            started = true;
+            brackets = true;
+          }
+        } else if (c == ']') {
+          if (!started || !brackets) {
+            // Unexpected right bracket
+            is.setstate(std::ios_base::failbit);
+            finished = true;
+          } else {
+            finished = true;
+          }
+          while (!is.eof() && (((c = is.peek()) == ' ') || (c == '\t'))) {
+            is.get();
+          }
+          if (!is.eof() && (c == '\n')) {
+            is.get();
+          }
+        } else {
+          started = true;
+          buffer << c;
+        }
+      }
+    }
+
+    if (!started) {
+      v.set_size(0, false);
+    } else {
+      v.set(buffer.str());
+    }
+
+    return is;
+  }
+
+  //! \cond
+
+  // ----------------------------------------------------------------------
+  // Instantiations
+  // ----------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  extern template class Vec<double>;
+  extern template class Vec<int>;
+  extern template class Vec<short int>;
+  extern template class Vec<std::complex<double> >;
+  extern template class Vec<bin>;
+
+  // addition operator
+
+  extern template const vec operator+(const vec &v1, const vec &v2);
+  extern template const cvec operator+(const cvec &v1, const cvec &v2);
+  extern template const ivec operator+(const ivec &v1, const ivec &v2);
+  extern template const svec operator+(const svec &v1, const svec &v2);
+  extern template const bvec operator+(const bvec &v1, const bvec &v2);
+
+  extern template const vec operator+(const vec &v1, double t);
+  extern template const cvec operator+(const cvec &v1, std::complex<double> t);
+  extern template const ivec operator+(const ivec &v1, int t);
+  extern template const svec operator+(const svec &v1, short t);
+  extern template const bvec operator+(const bvec &v1, bin t);
+
+  extern template const vec operator+(double t, const vec &v1);
+  extern template const cvec operator+(std::complex<double> t, const cvec &v1);
+  extern template const ivec operator+(int t, const ivec &v1);
+  extern template const svec operator+(short t, const svec &v1);
+  extern template const bvec operator+(bin t, const bvec &v1);
+
+  // subraction operator
+
+  extern template const vec operator-(const vec &v1, const vec &v2);
+  extern template const cvec operator-(const cvec &v1, const cvec &v2);
+  extern template const ivec operator-(const ivec &v1, const ivec &v2);
+  extern template const svec operator-(const svec &v1, const svec &v2);
+  extern template const bvec operator-(const bvec &v1, const bvec &v2);
+
+  extern template const vec operator-(const vec &v, double t);
+  extern template const cvec operator-(const cvec &v, std::complex<double> t);
+  extern template const ivec operator-(const ivec &v, int t);
+  extern template const svec operator-(const svec &v, short t);
+  extern template const bvec operator-(const bvec &v, bin t);
+
+  extern template const vec operator-(double t, const vec &v);
+  extern template const cvec operator-(std::complex<double> t, const cvec &v);
+  extern template const ivec operator-(int t, const ivec &v);
+  extern template const svec operator-(short t, const svec &v);
+  extern template const bvec operator-(bin t, const bvec &v);
+
+  // unary minus
+
+  extern template const vec operator-(const vec &v);
+  extern template const cvec operator-(const cvec &v);
+  extern template const ivec operator-(const ivec &v);
+  extern template const svec operator-(const svec &v);
+  extern template const bvec operator-(const bvec &v);
+
+  // multiplication operator
+
+#if !defined(HAVE_BLAS)
+  extern template double dot(const vec &v1, const vec &v2);
+  extern template std::complex<double> dot(const cvec &v1, const cvec &v2);
+#endif
+  extern template int dot(const ivec &v1, const ivec &v2);
+  extern template short dot(const svec &v1, const svec &v2);
+  extern template bin dot(const bvec &v1, const bvec &v2);
+
+#if !defined(HAVE_BLAS)
+  extern template double operator*(const vec &v1, const vec &v2);
+  extern template std::complex<double> operator*(const cvec &v1,
+                                                 const cvec &v2);
+#endif
+  extern template int operator*(const ivec &v1, const ivec &v2);
+  extern template short operator*(const svec &v1, const svec &v2);
+  extern template bin operator*(const bvec &v1, const bvec &v2);
+
+#if !defined(HAVE_BLAS)
+  extern template const mat outer_product(const vec &v1, const vec &v2,
+					  bool hermitian);
+#endif
+  extern template const imat outer_product(const ivec &v1, const ivec &v2,
+					   bool hermitian);
+  extern template const smat outer_product(const svec &v1, const svec &v2,
+					   bool hermitian);
+  extern template const bmat outer_product(const bvec &v1, const bvec &v2,
+					   bool hermitian);
+
+  extern template const vec operator*(const vec &v, double t);
+  extern template const cvec operator*(const cvec &v, std::complex<double> t);
+  extern template const ivec operator*(const ivec &v, int t);
+  extern template const svec operator*(const svec &v, short t);
+  extern template const bvec operator*(const bvec &v, bin t);
+
+  extern template const vec operator*(double t, const vec &v);
+  extern template const cvec operator*(std::complex<double> t, const cvec &v);
+  extern template const ivec operator*(int t, const ivec &v);
+  extern template const svec operator*(short t, const svec &v);
+  extern template const bvec operator*(bin t, const bvec &v);
+
+  // elementwise multiplication
+
+  extern template const vec elem_mult(const vec &a, const vec &b);
+  extern template const cvec elem_mult(const cvec &a, const cvec &b);
+  extern template const ivec elem_mult(const ivec &a, const ivec &b);
+  extern template const svec elem_mult(const svec &a, const svec &b);
+  extern template const bvec elem_mult(const bvec &a, const bvec &b);
+
+  extern template void elem_mult_out(const vec &a, const vec &b, vec &out);
+  extern template void elem_mult_out(const cvec &a, const cvec &b, cvec &out);
+  extern template void elem_mult_out(const ivec &a, const ivec &b, ivec &out);
+  extern template void elem_mult_out(const svec &a, const svec &b, svec &out);
+  extern template void elem_mult_out(const bvec &a, const bvec &b, bvec &out);
+
+  extern template const vec elem_mult(const vec &a, const vec &b,
+                                      const vec &c);
+  extern template const cvec elem_mult(const cvec &a, const cvec &b,
+                                       const cvec &c);
+  extern template const ivec elem_mult(const ivec &a, const ivec &b,
+                                       const ivec &c);
+  extern template const svec elem_mult(const svec &a, const svec &b,
+                                       const svec &c);
+  extern template const bvec elem_mult(const bvec &a, const bvec &b,
+                                       const bvec &c);
+
+  extern template void elem_mult_out(const vec &a, const vec &b, const vec &c,
+                                     vec &out);
+  extern template void elem_mult_out(const cvec &a, const cvec &b,
+                                     const cvec &c, cvec &out);
+  extern template void elem_mult_out(const ivec &a, const ivec &b,
+                                     const ivec &c, ivec &out);
+  extern template void elem_mult_out(const svec &a, const svec &b,
+                                     const svec &c, svec &out);
+  extern template void elem_mult_out(const bvec &a, const bvec &b,
+                                     const bvec &c, bvec &out);
+
+  extern template const vec elem_mult(const vec &a, const vec &b, const vec &c,
+                                      const vec &d);
+  extern template const cvec elem_mult(const cvec &a, const cvec &b,
+                                       const cvec &c, const cvec &d);
+  extern template const ivec elem_mult(const ivec &a, const ivec &b,
+                                       const ivec &c, const ivec &d);
+  extern template const svec elem_mult(const svec &a, const svec &b,
+                                       const svec &c, const svec &d);
+  extern template const bvec elem_mult(const bvec &a, const bvec &b,
+                                       const bvec &c, const bvec &d);
+
+  extern template void elem_mult_out(const vec &a, const vec &b, const vec &c,
+                                     const vec &d, vec &out);
+  extern template void elem_mult_out(const cvec &a, const cvec &b,
+                                     const cvec &c, const cvec &d, cvec &out);
+  extern template void elem_mult_out(const ivec &a, const ivec &b,
+                                     const ivec &c, const ivec &d, ivec &out);
+  extern template void elem_mult_out(const svec &a, const svec &b,
+                                     const svec &c, const svec &d, svec &out);
+  extern template void elem_mult_out(const bvec &a, const bvec &b,
+                                     const bvec &c, const bvec &d, bvec &out);
+
+  // in-place elementwise multiplication
+
+  extern template void elem_mult_inplace(const vec &a, vec &b);
+  extern template void elem_mult_inplace(const cvec &a, cvec &b);
+  extern template void elem_mult_inplace(const ivec &a, ivec &b);
+  extern template void elem_mult_inplace(const svec &a, svec &b);
+  extern template void elem_mult_inplace(const bvec &a, bvec &b);
+
+  // elementwise multiplication followed by summation
+
+  extern template double elem_mult_sum(const vec &a, const vec &b);
+  extern template std::complex<double> elem_mult_sum(const cvec &a,
+                                                     const cvec &b);
+  extern template int elem_mult_sum(const ivec &a, const ivec &b);
+  extern template short elem_mult_sum(const svec &a, const svec &b);
+  extern template bin elem_mult_sum(const bvec &a, const bvec &b);
+
+  // division operator
+
+  extern template const vec operator/(const vec &v, double t);
+  extern template const cvec operator/(const cvec &v, std::complex<double> t);
+  extern template const ivec operator/(const ivec &v, int t);
+  extern template const svec operator/(const svec &v, short t);
+  extern template const bvec operator/(const bvec &v, bin t);
+
+  extern template const vec operator/(double t, const vec &v);
+  extern template const cvec operator/(std::complex<double> t, const cvec &v);
+  extern template const ivec operator/(int t, const ivec &v);
+  extern template const svec operator/(short t, const svec &v);
+  extern template const bvec operator/(bin t, const bvec &v);
+
+  // elementwise division operator
+
+  extern template const vec elem_div(const vec &a, const vec &b);
+  extern template const cvec elem_div(const cvec &a, const cvec &b);
+  extern template const ivec elem_div(const ivec &a, const ivec &b);
+  extern template const svec elem_div(const svec &a, const svec &b);
+  extern template const bvec elem_div(const bvec &a, const bvec &b);
+
+  extern template const vec elem_div(double t, const vec &v);
+  extern template const cvec elem_div(std::complex<double> t, const cvec &v);
+  extern template const ivec elem_div(int t, const ivec &v);
+  extern template const svec elem_div(short t, const svec &v);
+  extern template const bvec elem_div(bin t, const bvec &v);
+
+  extern template void elem_div_out(const vec &a, const vec &b, vec &out);
+  extern template void elem_div_out(const cvec &a, const cvec &b, cvec &out);
+  extern template void elem_div_out(const ivec &a, const ivec &b, ivec &out);
+  extern template void elem_div_out(const svec &a, const svec &b, svec &out);
+  extern template void elem_div_out(const bvec &a, const bvec &b, bvec &out);
+
+  // elementwise division followed by summation
+
+  extern template double elem_div_sum(const vec &a, const vec &b);
+  extern template std::complex<double> elem_div_sum(const cvec &a,
+                                                    const cvec &b);
+  extern template int elem_div_sum(const ivec &a, const ivec &b);
+  extern template short elem_div_sum(const svec &a, const svec &b);
+  extern template bin elem_div_sum(const bvec &a, const bvec &b);
+
+  // concat operator
+
+  extern template const vec concat(const vec &v, double a);
+  extern template const cvec concat(const cvec &v, std::complex<double> a);
+  extern template const ivec concat(const ivec &v, int a);
+  extern template const svec concat(const svec &v, short a);
+  extern template const bvec concat(const bvec &v, bin a);
+
+  extern template const vec concat(double a, const vec &v);
+  extern template const cvec concat(std::complex<double> a, const cvec &v);
+  extern template const ivec concat(int a, const ivec &v);
+  extern template const svec concat(short a, const svec &v);
+  extern template const bvec concat(bin a, const bvec &v);
+
+  extern template const vec concat(const vec &v1, const vec &v2);
+  extern template const cvec concat(const cvec &v1, const cvec &v2);
+  extern template const ivec concat(const ivec &v1, const ivec &v2);
+  extern template const svec concat(const svec &v1, const svec &v2);
+  extern template const bvec concat(const bvec &v1, const bvec &v2);
+
+  extern template const vec concat(const vec &v1, const vec &v2,
+                                   const vec &v3);
+  extern template const cvec concat(const cvec &v1, const cvec &v2,
+                                    const cvec &v3);
+  extern template const ivec concat(const ivec &v1, const ivec &v2,
+                                    const ivec &v3);
+  extern template const svec concat(const svec &v1, const svec &v2,
+                                    const svec &v3);
+  extern template const bvec concat(const bvec &v1, const bvec &v2,
+                                    const bvec &v3);
+
+  extern template const vec concat(const vec &v1, const vec &v2, const vec &v3,
+                                   const vec &v4);
+  extern template const cvec concat(const cvec &v1, const cvec &v2,
+                                    const cvec &v3, const cvec &v4);
+  extern template const ivec concat(const ivec &v1, const ivec &v2,
+                                    const ivec &v3, const ivec &v4);
+  extern template const svec concat(const svec &v1, const svec &v2,
+                                    const svec &v3, const svec &v4);
+  extern template const bvec concat(const bvec &v1, const bvec &v2,
+                                    const bvec &v3, const bvec &v4);
+
+  extern template const vec concat(const vec &v1, const vec &v2, const vec &v3,
+                                   const vec &v4, const vec &v5);
+  extern template const cvec concat(const cvec &v1, const cvec &v2,
+                                    const cvec &v3, const cvec &v4,
+                                    const cvec &v5);
+  extern template const ivec concat(const ivec &v1, const ivec &v2,
+                                    const ivec &v3, const ivec &v4,
+                                    const ivec &v5);
+  extern template const svec concat(const svec &v1, const svec &v2,
+                                    const svec &v3, const svec &v4,
+                                    const svec &v5);
+  extern template const bvec concat(const bvec &v1, const bvec &v2,
+                                    const bvec &v3, const bvec &v4,
+                                    const bvec &v5);
+
+  // I/O streams
+
+  extern template std::ostream &operator<<(std::ostream& os, const vec &vect);
+  extern template std::ostream &operator<<(std::ostream& os, const cvec &vect);
+  extern template std::ostream &operator<<(std::ostream& os, const svec &vect);
+  extern template std::ostream &operator<<(std::ostream& os, const ivec &vect);
+  extern template std::ostream &operator<<(std::ostream& os, const bvec &vect);
+  extern template std::istream &operator>>(std::istream& is, vec &vect);
+  extern template std::istream &operator>>(std::istream& is, cvec &vect);
+  extern template std::istream &operator>>(std::istream& is, svec &vect);
+  extern template std::istream &operator>>(std::istream& is, ivec &vect);
+  extern template std::istream &operator>>(std::istream& is, bvec &vect);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // #ifndef VEC_H
Index: /win32/itpp-4.0.1/itpp/base/array.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/array.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/array.h (revision 35)
@@ -0,0 +1,617 @@
+/*!
+ * \file
+ * \brief Definition of Array class (container)
+ * \author Tobias Ringstrom and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include <itpp/base/itassert.h>
+#include <itpp/base/math/misc.h>
+#include <itpp/base/factory.h>
+#include <itpp/base/copy_vector.h>
+
+
+namespace itpp {
+
+  // Forward declarations
+  template<class T> class Array;
+  //! Append element \c e to the end of the Array \c a
+  template<class T> const Array<T> concat(const Array<T> &a, const T e);
+  //! Append element \c e to the beginning of the Array \c a
+  template<class T> const Array<T> concat(const T e, const Array<T> &a);
+  //! Concat Arrays \c a1 and \c a2
+  template<class T> const Array<T> concat(const Array<T> &a1,
+					  const Array<T> &a2);
+  //! Concat Arrays \c a1, \c a2 and \c a3
+  template<class T> const Array<T> concat(const Array<T> &a1,
+					  const Array<T> &a2,
+					  const Array<T> &a3);
+
+  /*!
+    \ingroup arr_vec_mat
+    \brief General array class
+    \author Tobias Ringstrom and Adam Piatyszek
+
+    This class is a general linear array class for arbitrary types. The
+    operations and functions are the same as for the vector \c Vec class
+    (except for the arithmetics).
+
+    For rarely used types you will need to instantiate the class by
+    \code
+    template class Array<type>;
+    \endcode
+
+    The following example shows how to define an Array of vectors:
+    \code
+    vec a = randn(10);
+    vec b = randn(20);
+    vec c = randn(30);
+    Array<vec> my_array(3);
+    my_array(0) = a;
+    my_array(1) = b;
+    my_array(2) = c;
+    \endcode
+
+    For types T with istream \c operator>> defined special constructor or
+    \c operator= or \c set_array functions (see Related Functions) can be
+    used to assign a string literal to an Array. The string literal has the
+    same format that is used by the istream/ostream operators:
+
+    \code
+    // Initialise an array with three bit vectors
+    Array<bvec> B = "{[1 0 1] [0 0 1] [1 0 0 0 1]}";
+
+    // Declare an Array of Arrays of vectors
+    Array<Array<ivec> > an_array;
+
+    // Assign with an Array containing 2 Arrays,
+    // the first Array containing [1 2] and
+    // the second Array containing [3 4 5] and [6 7]
+    set_array(an_array, "{{[1 2]} {[3 4 5] [6 7]}}");
+    \endcode
+
+    By default, Array elements are created using the default constructor
+    for the element type. This can be changed by specifying a suitable
+    Factory in the Array constructor call (see Detailed Description for
+    Factory).
+  */
+  template<class T>
+  class Array {
+  public:
+    //! Default constructor. An element factory \c f can be specified.
+    explicit Array(const Factory &f = DEFAULT_FACTORY);
+    //! Create an Array of size \c n. An element factory \c f can be specified.
+    Array(int n, const Factory &f = DEFAULT_FACTORY);
+    //! Copy constructor. An element factory \c f can be specified.
+    Array(const Array<T> &a, const Factory &f = DEFAULT_FACTORY);
+    //! Create an Array from string. An element factory \c f can be specified.
+    Array(const std::string& values, const Factory &f = DEFAULT_FACTORY);
+    //! Create an Array from char*. An element factory \c f can be specified.
+    Array(const char* values, const Factory &f = DEFAULT_FACTORY);
+
+    //! Destructor
+    virtual ~Array();
+
+    //! Get the \c i element
+    T &operator()(int i);
+    //! Get the \c i element
+    const T &operator()(int i) const;
+    //! Sub-array from element \c i1 to element \c i2
+    const Array<T> operator()(int i1, int i2) const;
+    //! Sub-array with the elements given by the integer Array
+    const Array<T> operator()(const Array<int> &indices) const;
+
+    //! Get \c n left elements of the array
+    Array<T> left(int n) const;
+    //! Get \c n right elements of the array
+    Array<T> right(int n) const;
+    //! Get \c n elements of the array starting from \c pos
+    Array<T> mid(int pos, int n) const;
+
+    //! Assignment operator
+    Array<T>& operator=(const T &e);
+    //! Assignment operator
+    Array<T>& operator=(const Array<T> &a);
+    //! Assignment operator
+    Array<T>& operator=(const char* values);
+
+    //! Append element \c e to the end of the Array \c a
+    friend const Array<T> concat <>(const Array<T> &a1, const T e);
+    //! Concat element \c e to the beginning of the Array \c a
+    friend const Array<T> concat <>(const T e, const Array<T> &a);
+    //! Concat Arrays \c a1 and \c a2
+    friend const Array<T> concat <>(const Array<T> &a1,const Array<T> &a2);
+    //! Concat Arrays \c a1, \c a2 and \c a3
+    friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2,
+				    const Array<T> &a3);
+
+    //! Returns the number of data elements in the array object
+    int size() const { return ndata; }
+    //! Returns the number of data elements in the array object
+    int length() const { return ndata; }
+    //! Resizing an Array<T>.
+    void set_size(int n, bool copy = false);
+    //! Resizing an Array<T>.
+    void set_length(int n, bool copy = false) { set_size(n, copy); }
+
+    //! Shift in data at position 0. Return data from the last position.
+    T shift_right(const T& e);
+    //! Shift in array at position 0. Return data from the last position.
+    const Array<T> shift_right(const Array<T> &a);
+    //! Shift in data at the last position. Return data from position 0.
+    T shift_left(const T& e);
+    //! Shift in array at the last position. Return data from position 0.
+    const Array<T> shift_left(const Array<T> &a);
+    //! Swap elements i and j.
+    void swap(int i, int j);
+
+    //! Set the subarray defined by indicies i1 to i2 to Array<T> a.
+    void set_subarray(int i1, int i2, const Array<T> &a);
+    //! Set the subarray defined by indicies i1 to i2 the element value t.
+    void set_subarray(int i1, int i2, const T t);
+
+  protected:
+    //! Allocate storage for an array of length \c n
+    void alloc(int n);
+    //! Free the storage space allocated by the array
+    void free();
+    //! Check whether index \c i is in the allowed range
+    bool in_range(int i) const { return ((i < ndata) && (i >= 0)); }
+    //! The current number of elements in the Array
+    int ndata;
+    //! A pointer to the data area
+    T *data;
+    //! Element factory (by default set to DEFAULT_FACTORY)
+    const Factory &factory;
+  };
+
+  // -------------------- Implementation starts here --------------------
+
+  template<class T> inline
+  void Array<T>::alloc(int n)
+  {
+    if (n > 0) {
+      create_elements(data, n, factory);
+      ndata = n;
+    }
+    else {
+      data = 0;
+      ndata = 0;
+    }
+  }
+
+  template<class T> inline
+  void Array<T>::free()
+  {
+    destroy_elements(data, ndata);
+    ndata = 0;
+  }
+
+  template<class T> inline
+  Array<T>::Array(const Factory &f) : ndata(0), data(0), factory(f) {}
+
+  template<class T> inline
+  Array<T>::Array(const int n, const Factory &f) : ndata(0), data(0), factory(f)
+  {
+    alloc(n);
+  }
+
+  template<class T> inline
+  Array<T>::Array(const Array<T> &a, const Factory &f)
+    : ndata(0), data(0), factory(f)
+  {
+    alloc(a.ndata);
+    for (int i = 0; i < a.ndata; i++)
+      data[i] = a.data[i];
+  }
+
+  template<class T> inline
+  Array<T>::Array(const std::string& values, const Factory &f)
+    : ndata(0), data(0), factory(f)
+  {
+    std::istringstream buffer(values);
+    buffer >> *this;
+  }
+
+  template<class T> inline
+  Array<T>::Array(const char* values, const Factory &f)
+    : ndata(0), data(0), factory(f)
+  {
+    std::istringstream buffer(values);
+    buffer >> *this;
+  }
+
+  template<class T>
+  Array<T>::~Array()
+  {
+    free();
+  }
+
+  template<class T>
+  void Array<T>::set_size(int size, bool copy)
+  {
+    it_assert_debug(size >= 0, "Array::set_size(): New size must not be negative");
+    if (ndata == size)
+      return;
+    if (copy) {
+      // create a temporary pointer to the allocated data
+      T* tmp = data;
+      // store the current number of elements
+      int old_ndata = ndata;
+      // check how many elements we need to copy
+      int min = (ndata < size) ? ndata : size;
+      // allocate new memory
+      alloc(size);
+      // copy old elements into a new memory region
+      for (int i = 0; i < min; ++i) {
+	data[i] = tmp[i];
+      }
+      // initialize the rest of resized array
+      for (int i = min; i < size; ++i) {
+	data[i] = T();
+      }
+      // delete old elements
+      destroy_elements(tmp, old_ndata);
+    }
+    else {
+      free();
+      alloc(size);
+    }
+  }
+
+
+  template<class T> inline
+  T& Array<T>::operator()(int i)
+  {
+    it_assert_debug(in_range(i), "Array::operator(): Improper index");
+    return data[i];
+  }
+
+  template<class T> inline
+  const T& Array<T>::operator()(int i) const
+  {
+    it_assert_debug(in_range(i), "Array::operator(): Improper index");
+    return data[i];
+  }
+
+  template<class T> inline
+  const Array<T> Array<T>::operator()(int i1, int i2) const
+  {
+    it_assert_debug(in_range(i1) && in_range(i2) && (i2 >= i1),
+	       "Array::operator()(i1, i2): Improper indexes.");
+    Array<T> s(i2-i1+1);
+    for (int i = 0; i < s.ndata; i++)
+      s.data[i] = data[i1+i];
+    return s;
+  }
+
+  template<class T> inline
+  const Array<T> Array<T>::operator()(const Array<int> &indices) const
+  {
+    Array<T> a(indices.size());
+    for (int i = 0; i < a.size(); i++) {
+      it_assert_debug(in_range(indices(i)),
+		 "Array::operator()(indices): Improper indices.");
+      a(i) = data[indices(i)];
+    }
+    return a;
+  }
+
+  template<class T> inline
+  Array<T>& Array<T>::operator=(const Array<T> &a)
+  {
+    if (this != &a) {
+      set_size(a.ndata);
+      for (int i=0; i<ndata; i++)
+	data[i] = a.data[i];
+    }
+    return *this;
+  }
+
+  template<class T> inline
+  Array<T>& Array<T>::operator=(const T &e)
+  {
+    if (ndata == 0)
+      set_size(1);
+    for (int i = 0; i < ndata; i++)
+      data[i] = e;
+    return *this;
+  }
+
+  template<class T>
+  Array<T>& Array<T>::operator=(const char* values)
+  {
+    std::istringstream buffer(values);
+    buffer >> *this;
+    return *this;
+  }
+
+
+  template<class T>
+  Array<T> Array<T>::left(int n) const
+  {
+    it_assert_debug(in_range(n), "Array::left(): Index out of range");
+    Array<T> tmp(n);
+    for (int i = 0; i < n; ++i)
+      tmp.data[i] = data[i];
+    return tmp;
+  }
+
+  template<class T>
+  Array<T> Array<T>::right(int n) const
+  {
+    it_assert_debug(in_range(n), "Array::right(): Index out of range");
+    Array<T> tmp(n);
+    for (int i = 0; i < n; ++i)
+      tmp.data[i] = data[ndata-n+i];
+    return tmp;
+  }
+
+  template<class T>
+  Array<T> Array<T>::mid(int pos, int n) const
+  {
+    it_assert_debug((pos >= 0) && (n > 0) && (pos + n <= ndata), "Array::mid(): Indexing out of range");
+    Array<T> tmp(n);
+    for (int i = 0; i < n; ++i)
+      tmp.data[i] = data[pos+i];
+    return tmp;
+  }
+
+
+  template<class T>
+  T Array<T>::shift_right(const T& x)
+  {
+    it_assert_debug(ndata > 0, "Array::shift_right(x): Array empty!");
+    T ret;
+
+    ret = data[ndata-1];
+    for (int i = ndata-1; i > 0; i--)
+      data[i] = data[i-1];
+    data[0] = x;
+
+    return ret;
+  }
+
+
+  template<class T>
+  const Array<T> Array<T>::shift_right(const Array<T> &a)
+  {
+    it_assert_debug(a.ndata <= ndata, "Array::shift_right(): Shift Array too large");
+    Array<T> out(a.ndata);
+
+    for (int i = 0; i < a.ndata; i++)
+      out.data[i] = data[ndata-a.ndata+i];
+    for (int i = ndata-1; i >= a.ndata; i--)
+      data[i] = data[i-a.ndata];
+    for (int i = 0; i < a.ndata; i++)
+      data[i] = a.data[i];
+
+    return out;
+  }
+
+  template<class T>
+  T Array<T>::shift_left(const T& x)
+  {
+    T temp = data[0];
+
+    for (int i = 0; i < ndata-1; i++)
+      data[i] = data[i+1];
+    data[ndata-1] = x;
+
+    return temp;
+  }
+
+  template<class T>
+  const Array<T> Array<T>::shift_left(const Array<T> &a)
+  {
+    it_assert_debug(a.ndata <= ndata, "Array::shift_left(): Shift Array too large");
+    Array<T> out(a.ndata);
+
+    for (int i = 0; i < a.ndata; i++)
+      out.data[i] = data[i];
+    for (int i = 0; i < ndata-a.ndata; i++)
+      data[i] = data[i+a.ndata];
+    for (int i = ndata-a.ndata; i < ndata; i++)
+      data[i] = a.data[i-ndata+a.ndata];
+
+    return out;
+  }
+
+  template<class T>
+  void Array<T>::swap(int i, int j)
+  {
+    it_assert_debug(in_range(i) && in_range(j),
+	       "Array::swap(): Indices out of range.");
+
+    T temp = data[i];
+    data[i] = data[j];
+    data[j] = temp;
+  }
+
+  template<class T>
+  void Array<T>::set_subarray(int i1, int i2, const Array<T> &a)
+  {
+    if (i1 == -1) i1 = ndata-1;
+    if (i2 == -1) i2 = ndata-1;
+
+    it_assert_debug(in_range(i1) && in_range(i2),
+	       "Array<T>::set_subarray(): Indices out of range.");
+    it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary.");
+    it_assert_debug(i2-i1+1 == a.ndata, "Array<T>::set_subarray(): Wrong sizes.");
+
+    copy_vector(a.ndata, a.data, data+i1);
+  }
+
+  template<class T>
+  void Array<T>::set_subarray(int i1, int i2, const T t)
+  {
+    if (i1 == -1) i1 = ndata-1;
+    if (i2 == -1) i2 = ndata-1;
+
+    it_assert_debug(in_range(i1) && in_range(i2),
+	       "Array<T>::set_subarray(): Indices out of range");
+    it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary");
+
+    for (int i = i1; i <= i2; i++)
+      data[i] = t;
+  }
+
+  template<class T>
+  const Array<T> concat(const Array<T> &a, const T e)
+  {
+    Array<T> temp(a.size()+1);
+
+    for (int i = 0; i < a.size(); i++)
+      temp(i) = a(i);
+    temp(a.size()) = e;
+
+    return temp;
+  }
+
+  template<class T>
+  const Array<T> concat(const T e, const Array<T> &a)
+  {
+    Array<T> temp(a.size()+1);
+
+    temp(0) = e;
+
+    for (int i = 0; i < a.size(); i++)
+      temp(i+1) = a(i);
+
+    return temp;
+  }
+
+  template<class T>
+  const Array<T> concat(const Array<T> &a1, const Array<T> &a2)
+  {
+    Array<T> temp(a1.size()+a2.size());
+
+    for (int i = 0; i < a1.size(); i++)
+      temp(i) = a1(i);
+    for (int i = 0; i < a2.size(); i++)
+      temp(a1.size()+i) = a2(i);
+
+    return temp;
+  }
+
+  template<class T>
+  const Array<T> concat(const Array<T> &a1, const Array<T> &a2,
+			const Array<T> &a3)
+  {
+    // There should be some error control?
+    Array<T> temp(a1.size()+a2.size()+a3.size());
+
+    for (int i = 0; i < a1.size(); i++)
+      temp(i) = a1(i);
+    for (int i = 0; i < a2.size(); i++)
+      temp(a1.size()+i) = a2(i);
+    for (int i = 0; i < a3.size(); i++)
+      temp(a1.size()+a2.size()+i) = a3(i);
+
+    return temp;
+  }
+
+  /*!
+    \relates Array
+    \brief Output stream for Array<T>. T must have ostream operator<< defined.
+  */
+  template<class T>
+  std::ostream &operator<<(std::ostream &os, const Array<T> &a)
+  {
+    os << "{";
+    for (int i = 0; i < a.size()-1; i++)
+      os << a(i) << " ";
+    if (a.size() > 0)
+      os << a(a.size()-1);
+    os << "}";
+
+    return os;
+  }
+
+  /*!
+    \relates Array
+    \brief Input stream for Array<T>. T must have istream operator>> defined.
+  */
+  template<class T>
+  std::istream &operator>>(std::istream &is, Array<T> &a)
+  {
+    int nrof_elements = 0;
+    char c;
+    is >> c;
+    if (c == '{') {
+      is >> c;
+      while (c != '}') {
+	if (is.eof()) {
+	  is.setstate(std::ios_base::failbit);
+	  break;
+	}
+	if (c != ',') {  // Discard comma signs between elements
+	  is.putback(c);
+	}
+	if (++nrof_elements > a.size()) {
+	  a.set_size(nrof_elements, true);  // Too slow?
+	}
+	is >> a(nrof_elements-1);
+	is >> c;
+      }
+      if (a.size() > nrof_elements) {
+	a.set_size(nrof_elements, true);
+      }
+    } else {
+      is.setstate(std::ios_base::failbit);
+    }
+
+    return is;
+  }
+
+  /*!
+    \relates Array
+    \brief Assign a C-style string to an Array<T>. T must have istream
+    operator>> defined.
+  */
+  template<class T>
+  void set_array(Array<T> &a, const char *values)
+  {
+    std::istringstream buffer(values);
+    buffer >> a;
+  }
+
+  /*!
+    \relates Array
+    \brief Assign a string to an Array<T>. T must have istream operator>>
+    defined.
+  */
+  template<class T>
+  void set_array(Array<T> &a, const std::string &str)
+  {
+    set_array(a, str.c_str());
+  }
+
+} // namespace itpp
+
+#endif // #ifndef ARRAY_H
Index: /win32/itpp-4.0.1/itpp/base/operators.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/operators.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/operators.h (revision 35)
@@ -0,0 +1,1099 @@
+/*!
+ * \file
+ * \brief Definitions of operators for vectors and matricies of different
+ *        types
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef OPERATORS_H
+#define OPERATORS_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/mat.h>
+#include <itpp/base/converters.h>
+
+
+namespace itpp {
+
+  //---------------------- between scalars and complex<double> -----------------
+  //! Addition operator for int and complex double
+  inline std::complex<double> operator+(const int &x, const std::complex<double> &y) {return std::complex<double>(x+y.real(), x+y.imag());}
+  //! Addition operator for float and complex double
+  inline std::complex<double> operator+(const float &x, const std::complex<double> &y) {return std::complex<double>(x+y.real(), x+y.imag());}
+  //! Addition operator for int and complex double
+  inline std::complex<double> operator+(const std::complex<double> &x, const int &y) {return std::complex<double>(x.real()+y, x.imag()+y);}
+  //! Addition operator for float and complex double
+  inline std::complex<double> operator+(const std::complex<double> &x, const float &y) {return std::complex<double>(x.real()+y, x.imag()+y);}
+
+  //! Subtraction operator for int and complex double
+  inline std::complex<double> operator-(const int &x, const std::complex<double> &y) {return std::complex<double>(x-y.real(), x-y.imag());}
+  //! Subtraction operator for float and complex double
+  inline std::complex<double> operator-(const float &x, const std::complex<double> &y) {return std::complex<double>(x-y.real(), x-y.imag());}
+  //! Subtraction operator for int and complex double
+  inline std::complex<double> operator-(const std::complex<double> &x, const int &y) {return std::complex<double>(x.real()-y, x.imag()-y);}
+  //! Subtraction operator for float and complex double
+  inline std::complex<double> operator-(const std::complex<double> &x, const float &y) {return std::complex<double>(x.real()-y, x.imag()-y);}
+
+  //! Multiplication operator for int and complex double
+  inline std::complex<double> operator*(const int &x, const std::complex<double> &y) {return std::complex<double>(x*y.real(), x*y.imag());}
+  //! Multiplication operator for float and complex double
+  inline std::complex<double> operator*(const float &x, const std::complex<double> &y) {return std::complex<double>(x*y.real(), x*y.imag());}
+  //! Multiplication operator for int and complex double
+  inline std::complex<double> operator*(const std::complex<double> &x, const int &y) {return std::complex<double>(x.real()*y, x.imag()*y);}
+  //! Multiplication operator for float and complex double
+  inline std::complex<double> operator*(const std::complex<double> &x, const float &y) {return std::complex<double>(x.real()*y, x.imag()*y);}
+
+  //! Division operator for complex double and int
+  inline std::complex<double> operator/(const std::complex<double> &x, const int &y) {return std::complex<double>(x.real()/y, x.imag()/y);}
+  //! Division operator for complex double and float
+  inline std::complex<double> operator/(const std::complex<double> &x, const float &y) {return std::complex<double>(x.real()/y, x.imag()/y);}
+
+
+  //---------------------- between vec and scalar --------------------
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for float and vec
+  */
+  inline vec operator+(const float &s, const vec &v) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for short and vec
+  */
+  inline vec operator+(const short &s, const vec &v) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for int and vec
+  */
+  inline vec operator+(const int &s, const vec &v) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for vec and float
+  */
+  inline vec operator+(const vec &v, const float &s) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for vec and short
+  */
+  inline vec operator+(const vec &v, const short &s) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for vec and int
+  */
+  inline vec operator+(const vec &v, const int &s) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for float and vec
+  */
+  inline vec operator-(const float &s, const vec &v) {return static_cast<double>(s)-v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for short and vec
+  */
+  inline vec operator-(const short &s, const vec &v) {return static_cast<double>(s)-v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for int and vec
+  */
+  inline vec operator-(const int &s, const vec &v) {return static_cast<double>(s)-v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for vec and float
+  */
+  inline vec operator-(const vec &v, const float &s) {return v-static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for vec and short
+  */
+  inline vec operator-(const vec &v, const short &s) {return v-static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for vec and int
+  */
+  inline vec operator-(const vec &v, const int &s) {return v-static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for float and vec
+  */
+  inline vec operator*(const float &s, const vec &v) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for short and vec
+  */
+  inline vec operator*(const short &s, const vec &v) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for int and vec
+  */
+  inline vec operator*(const int &s, const vec &v) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for complex<double> and vec
+  */
+  cvec operator*(const std::complex<double> &s, const vec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and float
+  */
+  inline vec operator*(const vec &v, const float &s) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and short
+  */
+  inline vec operator*(const vec &v, const short &s) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and int
+  */
+  inline vec operator*(const vec &v, const int &s) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and complex<double>
+  */
+  cvec operator*(const vec &v, const std::complex<double> &s);
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for vec and float
+  */
+  inline vec operator/(const vec &v, const float &s) {return v/static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for vec and short
+  */
+  inline vec operator/(const vec &v, const short &s) {return v/static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for vec and int
+  */
+  inline vec operator/(const vec &v, const int &s) {return v/static_cast<double>(s);}
+
+
+  //---------------------- between ivec and scalar --------------------
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for double and ivec
+  */
+  vec operator+(const double &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for ivec and double
+  */
+  inline vec operator+(const ivec &v, const double &s) { return s+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for double and ivec
+  */
+  vec operator-(const double &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for ivec and double
+  */
+  inline vec operator-(const ivec &v, const double &s) { return v+(-s); }
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for double and ivec
+  */
+  vec operator*(const double &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for ivec and double
+  */
+  inline vec operator*(const ivec &v, const double &s) { return s*v; }
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for double and ivec
+  */
+  vec operator/(const double &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for ivec and double
+  */
+  vec operator/(const ivec &v, const double &s);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for complex<double> and ivec
+  */
+  cvec operator+(const std::complex<double> &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for ivec and complex<double>
+  */
+  inline cvec operator+(const ivec &v, const std::complex<double> &s) { return s+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for complex<double> and ivec
+  */
+  cvec operator-(const std::complex<double> &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for ivec and complex<double>
+  */
+  inline cvec operator-(const ivec &v, const std::complex<double> &s) { return v+(-s); }
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for complex<double> and ivec
+  */
+  cvec operator*(const std::complex<double> &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for ivec and complex<double>
+  */
+  inline cvec operator*(const ivec &v, const std::complex<double> &s) { return s*v; }
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for complex<double> and ivec
+  */
+  cvec operator/(const std::complex<double> &s, const ivec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for ivec and complex<double>
+  */
+  cvec operator/(const ivec &v, const std::complex<double> &s);
+
+  //---------------------- between cvec and scalar --------------------
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for double and cvec
+  */
+  cvec operator+(const double &s, const cvec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for float and cvec
+  */
+  inline cvec operator+(const float &s, const cvec &v) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for short and cvec
+  */
+  inline cvec operator+(const short &s, const cvec &v) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for int and cvec
+  */
+  inline cvec operator+(const int &s, const cvec &v) {return static_cast<double>(s)+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and float
+  */
+  inline cvec operator+(const cvec &v, const float &s) {return s+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and double
+  */
+  inline cvec operator+(const cvec &v, const double &s) {return s+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and short
+  */
+  inline cvec operator+(const cvec &v, const short &s) {return s+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and int
+  */
+  inline cvec operator+(const cvec &v, const int &s) {return s+v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for double and cvec
+  */
+  cvec operator-(const double &s, const cvec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for float and cvec
+  */
+  inline cvec operator-(const float &s, const cvec &v) {return static_cast<double>(s)-v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for short and cvec
+  */
+  inline cvec operator-(const short &s, const cvec &v) {return static_cast<double>(s)-v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for int and cvec
+  */
+  inline cvec operator-(const int &s, const cvec &v) {return static_cast<double>(s)-v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and float
+  */
+  inline cvec operator-(const cvec &v, const float &s) {return v+(-s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and double
+  */
+  inline cvec operator-(const cvec &v, const double &s) {return v+(-s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and short
+  */
+  inline cvec operator-(const cvec &v, const short &s) {return v+(-s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and int
+  */
+  inline cvec operator-(const cvec &v, const int &s) {return v+(-s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for double and cvec
+  */
+  cvec operator*(const double &s, const cvec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for float and cvec
+  */
+  inline cvec operator*(const float &s, const cvec &v) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for short and cvec
+  */
+  inline cvec operator*(const short &s, const cvec &v) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for int and cvec
+  */
+  inline cvec operator*(const int &s, const cvec &v) {return static_cast<double>(s)*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and float
+  */
+  inline cvec operator*(const cvec &v, const float &s) {return s*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and double
+  */
+  inline cvec operator*(const cvec &v, const double &s) {return s*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and short
+  */
+  inline cvec operator*(const cvec &v, const short &s) {return s*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and int
+  */
+  inline cvec operator*(const cvec &v, const int &s) {return s*v;}
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for cvec and double
+  */
+  cvec operator/(const cvec &v, const double &s);
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for double and cvec
+  */
+  cvec operator/(const double &s, const cvec &v);
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for cvec and float
+  */
+  inline cvec operator/(const cvec &v, const float &s) {return v/static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for cvec and short
+  */
+  inline cvec operator/(const cvec &v, const short &s) {return v/static_cast<double>(s);}
+
+  /*!
+    \relatesalso Vec
+    \brief Division operator for cvec and int
+  */
+  inline cvec operator/(const cvec &v, const int &s) {return v/static_cast<double>(s);}
+
+  //---------------------- between mat and scalar --------------------
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for float and mat
+  */
+  inline mat operator+(const float &s, const mat &m) {return static_cast<double>(s)+m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for short and mat
+  */
+  inline mat operator+(const short &s, const mat &m) {return static_cast<double>(s)+m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for int and mat
+  */
+  inline mat operator+(const int &s, const mat &m) {return static_cast<double>(s)+m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and float
+  */
+  inline mat operator+(const mat &m, const float &s) {return static_cast<double>(s)+m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and short
+  */
+  inline mat operator+(const mat &m, const short &s) {return static_cast<double>(s)+m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and int
+  */
+  inline mat operator+(const mat &m, const int &s) {return static_cast<double>(s)+m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for float and mat
+  */
+  inline mat operator-(const float &s, const mat &m) {return static_cast<double>(s)-m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for short and mat
+  */
+  inline mat operator-(const short &s, const mat &m) {return static_cast<double>(s)-m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for int and mat
+  */
+  inline mat operator-(const int &s, const mat &m) {return static_cast<double>(s)-m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and float
+  */
+  inline mat operator-(const mat &m, const float &s) {return m-static_cast<double>(s);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and short
+  */
+  inline mat operator-(const mat &m, const short &s) {return m-static_cast<double>(s);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and int
+  */
+  inline mat operator-(const mat &m, const int &s) {return m-static_cast<double>(s);}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for float and mat
+  */
+  inline mat operator*(const float &s, const mat &m) {return static_cast<double>(s)*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for short and mat
+  */
+  inline mat operator*(const short &s, const mat &m) {return static_cast<double>(s)*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for int and mat
+  */
+  inline mat operator*(const int &s, const mat &m) {return static_cast<double>(s)*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for mat and float
+  */
+  inline mat operator*(const mat &m, const float &s) {return static_cast<double>(s)*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for mat and short
+  */
+  inline mat operator*(const mat &m, const short &s) {return static_cast<double>(s)*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for mat and int
+  */
+  inline mat operator*(const mat &m, const int &s) {return static_cast<double>(s)*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Division operator for mat and float
+  */
+  inline mat operator/(const mat &m, const float &s) {return m/static_cast<double>(s);}
+
+  /*!
+    \relatesalso Mat
+    \brief Division operator for mat and short
+  */
+  inline mat operator/(const mat &m, const short &s) {return m/static_cast<double>(s);}
+
+  /*!
+    \relatesalso Mat
+    \brief Division operator for mat and int
+  */
+  inline mat operator/(const mat &m, const int &s) {return m/static_cast<double>(s);}
+
+  //---------------------- between cmat and scalar --------------------
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for double and cmat
+  */
+  cmat operator+(const double &s, const cmat &m);
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for double and cmat
+  */
+  cmat operator-(const double &s, const cmat &m);
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for double and cmat
+  */
+  cmat operator*(const double &s, const cmat &m);
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for complex<double> and mat
+  */
+  cmat operator*(const std::complex<double> &s, const mat &m);
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for mat and complex<double>
+  */
+  inline cmat operator*(const mat &m, const std::complex<double> &s) {return s*m;}
+
+  /*!
+    \relatesalso Mat
+    \brief Division operator for cmat and double
+  */
+  cmat operator/(const cmat &m, const double &s);
+
+  //---------------------- between vec and vectors --------------------
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for bvec and vec
+  */
+  vec operator+(const bvec &a, const vec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for svec and vec
+  */
+  vec operator+(const svec &a, const vec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for ivec and vec
+  */
+  vec operator+(const ivec &a, const vec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for vec and bvec
+  */
+  inline vec operator+(const vec &a, const bvec &b) {return b+a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for vec and svec
+  */
+  inline vec operator+(const vec &a, const svec &b) {return b+a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for vec and ivec
+  */
+  inline vec operator+(const vec &a, const ivec &b) {return b+a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for bvec and vec
+  */
+  inline vec operator-(const bvec &a, const vec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for svec and vec
+  */
+  inline vec operator-(const svec &a, const vec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for ivec and vec
+  */
+  inline vec operator-(const ivec &a, const vec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for vec and bvec
+  */
+  inline vec operator-(const vec &a, const bvec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for vec and svec
+  */
+  inline vec operator-(const vec &a, const svec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for vec and ivec
+  */
+  inline vec operator-(const vec &a, const ivec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for bvec and vec
+  */
+  double operator*(const bvec &a, const vec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for svec and vec
+  */
+  double operator*(const svec &a, const vec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for ivec and vec
+  */
+  double operator*(const ivec &a, const vec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and bvec
+  */
+  inline double operator*(const vec &a, const bvec &b) {return b*a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and svec
+  */
+  inline double operator*(const vec &a, const svec &b) {return b*a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for vec and ivec
+  */
+  inline double operator*(const vec &a, const ivec &b) {return b*a;}
+
+  //---------------------- between cvec and vectors --------------------
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for bvec and cvec
+  */
+  cvec operator+(const bvec &a, const cvec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for svec and cvec
+  */
+  cvec operator+(const svec &a, const cvec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for ivec and cvec
+  */
+  cvec operator+(const ivec &a, const cvec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and bvec
+  */
+  inline cvec operator+(const cvec &a, const bvec &b) {return b+a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and svec
+  */
+  inline cvec operator+(const cvec &a, const svec &b) {return b+a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Addition operator for cvec and ivec
+  */
+  inline cvec operator+(const cvec &a, const ivec &b) {return b+a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for bvec and cvec
+  */
+  inline cvec operator-(const bvec &a, const cvec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for svec and cvec
+  */
+  inline cvec operator-(const svec &a, const cvec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for ivec and cvec
+  */
+  inline cvec operator-(const ivec &a, const cvec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and bvec
+  */
+  inline cvec operator-(const cvec &a, const bvec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and svec
+  */
+  inline cvec operator-(const cvec &a, const svec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Subtraction operator for cvec and ivec
+  */
+  inline cvec operator-(const cvec &a, const ivec &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for bvec and cvec
+  */
+  std::complex<double> operator*(const bvec &a, const cvec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for svec and cvec
+  */
+  std::complex<double> operator*(const svec &a, const cvec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for ivec and cvec
+  */
+  std::complex<double> operator*(const ivec &a, const cvec &b);
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and bvec
+  */
+  inline std::complex<double> operator*(const cvec &a, const bvec &b) {return b*a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and svec
+  */
+  inline std::complex<double> operator*(const cvec &a, const svec &b) {return b*a;}
+
+  /*!
+    \relatesalso Vec
+    \brief Multiplication operator for cvec and ivec
+  */
+  inline std::complex<double> operator*(const cvec &a, const ivec &b) {return b*a;}
+
+  //---------------------- between mat and matricies --------------------
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for bmat and mat
+  */
+  mat operator+(const bmat &a, const mat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for smat and mat
+  */
+  mat operator+(const smat &a, const mat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for imat and mat
+  */
+  mat operator+(const imat &a, const mat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and bmat
+  */
+  inline mat operator+(const mat &a, const bmat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and smat
+  */
+  inline mat operator+(const mat &a, const smat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and imat
+  */
+  inline mat operator+(const mat &a, const imat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for bmat and mat
+  */
+  inline mat operator-(const bmat &a, const mat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for smat and mat
+  */
+  inline mat operator-(const smat &a, const mat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for imat and mat
+  */
+  inline mat operator-(const imat &a, const mat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and bmat
+  */
+  inline mat operator-(const mat &a, const bmat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and smat
+  */
+  inline mat operator-(const mat &a, const smat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and imat
+  */
+  inline mat operator-(const mat &a, const imat &b) {return a+(-b);}
+
+  //---------------------- between cmat and matricies --------------------
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for bmat and cmat
+  */
+  cmat operator+(const bmat &a, const cmat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for smat and cmat
+  */
+  cmat operator+(const smat &a, const cmat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for imat and cmat
+  */
+  cmat operator+(const imat &a, const cmat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for mat and cmat
+  */
+  cmat operator+(const mat &a, const cmat &b);
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for cmat and bmat
+  */
+  inline cmat operator+(const cmat &a, const bmat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for cmat and smat
+  */
+  inline cmat operator+(const cmat &a, const smat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for cmat and imat
+  */
+  inline cmat operator+(const cmat &a, const imat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Addition operator for cmat and mat
+  */
+  inline cmat operator+(const cmat &a, const mat &b) {return b+a;}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for bmat and cmat
+  */
+  inline cmat operator-(const bmat &a, const cmat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for smat and cmat
+  */
+  inline cmat operator-(const smat &a, const cmat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for imat and cmat
+  */
+  inline cmat operator-(const imat &a, const cmat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for mat and cmat
+  */
+  inline cmat operator-(const mat &a, const cmat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for cmat and bmat
+  */
+  inline cmat operator-(const cmat &a, const bmat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for cmat and smat
+  */
+  inline cmat operator-(const cmat &a, const smat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for cmat and imat
+  */
+  inline cmat operator-(const cmat &a, const imat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Subtraction operator for cmat and mat
+  */
+  inline cmat operator-(const cmat &a, const mat &b) {return a+(-b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for mat and cmat
+  */
+  inline cmat operator*(const mat &a, const cmat &b) {return to_cmat(a)*b;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for bmat and cmat
+  */
+  inline cmat operator*(const bmat &a, const cmat &b) {return to_cmat(a)*b;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for smat and cmat
+  */
+  inline cmat operator*(const smat &a, const cmat &b) {return to_cmat(a)*b;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for imat and cmat
+  */
+  inline cmat operator*(const imat &a, const cmat &b) {return to_cmat(a)*b;}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for cmat and mat
+  */
+  inline cmat operator*(const cmat &a, const mat &b) {return a*to_cmat(b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for cmat and bmat
+  */
+  inline cmat operator*(const cmat &a, const bmat &b) {return a*to_cmat(b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for cmat and smat
+  */
+  inline cmat operator*(const cmat &a, const smat &b) {return a*to_cmat(b);}
+
+  /*!
+    \relatesalso Mat
+    \brief Multiplication operator for cmat and imat
+  */
+  inline cmat operator*(const cmat &a, const imat &b) {return a*to_cmat(b);}
+
+} // namespace itpp
+
+#endif // #ifndef OPERATORS_H
+
Index: /win32/itpp-4.0.1/itpp/base/help_functions.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/help_functions.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/help_functions.h (revision 35)
@@ -0,0 +1,263 @@
+/*!
+ * \file
+ * \brief Help functions to make functions with vec and mat as arguments
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef HELP_FUNCTIONS_H
+#define HELP_FUNCTIONS_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/mat.h>
+
+
+namespace itpp {
+
+  //! \addtogroup miscfunc
+  //!@{
+
+  //! Help function to call for a function: Vec<T> function(Vec<T>)
+  template<typename T>
+  inline Vec<T> apply_function(T (*f)(T), const Vec<T>& v)
+  {
+    Vec<T> out(v.length());
+    for (int i = 0; i < v.length(); i++) {
+      out(i) = f(v(i));
+    }
+    return out;
+  }
+
+  //! Help function to call for a function: Vec<T> function(const Vec<T>&)
+  template<typename T>
+  inline Vec<T> apply_function(T (*f)(const T&), const Vec<T>& v)
+  {
+    Vec<T> out(v.length());
+    for (int i = 0; i < v.length(); i++) {
+      out(i) = f(v(i));
+    }
+    return out;
+  }
+
+  //! Help function to call for a function: Mat<T> function(Mat<T>&)
+  template<typename T>
+  inline Mat<T> apply_function(T (*f)(T), const Mat<T>& m)
+  {
+    Mat<T> out(m.rows(), m.cols());
+    for (int i = 0; i < m.rows(); i++) {
+      for (int j = 0; j < m.cols(); j++) {
+	out(i, j) = f(m(i, j));
+      }
+    }
+    return out;
+  }
+
+  //! Help function to call for a function: Mat<T> function(const Mat<T>&)
+  template<typename T>
+  inline Mat<T> apply_function(T (*f)(const T&), const Mat<T>& m)
+  {
+    Mat<T> out(m.rows(), m.cols());
+    for (int i = 0; i < m.rows(); i++) {
+      for (int j = 0; j < m.cols(); j++) {
+	out(i, j) = f(m(i, j));
+      }
+    }
+    return out;
+  }
+
+
+  //! Help function to call for a function: Vec<T> function(T, Vec<T>)
+  template<typename T>
+  inline Vec<T> apply_function(T (*f)(T, T), const T& x, const Vec<T>& v)
+  {
+    Vec<T> out(v.length());
+    for (int i = 0; i < v.length(); i++) {
+      out(i) = f(x, v(i));
+    }
+    return out;
+  }
+
+  //! \brief Help function to call for a function:
+  //!        Vec<T> function(const T&, const Vec<T>&)
+  template<typename T>
+  inline Vec<T> apply_function(T (*f)(const T&, const T&), const T& x,
+			       const Vec<T>& v)
+  {
+    Vec<T> out(v.length());
+    for (int i = 0; i < v.length(); i++) {
+      out(i) = f(x, v(i));
+    }
+    return out;
+  }
+
+  //! Help function to call for a function: Mat<T> function(T, Mat<T>)
+  template<typename T>
+  inline Mat<T> apply_function(T (*f)(T, T), const T& x, const Mat<T>& m)
+  {
+    Mat<T> out(m.rows(), m.cols());
+    for (int i = 0; i < m.rows(); i++) {
+      for (int j = 0; j < m.cols(); j++) {
+	out(i, j) = f(x, m(i, j));
+      }
+    }
+    return out;
+  }
+
+  //! \brief Help function to call for a function:
+  //!        Mat<T> function(const T&, const Mat<T>&)
+  template<typename T>
+  inline Mat<T> apply_function(T (*f)(const T&, const T&), const T& x,
+			       const Mat<T>& m)
+  {
+    Mat<T> out(m.rows(), m.cols());
+    for (int i = 0; i < m.rows(); i++) {
+      for (int j = 0; j < m.cols(); j++) {
+	out(i, j) = f(x, m(i, j));
+      }
+    }
+    return out;
+  }
+
+  //! Help function to call for a function: Vec<T> function(Vec<T>, T)
+  template<typename T>
+  inline Vec<T> apply_function(T (*f)(T, T), const Vec<T>& v, const T& x)
+  {
+    Vec<T> out(v.length());
+    for (int i = 0; i < v.length(); i++) {
+      out(i) = f(v(i), x);
+    }
+    return out;
+  }
+
+  //! \brief Help function to call for a function:
+  //!        Vec<T> function(const Vec<T>&, const T&)
+  template<typename T>
+  inline Vec<T> apply_function(T (*f)(const T&, const T&), const Vec<T>& v,
+			       const T& x)
+  {
+    Vec<T> out(v.length());
+    for (int i = 0; i < v.length(); i++) {
+      out(i) = f(v(i), x);
+    }
+    return out;
+  }
+
+  //! Help function to call for a function: Mat<T> function(Mat<T>, T)
+  template<typename T>
+  inline Mat<T> apply_function(T (*f)(T, T), const Mat<T>& m, const T& x)
+  {
+    Mat<T> out(m.rows(), m.cols());
+    for (int i = 0; i < m.rows(); i++) {
+      for (int j = 0; j < m.cols(); j++) {
+	out(i, j) = f(m(i, j), x);
+      }
+    }
+    return out;
+  }
+
+  //! \brief Help function to call for a function:
+  //!        Mat<T> function(const Mat<T>&, const T&)
+  template<typename T>
+  inline Mat<T> apply_function(T (*f)(const T&, const T&), const Mat<T>& m,
+			       const T& x)
+  {
+    Mat<T> out(m.rows(), m.cols());
+    for (int i = 0; i < m.rows(); i++) {
+      for (int j = 0; j < m.cols(); j++) {
+	out(i, j) = f(m(i, j), x);
+      }
+    }
+    return out;
+  }
+
+  //!@}
+
+  //! \cond
+
+  // ----------------------------------------------------------------------
+  // Instantiations
+  // ----------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  extern template vec apply_function(double (*f)(double), const vec &v);
+  extern template cvec apply_function(std::complex<double> (*f)(const std::complex<double> &),
+                                      const cvec &v);
+  extern template svec apply_function(short (*f)(short), const svec &v);
+  extern template ivec apply_function(int (*f)(int), const ivec &v);
+  extern template bvec apply_function(bin (*f)(bin), const bvec &v);
+
+  extern template mat apply_function(double (*f)(double), const mat &m);
+  extern template cmat apply_function(std::complex<double> (*f)(const std::complex<double> &),
+                                      const cmat &m);
+  extern template smat apply_function(short (*f)(short), const smat &m);
+  extern template imat apply_function(int (*f)(int), const imat &m);
+  extern template bmat apply_function(bin (*f)(bin), const bmat &m);
+
+  extern template vec apply_function(double (*f)(double, double), const double& x, const vec &v);
+  extern template cvec apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                                                                const std::complex<double> &),
+                                      const std::complex<double>& x, const cvec &v);
+  extern template svec apply_function(short (*f)(short, short), const short& x, const svec &v);
+  extern template ivec apply_function(int (*f)(int, int), const int& x, const ivec &v);
+  extern template bvec apply_function(bin (*f)(bin, bin), const bin& x, const bvec &v);
+
+  extern template mat apply_function(double (*f)(double, double), const double& x, const mat &m);
+  extern template cmat apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                                                                const std::complex<double> &),
+                                      const std::complex<double>& x, const cmat &m);
+  extern template smat apply_function(short (*f)(short, short), const short& x, const smat &m);
+  extern template imat apply_function(int (*f)(int, int), const int& x, const imat &m);
+  extern template bmat apply_function(bin (*f)(bin, bin), const bin& x, const bmat &m);
+
+  extern template vec apply_function(double (*f)(double, double), const vec &v, const double& x);
+  extern template cvec apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                                                                const std::complex<double> &),
+                                      const cvec &v, const std::complex<double>& x);
+  extern template svec apply_function(short (*f)(short, short), const svec &v, const short& x);
+  extern template ivec apply_function(int (*f)(int, int), const ivec &v, const int& x);
+  extern template bvec apply_function(bin (*f)(bin, bin), const bvec &v, const bin& x);
+
+  extern template mat apply_function(double (*f)(double, double), const mat &m, const double& x);
+  extern template cmat apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                                                                const std::complex<double> &),
+                                      const cmat &m, const std::complex<double>& x);
+  extern template smat apply_function(short (*f)(short, short), const smat &m, const short& x);
+  extern template imat apply_function(int (*f)(int, int), const imat &m, const int& x);
+  extern template bmat apply_function(bin (*f)(bin, bin), const bmat &m, const bin& x);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // #ifndef HELP_FUNCTIONS_H
+
Index: /win32/itpp-4.0.1/itpp/base/gf2mat.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/gf2mat.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/gf2mat.h (revision 35)
@@ -0,0 +1,500 @@
+/*!
+ * \file
+ * \brief Definition of a class for algebra on GF(2) (binary) matrices
+ * \author Erik G. Larsson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ *
+ * Two representations are offered: GF2mat_sparse for sparse GF(2)
+ * matrices and GF2mat for dense GF(2) matrices. Conversions between
+ * dense and sparse GF(2) are also possible.
+ *
+ * Binary vectors are represented either via the bvec class (memory
+ * typically is not an issue here) or as n*1 (or 1*n) GF(2) matrix.
+ *
+ * Note that the \c bmat class also provides some functionality for
+ * matrix algebra over GF(2) but this class is based on \c Mat<> which
+ * has a fundamentally different addressing mechanism and which is
+ * much less memory efficient (\c Mat<> uses one byte memory minimum
+ * per element).
+ */
+
+#ifndef GF2MAT_H
+#define GF2MAT_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/mat.h>
+#include <itpp/base/svec.h>
+#include <itpp/base/smat.h>
+#include <itpp/base/itfile.h>
+
+
+namespace itpp {
+
+  // ----------------------------------------------------------------------
+  // Sparse GF(2) matrix class
+  // ----------------------------------------------------------------------
+
+  //! Sparse GF(2) vector
+  typedef Sparse_Vec<bin> GF2vec_sparse;
+
+  //! Sparse GF(2) matrix
+  typedef Sparse_Mat<bin> GF2mat_sparse;
+
+
+  // ----------------------------------------------------------------------
+  // Alist parameterization of sparse GF(2) matrix class
+  // ----------------------------------------------------------------------
+
+  /*!
+    \relatesalso GF2mat_sparse
+    \brief Parameterized "alist" representation of sparse GF(2) matrix
+    \author Adam Piatyszek and Erik G. Larsson
+
+    This class is used to provide a parameterized representation of a \c
+    GF2mat_sparse class. The format is compatible with the "alist" format
+    defined by David MacKay, Matthew Davey and John Lafferty:
+    - http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html
+
+    For examples of "alist" representation visit David MacKay's Encyclopedia
+    of Sparse Graph Codes:
+    - http://www.inference.phy.cam.ac.uk/mackay/codes/data.html
+  */
+  class GF2mat_sparse_alist {
+  public:
+    //! Default constructor
+    GF2mat_sparse_alist() : data_ok(false) {}
+    //! Constructor, which reads alist data from a file named \c fname
+    GF2mat_sparse_alist(const std::string &fname);
+
+    //! Read alist data from a file named \c fname
+    void read(const std::string &fname);
+    //! Write alist data to a file named \c fname
+    void write(const std::string &fname) const;
+
+    /*!
+      \brief Convert "alist" representation to \c GF2mat_sparse
+
+      \param transpose Indicates whether a matrix should be transposed
+      during the conversion process
+    */
+    GF2mat_sparse to_sparse(bool transpose = false) const;
+
+    /*!
+      \brief Import "alist" representation from \c GF2mat_sparse
+
+      \param mat Matrix to import
+      \param transpose Indicates whether a matrix should be transposed
+      during the conversion process
+    */
+    void from_sparse(const GF2mat_sparse &mat, bool transpose = false);
+
+  protected:
+    //! Flag indicating that "alist" matrix data are properly set
+    bool data_ok;
+    //! Size of the matrix: \c M rows x \c N columns
+    int M;
+    //! Size of the matrix: \c M rows x \c N columns
+    int N;
+    //! List of integer coordinates in the m direction with non-zero entries
+    imat mlist;
+    //! List of integer coordinates in the n direction with non-zero entries
+    imat nlist;
+    //! Weight of each row m
+    ivec num_mlist;
+    //! Weight of each column n
+    ivec num_nlist;
+    //! Maximum weight of rows
+    int max_num_m;
+    //! Maximum weight of columns
+    int max_num_n;
+  };
+
+
+  // ----------------------------------------------------------------------
+  // Dense GF(2) matrix class
+  // ----------------------------------------------------------------------
+
+  /*!
+    \relatesalso bmat
+    \brief Class for dense GF(2) matrices
+    \author Erik G. Larsson
+
+    This class can be used as an alternative to \c bmat to represent
+    GF(2) matrices. It extends the functionality of \c bmat in two ways:
+
+    - \c GF2mat makes more efficient use of computer memory than \c bmat
+    (one bit in the matrix requires one bit of memory)
+    - \c GF2mat provides several functions for linear algebra and matrix
+    factorizations
+
+    See also \c GF2mat_sparse which offers an efficient representation
+    of sparse GF(2) matrices, and \c GF2mat_sparse_alist for a
+    parameterized representation of sparse GF(2) matrices.
+  */
+  class GF2mat {
+  public:
+
+    // ----------- Constructors -----------
+
+    //! Default constructor (gives an empty 1 x 1 matrix)
+    GF2mat();
+
+    //! Construct an empty (all-zero) m x n matrix
+    GF2mat(int m, int n);
+
+    //! Construct a dense GF(2) matrix from a sparse GF(2) matrix
+    GF2mat(const GF2mat_sparse &X);
+
+    /*! \brief Constructor, from subset of sparse GF(2) matrix
+
+    This constructor forms a dense GF(2) matrix from a subset (m1,n1)
+    to (m2,n2) of a sparse GF(2) matrix */
+    GF2mat(const GF2mat_sparse &X, int m1, int n1, int m2, int n2);
+
+    /*! \brief Constructor, from subset of sparse GF(2) matrix
+
+    This constructor forms a dense GF(2) matrix from a subset of
+    columns in sparse GF(2) matrix
+
+    \param X matrix to copy from
+    \param columns subset of columns to copy
+    */
+    GF2mat(const GF2mat_sparse &X, const ivec &columns);
+
+    /*!
+      \brief Create a dense GF(2) matrix from a single vector.
+
+      \param x The input vector
+      \param is_column A parameter that indicates whether the result should
+      be a row vector (false), or a column vector (true - default)
+    */
+    GF2mat(const bvec &x, bool is_column = true);
+
+    //! Create a dense GF(2) matrix from a bmat
+    GF2mat(const bmat &X);
+
+    //! Set size of GF(2) matrix. If copy = true, keep data before resizing.
+    void set_size(int m, int n, bool copy = false);
+
+    //! Create a sparse GF(2) matrix from a dense GF(2) matrix
+    GF2mat_sparse sparsify() const;
+
+    //! Create a bvec from a GF(2) matrix (must have one column or one row)
+    bvec bvecify() const;
+
+    // ----------- Elementwise manipulation and simple functions -------------
+
+    //! Getting element
+    inline bin get(int i, int j) const;
+
+    //! Getting element
+    inline bin operator()(int i, int j) const { return get(i,j); };
+
+    //! Set element i,j to s (0 or 1)
+    inline void set(int i, int j, bin s);
+
+    //! Add s (0 or 1) to element (i,j)
+    inline void addto_element(int i, int j, bin s);
+
+    //! Set column j to a binary vector x
+    void set_col(int j, bvec x);
+
+    //! Set row i to a binary vector x
+    void set_row(int i, bvec x);
+
+    //! Check whether the matrix is identical to zero
+    bool is_zero() const;
+
+    //! Swap rows i and j
+    void swap_rows(int i, int j);
+
+    //! Swap columns i and j
+    void swap_cols(int i, int j);
+
+    /*! \brief Multiply from left with permutation matrix (permute rows).
+
+    \param perm Permutation vector
+    \param I Parameter that determines permutation.
+    I=0: apply permutation, I=1: apply inverse permutation
+    */
+    void permute_rows(ivec &perm, bool I);
+
+    /*! \brief Multiply a matrix from right with a permutation matrix
+      (i.e., permute the columns).
+
+    \param perm Permutation vector
+    \param I Parameter that determines permutation.
+    I=0: apply permutation, I=1: apply inverse permutation
+    */
+    void permute_cols(ivec &perm, bool I);
+
+    //! Transpose
+    GF2mat transpose() const;
+
+    //! Submatrix from (m1,n1) to (m2,n2)
+    GF2mat get_submatrix(int m1, int n1, int m2, int n2) const;
+
+    //! Concatenate horizontally (append X on the right side of matrix)
+    GF2mat concatenate_horizontal(const GF2mat &X) const;
+
+    //! Concatenate vertically (append X underneath)
+    GF2mat concatenate_vertical(const GF2mat &X) const;
+
+    //! Get row
+    bvec get_row(int i) const;
+
+    //! Get column
+    bvec get_col(int j) const;
+
+    //! Compute the matrix density (fraction of elements equal to "1")
+    double density() const;
+
+    //! Get number of rows
+    int rows() const { return nrows; }
+
+    //! Get number of columns
+    int cols() const { return ncols; }
+
+    /*! \brief Add (or equivalently, subtract) rows
+
+    This function updates row i according to row_i = row_i+row_j
+
+    \param i Row to add to. This row will be modified
+    \param j Row to add. This row will <b>not</b> be modified.
+    */
+    void add_rows(int i, int j);
+
+    // ---------- Linear algebra --------------
+
+    /*!  \brief Inversion.
+
+    The matrix must be invertible, otherwise the
+      function will terminate with an error.
+    */
+    GF2mat inverse() const;
+
+    //! Returns the number of linearly independent rows
+    int row_rank() const;
+
+    /*! \brief TXP factorization.
+
+    Given X, compute a factorization of the form U=TXP, where U is
+      upper triangular, T is square and invertible, and P is a
+      permutation matrix.  This is basically an "LU"-factorization,
+      but not called so here because T is not necessarily lower
+      trianglular.  The matrix X may have any dimension. The
+      permutation matrix P is represented as a permutation vector.
+
+      The function returns the row rank of X.  (If X is full row rank,
+      then the number of rows is returned.)
+
+      The function uses Gaussian elimination combined with
+      permutations.  The computational complexity is O(m*m*n) for an
+      m*n matrix.
+    */
+    int T_fact(GF2mat &T, GF2mat &U, ivec &P) const;
+
+    /*! \brief TXP factorization update, when bit is flipped.
+
+    Update upper triangular factor U in the TXP-factorization (U=TXP)
+    when the bit at position (r,c) is changed (0->1 or 1->0). The
+    purpose of this function is to avoid re-running a complete
+    T-factorization when a single bit is changed. The function assumes
+    that T, U, and P already exist and that U=TXP before the function
+    is called. The function also assumes that the rank provided is
+    correct. The function updates T, U and P these matrices.  The
+    function returns the new rank of the matrix after the bitflip.
+
+    \note T, U, P and the rank value supplied to the function must be
+    correct one. This is not checked by the function (for reasons of
+    efficiency).
+
+    The function works by performing permutations to bring the matrix
+    to a form where the Gaussian eliminated can be restarted from the
+    point (rank-1,rank-1). The function is very fast for matrices with
+    close to full rank but it is generally slower for non-full rank
+    matrices.
+    */
+    int T_fact_update_bitflip(GF2mat &T, GF2mat &U,
+			      ivec &P, int rank, int r, int c) const;
+
+    /*!  \brief TXP factorization update, when column is added
+
+    Update upper triangular factor U in the T-factorization (U=TXP)
+    when a column (newcol) is appended at the right side of the
+    matrix.  The purpose of this function is to avoid re-running a
+    complete T-factorization when a column is added. The function ONLY
+    adds the column if it improves the rank of the matrix (nothing is
+    done otherwise).  The function returns "true" if the column was
+    added, and "false" otherwise.
+
+    \note This function does not actually add the column newcol to the
+    GF2 matrix. It only checks whether doing so would increase the
+    rank, and if this is the case, it updates the T-factorization.  A
+    typical calling sequence would be
+    \code
+    bool rank_will_improve =  X.T_fact_update_addcol(T,U,perm,c);
+    if (rank_will_improve) { X = X.concatenate_horizontal(c); }
+    \endcode
+
+    The complexity is O(m^2) for an m*n matrix.
+    */
+    bool T_fact_update_addcol(GF2mat &T, GF2mat &U,
+			      ivec &P, bvec newcol) const;
+
+    // ----- Operators -----------
+
+    //! Assignment operator
+    void operator=(const GF2mat &X);
+
+    //! Check if equal
+    bool operator==(const GF2mat &X) const;
+
+    // ----- Friends ------
+
+    //! Multiplication operator
+    friend GF2mat operator*(const GF2mat &X, const GF2mat &Y);
+
+    //! Multiplication operator with binary vector
+    friend bvec operator*(const GF2mat &X, const bvec &y);
+
+    /*! \brief Addition operator
+
+    Subtraction is not implemented because it is
+      equivalent to addition. */
+    friend GF2mat operator+(const GF2mat &X, const GF2mat &Y);
+
+    //! Output stream operator (plain text)
+    friend std::ostream &operator<<(std::ostream &os, const GF2mat &X);
+
+    //! Write the matrix to file
+    friend it_file &operator<<(it_file &f, const GF2mat &X);
+
+    //! Read the matrix from file
+    friend it_ifile &operator>>(it_ifile &f, GF2mat &X);
+
+    //!Multiplication X*Y' where X and Y are GF(2) matrices
+    friend GF2mat mult_trans(const GF2mat &X, const GF2mat &Y);
+
+  private:
+    int nrows, ncols;            // number of rows and columns of matrix
+    int nwords;                  // number of bytes used
+    Mat<unsigned char> data;		 // data structure
+
+    // This value is used to perform division by bit shift and is equal to
+    // log2(8)
+    static const unsigned char shift_divisor = 3;
+
+    // This value is used as a mask when computing the bit position of the
+    // division remainder
+    static const unsigned char rem_mask = (1 << shift_divisor) - 1;
+  };
+
+
+  // ----------------------------------------------------------------------
+  // GF2mat related functions
+  // ----------------------------------------------------------------------
+
+  /*!
+    /relatesalso GF2mat
+    /brief Write GF(2) matrix to file.
+  */
+  it_file &operator<<(it_file &f, const GF2mat &X);
+
+  /*!
+    /relatesalso GF2mat
+    /brief Read GF(2) matrix from file.
+  */
+  it_ifile &operator>>(it_ifile &f, GF2mat &X);
+
+  /*!
+    \relatesalso GF2mat
+    \brief GF(2) matrix multiplication
+  */
+  GF2mat operator*(const GF2mat &X, const GF2mat &Y);
+
+  /*!
+    \relatesalso GF2mat
+    \brief GF(2) matrix multiplication with "regular" binary vector
+  */
+  bvec operator*(const GF2mat &X, const bvec &y);
+
+  /*!
+    \relatesalso GF2mat
+    \brief GF(2) matrix addition
+  */
+  GF2mat operator+(const GF2mat &X, const GF2mat &Y);
+
+  /*!
+    \relatesalso GF2mat
+    \brief Output stream (plain text) operator for dense GF(2) matrices
+  */
+  std::ostream &operator<<(std::ostream &os, const GF2mat &X);
+
+  /*!
+    \relatesalso GF2mat
+    \brief GF(2) Identity matrix
+  */
+  GF2mat gf2dense_eye(int m);
+
+  /*!
+    \relatesalso GF2mat
+    \brief Multiplication X*Y' where X and Y are GF(2) matrices
+  */
+  GF2mat mult_trans(const GF2mat &X, const GF2mat &Y);
+
+
+  // ----------------------------------------------------------------------
+  // Inline implementations
+  // ----------------------------------------------------------------------
+
+  inline void GF2mat::addto_element(int i, int j, bin s)
+  {
+    it_assert_debug(i >= 0 && i < nrows, "GF2mat::addto_element()");
+    it_assert_debug(j >= 0 && j < ncols, "GF2mat::addto_element()");
+    if (s == 1)
+      data(i, (j >> shift_divisor)) ^= (1 << (j & rem_mask));
+  }
+
+  inline bin GF2mat::get(int i, int j) const
+  {
+    it_assert_debug(i >= 0 && i < nrows, "GF2mat::get_element()");
+    it_assert_debug(j >= 0 && j < ncols, "GF2mat::get_element()");
+    return (data(i, (j >> shift_divisor)) >> (j & rem_mask)) & 1;
+  }
+
+  inline void GF2mat::set(int i, int j, bin s)
+  {
+    it_assert_debug(i >= 0 && i < nrows, "GF2mat::set_element()");
+    it_assert_debug(j >= 0 && j < ncols, "GF2mat::set_element()");
+    if (s == 1) // set bit to one
+      data(i, (j >> shift_divisor)) |= (1 << (j & rem_mask));
+    else // set bit to zero
+      data(i, (j >> shift_divisor)) &= (~(1 << (j & rem_mask)));
+  }
+
+} // namespace itpp
+
+#endif // #ifndef GF2MAT_H
Index: /win32/itpp-4.0.1/itpp/base/random.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/random.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/random.h (revision 35)
@@ -0,0 +1,843 @@
+/*!
+ * \file
+ * \brief Definition of classes for random number generators
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#include <itpp/base/operators.h>
+#include <ctime>
+
+
+namespace itpp {
+
+  //! \addtogroup randgen
+
+  /*!
+   * \brief Base class for random (stochastic) sources.
+   * \ingroup randgen
+   *
+   * The Random_Generator class is based on the MersenneTwister MTRand
+   * class code in version 1.0 (15 May 2003) by Richard J. Wagner. See
+   * http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
+   * for details.
+   *
+   * Here are the original release notes copied from the
+   * \c MersenneTwister.h file:
+   *
+   * \verbatim
+   * Mersenne Twister random number generator -- a C++ class MTRand Based on
+   * code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus Richard J.
+   * Wagner v1.0 15 May 2003 rjwagner@writeme.com
+   *
+   * The Mersenne Twister is an algorithm for generating random numbers. It
+   * was designed with consideration of the flaws in various other generators.
+   * The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
+   * are far greater. The generator is also fast; it avoids multiplication and
+   * division, and it benefits from caches and pipelines. For more information
+   * see the inventors' web page at
+   * http://www.math.keio.ac.jp/~matumoto/emt.html
+
+   * Reference:
+   * M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
+   * Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions
+   * on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp.
+   * 3-30.
+   *
+   * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+   * Copyright (C) 2000 - 2003, Richard J. Wagner
+   * All rights reserved.
+   *
+   * Redistribution and use in source and binary forms, with or without
+   * modification, are permitted provided that the following conditions
+   * are met:
+   *
+   *   1. Redistributions of source code must retain the above copyright
+   *      notice, this list of conditions and the following disclaimer.
+   *
+   *   2. Redistributions in binary form must reproduce the above copyright
+   *      notice, this list of conditions and the following disclaimer in the
+   *      documentation and/or other materials provided with the distribution.
+   *
+   *   3. The names of its contributors may not be used to endorse or promote
+   *      products derived from this software without specific prior written
+   *      permission.
+   *
+   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+   * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+   *
+   * The original code included the following notice:
+   *
+   *     When you use this, send an email to: matumoto@math.keio.ac.jp with an
+   *     appropriate reference to your work.
+   *
+   * It would be nice to CC: rjwagner@writeme.com and
+   * Cokus@math.washington.edu when you write.
+   * \endverbatim
+   */
+  class Random_Generator {
+  public:
+    //! Construct a new Random_Generator.
+    Random_Generator() { if (!initialized) reset(4357U); }
+    //! Construct Random_Generator object using \c seed
+    Random_Generator(unsigned int seed) { reset(seed); }
+    //! Set the seed to a semi-random value (based on hashed time and clock).
+    void randomize() { reset(hash(time(0), clock())); }
+    //! Reset the source. The same sequance will be generated as the last time.
+    void reset() { initialize(last_seed); reload(); initialized = true; }
+    //! Reset the source after setting the seed to seed.
+    void reset(unsigned int seed) { last_seed = seed; reset(); }
+
+    //! Return a uniformly distributed [0,2^32-1] integer.
+    unsigned int random_int()
+    {
+      if( left == 0 ) reload();
+      --left;
+
+      register unsigned int s1;
+      s1 = *pNext++;
+      s1 ^= (s1 >> 11);
+      s1 ^= (s1 <<  7) & 0x9d2c5680U;
+      s1 ^= (s1 << 15) & 0xefc60000U;
+      return ( s1 ^ (s1 >> 18) );
+    }
+
+    //! Return a uniformly distributed (0,1) value.
+    double random_01() { return (random_int() + 0.5) * (1.0/4294967296.0); }
+    //! Return a uniformly distributed [0,1) value.
+    double random_01_lclosed() { return random_int() * (1.0/4294967296.0); }
+    //! Return a uniformly distributed [0,1] value.
+    double random_01_closed() { return random_int() * (1.0/4294967295.0); }
+    //! Return a uniformly distributed [0,1) value in 53-bit resolution.
+    double random53_01_lclosed()
+    {
+      return ((random_int() >> 5) * 67108864.0 + (random_int() >> 6))
+	* (1.0/9007199254740992.0); // by Isaku Wada
+    }
+
+    //! Save current full state of generator in memory
+    void get_state(ivec &out_state);
+    //! Resume the state saved in memory. Clears memory.
+    void set_state(ivec &new_state);
+
+  private:
+    //! initialization flag
+    static bool initialized;
+    //! seed used for initialisation
+    unsigned int last_seed;
+    //! internal state
+    static unsigned int state[624];
+    //! next value to get from state
+    static unsigned int *pNext;
+    //! number of values left before reload needed
+    static int left;
+
+    /*!
+     * \brief Initialize generator state with seed.
+     * See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
+     * \note In previous versions, most significant bits (MSBs) of the seed
+     * affect only MSBs of the state array. Modified 9 Jan 2002 by Makoto
+     * Matsumoto.
+     */
+    void initialize( unsigned int seed )
+    {
+      register unsigned int *s = state;
+      register unsigned int *r = state;
+      register int i = 1;
+      *s++ = seed & 0xffffffffU;
+      for( ; i < 624; ++i )
+	{
+	  *s++ = ( 1812433253U * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffU;
+	  r++;
+	}
+    }
+
+    /*!
+     * \brief Generate N new values in state.
+     * Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
+     */
+    void reload()
+    {
+      register unsigned int *p = state;
+      register int i;
+      for( i = 624 - 397; i--; ++p )
+	*p = twist( p[397], p[0], p[1] );
+      for( i = 397; --i; ++p )
+	*p = twist( p[397-624], p[0], p[1] );
+      *p = twist( p[397-624], p[0], state[0] );
+
+      left = 624, pNext = state;
+    }
+    //!
+    unsigned int hiBit( const unsigned int& u ) const { return u & 0x80000000U; }
+    //!
+    unsigned int loBit( const unsigned int& u ) const { return u & 0x00000001U; }
+    //!
+    unsigned int loBits( const unsigned int& u ) const { return u & 0x7fffffffU; }
+    //!
+    unsigned int mixBits( const unsigned int& u, const unsigned int& v ) const
+    { return hiBit(u) | loBits(v); }
+
+    /*
+     * ----------------------------------------------------------------------
+     * --- ediap - 2007/01/17 ---
+     * ----------------------------------------------------------------------
+     * Wagners's implementation of the twist() function was as follows:
+     *  { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfU); }
+     * However, this code caused a warning/error under MSVC++, because
+     * unsigned value loBit(s1) is being negated with `-' (c.f. bug report
+     * [1635988]). I changed this to the same implementation as is used in
+     * original C sources of Mersenne Twister RNG:
+     *  #define MATRIX_A 0x9908b0dfUL
+     *  #define UMASK 0x80000000UL
+     *  #define LMASK 0x7fffffffUL
+     *  #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
+     *  #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
+     * ----------------------------------------------------------------------
+     */
+    //!
+    unsigned int twist( const unsigned int& m, const unsigned int& s0,
+			const unsigned int& s1 ) const
+    { return m ^ (mixBits(s0,s1)>>1) ^ (loBit(s1) ? 0x9908b0dfU : 0U); }
+    //!
+    unsigned int hash( time_t t, clock_t c );
+  };
+
+
+  //! \addtogroup randgen
+  //!@{
+
+  //! Set the seed of the Global Random Number Generator
+  void RNG_reset(unsigned int seed);
+  //! Set the seed of the Global Random Number Generator to the same as last reset/init
+  void RNG_reset();
+  //! Set a random seed for the Global Random Number Generator.
+  void RNG_randomize();
+  //! Save current full state of generator in memory
+  void RNG_get_state(ivec &state);
+  //! Resume the state saved in memory
+  void RNG_set_state(ivec &state);
+  //!@}
+
+  /*!
+    \brief Bernoulli distribution
+    \ingroup randgen
+  */
+  class Bernoulli_RNG {
+  public:
+    //! Binary source with probability prob for a 1
+    Bernoulli_RNG(double prob) { setup(prob); }
+    //! Binary source with probability prob for a 1
+    Bernoulli_RNG() { p=0.5; }
+    //! set the probability
+    void setup(double prob)
+    {
+      it_assert(prob>=0.0 && prob<=1.0, "The bernoulli source probability must be between 0 and 1");
+      p = prob;
+    }
+    //! return the probability
+    double get_setup() const { return p; }
+    //! Get one sample.
+    bin operator()() { return sample(); }
+    //! Get a sample vector.
+    bvec operator()(int n) { bvec temp(n); sample_vector(n, temp); return temp; }
+    //! Get a sample matrix.
+    bmat operator()(int h, int w) { bmat temp(h, w); sample_matrix(h, w, temp); return temp; }
+    //! Get a sample
+    bin sample() { return bin( RNG.random_01() < p ? 1 : 0 ); }
+    //! Get a sample vector.
+    void sample_vector(int size, bvec &out)
+    {
+      out.set_size(size, false);
+      for (int i=0; i<size; i++) out(i) = sample();
+    }
+    //! Get a sample matrix.
+    void sample_matrix(int rows, int cols, bmat &out)
+    {
+      out.set_size(rows, cols, false);
+      for (int i=0; i<rows*cols; i++) out(i) = sample();
+    }
+  protected:
+  private:
+    //!
+    double p;
+    //!
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief Integer uniform distribution
+    \ingroup randgen
+
+    Example: Generation of random uniformly distributed integers in the interval [0,10].
+    \code
+    #include "itpp/sigproc.h"
+
+    int main() {
+
+    I_Uniform_RNG gen(0, 10);
+
+    cout << gen() << endl; // prints a random integer
+    cout << gen(10) << endl; // prints 10 random integers
+    }
+    \endcode
+  */
+  class I_Uniform_RNG {
+  public:
+    //! constructor. Sets min and max values.
+    I_Uniform_RNG(int min=0, int max=1);
+    //! set min and max values
+    void setup(int min, int max);
+    //! get the parameters
+    void get_setup(int &min, int &max) const;
+    //! Get one sample.
+    int operator()() { return sample(); }
+    //! Get a sample vector.
+    ivec operator()(int n);
+    //! Get a sample matrix.
+    imat operator()(int h, int w);
+    //! Return a single value from this random generator
+    int sample() { return ( floor_i(RNG.random_01() * (hi - lo + 1)) + lo ); }
+  protected:
+  private:
+    //!
+    int lo;
+    //!
+    int hi;
+    //!
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief Uniform distribution
+    \ingroup randgen
+  */
+  class Uniform_RNG {
+  public:
+    //! Constructor. Set min, max and seed.
+    Uniform_RNG(double min=0, double max=1.0);
+    //! set min and max
+    void setup(double min, double max);
+    //! get parameters
+    void get_setup(double &min, double &max) const;
+    //! Get one sample.
+    double operator()() { return (sample() * (hi_bound - lo_bound) + lo_bound); }
+    //! Get a sample vector.
+    vec operator()(int n)
+    {
+      vec temp(n);
+      sample_vector(n, temp);
+      temp *= hi_bound - lo_bound;
+      temp += lo_bound;
+      return temp;
+    }
+    //! Get a sample matrix.
+    mat operator()(int h, int w)
+    {
+      mat temp(h, w);
+      sample_matrix(h, w, temp);
+      temp *= hi_bound - lo_bound;
+      temp += lo_bound;
+      return temp;
+    }
+    //! Get a Uniformly distributed (0,1) sample
+    double sample() {  return RNG.random_01(); }
+    //! Get a Uniformly distributed (0,1) vector
+    void sample_vector(int size, vec &out)
+    {
+      out.set_size(size, false);
+      for (int i=0; i<size; i++) out(i) = sample();
+    }
+    //! Get a Uniformly distributed (0,1) matrix
+    void sample_matrix(int rows, int cols, mat &out)
+    {
+      out.set_size(rows, cols, false);
+      for (int i=0; i<rows*cols; i++) out(i) = sample();
+    }
+  protected:
+  private:
+    //!
+    double lo_bound, hi_bound;
+    //!
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief Exponential distribution
+    \ingroup randgen
+  */
+  class Exponential_RNG {
+  public:
+    //! constructor. Set lambda.
+    Exponential_RNG(double lambda=1.0);
+    //! Set lambda
+    void setup(double lambda) { l=lambda; }
+    //! get lambda
+    double get_setup() const;
+    //! Get one sample.
+    double operator()() { return sample(); }
+    //! Get a sample vector.
+    vec operator()(int n);
+    //! Get a sample matrix.
+    mat operator()(int h, int w);
+  protected:
+  private:
+    //!
+    double sample() {  return ( -std::log(RNG.random_01()) / l ); }
+    //!
+    double l;
+    //!
+    Random_Generator RNG;
+  };
+
+  /*!
+   * \brief Normal distribution
+   * \ingroup randgen
+   *
+   * Normal (Gaussian) random variables, using a simplified Ziggurat method.
+   *
+   * For details see the following arcticle: George Marsaglia, Wai Wan
+   * Tsang, "The Ziggurat Method for Generating Random Variables", Journal
+   * of Statistical Software, vol. 5 (2000), no. 8
+   *
+   * This implementation is based on the generator written by Jochen Voss
+   * found at http://seehuhn.de/comp/ziggurat/, which is also included in
+   * the GSL library (randlist/gauss.c).
+   */
+  class Normal_RNG {
+  public:
+    //! Constructor. Set mean and variance.
+    Normal_RNG(double meanval, double variance):
+      mean(meanval), sigma(std::sqrt(variance)) {}
+    //! Constructor. Set mean and variance.
+    Normal_RNG(): mean(0.0), sigma(1.0) {}
+    //! Set mean, and variance
+    void setup(double meanval, double variance)
+    { mean = meanval; sigma = std::sqrt(variance); }
+    //! Get mean and variance
+    void get_setup(double &meanval, double &variance) const;
+    //! Get one sample.
+    double operator()() { return (sigma*sample()+mean); }
+    //! Get a sample vector.
+    vec operator()(int n)
+    {
+      vec temp(n);
+      sample_vector(n, temp);
+      temp *= sigma;
+      temp += mean;
+      return temp;
+    }
+    //! Get a sample matrix.
+    mat operator()(int h, int w)
+    {
+      mat temp(h, w);
+      sample_matrix(h, w, temp);
+      temp *= sigma;
+      temp += mean;
+      return temp;
+    }
+    //! Get a Normal distributed (0,1) sample
+    double sample()
+    {
+      unsigned int u, sign, i, j;
+      double x, y;
+
+      while(true) {
+	u = RNG.random_int();
+	sign = u & 0x80; // 1 bit for the sign
+	i = u & 0x7f; // 7 bits to choose the step
+	j = u >> 8; // 24 bits for the x-value
+
+	x = j * wtab[i];
+
+	if (j < ktab[i])
+	  break;
+
+	if (i < 127) {
+	  y = ytab[i+1] + (ytab[i] - ytab[i+1]) * RNG.random_01();
+	}
+	else {
+	  x = PARAM_R - std::log(1.0 - RNG.random_01()) / PARAM_R;
+	  y = std::exp(-PARAM_R * (x - 0.5 * PARAM_R)) * RNG.random_01();
+	}
+
+	if (y < std::exp(-0.5 * x * x))
+	  break;
+      }
+      return sign ? x : -x;
+    }
+
+    //! Get a Normal distributed (0,1) vector
+    void sample_vector(int size, vec &out)
+    {
+      out.set_size(size, false);
+      for (int i=0; i<size; i++) out(i) = sample();
+    }
+
+    //! Get a Normal distributed (0,1) matrix
+    void sample_matrix(int rows, int cols, mat &out)
+    {
+      out.set_size(rows, cols, false);
+      for (int i=0; i<rows*cols; i++) out(i) = sample();
+    }
+  private:
+    double mean, sigma;
+    static const double ytab[128];
+    static const unsigned int ktab[128];
+    static const double wtab[128];
+    static const double PARAM_R;
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief Laplacian distribution
+    \ingroup randgen
+  */
+  class Laplace_RNG {
+  public:
+    //! Constructor. Set mean and variance.
+    Laplace_RNG(double meanval = 0.0, double variance = 1.0);
+    //! Set mean and variance
+    void setup(double meanval, double variance);
+    //! Get mean and variance
+    void get_setup(double &meanval, double &variance) const;
+    //! Get one sample.
+    double operator()() { return sample(); }
+    //! Get a sample vector.
+    vec operator()(int n);
+    //! Get a sample matrix.
+    mat operator()(int h, int w);
+    //! Returns a single sample
+    double sample()
+    {
+      double u = RNG.random_01();
+      double l = sqrt_12var;
+      if (u < 0.5)
+	l *= std::log(2.0 * u);
+      else
+	l *= -std::log(2.0 * (1-u));
+      return (l + mean);
+    }
+  private:
+    double mean, var, sqrt_12var;
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief A Complex Normal Source
+    \ingroup randgen
+  */
+  class Complex_Normal_RNG {
+  public:
+    //! Constructor. Set mean and variance.
+    Complex_Normal_RNG(std::complex<double> mean, double variance):
+      norm_factor(1.0/std::sqrt(2.0))
+    {
+      setup(mean, variance);
+    }
+    //! Default constructor
+    Complex_Normal_RNG(): m(0.0), sigma(1.0), norm_factor(1.0/std::sqrt(2.0)) {}
+    //! Set mean and variance
+    void setup(std::complex<double> mean, double variance)
+    {
+      m = mean; sigma = std::sqrt(variance);
+    }
+    //! Get mean and variance
+    void get_setup(std::complex<double> &mean, double &variance)
+    {
+      mean = m; variance = sigma*sigma;
+    }
+    //! Get one sample.
+    std::complex<double> operator()() { return sigma*sample()+m; }
+    //! Get a sample vector.
+    cvec operator()(int n)
+    {
+      cvec temp(n);
+      sample_vector(n, temp);
+      temp *= sigma;
+      temp += m;
+      return temp;
+    }
+    //! Get a sample matrix.
+    cmat operator()(int h, int w)
+    {
+      cmat temp(h, w);
+      sample_matrix(h, w, temp);
+      temp *= sigma;
+      temp += m;
+      return temp;
+    }
+    //! Get a Complex Normal (0,1) distributed sample
+    std::complex<double> sample()
+    {
+      double a = nRNG.sample() * norm_factor;
+      double b = nRNG.sample() * norm_factor;
+      return std::complex<double>(a, b);
+    }
+
+    //! Get a Complex Normal (0,1) distributed vector
+    void sample_vector(int size, cvec &out)
+    {
+      out.set_size(size, false);
+      for (int i=0; i<size; i++) out(i) = sample();
+    }
+
+    //! Get a Complex Normal (0,1) distributed matrix
+    void sample_matrix(int rows, int cols, cmat &out)
+    {
+      out.set_size(rows, cols, false);
+      for (int i=0; i<rows*cols; i++) out(i) = sample();
+    }
+  private:
+    std::complex<double> m;
+    double sigma;
+    const double norm_factor;
+    Normal_RNG nRNG;
+  };
+
+  /*!
+    \brief Filtered normal distribution
+    \ingroup randgen
+  */
+  class AR1_Normal_RNG {
+  public:
+    //! Constructor. Set mean, variance, and correlation.
+    AR1_Normal_RNG(double meanval = 0.0, double variance = 1.0,
+		   double rho = 0.0);
+    //! Set mean, variance, and correlation
+    void setup(double meanval, double variance, double rho);
+    //! Get mean, variance and correlation
+    void get_setup(double &meanval, double &variance, double &rho) const;
+    //! Set memory contents to zero
+    void reset();
+    //! Get a single random sample
+    double operator()() { return sample(); }
+    //! Get a sample vector.
+    vec operator()(int n);
+    //! Get a sample matrix.
+    mat operator()(int h, int w);
+  private:
+    double sample()
+    {
+      mem *= r;
+      if (odd) {
+	r1 = m_2pi * RNG.random_01();
+	r2 = std::sqrt(factr * std::log(RNG.random_01()));
+	mem += r2 * std::cos(r1);
+      }
+      else {
+	mem += r2 * std::sin(r1);
+      }
+      odd = !odd;
+      return (mem + mean);
+    }
+    double mem, r, factr, mean, var, r1, r2;
+    bool odd;
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief Gauss_RNG is the same as Normal Source
+    \ingroup randgen
+  */
+  typedef Normal_RNG Gauss_RNG;
+
+  /*!
+    \brief AR1_Gauss_RNG is the same as AR1_Normal_RNG
+    \ingroup randgen
+  */
+  typedef AR1_Normal_RNG AR1_Gauss_RNG;
+
+  /*!
+    \brief Weibull distribution
+    \ingroup randgen
+  */
+  class Weibull_RNG {
+  public:
+    //! Constructor. Set lambda and beta.
+    Weibull_RNG(double lambda = 1.0, double beta = 1.0);
+    //! Set lambda, and beta
+    void setup(double lambda, double beta);
+    //! Get lambda and beta
+    void get_setup(double &lambda, double &beta) { lambda = l; beta = b; }
+    //! Get one sample.
+    double operator()() { return sample(); }
+    //! Get a sample vector.
+    vec operator()(int n);
+    //! Get a sample matrix.
+    mat operator()(int h, int w);
+  private:
+    double sample()
+    {
+      return (std::pow(-std::log(RNG.random_01()), 1.0/b) / l);
+    }
+    double l, b;
+    double mean, var;
+    Random_Generator RNG;
+  };
+
+  /*!
+    \brief Rayleigh distribution
+    \ingroup randgen
+  */
+  class Rayleigh_RNG {
+  public:
+    //! Constructor. Set sigma.
+    Rayleigh_RNG(double sigma = 1.0);
+    //! Set sigma
+    void setup(double sigma) { sig = sigma; }
+    //! Get sigma
+    double get_setup() { return sig; }
+    //! Get one sample.
+    double operator()() { return sample(); }
+    //! Get a sample vector.
+    vec operator()(int n);
+    //! Get a sample matrix.
+    mat operator()(int h, int w);
+  private:
+    double sample()
+    {
+      double s1 = nRNG.sample();
+      double s2 = nRNG.sample();
+      // s1 and s2 are N(0,1) and independent
+      return (sig * std::sqrt(s1*s1 + s2*s2));
+    }
+    double sig;
+    Normal_RNG nRNG;
+  };
+
+  /*!
+    \brief Rice distribution
+    \ingroup randgen
+  */
+  class Rice_RNG {
+  public:
+    //! Constructor. Set sigma, and v (if v = 0, Rice -> Rayleigh).
+    Rice_RNG(double sigma = 1.0, double v = 1.0);
+    //! Set sigma, and v (if v = 0, Rice -> Rayleigh).
+    void setup(double sigma, double v) { sig = sigma; s = v; }
+    //! Get parameters
+    void get_setup(double &sigma, double &v) { sigma = sig; v = s; }
+    //! Get one sample
+    double operator()() { return sample(); }
+    //! Get a sample vector
+    vec operator()(int n);
+    //! Get a sample matrix
+    mat operator()(int h, int w);
+  private:
+    double sample()
+    {
+      double s1 = nRNG.sample() + s;
+      double s2 = nRNG.sample();
+      // s1 and s2 are N(0,1) and independent
+      return (sig * std::sqrt(s1*s1 + s2*s2));
+    }
+    double sig, s;
+    Normal_RNG nRNG;
+  };
+
+  //! \addtogroup randgen
+  //!@{
+
+  //! Generates a random bit (equally likely 0s and 1s)
+  inline bin randb(void) { Bernoulli_RNG src; return src.sample(); }
+  //! Generates a random bit vector (equally likely 0s and 1s)
+  inline void randb(int size, bvec &out) { Bernoulli_RNG src; src.sample_vector(size, out); }
+  //! Generates a random bit vector (equally likely 0s and 1s)
+  inline bvec randb(int size) { bvec temp; randb(size, temp); return temp; }
+  //! Generates a random bit matrix (equally likely 0s and 1s)
+  inline void randb(int rows, int cols, bmat &out) { Bernoulli_RNG src; src.sample_matrix(rows, cols, out); }
+  //! Generates a random bit matrix (equally likely 0s and 1s)
+  inline bmat randb(int rows, int cols){ bmat temp; randb(rows, cols, temp); return temp; }
+
+  //! Generates a random uniform (0,1) number
+  inline double randu(void) { Uniform_RNG src; return src.sample(); }
+  //! Generates a random uniform (0,1) vector
+  inline void randu(int size, vec &out) { Uniform_RNG src; src.sample_vector(size, out); }
+  //! Generates a random uniform (0,1) vector
+  inline vec randu(int size){ vec temp; randu(size, temp); return temp; }
+  //! Generates a random uniform (0,1) matrix
+  inline void randu(int rows, int cols, mat &out) { Uniform_RNG src; src.sample_matrix(rows, cols, out); }
+  //! Generates a random uniform (0,1) matrix
+  inline mat randu(int rows, int cols) { mat temp; randu(rows, cols, temp); return temp; }
+
+  //! Generates a random integer in the interval [low,high]
+  inline int randi(int low, int high) { I_Uniform_RNG src; src.setup(low, high); return src(); }
+  //! Generates a random ivec with elements in the interval [low,high]
+  inline ivec randi(int size, int low, int high) { I_Uniform_RNG src; src.setup(low, high); return src(size); }
+  //! Generates a random imat with elements in the interval [low,high]
+  inline imat randi(int rows, int cols, int low, int high) { I_Uniform_RNG src; src.setup(low, high); return src(rows, cols); }
+
+  //! Generates a random Rayleigh vector
+  inline vec randray(int size, double sigma = 1.0) { Rayleigh_RNG src; src.setup(sigma); return src(size); }
+
+  //! Generates a random Rice vector (See J.G. Poakis, "Digital Communications, 3rd ed." p.47)
+  inline vec randrice(int size, double sigma = 1.0, double s = 1.0) { Rice_RNG src; src.setup(sigma, s); return src(size); }
+
+  //! Generates a random complex Gaussian vector
+  inline vec randexp(int size, double lambda = 1.0) { Exponential_RNG src; src.setup(lambda); return src(size); }
+
+  //! Generates a random Gaussian (0,1) variable
+  inline double randn(void) { Normal_RNG src; return src.sample(); }
+  //! Generates a random Gaussian (0,1) vector
+  inline void randn(int size, vec &out) { Normal_RNG src; src.sample_vector(size, out); }
+  //! Generates a random Gaussian (0,1) vector
+  inline vec randn(int size) { vec temp; randn(size, temp); return temp; }
+  //! Generates a random Gaussian (0,1) matrix
+  inline void randn(int rows, int cols, mat &out)  { Normal_RNG src; src.sample_matrix(rows, cols, out); }
+  //! Generates a random Gaussian (0,1) matrix
+  inline mat randn(int rows, int cols){ mat temp; randn(rows, cols, temp); return temp; }
+
+  /*! \brief Generates a random complex Gaussian (0,1) variable
+
+  The real and imaginary parts are independent and have variances equal to 0.5
+  */
+  inline std::complex<double> randn_c(void) { Complex_Normal_RNG src; return src.sample(); }
+  //! Generates a random complex Gaussian (0,1) vector
+  inline void randn_c(int size, cvec &out)  { Complex_Normal_RNG src; src.sample_vector(size, out); }
+  //! Generates a random complex Gaussian (0,1) vector
+  inline cvec randn_c(int size){ cvec temp; randn_c(size, temp); return temp; }
+  //! Generates a random complex Gaussian (0,1) matrix
+  inline void randn_c(int rows, int cols, cmat &out) { Complex_Normal_RNG src; src.sample_matrix(rows, cols, out); }
+  //! Generates a random complex Gaussian (0,1) matrix
+  inline cmat randn_c(int rows, int cols) { cmat temp; randn_c(rows, cols, temp); return temp; }
+
+  //!@}
+
+} // namespace itpp
+
+#endif // #ifndef RANDOM_H
Index: /win32/itpp-4.0.1/itpp/base/mat.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/mat.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/mat.h (revision 35)
@@ -0,0 +1,2000 @@
+/*!
+ * \file
+ * \brief Matrix Class Definitions
+ * \author Tony Ottosson, Tobias Ringstrom, Adam Piatyszek and Conrad Sanderson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef MAT_H
+#define MAT_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/itassert.h>
+#include <itpp/base/math/misc.h>
+#include <itpp/base/factory.h>
+
+
+namespace itpp {
+
+  // Declaration of Vec
+  template<class Num_T> class Vec;
+  // Declaration of Mat
+  template<class Num_T> class Mat;
+  // Declaration of bin
+  class bin;
+
+  //! Horizontal concatenation of two matrices
+  template<class Num_T> const Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Vertical concatenation of two matrices
+  template<class Num_T> const Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+
+  //! Addition of two matricies
+  template<class Num_T> const Mat<Num_T> operator+(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Addition of a matrix and a scalar
+  template<class Num_T> const Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t);
+  //! Addition of a scalar and a matrix
+  template<class Num_T> const Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m);
+
+  //! Subtraction of two matrices
+  template<class Num_T> const Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Subtraction of matrix and scalar
+  template<class Num_T> const Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t);
+  //! Subtraction of scalar and matrix
+  template<class Num_T> const Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m);
+  //! Negation of matrix
+  template<class Num_T> const Mat<Num_T> operator-(const Mat<Num_T> &m);
+
+  //! Multiplication of two matricies
+  template<class Num_T> const Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Multiplication of matrix and vector
+  template<class Num_T> const Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v);
+  //! Multiplication of vector and matrix (only works for a matrix that is a row vector)
+  template<class Num_T> const Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m);
+  //! Multiplication of matrix and scalar
+  template<class Num_T> const Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t);
+  //! Multiplication of scalar and matrix
+  template<class Num_T> const Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m);
+
+  //! Element wise multiplication of two matrices. Same functionality as Matlab/Octave expression A .* B
+  template<class Num_T> const Mat<Num_T> elem_mult(const Mat<Num_T> &A, const Mat<Num_T> &B);
+  //! Element wise multiplication of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
+  //! Element wise multiplication of three matrices, storing the result in matrix \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, Mat<Num_T> &out);
+  //! Element wise multiplication of four matrices, storing the result in matrix \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, const Mat<Num_T> &D, Mat<Num_T> &out);
+  //! In-place element wise multiplication of two matrices. Fast version of B = elem_mult(A,B)
+  template<class Num_T> void elem_mult_inplace(const Mat<Num_T> &A, Mat<Num_T> &B);
+  //! Element wise multiplication of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_mult(A,B))
+  template<class Num_T> Num_T elem_mult_sum(const Mat<Num_T> &A, const Mat<Num_T> &B);
+
+  //! Division of matrix and scalar
+  template<class Num_T> const Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t);
+
+  //! Element wise division of two matrices. Same functionality as Matlab/Octave expression A ./ B
+  template<class Num_T> const Mat<Num_T> elem_div(const Mat<Num_T> &A, const Mat<Num_T> &B);
+  //! Element wise division of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
+  template<class Num_T> void elem_div_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
+  //! Element wise division of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_div(A,B))
+  template<class Num_T> Num_T elem_div_sum(const Mat<Num_T> &A, const Mat<Num_T> &B);
+
+  // -------------------------------------------------------------------------------------
+  // Declaration of Mat
+  // -------------------------------------------------------------------------------------
+
+  /*!
+    \ingroup arr_vec_mat
+    \brief Matrix Class (Templated)
+    \author Tony Ottosson, Tobias Ringstrom, Adam Piatyszek and Conrad Sanderson
+
+    Matrices can be of arbitrarily types, but conversions and functions are
+    prepared for \c bin, \c short, \c int, \c double, and \c complex<double>
+    vectors and these are predefined as: \c bmat, \c smat, \c imat, \c mat,
+    and \c cmat. \c double and \c complex<double> are usually \c double and
+    \c complex<double> respectively. However, this can be changed when
+    compiling the it++ (see installation notes for more details). (Note: for
+    binary matrices, an alternative to the bmat class is \c GF2mat and
+    \c GF2mat_dense, which offer a more memory efficient representation and
+    additional functions for linear algebra.)
+
+    Examples:
+
+    Matrix Constructors:
+    When constructing a matrix without dimensions (memory) use
+    \code mat temp; \endcode
+    For construction of a matrix of a given size use
+    \code mat temp(rows, cols); \endcode
+    It is also possible to assign the constructed matrix the value and dimension
+    of another matrix by
+    \code vec temp(inmatrix); \endcode
+    If you have explicit values you would like to assign to the matrix it is
+    possible to do this using strings as:
+    \code
+    mat a("0 0.7;5 9.3"); // that is a = [0, 0.7; 5, 9.3]
+    mat a="0 0.7;5 9.3";  // the constructor are called implicitly
+    \endcode
+    It is also possible to change dimension by
+    \code temp.set_size(new_rows, new_cols, false); \endcode
+    where \c false is used to indicate that the old values in \c temp
+    is not copied. If you like to preserve the values use \c true.
+
+    There are a number of methods to access parts of a matrix. Examples are
+    \code
+    a(5,3);     // Element number (5,3)
+    a(5,9,3,5);  // Sub-matrix from rows 5, 6, 7, 8, 9 the columns 3, 4, and 5
+    a.get_row(10);  // Row 10
+    a.get_col(10); // Column 10
+    \endcode
+
+    It is also possible to modify parts of a vector as e.g. in
+    \code
+    a.set_row(5, invector);    // Set row 5 to \c invector
+    a.set_col(3, invector); // Set column 3 to \c invector
+    a.copy_col(1, 5); // Copy column 5 to column 1
+    a.swap_cols(1, 5); // Swap the contents of columns 1 and 5
+    \endcode
+
+    It is of course also possible to perform the common linear algebra
+    methods such as addition, subtraction, and matrix multiplication. Observe
+    though, that vectors are assumed to be column-vectors in operations with
+    matrices.
+
+    Most elementary functions such as sin(), cosh(), log(), abs(), ..., are
+    available as operations on the individual elements of the matrices. Please
+    see the individual functions for more details.
+
+    By default, the Mat elements are created using the default constructor for
+    the element type. This can be changed by specifying a suitable Factory in
+    the Mat constructor call; see Detailed Description for Factory.
+  */
+  template<class Num_T>
+  class Mat {
+  public:
+    //! The type of the matrix values
+    typedef Num_T value_type;
+
+    //! Default constructor. An element factory \c f can be specified
+    explicit Mat(const Factory &f = DEFAULT_FACTORY);
+    //! Create a matrix of size (inrow, incol). An element factory \c f can be specified
+    Mat(int inrow, int incol, const Factory &f = DEFAULT_FACTORY);
+    //! Copy constructor
+    Mat(const Mat<Num_T> &m);
+    //! Constructor, similar to the copy constructor, but also takes an element factory \c f as argument
+    Mat(const Mat<Num_T> &m, const Factory &f);
+    //! Create a copy of the vector \c invector treated as a column vector. An element factory \c f can be specified
+    Mat(const Vec<Num_T> &invector, const Factory &f = DEFAULT_FACTORY);
+    //! Set matrix equal to values in string. An element factory \c f can be specified
+    Mat(const std::string &str, const Factory &f = DEFAULT_FACTORY);
+    //! Set matrix equal to values in string. An element factory \c f can be specified
+    Mat(const char *str, const Factory &f = DEFAULT_FACTORY);
+    /*!
+      \brief Constructor taking a C-array as input. Copies all data. An element factory \c f can be specified
+
+      By default the matrix is stored as a RowMajor matrix (i.e. listing elements in sequence
+      beginning with the first column).
+    */
+    Mat(const Num_T *c_array, int rows, int cols, bool RowMajor = true, const Factory &f = DEFAULT_FACTORY);
+
+    //! Destructor
+    ~Mat();
+
+    //! The number of columns
+    int cols() const { return no_cols; }
+    //! The number of rows
+    int rows() const { return no_rows; }
+    //! The number of elements
+    int size() const { return datasize; }
+    //! Set size of matrix. If copy = true then keep the data before resizing.
+    void set_size(int inrow, int incol, bool copy = false);
+    //! Set matrix equal to the all zero matrix
+    void zeros();
+    //! Set matrix equal to the all zero matrix
+    void clear() { zeros(); }
+    //! Set matrix equal to the all one matrix
+    void ones();
+    //! Set matrix equal to values in \c values
+    void set(const char *str);
+    //! Set matrix equal to values in the string \c str
+    void set(const std::string &str);
+
+    //! Get element (R,C) from matrix
+    const Num_T &operator()(int R, int C) const;
+    //! Get element (R,C) from matrix
+    Num_T &operator()(int R, int C);
+    //! Get element \c index using linear addressing (by rows)
+    const Num_T &operator()(int index) const;
+    //! Get element \c index using linear addressing (by rows)
+    Num_T &operator()(int index);
+    //! Get element (R,C) from matrix
+    const Num_T &get(int R,int C) const;
+    //! Set element (R,C) of matrix
+    void set(int R,int C, const Num_T &v);
+
+    /*!
+      \brief Sub-matrix from row \c r1 to row \c r2 and columns \c c1 to \c c2.
+
+      Value -1 indicates the last row and column, respectively.
+    */
+    const Mat<Num_T> operator()(int r1, int r2, int c1, int c2) const;
+    /*!
+      \brief Sub-matrix from row \c r1 to row \c r2 and columns \c c1 to \c c2.
+
+      Value -1 indicates the last row and column, respectively.
+    */
+    const Mat<Num_T> get(int r1, int r2, int c1, int c2) const;
+
+    //! Get row \c Index
+    const Vec<Num_T> get_row(int Index) const ;
+    //! Get rows \c r1 through \c r2
+    const Mat<Num_T> get_rows(int r1, int r2) const;
+    //! Get the rows specified by \c indexlist
+    const Mat<Num_T> get_rows(const Vec<int> &indexlist) const;
+    //! Get column \c Index
+    const Vec<Num_T> get_col(int Index) const ;
+    //! Get columns \c c1 through \c c2
+    const Mat<Num_T> get_cols(int c1, int c2) const;
+    //! Get the columns specified by \c indexlist
+    const Mat<Num_T> get_cols(const Vec<int> &indexlist) const;
+    //! Set row \c Index to \c invector
+    void set_row(int Index, const Vec<Num_T> &invector);
+    //! Set column \c Index to \c invector
+    void set_col(int Index, const Vec<Num_T> &invector);
+    //! Set rows to matrix \c m, staring from row \c r
+    void set_rows(int r, const Mat<Num_T> &m);
+    //! Set colums to matrix \c m, starting from column \c c
+    void set_cols(int c, const Mat<Num_T> &m);
+    //! Copy row \c from onto row \c to
+    void copy_row(int to, int from);
+    //! Copy column \c from onto column \c to
+    void copy_col(int to, int from);
+    //! Swap the rows \c r1 and \c r2
+    void swap_rows(int r1, int r2);
+    //! Swap the columns \c c1 and \c c2
+    void swap_cols(int c1, int c2);
+
+    //! Set submatrix defined by rows r1,r2 and columns c1,c2 to matrix m
+    void set_submatrix(int r1, int r2, int c1, int c2, const Mat<Num_T> &m);
+    //! Set submatrix defined by upper-left element (r,c) and the size of matrix m to m
+    void set_submatrix(int r, int c, const Mat<Num_T> &m);
+    //! Set all elements of submatrix defined by rows r1,r2 and columns c1,c2 to value t
+    void set_submatrix(int r1, int r2, int c1, int c2, const Num_T t);
+
+    //! Delete row number \c r
+    void del_row(int r);
+    //! Delete rows from \c r1 to \c r2
+    void del_rows(int r1, int r2);
+    //! Delete column number \c c
+    void del_col(int c);
+    //! Delete columns from \c c1 to \c c2
+    void del_cols(int c1, int c2);
+    //! Insert vector \c in at row number \c r, the matrix can be empty.
+    void ins_row(int r, const Vec<Num_T> &in);
+    //! Insert vector \c in at column number \c c, the matrix can be empty.
+    void ins_col(int c, const Vec<Num_T> &in);
+    //! Append vector \c to the bottom of the matrix, the matrix can be empty.
+    void append_row(const Vec<Num_T> &in);
+    //! Append vector \c to the right of the matrix, the matrix can be empty.
+    void append_col(const Vec<Num_T> &in);
+
+    //! Matrix transpose
+    const Mat<Num_T> transpose() const;
+    //! Matrix transpose
+    const Mat<Num_T> T() const { return this->transpose(); }
+    //! Hermitian matrix transpose (conjugate transpose)
+    const Mat<Num_T> hermitian_transpose() const;
+    //! Hermitian matrix transpose (conjugate transpose)
+    const Mat<Num_T> H() const { return this->hermitian_transpose(); }
+
+    //! Concatenate the matrices \c m1 and \c m2 horizontally
+    friend const Mat<Num_T> concat_horizontal <>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+    //! Concatenate the matrices \c m1 and \c m2 vertically
+    friend const Mat<Num_T> concat_vertical <>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+
+    //! Set all elements of the matrix equal to \c t
+    Mat<Num_T>& operator=(Num_T t);
+    //! Set matrix equal to \c m
+    Mat<Num_T>& operator=(const Mat<Num_T> &m);
+    //! Set matrix equal to the vector \c v, assuming column vector
+    Mat<Num_T>& operator=(const Vec<Num_T> &v);
+    //! Set matrix equal to values in the string
+    Mat<Num_T>& operator=(const char *values);
+
+    //! Addition of matrices
+    Mat<Num_T>& operator+=(const Mat<Num_T> &m);
+    //! Addition of scalar to matrix
+    Mat<Num_T>& operator+=(Num_T t);
+    //! Addition of two matrices
+    friend const  Mat<Num_T> operator+<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+    //! Addition of matrix and scalar
+    friend const Mat<Num_T> operator+<>(const Mat<Num_T> &m, Num_T t);
+    //! Addition of scalar and matrix
+    friend const Mat<Num_T> operator+<>(Num_T t, const Mat<Num_T> &m);
+
+    //! Subtraction of matrix
+    Mat<Num_T>& operator-=(const Mat<Num_T> &m);
+    //! Subtraction of scalar from matrix
+    Mat<Num_T>& operator-=(Num_T t);
+    //! Subtraction of \c m2 from \c m1
+    friend const Mat<Num_T> operator-<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+    //! Subraction of scalar from matrix
+    friend const Mat<Num_T> operator-<>(const Mat<Num_T> &m, Num_T t);
+    //! Subtract matrix from scalar
+    friend const Mat<Num_T> operator-<>(Num_T t, const Mat<Num_T> &m);
+    //! Subraction of matrix
+    friend const Mat<Num_T> operator-<>(const Mat<Num_T> &m);
+
+    //! Matrix multiplication
+    Mat<Num_T>& operator*=(const Mat<Num_T> &m);
+    //! Multiplication by a scalar
+    Mat<Num_T>& operator*=(Num_T t);
+    //! Multiplication of two matrices
+    friend const Mat<Num_T> operator*<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+    //! Multiplication of matrix \c m and vector \c v (column vector)
+    friend const Vec<Num_T> operator*<>(const Mat<Num_T> &m, const Vec<Num_T> &v);
+    /*!
+     * \brief Multiplication of vector \c v and matrix \c m with only one row
+     *
+     * This operator multiplies a column vector \c v times matrix \c m that
+     * consists of only one row. Thus, the result of this operator is
+     * exactly the same as the result of the outer product of two vectors,
+     * i.e.: <tt>outer_product(v, m.get_col(0))</tt>.
+     *
+     * \note This operator is deprecated and might be removed or changed in
+     * future releases of IT++.
+     */
+    friend const Mat<Num_T> operator*<>(const Vec<Num_T> &v,
+                                        const Mat<Num_T> &m);
+    //! Multiplication of matrix and scalar
+    friend const Mat<Num_T> operator*<>(const Mat<Num_T> &m, Num_T t);
+    //! Multiplication of scalar and matrix
+    friend const Mat<Num_T> operator*<>(Num_T t, const Mat<Num_T> &m);
+
+    //! Element wise multiplication of two matrices. Same functionality as Matlab expression A .* B
+    friend const Mat<Num_T> elem_mult <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
+    //! Element wise multiplication of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
+    friend void elem_mult_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
+    //! Element wise multiplication of three matrices, storing the result in matrix \c out (which is re-sized if necessary)
+    friend void elem_mult_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, Mat<Num_T> &out);
+    //! Element wise multiplication of four matrices, storing the result in matrix \c out (which is re-sized if necessary)
+    friend void elem_mult_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, const Mat<Num_T> &D, Mat<Num_T> &out);
+    //! In-place element wise multiplication of two matrices. Fast version of B = elem_mult(A,B)
+    friend void elem_mult_inplace <>(const Mat<Num_T> &A, Mat<Num_T> &B);
+    //! Element wise multiplication of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_mult(A,B))
+    friend Num_T elem_mult_sum <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
+
+    //! Division by a scalar
+    Mat<Num_T>& operator/=(Num_T t);
+    //! Division of matrix with scalar
+    friend const Mat<Num_T> operator/<>(const Mat<Num_T> &m, Num_T t);
+    //! Elementwise division with the current matrix
+    Mat<Num_T>& operator/=(const Mat<Num_T> &m);
+
+    //! Element wise division of two matrices. Same functionality as Matlab expression A ./ B
+    friend const Mat<Num_T> elem_div <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
+    //! Element wise division of two matrices, storing the result in matrix \c out (which is re-sized if necessary)
+    friend void elem_div_out <>(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out);
+    //! Element wise division of two matrices, followed by summation of the resultant elements. Fast version of sumsum(elem_div(A,B))
+    friend Num_T elem_div_sum <>(const Mat<Num_T> &A, const Mat<Num_T> &B);
+
+    //! Compare two matrices. False if wrong sizes or different values
+    bool operator==(const Mat<Num_T> &m) const;
+    //! Compare two matrices. True if different
+    bool operator!=(const Mat<Num_T> &m) const;
+
+    //! Get element (R,C) from matrix without boundary check (Not recommended to use).
+    Num_T &_elem(int R,int C) { return data[R+C*no_rows]; }
+    //! Get element (R,C) from matrix without boundary check (Not recommended to use).
+    const Num_T &_elem(int R,int C) const { return data[R+C*no_rows]; }
+    //! Get element \c index using linear addressing (by rows) without boundary check (Not recommended to use).
+    Num_T &_elem(int index) { return data[index]; }
+    //! Get element \c index using linear addressing (by rows) without boundary check (Not recommended to use).
+    const Num_T &_elem(int index) const { return data[index]; }
+
+    //! Access of the internal data structure. Don't use. May be changed!
+    Num_T *_data() { return data; }
+    //! Access to the internal data structure. Don't use. May be changed!
+    const Num_T *_data() const { return data; }
+    //! Access to the internal data structure. Don't use. May be changed!
+    int _datasize() const { return datasize; }
+
+  protected:
+    //! Allocate memory for the matrix
+    void alloc(int rows, int cols);
+    //! Free the memory space of the matrix
+    void free();
+
+    /*! Protected integer variables
+     * @{ */
+    int datasize, no_rows, no_cols;
+    /*! @} */
+    //! Protected data pointer
+    Num_T *data;
+    //! Element factory (set to DEFAULT_FACTORY to use Num_T default constructors only)
+    const Factory &factory;
+  };
+
+  // -------------------------------------------------------------------------------------
+  // Type definitions of mat, cmat, imat, smat, and bmat
+  // -------------------------------------------------------------------------------------
+
+  /*!
+    \relates Mat
+    \brief Default Matrix Type
+  */
+  typedef Mat<double> mat;
+
+  /*!
+    \relates Mat
+    \brief Default Complex Matrix Type
+  */
+  typedef Mat<std::complex<double> > cmat;
+
+  /*!
+    \relates Mat
+    \brief Integer matrix
+  */
+  typedef Mat<int> imat;
+
+  /*!
+    \relates Mat
+    \brief short int matrix
+  */
+  typedef Mat<short int> smat;
+
+  /*!
+    \relates Mat
+    \relates GF2mat
+    \relates GF2mat_sparse
+    \brief bin matrix
+  */
+  typedef Mat<bin> bmat;
+
+} //namespace itpp
+
+
+#include <itpp/base/vec.h>
+
+namespace itpp {
+
+  // ----------------------------------------------------------------------
+  // Declaration of input and output streams for Mat
+  // ----------------------------------------------------------------------
+
+  /*!
+    \relatesalso Mat
+    \brief Output stream for matrices
+  */
+  template <class Num_T>
+  std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m);
+
+  /*!
+    \relatesalso Mat
+    \brief Input stream for matrices
+
+    The input can be on the form "1 2 3; 4 5 6" or "[[1 2 3][4 5 6]]", i.e. with
+    brackets or semicolons as row delimiters. The first form is compatible with
+    the set method, while the second form is compatible with the ostream
+    operator. The elements on a row can be separated by blank space or commas.
+    Rows that are shorter than the longest row are padded with zero elements.
+    "[]" means an empty matrix.
+  */
+  template <class Num_T>
+  std::istream &operator>>(std::istream &is, Mat<Num_T> &m);
+
+  // ----------------------------------------------------------------------
+  // Implementation of templated Mat members and friends
+  // ----------------------------------------------------------------------
+
+  template<class Num_T> inline
+  void Mat<Num_T>::alloc(int rows, int cols)
+  {
+    if ((rows > 0) && (cols > 0)) {
+      datasize = rows * cols;
+      no_rows = rows;
+      no_cols = cols;
+      create_elements(data, datasize, factory);
+    }
+    else {
+      data = 0;
+      datasize = 0;
+      no_rows = 0;
+      no_cols = 0;
+    }
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::free()
+  {
+    destroy_elements(data, datasize);
+    datasize = 0;
+    no_rows = 0;
+    no_cols = 0;
+  }
+
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f) {}
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(int inrow, int incol, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+  {
+    it_assert_debug((inrow >= 0) && (incol >= 0), "The rows and columns must be >= 0");
+    alloc(inrow, incol);
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const Mat<Num_T> &m) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(m.factory)
+  {
+    alloc(m.no_rows, m.no_cols);
+    copy_vector(m.datasize, m.data, data);
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const Mat<Num_T> &m, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+  {
+    alloc(m.no_rows, m.no_cols);
+    copy_vector(m.datasize, m.data, data);
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const Vec<Num_T> &invector, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+  {
+    int size = invector.size();
+    alloc(size, 1);
+    copy_vector(size, invector._data(), data);
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const std::string &str, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+  {
+    set(str);
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const char *str, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+  {
+    set(str);
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::Mat(const Num_T *c_array, int rows, int cols, bool RowMajor, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+  {
+    alloc(rows, cols);
+
+    if (!RowMajor)
+      copy_vector(datasize, c_array, data);
+    else { // Row Major
+      for (int i=0; i<rows; i++) {
+	for (int j=0; j<cols; j++)
+	  data[i+j*no_rows] = c_array[i*no_cols+j];
+      }
+    }
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>::~Mat()
+  {
+    free();
+  }
+
+
+  template<class Num_T>
+  void Mat<Num_T>::set_size(int inrow, int incol, bool copy)
+  {
+    it_assert_debug((inrow >= 0) && (incol >= 0), "Mat<Num_T>::set_size: "
+		    "The number of rows and columns must be >= 0");
+    // check if we have to resize the current matrix
+    if ((no_rows == inrow) && (no_cols == incol))
+      return;
+    // conditionally copy previous matrix content
+    if (copy) {
+      // create a temporary pointer to the allocated data
+      Num_T* tmp = data;
+      // store the current number of elements and number of rows
+      int old_datasize = datasize;
+      int old_rows = no_rows;
+      // check the boundaries of the copied data
+      int min_r = (no_rows < inrow) ? no_rows : inrow;
+      int min_c = (no_cols < incol) ? no_cols : incol;
+      // allocate new memory
+      alloc(inrow, incol);
+      // copy the previous data into the allocated memory
+      for (int i = 0; i < min_c; ++i) {
+	copy_vector(min_r, &tmp[i*old_rows], &data[i*no_rows]);
+      }
+      // fill-in the rest of matrix with zeros
+      for (int i = min_r; i < inrow; ++i)
+	for (int j = 0; j < incol; ++j)
+	  data[i+j*inrow] = Num_T(0);
+      for (int j = min_c; j < incol; ++j)
+	for (int i = 0; i < min_r; ++i)
+	  data[i+j*inrow] = Num_T(0);
+      // delete old elements
+      destroy_elements(tmp, old_datasize);
+    }
+    // if possible, reuse the allocated memory
+    else if (datasize == inrow * incol) {
+      no_rows = inrow;
+      no_cols = incol;
+    }
+    // finally release old memory and allocate a new one
+    else {
+      free();
+      alloc(inrow, incol);
+    }
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::zeros()
+  {
+    for(int i=0; i<datasize; i++)
+      data[i] = Num_T(0);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::ones()
+  {
+    for(int i=0; i<datasize; i++)
+      data[i] = Num_T(1);
+  }
+
+  template<class Num_T> inline
+  const Num_T& Mat<Num_T>::operator()(int R,int C) const
+  {
+    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
+	       "Mat<Num_T>::operator(): index out of range");
+    return data[R+C*no_rows];
+  }
+
+  template<class Num_T> inline
+  Num_T& Mat<Num_T>::operator()(int R,int C)
+  {
+    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
+	       "Mat<Num_T>::operator(): index out of range");
+    return data[R+C*no_rows];
+  }
+
+  template<class Num_T> inline
+  Num_T& Mat<Num_T>::operator()(int index)
+  {
+    it_assert_debug((index < no_rows*no_cols) && (index >= 0),
+	       "Mat<Num_T>::operator(): index out of range");
+    return data[index];
+  }
+
+  template<class Num_T> inline
+  const Num_T& Mat<Num_T>::operator()(int index) const
+  {
+    it_assert_debug((index < no_rows*no_cols) && (index >= 0),
+	       "Mat<Num_T>::operator(): index out of range");
+    return data[index];
+  }
+
+  template<class Num_T> inline
+  const Num_T& Mat<Num_T>::get(int R,int C) const
+  {
+    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
+	       "Mat<Num_T>::get(): index out of range");
+    return data[R+C*no_rows];
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set(int R, int C, const Num_T &v)
+  {
+    it_assert_debug((R >= 0) && (R < no_rows) && (C >= 0) && (C < no_cols),
+	       "Mat<Num_T>::set(): index out of range");
+    data[R+C*no_rows] = v;
+  }
+
+
+  template<class Num_T>
+  void Mat<Num_T>::set(const std::string &str)
+  {
+    // actual row counter
+    int rows = 0;
+    // number of rows to allocate next time (8, 16, 32, 64, etc.)
+    int maxrows = 8;
+
+    // clean the current matrix content
+    free();
+
+    // variable to store the start of a current vector
+    std::string::size_type beg = 0;
+    std::string::size_type end = 0;
+    while (end != std::string::npos) {
+      // find next occurence of a semicolon in string str
+      end = str.find(';', beg);
+      // parse first row into a vector v
+      Vec<Num_T> v(str.substr(beg, end-beg));
+      int v_size = v.size();
+
+      // this check is necessary to parse the following two strings as the
+      // same matrix: "1 0 1; ; 1 1; " and "1 0 1; 0 0 0; 1 1 0"
+      if ((end != std::string::npos) || (v_size > 0)) {
+	// matrix empty -> insert v as a first row and allocate maxrows
+	if (rows == 0) {
+	  set_size(maxrows, v_size, true);
+	  set_row(rows++, v);
+	}
+	else {
+	  // check if we need to resize the matrix
+	  if ((rows == maxrows) || (v_size != no_cols)) {
+	    // we need to add new rows
+	    if (rows == maxrows) {
+	      maxrows *= 2;
+	    }
+	    // check if ne need to add new colums
+	    if (v_size > no_cols) {
+	      set_size(maxrows, v_size, true);
+	    }
+	    else {
+	      set_size(maxrows, no_cols, true);
+	      // set the size of the parsed vector to the number of colums
+	      v.set_size(no_cols, true);
+	    }
+	  }
+	  // set the parsed vector as the next row
+	  set_row(rows++, v);
+	}
+      }
+      // update the starting position of the next vector in the parsed
+      // string
+      beg = end + 1;
+    } // if ((end != std::string::npos) || (v.size > 0))
+
+    set_size(rows, no_cols, true);
+  }
+
+  template<class Num_T>
+  void Mat<Num_T>::set(const char *str)
+  {
+    set(std::string(str));
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> Mat<Num_T>::operator()(int r1, int r2, int c1, int c2) const
+  {
+    if (r1 == -1) r1 = no_rows-1;
+    if (r2 == -1) r2 = no_rows-1;
+    if (c1 == -1) c1 = no_cols-1;
+    if (c2 == -1) c2 = no_cols-1;
+
+    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
+	       c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "operator()(r1,r2,c1,c2)");
+
+    it_assert_debug(r2>=r1 && c2>=c1, "Mat<Num_T>::op(): r2>=r1 or c2>=c1 not fulfilled");
+
+    Mat<Num_T> s(r2-r1+1, c2-c1+1);
+
+    for (int i=0;i<s.no_cols;i++)
+      copy_vector(s.no_rows, data+r1+(c1+i)*no_rows, s.data+i*s.no_rows);
+
+    return s;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> Mat<Num_T>::get(int r1, int r2, int c1, int c2) const
+  {
+    return (*this)(r1, r2, c1, c2);
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> Mat<Num_T>::get_row(int Index) const
+  {
+    it_assert_debug(Index>=0 && Index<no_rows, "Mat<Num_T>::get_row: index out of range");
+    Vec<Num_T> a(no_cols);
+
+    copy_vector(no_cols, data+Index, no_rows, a._data(), 1);
+    return a;
+  }
+
+  template<class Num_T>
+  const Mat<Num_T> Mat<Num_T>::get_rows(int r1, int r2) const
+  {
+    it_assert_debug(r1>=0 && r2<no_rows && r1<=r2, "Mat<Num_T>::get_rows: index out of range");
+    Mat<Num_T> m(r2-r1+1, no_cols);
+
+    for (int i=0; i<m.rows(); i++)
+      copy_vector(no_cols, data+i+r1, no_rows, m.data+i, m.no_rows);
+
+    return m;
+  }
+
+  template<class Num_T>
+  const Mat<Num_T> Mat<Num_T>::get_rows(const Vec<int> &indexlist) const
+  {
+    Mat<Num_T> m(indexlist.size(),no_cols);
+
+    for (int i=0;i<indexlist.size();i++) {
+      it_assert_debug(indexlist(i)>=0 && indexlist(i)<no_rows, "Mat<Num_T>::get_rows: index out of range");
+      copy_vector(no_cols, data+indexlist(i), no_rows, m.data+i, m.no_rows);
+    }
+
+    return m;
+  }
+
+  template<class Num_T> inline
+  const Vec<Num_T> Mat<Num_T>::get_col(int Index) const
+  {
+    it_assert_debug(Index>=0 && Index<no_cols, "Mat<Num_T>::get_col: index out of range");
+    Vec<Num_T> a(no_rows);
+
+    copy_vector(no_rows, data+Index*no_rows, a._data());
+
+    return a;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> Mat<Num_T>::get_cols(int c1, int c2) const
+  {
+    it_assert_debug(c1>=0 && c2<no_cols && c1<=c2, "Mat<Num_T>::get_cols: index out of range");
+    Mat<Num_T> m(no_rows, c2-c1+1);
+
+    for (int i=0; i<m.cols(); i++)
+      copy_vector(no_rows, data+(i+c1)*no_rows, m.data+i*m.no_rows);
+
+    return m;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> Mat<Num_T>::get_cols(const Vec<int> &indexlist) const
+  {
+    Mat<Num_T> m(no_rows,indexlist.size());
+
+    for (int i=0; i<indexlist.size(); i++) {
+      it_assert_debug(indexlist(i)>=0 && indexlist(i)<no_cols, "Mat<Num_T>::get_cols: index out of range");
+      copy_vector(no_rows, data+indexlist(i)*no_rows, m.data+i*m.no_rows);
+    }
+
+    return m;
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_row(int Index, const Vec<Num_T> &v)
+  {
+    it_assert_debug(Index>=0 && Index<no_rows, "Mat<Num_T>::set_row: index out of range");
+    it_assert_debug(v.length() == no_cols, "Mat<Num_T>::set_row: lengths doesn't match");
+
+    copy_vector(v.size(), v._data(), 1, data+Index, no_rows);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_col(int Index, const Vec<Num_T> &v)
+  {
+    it_assert_debug(Index>=0 && Index<no_cols, "Mat<Num_T>::set_col: index out of range");
+    it_assert_debug(v.length() == no_rows, "Mat<Num_T>::set_col: lengths doesn't match");
+
+    copy_vector(v.size(), v._data(), data+Index*no_rows);
+  }
+
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_rows(int r, const Mat<Num_T> &m)
+  {
+    it_assert_debug((r >= 0) && (r < no_rows),
+		    "Mat<>::set_rows(): Index out of range");
+    it_assert_debug(no_cols == m.cols(),
+		    "Mat<>::set_rows(): Column sizes do not match");
+    it_assert_debug(m.rows() + r <= no_rows,
+		    "Mat<>::set_rows(): Not enough rows");
+
+    for (int i = 0; i < m.rows(); ++i) {
+      copy_vector(no_cols, m.data+i, m.no_rows, data+i+r, no_rows);
+    }
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_cols(int c, const Mat<Num_T> &m)
+  {
+    it_assert_debug((c >= 0) && (c < no_cols),
+		    "Mat<>::set_cols(): Index out of range");
+    it_assert_debug(no_rows == m.rows(),
+		    "Mat<>::set_cols(): Row sizes do not match");
+    it_assert_debug(m.cols() + c <= no_cols,
+		    "Mat<>::set_cols(): Not enough colums");
+
+    for (int i = 0; i < m.cols(); ++i) {
+      copy_vector(no_rows, m.data+i*no_rows, data+(i+c)*no_rows);
+    }
+  }
+
+
+  template<class Num_T> inline
+  void Mat<Num_T>::copy_row(int to, int from)
+  {
+    it_assert_debug(to>=0 && from>=0 && to<no_rows && from<no_rows,
+	       "Mat<Num_T>::copy_row: index out of range");
+
+    if (from == to)
+      return;
+
+    copy_vector(no_cols, data+from, no_rows, data+to, no_rows);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::copy_col(int to, int from)
+  {
+    it_assert_debug(to>=0 && from>=0 && to<no_cols && from<no_cols,
+	       "Mat<Num_T>::copy_col: index out of range");
+
+    if (from == to)
+      return;
+
+    copy_vector(no_rows, data+from*no_rows, data+to*no_rows);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::swap_rows(int r1, int r2)
+  {
+    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows,
+	       "Mat<Num_T>::swap_rows: index out of range");
+
+    if (r1 == r2)
+      return;
+
+    swap_vector(no_cols, data+r1, no_rows, data+r2, no_rows);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::swap_cols(int c1, int c2)
+  {
+    it_assert_debug(c1>=0 && c2>=0 && c1<no_cols && c2<no_cols,
+	       "Mat<Num_T>::swap_cols: index out of range");
+
+    if (c1 == c2)
+      return;
+
+    swap_vector(no_rows, data+c1*no_rows, data+c2*no_rows);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_submatrix(int r1, int r2, int c1, int c2, const Mat<Num_T> &m)
+  {
+
+    if (r1 == -1) r1 = no_rows-1;
+    if (r2 == -1) r2 = no_rows-1;
+    if (c1 == -1) c1 = no_cols-1;
+    if (c2 == -1) c2 = no_cols-1;
+
+    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
+	       c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "Mat<Num_T>::set_submatrix(): index out of range");
+
+    it_assert_debug(r2>=r1 && c2>=c1, "Mat<Num_T>::set_submatrix: r2<r1 or c2<c1");
+    it_assert_debug(m.no_rows == r2-r1+1 && m.no_cols == c2-c1+1, "Mat<Num_T>::set_submatrix(): sizes don't match");
+
+    for (int i=0; i<m.no_cols; i++)
+      copy_vector(m.no_rows, m.data+i*m.no_rows, data+(c1+i)*no_rows+r1);
+  }
+
+
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_submatrix(int r, int c, const Mat<Num_T> &m)
+  {
+
+    it_assert_debug(r>=0 && r+m.no_rows<=no_rows &&
+	       c>=0 && c+m.no_cols<=no_cols, "Mat<Num_T>::set_submatrix(): index out of range");
+
+    for (int i=0; i<m.no_cols; i++)
+      copy_vector(m.no_rows, m.data+i*m.no_rows, data+(c+i)*no_rows+r);
+  }
+
+
+
+  template<class Num_T> inline
+  void Mat<Num_T>::set_submatrix(int r1, int r2, int c1, int c2, const Num_T t)
+  {
+
+    if (r1 == -1) r1 = no_rows-1;
+    if (r2 == -1) r2 = no_rows-1;
+    if (c1 == -1) c1 = no_cols-1;
+    if (c2 == -1) c2 = no_cols-1;
+
+    it_assert_debug(r1>=0 && r2>=0 && r1<no_rows && r2<no_rows &&
+	       c1>=0 && c2>=0 && c1<no_cols && c2<no_cols, "Mat<Num_T>::set_submatrix(): index out of range");
+
+    it_assert_debug(r2>=r1 && c2>=c1, "Mat<Num_T>::set_submatrix: r2<r1 or c2<c1");
+
+    int i, j, pos, rows = r2-r1+1;
+
+    for (i=c1; i<=c2; i++) {
+      pos = i*no_rows+r1;
+      for (j=0; j<rows; j++) {
+	data[pos++] = t;
+      }
+    }
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::del_row(int r)
+  {
+    it_assert_debug(r>=0 && r<no_rows, "Mat<Num_T>::del_row(): index out of range");
+    Mat<Num_T> Temp(*this);
+    set_size(no_rows-1, no_cols, false);
+    for (int i=0 ; i < r ; i++) {
+      copy_vector(no_cols, &Temp.data[i], no_rows+1, &data[i], no_rows);
+    }
+    for (int i=r ; i < no_rows ; i++) {
+      copy_vector(no_cols, &Temp.data[i+1], no_rows+1, &data[i], no_rows);
+    }
+
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::del_rows(int r1, int r2)
+  {
+    it_assert_debug((r1 >= 0) && (r2 < no_rows) && (r1 <= r2),
+		    "Mat<Num_T>::del_rows(): indices out of range");
+
+    Mat<Num_T> Temp(*this);
+    int no_del_rows = r2-r1+1;
+    set_size(no_rows-no_del_rows, no_cols, false);
+    for (int i = 0; i < r1 ; ++i) {
+      copy_vector(no_cols, &Temp.data[i], Temp.no_rows, &data[i], no_rows);
+    }
+    for (int i = r2+1; i < Temp.no_rows; ++i) {
+      copy_vector(no_cols, &Temp.data[i], Temp.no_rows, &data[i-no_del_rows],
+		  no_rows);
+    }
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::del_col(int c)
+  {
+    it_assert_debug(c>=0 && c<no_cols, "Mat<Num_T>::del_col(): index out of range");
+    Mat<Num_T> Temp(*this);
+
+    set_size(no_rows, no_cols-1, false);
+    copy_vector(c*no_rows, Temp.data, data);
+    copy_vector((no_cols - c)*no_rows, &Temp.data[(c+1)*no_rows], &data[c*no_rows]);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::del_cols(int c1, int c2)
+  {
+    it_assert_debug(c1>=0 && c2<no_cols && c1<=c2, "Mat<Num_T>::del_cols(): index out of range");
+    Mat<Num_T> Temp(*this);
+    int n_deleted_cols = c2-c1+1;
+    set_size(no_rows, no_cols-n_deleted_cols, false);
+    copy_vector(c1*no_rows, Temp.data, data);
+    copy_vector((no_cols-c1)*no_rows, &Temp.data[(c2+1)*no_rows], &data[c1*no_rows]);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::ins_row(int r, const Vec<Num_T> &in)
+  {
+    it_assert_debug(r>=0 && r<=no_rows, "Mat<Num_T>::ins_row(): index out of range");
+    it_assert_debug((in.size() == no_cols) || no_rows==0, "Mat<Num_T>::ins_row(): vector size does not match");
+
+    if (no_cols==0) {
+      no_cols = in.size();
+    }
+
+    Mat<Num_T> Temp(*this);
+    set_size(no_rows+1, no_cols, false);
+
+    for (int i=0 ; i < r ; i++) {
+      copy_vector(no_cols, &Temp.data[i], no_rows-1, &data[i], no_rows);
+    }
+    copy_vector(no_cols, in._data(), 1, &data[r], no_rows);
+    for (int i=r+1 ; i < no_rows ; i++) {
+      copy_vector(no_cols, &Temp.data[i-1], no_rows-1, &data[i], no_rows);
+    }
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::ins_col(int c, const Vec<Num_T> &in)
+  {
+    it_assert_debug(c>=0 && c<=no_cols, "Mat<Num_T>::ins_col(): index out of range");
+    it_assert_debug(in.size() == no_rows || no_cols==0, "Mat<Num_T>::ins_col(): vector size does not match");
+
+    if (no_rows==0) {
+      no_rows = in.size();
+    }
+
+    Mat<Num_T> Temp(*this);
+    set_size(no_rows, no_cols+1, false);
+
+    copy_vector(c*no_rows, Temp.data, data);
+    copy_vector(no_rows, in._data(), &data[c*no_rows]);
+    copy_vector((no_cols-c-1)*no_rows, &Temp.data[c*no_rows], &data[(c+1)*no_rows]);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::append_row(const Vec<Num_T> &in)
+  {
+    ins_row(no_rows, in);
+  }
+
+  template<class Num_T> inline
+  void Mat<Num_T>::append_col(const Vec<Num_T> &in)
+  {
+    ins_col(no_cols, in);
+  }
+
+  template<class Num_T>
+  const Mat<Num_T> Mat<Num_T>::transpose() const
+  {
+    Mat<Num_T> temp(no_cols, no_rows);
+    for (int i = 0; i < no_rows; ++i) {
+      copy_vector(no_cols, &data[i], no_rows, &temp.data[i * no_cols], 1);
+    }
+    return temp;
+  }
+
+  //! \cond
+  template<>
+  const cmat Mat<std::complex<double> >::hermitian_transpose() const;
+  //! \endcond
+
+  template<class Num_T>
+  const Mat<Num_T> Mat<Num_T>::hermitian_transpose() const
+  {
+    Mat<Num_T> temp(no_cols, no_rows);
+    for (int i = 0; i < no_rows; ++i) {
+      copy_vector(no_cols, &data[i], no_rows, &temp.data[i * no_cols], 1);
+    }
+    return temp;
+  }
+
+  template<class Num_T>
+  const Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+  {
+    it_assert_debug(m1.no_rows == m2.no_rows,
+		    "Mat<Num_T>::concat_horizontal(): wrong sizes");
+    int no_rows = m1.no_rows;
+    Mat<Num_T> temp(no_rows, m1.no_cols + m2.no_cols);
+    for (int i = 0; i < m1.no_cols; ++i) {
+      copy_vector(no_rows, &m1.data[i * no_rows], &temp.data[i * no_rows]);
+    }
+    for (int i = 0; i < m2.no_cols; ++i) {
+      copy_vector(no_rows, &m2.data[i * no_rows], &temp.data[(m1.no_cols + i)
+							     * no_rows]);
+    }
+    return temp;
+  }
+
+  template<class Num_T>
+  const Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+  {
+    it_assert_debug(m1.no_cols == m2.no_cols,
+		    "Mat<Num_T>::concat_vertical; wrong sizes");
+    int no_cols = m1.no_cols;
+    Mat<Num_T> temp(m1.no_rows + m2.no_rows, no_cols);
+    for (int i = 0; i < no_cols; ++i) {
+      copy_vector(m1.no_rows, &m1.data[i * m1.no_rows],
+		  &temp.data[i * temp.no_rows]);
+      copy_vector(m2.no_rows, &m2.data[i * m2.no_rows],
+		  &temp.data[i * temp.no_rows + m1.no_rows]);
+    }
+    return temp;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator=(Num_T t)
+  {
+    for (int i=0; i<datasize; i++)
+      data[i] = t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator=(const Mat<Num_T> &m)
+  {
+    if (this != &m) {
+      set_size(m.no_rows,m.no_cols, false);
+      if (m.datasize != 0)
+	copy_vector(m.datasize, m.data, data);
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator=(const Vec<Num_T> &v)
+  {
+    it_assert_debug((no_rows == 1 && no_cols == v.size())
+		    || (no_cols == 1 && no_rows == v.size()),
+		    "Mat<Num_T>::operator=(): Wrong size of the argument");
+    set_size(v.size(), 1, false);
+    copy_vector(v.size(), v._data(), data);
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator=(const char *values)
+  {
+    set(values);
+    return *this;
+  }
+
+  //-------------------- Templated friend functions --------------------------
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator+=(const Mat<Num_T> &m)
+  {
+    if (datasize == 0)
+      operator=(m);
+    else {
+      int i, j, m_pos=0, pos=0;
+      it_assert_debug(m.no_rows==no_rows && m.no_cols==no_cols,"Mat<Num_T>::operator+=: wrong sizes");
+      for (i=0; i<no_cols; i++) {
+	for (j=0; j<no_rows; j++)
+	  data[pos+j] += m.data[m_pos+j];
+	pos += no_rows;
+	m_pos += m.no_rows;
+      }
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator+=(Num_T t)
+  {
+    for (int i=0; i<datasize; i++)
+      data[i] += t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator+(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+  {
+    Mat<Num_T> r(m1.no_rows, m1.no_cols);
+    int i, j, m1_pos=0, m2_pos=0, r_pos=0;
+
+    it_assert_debug(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<Num_T>::operator+: wrong sizes");
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++)
+	r.data[r_pos+j] = m1.data[m1_pos+j] + m2.data[m2_pos+j];
+      // next column
+      m1_pos += m1.no_rows;
+      m2_pos += m2.no_rows;
+      r_pos += r.no_rows;
+    }
+
+    return r;
+  }
+
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+
+    for (int i=0; i<r.datasize; i++)
+      r.data[i] = m.data[i] + t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+
+    for (int i=0; i<r.datasize; i++)
+      r.data[i] = t + m.data[i];
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator-=(const Mat<Num_T> &m)
+  {
+    int i,j, m_pos=0, pos=0;
+
+    if (datasize == 0) {
+      set_size(m.no_rows, m.no_cols, false);
+      for (i=0; i<no_cols; i++) {
+	for (j=0; j<no_rows; j++)
+	  data[pos+j] = -m.data[m_pos+j];
+	// next column
+	m_pos += m.no_rows;
+	pos += no_rows;
+      }
+    } else {
+      it_assert_debug(m.no_rows==no_rows && m.no_cols==no_cols,"Mat<Num_T>::operator-=: wrong sizes");
+      for (i=0; i<no_cols; i++) {
+	for (j=0; j<no_rows; j++)
+	  data[pos+j] -= m.data[m_pos+j];
+	// next column
+	m_pos += m.no_rows;
+	pos += no_rows;
+      }
+    }
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+  {
+    Mat<Num_T> r(m1.no_rows, m1.no_cols);
+    int i, j, m1_pos=0, m2_pos=0, r_pos=0;
+
+    it_assert_debug(m1.no_rows==m2.no_rows && m1.no_cols == m2.no_cols, "Mat<Num_T>::operator-: wrong sizes");
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++)
+	r.data[r_pos+j] = m1.data[m1_pos+j] - m2.data[m2_pos+j];
+      // next column
+      m1_pos += m1.no_rows;
+      m2_pos += m2.no_rows;
+      r_pos += r.no_rows;
+    }
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator-=(Num_T t)
+  {
+    for (int i=0; i<datasize; i++)
+      data[i] -= t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+    int i, j, m_pos=0, r_pos=0;
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++)
+	r.data[r_pos+j] = m.data[m_pos+j] - t;
+      // next column
+      m_pos += m.no_rows;
+      r_pos += r.no_rows;
+    }
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+    int i, j, m_pos=0, r_pos=0;
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++)
+	r.data[r_pos+j] = t - m.data[m_pos+j];
+      // next column
+      m_pos += m.no_rows;
+      r_pos += r.no_rows;
+    }
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator-(const Mat<Num_T> &m)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+    int i, j, m_pos=0, r_pos=0;
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++)
+	r.data[r_pos+j] = -m.data[m_pos+j];
+      // next column
+      m_pos += m.no_rows;
+      r_pos += r.no_rows;
+    }
+
+    return r;
+  }
+
+#if defined(HAVE_BLAS)
+  template<> mat& Mat<double>::operator*=(const mat &m);
+  template<> cmat& Mat<std::complex<double> >::operator*=(const cmat &m);
+#endif
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator*=(const Mat<Num_T> &m)
+  {
+    it_assert_debug(no_cols == m.no_rows,"Mat<Num_T>::operator*=: wrong sizes");
+    Mat<Num_T> r(no_rows, m.no_cols);
+
+    Num_T tmp;
+
+    int i,j,k, r_pos=0, pos=0, m_pos=0;
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++) {
+	tmp = Num_T(0);
+	pos = 0;
+	for (k=0; k<no_cols; k++) {
+	  tmp += data[pos+j] * m.data[m_pos+k];
+	  pos += no_rows;
+	}
+	r.data[r_pos+j] = tmp;
+      }
+      r_pos += r.no_rows;
+      m_pos += m.no_rows;
+    }
+    operator=(r); // time consuming
+    return *this;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator*=(Num_T t)
+  {
+    scal_vector(datasize, t, data);
+    return *this;
+  }
+
+#if defined(HAVE_BLAS)
+  template<> const mat operator*(const mat &m1, const mat &m2);
+  template<> const cmat operator*(const cmat &m1, const cmat &m2);
+#endif
+
+
+  template<class Num_T>
+  const Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+  {
+    it_assert_debug(m1.no_cols == m2.no_rows,"Mat<Num_T>::operator*: wrong sizes");
+    Mat<Num_T> r(m1.no_rows, m2.no_cols);
+
+    Num_T tmp;
+    int i, j, k;
+    Num_T *tr=r.data, *t1, *t2=m2.data;
+
+    for (i=0; i<r.no_cols; i++) {
+      for (j=0; j<r.no_rows; j++) {
+	tmp = Num_T(0); t1 = m1.data+j;
+	for (k=m1.no_cols; k>0; k--) {
+	  tmp += *(t1) * *(t2++);
+	  t1 += m1.no_rows;
+	}
+	*(tr++) = tmp; t2 -= m2.no_rows;
+      }
+      t2 += m2.no_rows;
+    }
+
+    return r;
+  }
+
+#if defined(HAVE_BLAS)
+  template<> const vec operator*(const mat &m, const vec &v);
+  template<> const cvec operator*(const cmat &m, const cvec &v);
+#endif
+
+  template<class Num_T>
+  const Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v)
+  {
+    it_assert_debug(m.no_cols == v.size(),"Mat<Num_T>::operator*: wrong sizes");
+    Vec<Num_T> r(m.no_rows);
+    int i, k, m_pos;
+
+    for (i=0; i<m.no_rows; i++) {
+      r(i) = Num_T(0);
+      m_pos = 0;
+      for (k=0; k<m.no_cols; k++) {
+	r(i) += m.data[m_pos+i] * v(k);
+	m_pos += m.no_rows;
+      }
+    }
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m)
+  {
+    it_assert((m.no_rows == 1),"Mat<Num_T>::operator*(): wrong sizes");
+    it_warning("Mat<Num_T>::operator*(v, m): This operator is deprecated. "
+               "Please use outer_product(v, m.get_row(0)) instead.");
+    return outer_product(v, m.get_row(0));
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+
+    for (int i=0; i<r.datasize; i++)
+      r.data[i] = m.data[i] * t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m)
+  {
+    return operator*(m, t);
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> elem_mult(const Mat<Num_T> &A, const Mat<Num_T> &B)
+  {
+    Mat<Num_T> out;
+    elem_mult_out(A,B,out);
+    return out;
+  }
+
+  template<class Num_T> inline
+  void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_mult_out: wrong sizes");
+
+    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
+      out.set_size(A.no_rows, A.no_cols);
+
+    for(int i=0; i<out.datasize; i++)
+      out.data[i] = A.data[i] * B.data[i];
+  }
+
+  template<class Num_T> inline
+  void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, Mat<Num_T> &out)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows==C.no_rows) \
+                && (A.no_cols==B.no_cols==C.no_cols), \
+                "Mat<Num_T>::elem_mult_out: wrong sizes" );
+
+    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
+      out.set_size(A.no_rows, A.no_cols);
+
+    for(int i=0; i<out.datasize; i++)
+      out.data[i] = A.data[i] * B.data[i] * C.data[i];
+  }
+
+  template<class Num_T> inline
+  void elem_mult_out(const Mat<Num_T> &A, const Mat<Num_T> &B, const Mat<Num_T> &C, const Mat<Num_T> &D, Mat<Num_T> &out)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows==C.no_rows==D.no_rows) \
+                && (A.no_cols==B.no_cols==C.no_cols==D.no_cols), \
+                "Mat<Num_T>::elem_mult_out: wrong sizes" );
+    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
+      out.set_size(A.no_rows, A.no_cols);
+
+    for(int i=0; i<out.datasize; i++)
+      out.data[i] = A.data[i] * B.data[i] * C.data[i] * D.data[i];
+  }
+
+  template<class Num_T> inline
+  void elem_mult_inplace(const Mat<Num_T> &A, Mat<Num_T> &B)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), \
+                "Mat<Num_T>::elem_mult_inplace: wrong sizes" );
+
+    for(int i=0; i<B.datasize; i++)
+      B.data[i] *= A.data[i];
+  }
+
+  template<class Num_T> inline
+  Num_T elem_mult_sum(const Mat<Num_T> &A, const Mat<Num_T> &B)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_mult_sum: wrong sizes" );
+
+    Num_T acc = 0;
+
+    for(int i=0; i<A.datasize; i++)
+      acc += A.data[i] * B.data[i];
+
+    return acc;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator/=(Num_T t)
+  {
+    for (int i=0; i<datasize; i++)
+      data[i] /= t;
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t)
+  {
+    Mat<Num_T> r(m.no_rows, m.no_cols);
+
+    for (int i=0; i<r.datasize; i++)
+      r.data[i] = m.data[i] / t;
+
+    return r;
+  }
+
+  template<class Num_T> inline
+  Mat<Num_T>& Mat<Num_T>::operator/=(const Mat<Num_T> &m)
+  {
+    it_assert_debug(m.no_rows==no_rows && m.no_cols==no_cols, "Mat<Num_T>::operator/=: wrong sizes");
+
+    for (int i=0; i<datasize; i++)
+      data[i] /= m.data[i];
+    return *this;
+  }
+
+  template<class Num_T> inline
+  const Mat<Num_T> elem_div(const Mat<Num_T> &A, const Mat<Num_T> &B)
+  {
+    Mat<Num_T> out;
+    elem_div_out(A,B,out);
+    return out;
+  }
+
+  template<class Num_T> inline
+  void elem_div_out(const Mat<Num_T> &A, const Mat<Num_T> &B, Mat<Num_T> &out)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_div_out: wrong sizes");
+
+    if( (out.no_rows != A.no_rows) || (out.no_cols != A.no_cols) )
+      out.set_size(A.no_rows, A.no_cols);
+
+    for(int i=0; i<out.datasize; i++)
+      out.data[i] = A.data[i] / B.data[i];
+  }
+
+  template<class Num_T> inline
+  Num_T elem_div_sum(const Mat<Num_T> &A, const Mat<Num_T> &B)
+  {
+    it_assert_debug( (A.no_rows==B.no_rows) && (A.no_cols==B.no_cols), "Mat<Num_T>::elem_div_sum: wrong sizes" );
+
+    Num_T acc = 0;
+
+    for(int i=0; i<A.datasize; i++)
+      acc += A.data[i] / B.data[i];
+
+    return acc;
+  }
+
+  template<class Num_T>
+  bool Mat<Num_T>::operator==(const Mat<Num_T> &m) const
+  {
+    if (no_rows!=m.no_rows || no_cols != m.no_cols) return false;
+    for (int i=0;i<datasize;i++) {
+      if (data[i]!=m.data[i]) return false;
+    }
+    return true;
+  }
+
+  template<class Num_T>
+  bool Mat<Num_T>::operator!=(const Mat<Num_T> &m) const
+  {
+    if (no_rows != m.no_rows || no_cols != m.no_cols) return true;
+    for (int i=0;i<datasize;i++) {
+      if (data[i]!=m.data[i]) return true;
+    }
+    return false;
+  }
+
+  template <class Num_T>
+  std::ostream &operator<<(std::ostream &os, const Mat<Num_T> &m)
+  {
+    int i;
+
+    switch (m.rows()) {
+    case 0 :
+      os << "[]";
+      break;
+    case 1 :
+      os << '[' << m.get_row(0) << ']';
+      break;
+    default:
+      os << '[' << m.get_row(0) << std::endl;
+      for (i=1; i<m.rows()-1; i++)
+	      os << ' ' << m.get_row(i) << std::endl;
+      os << ' ' << m.get_row(m.rows()-1) << ']';
+    }
+
+    return os;
+  }
+
+  template <class Num_T>
+  std::istream &operator>>(std::istream &is, Mat<Num_T> &m)
+  {
+    std::ostringstream buffer;
+    bool started = false;
+    bool finished = false;
+    bool brackets = false;
+    bool within_double_brackets = false;
+    char c;
+
+    while (!finished) {
+      if (is.eof()) {
+        finished = true;
+      } else {
+        c = is.get();
+
+        if (is.eof() || (c == '\n')) {
+          if (brackets) {
+            // Right bracket missing
+            is.setstate(std::ios_base::failbit);
+            finished = true;
+          } else if (!((c == '\n') && !started)) {
+            finished = true;
+          }
+        } else if ((c == ' ') || (c == '\t')) {
+          if (started) {
+            buffer << ' ';
+          }
+        } else if (c == '[') {
+          if ((started && !brackets) || within_double_brackets) {
+            // Unexpected left bracket
+            is.setstate(std::ios_base::failbit);
+            finished = true;
+          } else if (!started) {
+            started = true;
+            brackets = true;
+          } else {
+            within_double_brackets = true;
+          }
+        } else if (c == ']') {
+          if (!started || !brackets) {
+            // Unexpected right bracket
+            is.setstate(std::ios_base::failbit);
+            finished = true;
+          } else if (within_double_brackets) {
+            within_double_brackets = false;
+            buffer << ';';
+          } else {
+            finished = true;
+          }
+          while (!is.eof() && (((c = is.peek()) == ' ') || (c == '\t'))) {
+            is.get();
+          }
+          if (!is.eof() && (c == '\n')) {
+            is.get();
+          }
+        } else {
+          started = true;
+          buffer << c;
+        }
+      }
+    }
+
+    if (!started) {
+      m.set_size(0, false);
+    } else {
+      m.set(buffer.str());
+    }
+
+    return is;
+  }
+
+  //! \cond
+
+  // ---------------------------------------------------------------------
+  // Instantiations
+  // ---------------------------------------------------------------------
+
+#ifdef HAVE_EXTERN_TEMPLATE
+
+  // class instantiations
+
+  extern template class Mat<double>;
+  extern template class Mat<std::complex<double> >;
+  extern template class Mat<int>;
+  extern template class Mat<short int>;
+  extern template class Mat<bin>;
+
+  // addition operators
+
+  extern template const mat operator+(const mat &m1, const mat &m2);
+  extern template const cmat operator+(const cmat &m1, const cmat &m2);
+  extern template const imat operator+(const imat &m1, const imat &m2);
+  extern template const smat operator+(const smat &m1, const smat &m2);
+  extern template const bmat operator+(const bmat &m1, const bmat &m2);
+
+  extern template const mat operator+(const mat &m, double t);
+  extern template const cmat operator+(const cmat &m, std::complex<double> t);
+  extern template const imat operator+(const imat &m, int t);
+  extern template const smat operator+(const smat &m, short t);
+  extern template const bmat operator+(const bmat &m, bin t);
+
+  extern template const mat operator+(double t, const mat &m);
+  extern template const cmat operator+(std::complex<double> t, const cmat &m);
+  extern template const imat operator+(int t, const imat &m);
+  extern template const smat operator+(short t, const smat &m);
+  extern template const bmat operator+(bin t, const bmat &m);
+
+  // subraction operators
+
+  extern template const mat operator-(const mat &m1, const mat &m2);
+  extern template const cmat operator-(const cmat &m1, const cmat &m2);
+  extern template const imat operator-(const imat &m1, const imat &m2);
+  extern template const smat operator-(const smat &m1, const smat &m2);
+  extern template const bmat operator-(const bmat &m1, const bmat &m2);
+
+  extern template const mat operator-(const mat &m, double t);
+  extern template const cmat operator-(const cmat &m, std::complex<double> t);
+  extern template const imat operator-(const imat &m, int t);
+  extern template const smat operator-(const smat &m, short t);
+  extern template const bmat operator-(const bmat &m, bin t);
+
+  extern template const mat operator-(double t, const mat &m);
+  extern template const cmat operator-(std::complex<double> t, const cmat &m);
+  extern template const imat operator-(int t, const imat &m);
+  extern template const smat operator-(short t, const smat &m);
+  extern template const bmat operator-(bin t, const bmat &m);
+
+  // unary minus
+
+  extern template const mat operator-(const mat &m);
+  extern template const cmat operator-(const cmat &m);
+  extern template const imat operator-(const imat &m);
+  extern template const smat operator-(const smat &m);
+  extern template const bmat operator-(const bmat &m);
+
+  // multiplication operators
+
+#if !defined(HAVE_BLAS)
+  extern template const mat operator*(const mat &m1, const mat &m2);
+  extern template const cmat operator*(const cmat &m1, const cmat &m2);
+#endif
+  extern template const imat operator*(const imat &m1, const imat &m2);
+  extern template const smat operator*(const smat &m1, const smat &m2);
+  extern template const bmat operator*(const bmat &m1, const bmat &m2);
+
+#if !defined(HAVE_BLAS)
+  extern template const vec operator*(const mat &m, const vec &v);
+  extern template const cvec operator*(const cmat &m, const cvec &v);
+#endif
+  extern template const ivec operator*(const imat &m, const ivec &v);
+  extern template const svec operator*(const smat &m, const svec &v);
+  extern template const bvec operator*(const bmat &m, const bvec &v);
+
+  extern template const mat operator*(const vec &v, const mat &m);
+  extern template const cmat operator*(const cvec &v, const cmat &m);
+  extern template const imat operator*(const ivec &v, const imat &m);
+  extern template const smat operator*(const svec &v, const smat &m);
+  extern template const bmat operator*(const bvec &v, const bmat &m);
+
+  extern template const mat operator*(const mat &m, double t);
+  extern template const cmat operator*(const cmat &m, std::complex<double> t);
+  extern template const imat operator*(const imat &m, int t);
+  extern template const smat operator*(const smat &m, short t);
+  extern template const bmat operator*(const bmat &m, bin t);
+
+  extern template const mat operator*(double t, const mat &m);
+  extern template const cmat operator*(std::complex<double> t, const cmat &m);
+  extern template const imat operator*(int t, const imat &m);
+  extern template const smat operator*(short t, const smat &m);
+  extern template const bmat operator*(bin t, const bmat &m);
+
+  // elementwise multiplication
+
+  extern template const mat elem_mult(const mat &A, const mat &B);
+  extern template const cmat elem_mult(const cmat &A, const cmat &B);
+  extern template const imat elem_mult(const imat &A, const imat &B);
+  extern template const smat elem_mult(const smat &A, const smat &B);
+  extern template const bmat elem_mult(const bmat &A, const bmat &B);
+
+  extern template void elem_mult_out(const mat &A, const mat &B, mat &out);
+  extern template void elem_mult_out(const cmat &A, const cmat &B, cmat &out);
+  extern template void elem_mult_out(const imat &A, const imat &B, imat &out);
+  extern template void elem_mult_out(const smat &A, const smat &B, smat &out);
+  extern template void elem_mult_out(const bmat &A, const bmat &B, bmat &out);
+
+  extern template void elem_mult_out(const mat &A, const mat &B, const mat &C,
+                                     mat &out);
+  extern template void elem_mult_out(const cmat &A, const cmat &B,
+                                     const cmat &C, cmat &out);
+  extern template void elem_mult_out(const imat &A, const imat &B,
+                                     const imat &C, imat &out);
+  extern template void elem_mult_out(const smat &A, const smat &B,
+                                     const smat &C, smat &out);
+  extern template void elem_mult_out(const bmat &A, const bmat &B,
+                                     const bmat &C, bmat &out);
+
+  extern template void elem_mult_out(const mat &A, const mat &B, const mat &C,
+                                     const mat &D, mat &out);
+  extern template void elem_mult_out(const cmat &A, const cmat &B,
+                                     const cmat &C, const cmat &D, cmat &out);
+  extern template void elem_mult_out(const imat &A, const imat &B,
+                                     const imat &C, const imat &D, imat &out);
+  extern template void elem_mult_out(const smat &A, const smat &B,
+                                     const smat &C, const smat &D, smat &out);
+  extern template void elem_mult_out(const bmat &A, const bmat &B,
+                                     const bmat &C, const bmat &D, bmat &out);
+
+  extern template void elem_mult_inplace(const mat &A, mat &B);
+  extern template void elem_mult_inplace(const cmat &A, cmat &B);
+  extern template void elem_mult_inplace(const imat &A, imat &B);
+  extern template void elem_mult_inplace(const smat &A, smat &B);
+  extern template void elem_mult_inplace(const bmat &A, bmat &B);
+
+  extern template double elem_mult_sum(const mat &A, const mat &B);
+  extern template std::complex<double> elem_mult_sum(const cmat &A,
+                                                     const cmat &B);
+  extern template int elem_mult_sum(const imat &A, const imat &B);
+  extern template short elem_mult_sum(const smat &A, const smat &B);
+  extern template bin elem_mult_sum(const bmat &A, const bmat &B);
+
+  // division operator
+
+  extern template const mat operator/(const mat &m, double t);
+  extern template const cmat operator/(const cmat &m, std::complex<double> t);
+  extern template const imat operator/(const imat &m, int t);
+  extern template const smat operator/(const smat &m, short t);
+  extern template const bmat operator/(const bmat &m, bin t);
+
+  // elementwise division
+
+  extern template const mat elem_div(const mat &A, const mat &B);
+  extern template const cmat elem_div(const cmat &A, const cmat &B);
+  extern template const imat elem_div(const imat &A, const imat &B);
+  extern template const smat elem_div(const smat &A, const smat &B);
+  extern template const bmat elem_div(const bmat &A, const bmat &B);
+
+  extern template void elem_div_out(const mat &A, const mat &B, mat &out);
+  extern template void elem_div_out(const cmat &A, const cmat &B, cmat &out);
+  extern template void elem_div_out(const imat &A, const imat &B, imat &out);
+  extern template void elem_div_out(const smat &A, const smat &B, smat &out);
+  extern template void elem_div_out(const bmat &A, const bmat &B, bmat &out);
+
+  extern template double elem_div_sum(const mat &A, const mat &B);
+  extern template std::complex<double> elem_div_sum(const cmat &A,
+                                                    const cmat &B);
+  extern template int elem_div_sum(const imat &A, const imat &B);
+  extern template short elem_div_sum(const smat &A, const smat &B);
+  extern template bin elem_div_sum(const bmat &A, const bmat &B);
+
+  // concatenation
+
+  extern template const mat concat_horizontal(const mat &m1, const mat &m2);
+  extern template const cmat concat_horizontal(const cmat &m1, const cmat &m2);
+  extern template const imat concat_horizontal(const imat &m1, const imat &m2);
+  extern template const smat concat_horizontal(const smat &m1, const smat &m2);
+  extern template const bmat concat_horizontal(const bmat &m1, const bmat &m2);
+
+  extern template const mat concat_vertical(const mat &m1, const mat &m2);
+  extern template const cmat concat_vertical(const cmat &m1, const cmat &m2);
+  extern template const imat concat_vertical(const imat &m1, const imat &m2);
+  extern template const smat concat_vertical(const smat &m1, const smat &m2);
+  extern template const bmat concat_vertical(const bmat &m1, const bmat &m2);
+
+  // I/O streams
+
+  extern template std::ostream &operator<<(std::ostream &os, const mat  &m);
+  extern template std::ostream &operator<<(std::ostream &os, const cmat &m);
+  extern template std::ostream &operator<<(std::ostream &os, const imat  &m);
+  extern template std::ostream &operator<<(std::ostream &os, const smat  &m);
+  extern template std::ostream &operator<<(std::ostream &os, const bmat  &m);
+
+  extern template std::istream &operator>>(std::istream &is, mat  &m);
+  extern template std::istream &operator>>(std::istream &is, cmat &m);
+  extern template std::istream &operator>>(std::istream &is, imat  &m);
+  extern template std::istream &operator>>(std::istream &is, smat  &m);
+  extern template std::istream &operator>>(std::istream &is, bmat  &m);
+
+#endif // HAVE_EXTERN_TEMPLATE
+
+  //! \endcond
+
+} // namespace itpp
+
+#endif // #ifndef MAT_H
Index: /win32/itpp-4.0.1/itpp/base/binary.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/binary.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/binary.h (revision 35)
@@ -0,0 +1,189 @@
+/*!
+ * \file
+ * \brief Binary class definition
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef BINARY_H
+#define BINARY_H
+
+#include <itpp/base/itassert.h>
+
+
+namespace itpp {
+
+  /*!
+    \brief Binary arithmetic (boolean) class
+    \author Tony Ottosson
+
+    This class creates a binary aritmetic class, following the ordinary
+    rules for binary (GF(2)) fields.
+
+    Examples:
+    \code
+    bin a;         // Creation of variable
+    bin a = 0;     // Creating a variable and assigning it value 0
+    bin b = 1;     // Creating a variable and assigning it value 1
+    bin c = a + b; // XOR operation
+    c = !a;        // NOT
+    c = a * b;     // AND
+    c = a / b;     // OR
+    \endcode
+  */
+  class bin {
+  public:
+    //! Default constructor
+    bin(): b(0) {}
+
+    //! Set the binary object equal to \c value. Either "0" or "1".
+    bin(const int &value): b(static_cast<char>(value)) {
+      it_assert_debug((value == 0) || (value == 1),
+                      "bin::bin(): value must be 0 or 1");
+    }
+
+    //! Copy constructor
+    bin(const bin &inbin): b(inbin.b) {}
+
+    //! Assign a value
+    void operator=(const int &value) {
+      it_assert_debug((value == 0) || (value == 1),
+                      "bin::operator=(): value must be 0 or 1");
+      b = static_cast<char>(value);
+    }
+
+    //! Assign a value
+    void operator=(const bin &inbin) { b = inbin.b; }
+
+    //! OR
+    void operator/=(const bin &inbin) { b |= inbin.b; }
+
+    //! OR
+    void operator|=(const bin &inbin) { b |= inbin.b; }
+    //! OR
+    bin operator/(const bin &inbin) const { return bin(b | inbin.b); }
+    //! OR
+    bin operator|(const bin &inbin) const { return bin(b | inbin.b); }
+
+    //! XOR
+    void operator+=(const bin &inbin) { b ^= inbin.b; }
+    //! XOR
+    void operator^=(const bin &inbin) { b ^= inbin.b; }
+    //! XOR
+    bin operator+(const bin &inbin) const { return bin(b ^ inbin.b); }
+    //! XOR
+    bin operator^(const bin &inbin) const { return bin(b ^ inbin.b); }
+    //! XOR
+    void operator-=(const bin &inbin) { b ^= inbin.b; }
+    //! XOR
+    bin operator-(const bin &inbin) const { return bin(b ^ inbin.b); }
+    //! Dummy definition to be able to use vec<bin>
+    bin operator-() const { return bin(b); }
+
+    //! AND
+    void operator*=(const bin &inbin) { b &= inbin.b; }
+    //! AND
+    void operator&=(const bin &inbin) { b &= inbin.b; }
+    //! AND
+    bin operator*(const bin &inbin) const { return bin(b & inbin.b); }
+    //! AND
+    bin operator&(const bin &inbin) const { return bin(b & inbin.b); }
+
+    //! NOT
+    bin operator!(void) const { return bin(b^1); }
+    //! NOT
+    bin operator~(void) const { return bin(b^1); }
+
+    //! Check if equal
+    bool operator==(const bin &inbin) const { return b == inbin.b; }
+    //! Check if equal
+    bool operator==(const int &i) const { return b == i; }
+
+    //! Check if not equal
+    bool operator!=(const bin &inbin) const { return b != inbin.b; }
+    //! Check if not equal
+    bool operator!=(const int &i) const { return b != i; }
+
+    //! Less than (interpret the binary values {0,1} as integers)
+    bool operator<(const bin &inbin) const  { return b < inbin.b; }
+    //! Less than equal (interpret the binary values {0,1} as integers)
+    bool operator<=(const bin &inbin) const { return b <= inbin.b; }
+
+    //! Greater than (interpret the binary values {0,1} as integers)
+    bool operator>(const bin &inbin) const  { return b > inbin.b; }
+    //! Greater than equal (interpret the binary values {0,1} as integers)
+    bool operator>=(const bin &inbin) const { return b >= inbin.b; }
+
+    //! Convert \c bin to \c short
+    operator short() const  { return static_cast<short>(b); }
+    //! Convert \c bin to \c int
+    operator int() const    { return static_cast<int>(b); }
+    //! Convert \c bin to \c bool
+    operator bool() const   { return b != 0; }
+    //! Convert \c bin to \c float
+    operator float() const  { return static_cast<float>(b); }
+    //! Convert \c bin to \c double
+    operator double() const { return static_cast<double>(b); }
+
+    //! Output the binary value of the object
+    char value() const { return b; }
+
+  private:
+    char b;
+  };
+
+  /*!
+    \relatesalso bin
+    \brief Output stream of bin
+  */
+  std::ostream &operator<<(std::ostream &output, const bin &inbin);
+
+  /*!
+    \relatesalso bin
+    \brief Input stream of bin
+  */
+  std::istream &operator>>(std::istream &input, bin &outbin);
+
+  /*!
+    \relatesalso bin
+    \brief absolute value of bin
+  */
+  inline bin abs(const bin &inbin) { return inbin; }
+
+} // namespace itpp
+
+
+namespace std { // added 11/2005, EGL
+
+  /*!
+    \relatesalso itpp::bin
+    \brief absolute value of bin
+  */
+  inline int abs(const itpp::bin &inbin) { return inbin; }
+
+} // namespace std
+
+#endif // #ifndef BINARY_H
+
Index: /win32/itpp-4.0.1/itpp/base/sort.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/sort.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/sort.h (revision 35)
@@ -0,0 +1,544 @@
+/*!
+ * \file
+ * \brief Sorting functions
+ * \author Tony Ottosson, Mark Dobossy and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef SORT_H
+#define SORT_H
+
+#include <itpp/base/vec.h>
+#include <itpp/base/converters.h>
+#include <itpp/base/math/log_exp.h>
+
+
+namespace itpp {
+
+  /*!
+   * \brief Soring algoritms that can be used in a \a Sort class
+   *
+   * - Introsort (the default and the fastest method in most cases)
+   * - Quicksort
+   * - Heapsort
+   * - Inertion Sort (suitable for very short vectors)
+   */
+  enum SORTING_METHOD { INTROSORT = 0, QUICKSORT = 1, HEAPSORT = 2,
+			INSERTSORT = 3 };
+
+  /*!
+   * \brief Class for sorting of vectors
+   *
+   * A class which takes a vector, and sorts its values descending. There
+   * are two types of sort: a normal sort (accessed via the Sort::sort()
+   * function) which sorts the vector passed in the argument, and an index
+   * sort (accessed via the Sort::sort_index() function) which leaves the
+   * passed vector intact, but returns an index vector describing the sorted
+   * order.
+   *
+   * The Sort class has four sorting methods implemented:
+   * - Introsort [1,2]: It is a sorting algorithm developed by David Musser.
+   *   I starts as a quicksort, but switches to a heapsort in cases where
+   *   the recursion becomes too deep. Additionally, when sub vectors become
+   *   smaller than 16 elements, it switches to an insertion sort. Introsort
+   *   has a worst-case of \f$\Theta(n\log n)\f$ comparisons, bu has the
+   *   efficiency of the quick sort algorithm in cases where the data is
+   *   well conditioned for quicksort.
+   * - Quicksort [3]: It is a comparison sorting algorithm that has an
+   *   average complexity of \f$\Theta(n\log n)\f$ comparisons. For most
+   *   data sets, the quicksort will be significantly more efficient than
+   *   this average. However for data sets not well suited to it, quicksort
+   *   may require as many as \f$\Theta(n^2)\f$ comparisons. Example of such
+   *   ill-suited data sets are those which are nearly in order, and data
+   *   sets with multiple elements of the same value.
+   * - Heapsort [4]: It is a comparison sorting algorithm. While it is
+   *   usually seen to be slower than quicksort routines, its worst-case
+   *   requires only \f$\Theta(n\log n)\f$ comparisons. This makes it an
+   *   ideal quicksort replacement for data sets that that are
+   *   ill-conditioned for quicksorting.
+   * - Insertion sort [5]: An insertion sort is a simple comparison sort,
+   *   which is widely considered to be one of the most efficient algorithms
+   *   for very small data sets (10-20 elements).
+   *   http://en.wikipedia.org/wiki/Insertion_sort
+   *
+   * References:
+   * - [1] http://en.wikipedia.org/wiki/Introsort
+   * - [2] http://www.cs.rpi.edu/~musser/gp/introsort.ps
+   * - [3] http://en.wikipedia.org/wiki/Quicksort
+   * - [4] http://en.wikipedia.org/wiki/Heapsort
+   * - [5] http://en.wikipedia.org/wiki/Insertion_sort
+   *
+   * \author Tony Ottosson (Quicksort), Mark Dobossy (Introsort, Heapsort
+   *         and Insertion Sort) and Adam Piatyszek (Sort class design, code
+   *         clean-up)
+   */
+  template<class T>
+  class Sort {
+  public:
+    //! Constructor that sets Intro Sort method by default
+    Sort(SORTING_METHOD method = INTROSORT): sort_method(method) {}
+
+    //! Set sorting method
+    void set_method(SORTING_METHOD method) { sort_method = method; }
+
+    //! Get current sorting method
+    SORTING_METHOD get_method() const { return sort_method; }
+
+    /*!
+     * \brief Sorting function of a subset of a vector \a data
+     *
+     * \param low Start index of a subvector to be sorted
+     * \param high End index of a subvector to be sorted
+     * \param data Data vector, in which a part of it is to be sorted
+     */
+    void sort(int low, int high, Vec<T> &data);
+
+    /*!
+     * \brief Sorting function that returns a sorted index vector
+     *
+     * \param low Start index of a subvector to be sorted
+     * \param high End index of a subvector to be sorted
+     * \param data Data vector, in which a part of it is to be sorted
+     */
+    ivec sort_index(int low, int high, const Vec<T> &data);
+
+    /*!
+     * \brief Introsort function of a subset of a vector \c data
+     *
+     * \param low Start index of a subvector to be sorted
+     * \param high End index of a subvector to be sorted
+     * \param max_depth Maximum recursion depth before switching to heap sort
+     *        recommended value: log2 of the length of the data vector
+     * \param data Data vector, in which a part of it is to be sorted
+     *
+     * \note An introsort is not a stable sort (i.e. it may not maintain
+     *       the relative order of elements with equal value.)
+     * \note This function uses recurence.
+     */
+    void intro_sort(int low, int high, int max_depth, Vec<T> &data);
+
+    /*!
+     * \brief Introsort function, which returns a sorted index vector
+     *
+     * \param low Start index of a subvector to be sorted
+     * \param high End index of a subvector to be sorted
+     * \param max_depth Maximum recursion depth before switching to heap sort
+     *        recommended value: log2 of the length of the data vector
+     * \param data Data vector, in which a part of it is to be sorted
+     *
+     * \note An Introsort is not a stable sort (i.e. it may not maintain
+     *       the relative order of elements with equal value.)
+     * \note This function uses recurence.
+     */
+    ivec intro_sort_index(int low, int high, int max_depth,
+			  const Vec<T> &data);
+
+  private:
+    SORTING_METHOD sort_method;
+
+    void IntroSort(int low, int high, int max_depth, T data[]);
+    void IntroSort_Index(int low, int high, int max_depth, int indexlist[],
+			 const T data[]);
+
+    void QuickSort(int low, int high, T data[]);
+    void QuickSort_Index(int low, int high, int indexlist[], const T data[]);
+
+    void HeapSort(int low, int high, T data[]);
+    void HeapSort_Index(int low, int high, int indexlist[], const T data[]);
+
+    void InsertSort(int low, int high, T data[]);
+    void InsertSort_Index(int low, int high, int indexlist[], const T data[]);
+  };
+
+
+  /*!
+   * \relates Vec
+   * \brief Sort the \a data vector in increasing order
+   *
+   * \param data Vector to be sorted
+   * \param method Sorting method: INTROSORT (default), QUICKSORT, HEAPSORT
+   * or INSERTSORT
+   */
+  template<class T>
+  void sort(Vec<T> &data, SORTING_METHOD method = INTROSORT)
+  {
+    Sort<T> s(method);
+    s.sort(0, data.size()-1, data);
+  }
+
+  /*!
+   * \relates Vec
+   * \brief Return an index vector corresponding to a sorted vector \a data
+   * in increasing order
+   *
+   * \param data Vector for which to return a sorted index vector
+   * \param method Sorting method: INTROSORT (default), QUICKSORT, HEAPSORT
+   * or INSERTSORT
+   */
+  template<class T>
+  ivec sort_index(const Vec<T> &data, SORTING_METHOD method = INTROSORT)
+  {
+    Sort<T> s(method);
+    return s.sort_index(0, data.size()-1, data);
+  }
+
+
+  // ----------------------------------------------------------------------
+  // Public functions for various sorting methods
+  // ----------------------------------------------------------------------
+
+  template<class T>
+  void Sort<T>::sort(int low, int high, Vec<T> &data)
+  {
+    int N = data.size();
+
+    it_assert((low >= 0) && (high > low) && (high < N), "Sort::sort(): "
+	      "low or high out of bounds");
+
+    switch (sort_method) {
+    case INTROSORT:
+      IntroSort(low, high, levels2bits(N), data._data());
+      break;
+    case QUICKSORT:
+      QuickSort(low, high, data._data());
+      break;
+    case HEAPSORT:
+      HeapSort(low, high, data._data());
+      break;
+    case INSERTSORT:
+      InsertSort(low, high, data._data());
+      break;
+    default:
+      it_error("Sort<T>::sort(): Unknown sorting method");
+    }
+  }
+
+
+  template<class T>
+  ivec Sort<T>::sort_index(int low, int high, const Vec<T> &data)
+  {
+    int N = data.size();
+
+    it_assert((low >= 0) && (high > low) && (high < N), "Sort::sort(): "
+	      "low or high out of bounds");
+
+    ivec indexlist(N);
+    for(int i = 0; i < N; ++i) {
+      indexlist(i) = i;
+    }
+
+    switch (sort_method) {
+    case INTROSORT:
+      IntroSort_Index(low, high, levels2bits(N), indexlist._data(),
+		      data._data());
+      break;
+    case QUICKSORT:
+      QuickSort_Index(low, high, indexlist._data(), data._data());
+      break;
+    case HEAPSORT:
+      HeapSort_Index(low, high, indexlist._data(), data._data());
+      break;
+    case INSERTSORT:
+      InsertSort_Index(low, high, indexlist._data(), data._data());
+      break;
+    default:
+      it_error("Sort<T>::sort_index(): Unknown sorting method");
+    }
+
+    return indexlist;
+  }
+
+
+  // INTRO SORT
+  template<class T>
+  void Sort<T>::intro_sort(int low, int high, int max_depth, Vec<T> &data)
+  {
+    it_assert((low >= 0) && (high > low) && (high < data.size()),
+	      "Sort::sort(): low or high out of bounds");
+    IntroSort(low, high, max_depth, data._data());
+  }
+
+  // INTRO SORT INDEX
+  template<class T>
+  ivec Sort<T>::intro_sort_index(int low, int high, int max_depth,
+				 const Vec<T> &data)
+  {
+    int N = data.size();
+    it_assert((low >= 0) && (high > low) && (high < N),
+	      "Sort::sort(): low or high out of bounds");
+
+    ivec indexlist(N);
+    for (int i = 0; i < N; ++i) {
+      indexlist(i) = i;
+    }
+
+    IntroSort_Index(low, high, max_depth, indexlist._data(), data._data());
+
+    return indexlist;
+  }
+
+
+  // ----------------------------------------------------------------------
+  // Private functions for sorting methods
+  // ----------------------------------------------------------------------
+
+  template<class T>
+  void Sort<T>::IntroSort(int low, int high, int max_depth, T data[])
+  {
+    if (high-low > 16) {
+      max_depth--;
+      if (max_depth == 0) {
+	HeapSort(low, high, data);
+	return;
+      }
+
+      if (high>low) {
+        T a = data[low];
+        int plow = low;
+        int phigh = high;
+        T test = data[phigh];
+        while (plow < phigh) {
+	  if (test < a) {
+	    data[plow] = test;
+	    plow++;
+	    test = data[plow];
+	  } else {
+	    data[phigh] = test;
+	    phigh--;
+	    test = data[phigh];
+	  }
+        }
+        data[plow] = a;
+        IntroSort(low,plow-1,max_depth,data);
+        IntroSort(plow+1,high,max_depth,data);
+        return;
+      }
+    } else {
+      InsertSort(low, high, data);
+      return;
+    }
+  }
+
+  template<class T>
+  void Sort<T>::IntroSort_Index(int low, int high, int max_depth,
+				int indexlist[], const T data[])
+  {
+    if (high-low > 16) {
+      max_depth--;
+      if (max_depth == 0) {
+	HeapSort_Index(low, high, indexlist, data);
+	return;
+      }
+
+      if (high > low) {
+        int aindex = indexlist[low];
+        T a = data[aindex];
+        int plow = low;
+        int phigh = high;
+        int testindex = indexlist[phigh];
+        T test = data[testindex];
+        while (plow < phigh) {
+	  if (test < a) {
+	    indexlist[plow] = testindex;
+	    plow++;
+	    testindex = indexlist[plow];
+	    test = data[testindex];
+	  } else {
+	    indexlist[phigh] = testindex;
+	    phigh--;
+	    testindex = indexlist[phigh];
+	    test = data[testindex];
+	  }
+	}
+	indexlist[plow] = aindex;
+        IntroSort_Index(low,plow-1,max_depth,indexlist,data);
+        IntroSort_Index(plow+1,high,max_depth,indexlist,data);
+      }
+    } else {
+      InsertSort_Index(low, high, indexlist, data);
+      return;
+    }
+  }
+
+  template <class T>
+  void Sort<T>::QuickSort(int low, int high, T data[])
+  {
+    if (high > low) {
+      T a = data[low];
+      int plow = low;
+      int phigh = high;
+      T test = data[phigh];
+      while (plow < phigh) {
+	if (test < a) {
+	  data[plow] = test;
+	  plow++;
+	  test = data[plow];
+	} else {
+	  data[phigh] = test;
+	  phigh--;
+	  test = data[phigh];
+	}
+      }
+      data[plow] = a;
+      QuickSort(low,plow-1,data);
+      QuickSort(plow+1,high,data);
+    }
+  }
+
+  template<class T>
+  void Sort<T>::QuickSort_Index(int low, int high, int indexlist[],
+				const T data[])
+  {
+    if (high > low) {
+      int aindex = indexlist[low];
+      T a = data[aindex];
+      int plow = low;
+      int phigh = high;
+      int testindex = indexlist[phigh];
+      T test = data[testindex];
+      while (plow < phigh) {
+	if (test < a) {
+	  indexlist[plow] = testindex;
+	  plow++;
+	  testindex = indexlist[plow];
+	  test = data[testindex];
+	} else {
+	  indexlist[phigh] = testindex;
+	  phigh--;
+	  testindex = indexlist[phigh];
+	  test = data[testindex];
+	}
+      }
+      indexlist[plow] = aindex;
+      QuickSort_Index(low,plow-1,indexlist,data);
+      QuickSort_Index(plow+1,high,indexlist,data);
+    }
+  }
+
+  template<class T>
+  void Sort<T>::HeapSort(int low, int high, T data[])
+  {
+    int size=(high+1)-low;
+    int i=size/2;
+    T temp;
+    while(1) {
+      if (i > 0)
+        temp = data[--i + low];
+      else {
+        if (size-- == 0)
+          break;
+        temp = data[size + low];
+        data[size + low] = data[low];
+      }
+
+      int parent = i;
+      int child = i*2 + 1;
+
+      while (child < size) {
+        if (child + 1 < size  &&  data[child + 1 + low] > data[child + low])
+          child++;
+        if (data[child + low] > temp) {
+          data[parent + low] = data[child + low];
+          parent = child;
+          child = parent*2 + 1;
+        } else
+          break;
+      }
+      data[parent + low] = temp;
+    }
+  }
+
+  template<class T>
+  void Sort<T>::HeapSort_Index(int low, int high, int indexlist[],
+			       const T data[])
+  {
+    int size=(high+1)-low;
+    int i=size/2;
+
+    while(1) {
+      T tempValue;
+      int tempIndex;
+      if (i > 0) {
+	i--;
+        tempValue = data[indexlist[i + low]];
+        tempIndex = indexlist[i + low];
+      } else {
+        if (size-- == 0)
+          break;
+        tempValue = data[indexlist[size + low]];
+        tempIndex = indexlist[size + low];
+        indexlist[size+low] = indexlist[low];
+      }
+
+      int parent = i;
+      int child = i*2 + 1;
+
+      while (child < size) {
+        if ((child + 1 < size)
+	    && data[indexlist[child + 1 + low]] > data[indexlist[child + low]])
+          child++;
+        if (data[indexlist[child + low]] > tempValue) {
+          indexlist[parent + low] = indexlist[child + low];
+          parent = child;
+          child = parent*2 + 1;
+        } else
+          break;
+      }
+      indexlist[parent + low] = tempIndex;
+    }
+  }
+
+  template<class T>
+  void Sort<T>::InsertSort(int low, int high, T data[])
+  {
+    for(int i = low+1; i <= high; i++) {
+      T value = data[i];
+      int j;
+      for (j = i - 1; j >= low && data[j] > value; j--) {
+	data[j + 1] = data[j];
+      }
+      data[j + 1] = value;
+    }
+  }
+
+  template<class T>
+  void Sort<T>::InsertSort_Index(int low, int high, int indexlist[],
+				 const T data[])
+  {
+    for(int i = low + 1; i <= high; i++) {
+      T value = data[indexlist[i]];
+      int tempIndex = indexlist[i];
+      int j;
+      for (j = i - 1; j >= low && data[indexlist[j]] > value; j--) {
+	indexlist[j + 1] = indexlist[j];
+      }
+      indexlist[j + 1] = tempIndex;
+    }
+  }
+
+
+} // namespace itpp
+
+#endif // #ifndef SORT_H
Index: /win32/itpp-4.0.1/itpp/base/timing.h
===================================================================
--- /win32/itpp-4.0.1/itpp/base/timing.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/base/timing.h (revision 35)
@@ -0,0 +1,175 @@
+/*!
+ * \file
+ * \brief Definitions of Timing classes
+ * \author Thomas Eriksson, Tony Ottosson and Tobias Ringstrom
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef TIMING_H
+#define TIMING_H
+
+
+namespace itpp {
+
+/*!
+  \addtogroup timers
+*/
+
+/*!
+  \brief A virtual base class for timers.
+  \ingroup timers
+*/
+class Timer {
+public:
+    //! Create a new timer.  Sets the time to zero.
+    Timer();
+    //! Virtual destructor
+    virtual ~Timer() { }
+    //! Start the timer.  This does not set the time to zero.
+    void start(void);
+    //! Stop the timer.  Returns the elapsed time in seconds.
+    double stop(void);
+    //! Sets the time to time t, which is zero by default. Stops the timer if it is running.
+    void reset(double t=0.0);
+    //! Resets the timer and starts it.
+    void tic(void);
+    //! Returns the elapsed time since last tic()
+    double toc(void);
+    //! Prints the elapsed time since last tic()
+    void toc_print(void);
+    //! Returns the elapsed time.
+    double get_time() const;
+
+protected:
+    //! Vitrual function that returns teh current time
+    virtual double get_current_time() const = 0;
+    //! The start time of the timer
+    double start_time;
+    //! The stop time of the timer
+    double stop_time;
+    //! The ellapsed time from start to stop
+    double elapsed_time;
+    //! A bool that indicates if the timer is running or not
+    bool running;
+};
+
+/*!
+  \brief A CPU time timer class
+  \ingroup timers
+
+  Measures the time spent by the CPU on the current process.  If two processes
+  are running concurrently, one real seconds equal 5 CPU seconds per process.
+  The resolution is not very good (in the order of 0.01 seconds).
+
+  Usage: Define a time object:
+  \code
+  CPU_Timer timer;
+  \endcode
+
+  Actions:
+  Reset: \code timer.reset(); \endcode
+  Start: \code timer.start(); \endcode
+  Stop: \code timer.stop(); \endcode
+  Get time: \code elapsedtime = timer.get_time(); \endcode
+
+  It is possible to get elapsed time without stopping the timer.
+  Observe that it is also possible to use the macros "time.tic();"
+  to reset and start clock and "time.toc();" stop and print the elapsed time.
+  \warning May give an negative answer if the measured time is too long.
+*/
+class CPU_Timer : public Timer {
+public:
+    //! Create a new timer. Sets the time to zero.
+    CPU_Timer() { }
+
+protected:
+    //!
+    double get_current_time() const;
+};
+
+/*!
+  \brief A real time timer class
+  \ingroup timers
+
+  Measures real time.
+
+  Usage: Define a time object:
+  \code
+  Real_Timer timer;
+  \endcode
+
+  Actions:
+  Reset: \code timer.reset(); \endcode
+  Start: \code timer.start(); \endcode
+  Stop: \code timer.stop(); \endcode
+  Get time: \code elapsedtime = timer.get_time(); \endcode
+
+  It is possible to get elapsed time without stopping the timer.
+  Observe that it is also possible to use the macros "time.tic();"
+  to reset and start clock and "time.toc_print();" to print the elapsed time.
+
+  \warning May give an negative answer if the measured time is too long.
+*/
+class Real_Timer : public Timer {
+public:
+    //! Create a new timer. Sets the time to zero.
+    Real_Timer() { }
+
+protected:
+    //!
+    double get_current_time() const;
+};
+
+/*!
+  \brief Reset and start timer
+  \ingroup timers
+*/
+void tic();
+
+/*!
+  \brief Returns the elapsed time since last tic()
+  \ingroup timers
+*/
+double toc();
+
+/*!
+  \brief Prints the elapsed time since last tic()
+  \ingroup timers
+*/
+void toc_print();
+
+/*!
+  \brief pause
+  \ingroup timers
+
+  \code pause(n); \endcode  Pauses for n seconds before continuing
+  \code pause(); \endcode  Pauses until a key is pressed
+
+*/
+void pause(double t=-1);
+
+} // namespace itpp
+
+#endif // #ifndef TIMING_H
Index: /win32/itpp-4.0.1/itpp/itbase.h
===================================================================
--- /win32/itpp-4.0.1/itpp/itbase.h (revision 35)
+++ /win32/itpp-4.0.1/itpp/itbase.h (revision 35)
@@ -0,0 +1,130 @@
+/*!
+ * \file
+ * \brief Include file for the IT++ base module
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#ifndef ITBASE_H
+#define ITBASE_H
+
+/*!
+ * \defgroup base Base Module
+ * @{
+ */
+
+//! \defgroup arr_vec_mat Array, Vector and Matrix Classes
+//! \defgroup parser Argument Parser
+
+/*!
+ * \defgroup math Basic and Miscellaneous Math Functions
+ * @{
+ */
+
+//! \defgroup errorfunc Error Functions
+//! \defgroup hypfunc Hyperbolic Functions
+//! \defgroup logexpfunc Logarithmic and Exponential Functions
+//! \defgroup miscfunc Miscellaneous Functions
+//! \defgroup integration Numerical Integration
+//! \defgroup trifunc Trigonometric Functions
+
+/*!
+ * @} end of math group
+ */
+
+//! \defgroup besselfunctions Bessel Functions
+//! \defgroup convertfunc Conversion Functions
+//! \defgroup diag Diagonal Matrices and Functions
+//! \defgroup errorhandlingfunc Error and Warning Handling
+//! \defgroup matrix_functions Functions on Matrices
+//! \defgroup itfile IT++ File Format
+
+/*!
+ * \defgroup algebra Linear Algebra
+ * @{
+ */
+
+//! \defgroup determinant Determinant
+//! \defgroup inverse Inverse Matrix
+//! \defgroup matrixdecomp Matrix Decompositions
+//! \defgroup linearequations Solving Linear Equation Systems
+
+/*!
+ * @} end of algebra group
+ */
+
+//! \defgroup randgen Random Number Generation
+//! \defgroup reshaping Reshaping of Vectors and Matrices
+//! \defgroup specmat Special Matrices
+//! \defgroup timers Timers
+
+/*!
+ * @} end of base group
+ */
+
+
+#include <itpp/base/algebra/cholesky.h>
+#include <itpp/base/algebra/det.h>
+#include <itpp/base/algebra/eigen.h>
+#include <itpp/base/algebra/inv.h>
+#include <itpp/base/algebra/ls_solve.h>
+#include <itpp/base/algebra/lu.h>
+#include <itpp/base/algebra/qr.h>
+#include <itpp/base/algebra/schur.h>
+#include <itpp/base/algebra/svd.h>
+
+#include <itpp/base/math/elem_math.h>
+#include <itpp/base/math/error.h>
+#include <itpp/base/math/integration.h>
+#include <itpp/base/math/log_exp.h>
+#include <itpp/base/math/min_max.h>
+#include <itpp/base/math/misc.h>
+#include <itpp/base/math/trig_hyp.h>
+
+#include <itpp/base/array.h>
+#include <itpp/base/bessel.h>
+#include <itpp/base/binary.h>
+#include <itpp/base/binfile.h>
+#include <itpp/base/circular_buffer.h>
+#include <itpp/base/converters.h>
+#include <itpp/base/factory.h>
+#include <itpp/base/fastmath.h>
+#include <itpp/base/gf2mat.h>
+#include <itpp/base/itassert.h>
+#include <itpp/base/itfile.h>
+#include <itpp/base/ittypes.h>
+#include <itpp/base/mat.h>
+#include <itpp/base/matfunc.h>
+#include <itpp/base/operators.h>
+#include <itpp/base/parser.h>
+#include <itpp/base/random.h>
+#include <itpp/base/smat.h>
+#include <itpp/base/sort.h>
+#include <itpp/base/specmat.h>
+#include <itpp/base/stack.h>
+#include <itpp/base/timing.h>
+#include <itpp/base/vec.h>
+
+#endif // #ifndef ITBASE_H
Index: /CMake_modules/FindACML.cmake
===================================================================
--- /CMake_modules/FindACML.cmake (revision 31)
+++ /CMake_modules/FindACML.cmake (revision 35)
@@ -8,14 +8,12 @@
 #  ACML_LIBRARY, where to find the ACML library.
 
-
 FIND_PATH(ACML_INCLUDE_DIR acml.h
- C:\\Program Files\\AMD\\acml3.6.0\\pgi32\\include  
+	"${ACML_DIR}\\pgi32\\include"
  )
 
 FIND_LIBRARY(ACML_LIBRARY
   NAMES libacml_dll
-  PATHS C:\\Program Files\\AMD\\acml3.6.0\\pgi32\\lib
+  PATHS "${ACML_DIR}\\pgi32\\lib"
   )
-
 
 IF (ACML_LIBRARY AND ACML_INCLUDE_DIR)
Index: /CMake_modules/FindITPP.cmake
===================================================================
--- /CMake_modules/FindITPP.cmake (revision 31)
+++ /CMake_modules/FindITPP.cmake (revision 35)
@@ -8,13 +8,11 @@
 #  ITPP_LIBRARY, where to find the ITPP library.
 
-
 FIND_PATH(ITPP_INCLUDE_DIR itpp/itbase.h
-  C:\\itpp-4.0.1
+	${ITPP_DIR}
   )
-
 
 FIND_LIBRARY(ITPP_LIBRARY
   NAMES itpp itpp_debug
-  PATHS C:\\itpp-4.0.1\\win32\\lib
+  PATHS "${ITPP_DIR}\\win32\\lib"
   )
 
Index: /CMakeLists.txt
===================================================================
--- /CMakeLists.txt (revision 31)
+++ /CMakeLists.txt (revision 35)
@@ -4,16 +4,21 @@
 project (BDM)
 
-
 # In order to be able to use the newly written FindXXX package, the 
 # location of the FindXXX.cmake file must be added to the cmake modules 
-# list from within a CMakeLists.txt file as follows (assuming that
-# FindFoo.cmake exists within a directory called cmake_modules within 
-# the top-level source directory):
-set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake_modules/")
-
+# list from within a CMakeLists.txt file as follows:
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}\\CMake_modules\\")
 
 ######################
 #Platform specific
 IF(WIN32)
+
+# IF YOU WANT TO USE YOUR OWN INSTALLATION OF ITTP AND/OR ACML LIBRARIES,
+# THEN IT IS NECESSARY TO CREATE TEXT FILE "\WIN32\LOCAL_PATHS.TXT" WITH 
+# COPIES OF THE TWO FOLLOWING LINES AND THEN CORECT BOTH INVOLVED PATHS
+	SET(ITPP_DIR ".\\win32\\itpp-4.0.1")
+	SET(ACML_DIR ".\\win32\\acml3.6.0")
+
+	INCLUDE(\\win32\\local_paths.txt OPTIONAL)	
+
 	FIND_PACKAGE(ITPP REQUIRED)
 	FIND_PACKAGE(ACML REQUIRED)
@@ -21,4 +26,5 @@
 	IF(ITPP_FOUND)
 	   INCLUDE_DIRECTORIES(${ITPP_INCLUDE_DIR})
+	   LINK_DIRECTORIES(${NATIVE_ITPP_LIB_PATH})
 	ENDIF(ITPP_FOUND)
 
